Update to v077r05 release.

byuu says:

Changelog:
- fixed .nec and both .rtc file extensions (thanks krom)
- randomized most S-PPU registers, should trip up some broken homebrew
  that does not initialize all registers
- randomization is now seeded with time(0) rather than 'byuu'
- SNES::interface.video_refresh() now always receives
  {256,512}x{240,480}
- PPU/accuracy scanline 0 does not render the screen back color anymore,
  fixes strange coloring look on first scanline in PAL TV mode in
  non-overscan games
- disabled hires blending in PPU/compatibility; all three cores act the
  same now
This commit is contained in:
Tim Allen 2011-04-27 18:57:31 +10:00
parent 721e0b1762
commit 378b78dad7
30 changed files with 325 additions and 165 deletions

View File

@ -1,7 +1,7 @@
include nall/Makefile include nall/Makefile
snes := snes snes := snes
gameboy := gameboy gameboy := gameboy
profile := compatibility profile := accuracy
ui := ui ui := ui
# debugger # debugger

View File

@ -21,7 +21,7 @@ namespace nall {
public: public:
enum class mode : unsigned { read, write, readwrite, writeread }; enum class mode : unsigned { read, write, readwrite, writeread };
bool opened() const { return p_opened(); } bool open() const { return p_open(); }
bool open(const char *filename, mode mode_) { return p_open(filename, mode_); } bool open(const char *filename, mode mode_) { return p_open(filename, mode_); }
void close() { return p_close(); } void close() { return p_close(); }
unsigned size() const { return p_size; } unsigned size() const { return p_size; }
@ -42,7 +42,7 @@ namespace nall {
HANDLE p_filehandle, p_maphandle; HANDLE p_filehandle, p_maphandle;
bool p_opened() const { bool p_open() const {
return p_handle; return p_handle;
} }
@ -128,7 +128,7 @@ namespace nall {
int p_fd; int p_fd;
bool p_opened() const { bool p_open() const {
return p_handle; return p_handle;
} }

View File

@ -0,0 +1,59 @@
static void Canvas_expose(pCanvas *self) {
self->redraw();
}
uint32_t* pCanvas::buffer() {
return bufferRGB;
}
void pCanvas::setGeometry(const Geometry &geometry) {
delete[] bufferRGB;
delete[] bufferBGR;
bufferRGB = new uint32_t[geometry.width * geometry.height]();
bufferBGR = new uint32_t[geometry.width * geometry.height]();
pWidget::setGeometry(geometry);
update();
}
void pCanvas::update() {
if(gtk_widget_get_realized(gtkWidget) == false) return;
GdkRectangle rect;
rect.x = 0;
rect.y = 0;
rect.width = gtkWidget->allocation.width;
rect.height = gtkWidget->allocation.height;
gdk_window_invalidate_rect(gtkWidget->window, &rect, true);
}
void pCanvas::constructor() {
bufferRGB = new uint32_t[256 * 256]();
bufferBGR = new uint32_t[256 * 256]();
gtkWidget = gtk_drawing_area_new();
GdkColor color;
color.pixel = color.red = color.green = color.blue = 0;
gtk_widget_modify_bg(gtkWidget, GTK_STATE_NORMAL, &color);
gtk_widget_set_double_buffered(gtkWidget, false);
gtk_widget_add_events(gtkWidget, GDK_EXPOSURE_MASK);
g_signal_connect_swapped(G_OBJECT(gtkWidget), "expose_event", G_CALLBACK(Canvas_expose), (gpointer)this);
}
void pCanvas::redraw() {
if(gtk_widget_get_realized(gtkWidget) == false) return;
uint32_t *rgb = bufferRGB, *bgr = bufferBGR;
for(unsigned y = gtkWidget->allocation.height; y; y--) {
for(unsigned x = gtkWidget->allocation.width; x; x--) {
uint32_t pixel = *rgb++;
*bgr++ = ((pixel << 16) & 0xff0000) | (pixel & 0x00ff00) | ((pixel >> 16) & 0x0000ff);
}
}
gdk_draw_rgb_32_image(
gtkWidget->window,
gtkWidget->style->fg_gc[GTK_WIDGET_STATE(gtkWidget)],
0, 0, gtkWidget->allocation.width, gtkWidget->allocation.height,
GDK_RGB_DITHER_NONE, (guchar*)bufferBGR, sizeof(uint32_t) * gtkWidget->allocation.width
);
}

View File

@ -0,0 +1,27 @@
uint32_t* pCanvas::buffer() {
return (uint32_t*)qtImage->bits();
}
void pCanvas::setGeometry(const Geometry &geometry) {
qtImage = new QImage(geometry.width, geometry.height, QImage::Format_RGB32);
qtImage->fill(0);
update();
pWidget::setGeometry(geometry);
}
void pCanvas::update() {
qtCanvas->update();
}
void pCanvas::constructor() {
qtWidget = qtCanvas = new QtCanvas(*this);
qtImage = new QImage(256, 256, QImage::Format_RGB32);
}
void pCanvas::QtCanvas::paintEvent(QPaintEvent *event) {
QPainter painter(self.qtCanvas);
painter.drawImage(0, 0, *self.qtImage);
}
pCanvas::QtCanvas::QtCanvas(pCanvas &self) : self(self) {
}

View File

@ -1,7 +1,7 @@
Geometry pButton::minimumGeometry() { Geometry pButton::minimumGeometry() {
Font &font = this->font(); Font &font = this->font();
Geometry geometry = font.geometry(button.state.text); Geometry geometry = font.geometry(button.state.text);
return { 0, 0, geometry.width + 20, font.p.height() + 12 }; return { 0, 0, geometry.width + 20, font.p.height() + 10 };
} }
void pButton::setText(const string &text) { void pButton::setText(const string &text) {

View File

@ -0,0 +1,54 @@
static LRESULT CALLBACK Canvas_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
if(msg == WM_PAINT) {
Object *object = (Object*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
if(object && dynamic_cast<Canvas*>(object)) {
Canvas &canvas = (Canvas&)*object;
canvas.update();
}
}
return DefWindowProc(hwnd, msg, wparam, lparam);
}
uint32_t* pCanvas::buffer() {
return bufferRGB;
}
void pCanvas::setGeometry(const Geometry &geometry) {
delete[] bufferRGB;
bufferRGB = new uint32_t[geometry.width * geometry.height]();
pWidget::setGeometry(geometry);
update();
}
void pCanvas::update() {
RECT rc;
GetClientRect(hwnd, &rc);
unsigned width = rc.right, height = rc.bottom;
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(BITMAPINFO));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biWidth = width;
bmi.bmiHeader.biHeight = -height; //GDI stores bitmaps upside now; negative height flips bitmap
bmi.bmiHeader.biSizeImage = sizeof(uint32_t) * width * height;
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
SetDIBitsToDevice(ps.hdc, 0, 0, width, height, 0, 0, 0, height, (void*)bufferRGB, &bmi, DIB_RGB_COLORS);
EndPaint(hwnd, &ps);
InvalidateRect(hwnd, 0, false);
}
void pCanvas::constructor() {
bufferRGB = new uint32_t[256 * 256]();
setParent(Window::None);
}
void pCanvas::setParent(Window &parent) {
if(hwnd) DestroyWindow(hwnd);
hwnd = CreateWindow(L"phoenix_canvas", L"", WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, parent.p.hwnd, (HMENU)id, GetModuleHandle(0), 0);
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&canvas);
}

View File

@ -1,7 +1,7 @@
Geometry pLabel::minimumGeometry() { Geometry pLabel::minimumGeometry() {
Font &font = this->font(); Font &font = this->font();
Geometry geometry = font.geometry(label.state.text); Geometry geometry = font.geometry(label.state.text);
return { 0, 0, geometry.width, font.p.height() }; return { 0, 0, geometry.width, geometry.height };
} }
void pLabel::setText(const string &text) { void pLabel::setText(const string &text) {

View File

@ -1,7 +1,7 @@
Geometry pLineEdit::minimumGeometry() { Geometry pLineEdit::minimumGeometry() {
Font &font = this->font(); Font &font = this->font();
Geometry geometry = font.geometry(lineEdit.state.text); Geometry geometry = font.geometry(lineEdit.state.text);
return { 0, 0, geometry.width + 12, font.p.height() + 8 }; return { 0, 0, geometry.width + 12, font.p.height() + 10 };
} }
void pLineEdit::setEditable(bool editable) { void pLineEdit::setEditable(bool editable) {

View File

@ -1,5 +1,5 @@
Geometry pProgressBar::minimumGeometry() { Geometry pProgressBar::minimumGeometry() {
return { 0, 0, 0, 25 }; return { 0, 0, 0, 23 };
} }
void pProgressBar::setPosition(unsigned position) { void pProgressBar::setPosition(unsigned position) {

View File

@ -96,13 +96,16 @@ inline void PPU::render_line_output() {
} }
} else { } else {
for(unsigned x = 0, prev = 0; x < 256; x++) { for(unsigned x = 0, prev = 0; x < 256; x++) {
//blending is disabled below, as this should be done via video filtering
//blending code is left for reference purposes
curr = luma[get_pixel_swap(x)]; curr = luma[get_pixel_swap(x)];
*ptr++ = (prev + curr - ((prev ^ curr) & 0x0421)) >> 1; *ptr++ = curr; //(prev + curr - ((prev ^ curr) & 0x0421)) >> 1;
prev = curr; //prev = curr;
curr = luma[get_pixel_normal(x)]; curr = luma[get_pixel_normal(x)];
*ptr++ = (prev + curr - ((prev ^ curr) & 0x0421)) >> 1; *ptr++ = curr; //(prev + curr - ((prev ^ curr) & 0x0421)) >> 1;
prev = curr; //prev = curr;
} }
} }
} }

View File

@ -247,7 +247,7 @@ void NECDSP::init() {
void NECDSP::load() { void NECDSP::load() {
if(revision == Revision::uPD96050) { if(revision == Revision::uPD96050) {
cartridge.nvram.append({ "nec", (uint8_t*)dataRAM, 4096 }); cartridge.nvram.append({ ".nec", (uint8_t*)dataRAM, 4096 });
} }
} }

View File

@ -15,7 +15,7 @@ void SPC7110::init() {
void SPC7110::load() { void SPC7110::load() {
for(unsigned n = 0; n < 20; n++) rtc[n] = 0xff; for(unsigned n = 0; n < 20; n++) rtc[n] = 0xff;
if(cartridge.has_spc7110rtc()) cartridge.nvram.append({ "rtc", rtc, 20 }); if(cartridge.has_spc7110rtc()) cartridge.nvram.append({ ".rtc", rtc, 20 });
} }
void SPC7110::unload() { void SPC7110::unload() {

View File

@ -14,7 +14,7 @@ void SRTC::init() {
void SRTC::load() { void SRTC::load() {
for(unsigned n = 0; n < 20; n++) rtc[n] = 0xff; for(unsigned n = 0; n < 20; n++) rtc[n] = 0xff;
cartridge.nvram.append({ "rtc", rtc, 20 }); cartridge.nvram.append({ ".rtc", rtc, 20 });
} }
void SRTC::unload() { void SRTC::unload() {

View File

@ -211,18 +211,18 @@ unsigned PPU::Background::get_tile_color() {
} }
void PPU::Background::reset() { void PPU::Background::reset() {
regs.tiledata_addr = 0; regs.tiledata_addr = random(0x0000);
regs.screen_addr = 0; regs.screen_addr = random(0x0000);
regs.screen_size = 0; regs.screen_size = random(0);
regs.mosaic = 0; regs.mosaic = random(0);
regs.tile_size = 0; regs.tile_size = random(0);
regs.mode = 0; regs.mode = 0;
regs.priority0 = 0; regs.priority0 = 0;
regs.priority1 = 0; regs.priority1 = 0;
regs.main_enable = 0; regs.main_enable = random(0);
regs.sub_enable = 0; regs.sub_enable = random(0);
regs.hoffset = 0; regs.hoffset = random(0x0000);
regs.voffset = 0; regs.voffset = random(0x0000);
output.main.palette = 0; output.main.palette = 0;
output.main.priority = 0; output.main.priority = 0;

View File

@ -8,10 +8,10 @@ class Background {
struct Screen { enum { Main, Sub }; }; struct Screen { enum { Main, Sub }; };
struct Regs { struct Regs {
unsigned tiledata_addr; uint16 tiledata_addr;
unsigned screen_addr; uint16 screen_addr;
unsigned screen_size; uint2 screen_size;
unsigned mosaic; uint4 mosaic;
bool tile_size; bool tile_size;
unsigned mode; unsigned mode;
@ -21,8 +21,8 @@ class Background {
bool main_enable; bool main_enable;
bool sub_enable; bool sub_enable;
unsigned hoffset; uint16 hoffset;
unsigned voffset; uint16 voffset;
} regs; } regs;
struct Output { struct Output {

View File

@ -681,14 +681,14 @@ uint8 PPU::mmio_r213f() {
} }
void PPU::mmio_reset() { void PPU::mmio_reset() {
regs.ppu1_mdr = 0xff; regs.ppu1_mdr = random(0xff);
regs.ppu2_mdr = 0xff; regs.ppu2_mdr = random(0xff);
regs.vram_readbuffer = 0x0000; regs.vram_readbuffer = random(0x0000);
regs.oam_latchdata = 0x00; regs.oam_latchdata = random(0x00);
regs.cgram_latchdata = 0x00; regs.cgram_latchdata = random(0x00);
regs.bgofs_latchdata = 0x00; regs.bgofs_latchdata = random(0x00);
regs.mode7_latchdata = 0x00; regs.mode7_latchdata = random(0x00);
regs.counters_latched = false; regs.counters_latched = false;
regs.latch_hcounter = 0; regs.latch_hcounter = 0;
regs.latch_vcounter = 0; regs.latch_vcounter = 0;
@ -702,58 +702,58 @@ void PPU::mmio_reset() {
//$2102 OAMADDL //$2102 OAMADDL
//$2103 OAMADDH //$2103 OAMADDH
regs.oam_baseaddr = 0x0000; regs.oam_baseaddr = random(0x0000);
regs.oam_addr = 0x0000; regs.oam_addr = random(0x0000);
regs.oam_priority = false; regs.oam_priority = random(false);
//$2105 BGMODE //$2105 BGMODE
regs.bg3_priority = false; regs.bg3_priority = false;
regs.bgmode = 0; regs.bgmode = 0;
//$210d BG1HOFS //$210d BG1HOFS
regs.mode7_hoffset = 0x0000; regs.mode7_hoffset = random(0x0000);
//$210e BG1VOFS //$210e BG1VOFS
regs.mode7_voffset = 0x0000; regs.mode7_voffset = random(0x0000);
//$2115 VMAIN //$2115 VMAIN
regs.vram_incmode = 1; regs.vram_incmode = random(1);
regs.vram_mapping = 0; regs.vram_mapping = random(0);
regs.vram_incsize = 1; regs.vram_incsize = 1;
//$2116 VMADDL //$2116 VMADDL
//$2117 VMADDH //$2117 VMADDH
regs.vram_addr = 0x0000; regs.vram_addr = random(0x0000);
//$211a M7SEL //$211a M7SEL
regs.mode7_repeat = 0; regs.mode7_repeat = random(0);
regs.mode7_vflip = false; regs.mode7_vflip = random(false);
regs.mode7_hflip = false; regs.mode7_hflip = random(false);
//$211b M7A //$211b M7A
regs.m7a = 0x0000; regs.m7a = random(0x0000);
//$211c M7B //$211c M7B
regs.m7b = 0x0000; regs.m7b = random(0x0000);
//$211d M7C //$211d M7C
regs.m7c = 0x0000; regs.m7c = random(0x0000);
//$211e M7D //$211e M7D
regs.m7d = 0x0000; regs.m7d = random(0x0000);
//$211f M7X //$211f M7X
regs.m7x = 0x0000; regs.m7x = random(0x0000);
//$2120 M7Y //$2120 M7Y
regs.m7y = 0x0000; regs.m7y = random(0x0000);
//$2121 CGADD //$2121 CGADD
regs.cgram_addr = 0x0000; regs.cgram_addr = random(0x0000);
//$2133 SETINI //$2133 SETINI
regs.mode7_extbg = false; regs.mode7_extbg = random(false);
regs.pseudo_hires = false; regs.pseudo_hires = random(false);
regs.overscan = false; regs.overscan = false;
regs.interlace = false; regs.interlace = false;

View File

@ -22,7 +22,7 @@ struct {
//$2100 INIDISP //$2100 INIDISP
bool display_disable; bool display_disable;
unsigned display_brightness; uint4 display_brightness;
//$2102 OAMADDL //$2102 OAMADDL
//$2103 OAMADDH //$2103 OAMADDH
@ -42,7 +42,7 @@ struct {
//$2115 VMAIN //$2115 VMAIN
bool vram_incmode; bool vram_incmode;
uint8 vram_mapping; uint2 vram_mapping;
uint8 vram_incsize; uint8 vram_incsize;
//$2116 VMADDL //$2116 VMADDL
@ -50,7 +50,7 @@ struct {
uint16 vram_addr; uint16 vram_addr;
//$211a M7SEL //$211a M7SEL
uint8 mode7_repeat; uint2 mode7_repeat;
bool mode7_vflip; bool mode7_vflip;
bool mode7_hflip; bool mode7_hflip;

View File

@ -6,6 +6,8 @@ void PPU::Screen::scanline() {
} }
void PPU::Screen::run() { void PPU::Screen::run() {
if(ppu.vcounter() == 0) return;
uint16 color; uint16 color;
if(self.regs.pseudo_hires == false && self.regs.bgmode != 5 && self.regs.bgmode != 6) { if(self.regs.pseudo_hires == false && self.regs.bgmode != 5 && self.regs.bgmode != 6) {
color = get_pixel(0); color = get_pixel(0);
@ -186,19 +188,19 @@ uint16 PPU::Screen::get_direct_color(unsigned palette, unsigned tile) {
} }
void PPU::Screen::reset() { void PPU::Screen::reset() {
regs.addsub_mode = 0; regs.addsub_mode = random(false);
regs.direct_color = 0; regs.direct_color = random(false);
regs.color_mode = 0; regs.color_mode = random(false);
regs.color_halve = 0; regs.color_halve = random(false);
regs.bg1_color_enable = 0; regs.bg1_color_enable = random(false);
regs.bg2_color_enable = 0; regs.bg2_color_enable = random(false);
regs.bg3_color_enable = 0; regs.bg3_color_enable = random(false);
regs.bg4_color_enable = 0; regs.bg4_color_enable = random(false);
regs.oam_color_enable = 0; regs.oam_color_enable = random(false);
regs.back_color_enable = 0; regs.back_color_enable = random(false);
regs.color_r = 0; regs.color_r = random(0);
regs.color_g = 0; regs.color_g = random(0);
regs.color_b = 0; regs.color_b = random(0);
} }
PPU::Screen::Screen(PPU &self) : self(self) { PPU::Screen::Screen(PPU &self) : self(self) {

View File

@ -14,9 +14,9 @@ class Screen {
bool oam_color_enable; bool oam_color_enable;
bool back_color_enable; bool back_color_enable;
uint8 color_b; uint5 color_b;
uint8 color_g; uint5 color_g;
uint8 color_r; uint5 color_r;
} regs; } regs;
void scanline(); void scanline();

View File

@ -32,6 +32,10 @@ void PPU::Sprite::update(unsigned addr, uint8 data) {
} }
} }
void PPU::Sprite::synchronize() {
for(unsigned n = 0; n < 544; n++) update(n, ppu.oam[n]);
}
unsigned PPU::Sprite::SpriteItem::width() const { unsigned PPU::Sprite::SpriteItem::width() const {
if(size == 0) { if(size == 0) {
static unsigned width[] = { 8, 8, 8, 16, 16, 32, 16, 16 }; static unsigned width[] = { 8, 8, 8, 16, 16, 32, 16, 16 };

View File

@ -171,6 +171,7 @@ void PPU::Sprite::reset() {
list[i].palette = 0; list[i].palette = 0;
list[i].size = 0; list[i].size = 0;
} }
synchronize();
t.x = 0; t.x = 0;
t.y = 0; t.y = 0;
@ -193,13 +194,13 @@ void PPU::Sprite::reset() {
} }
} }
regs.main_enable = 0; regs.main_enable = random(false);
regs.sub_enable = 0; regs.sub_enable = random(false);
regs.interlace = 0; regs.interlace = random(false);
regs.base_size = 0; regs.base_size = random(0);
regs.nameselect = 0; regs.nameselect = random(0);
regs.tiledata_addr = 0; regs.tiledata_addr = random(0x0000);
regs.first_sprite = 0; regs.first_sprite = 0;
regs.priority0 = 0; regs.priority0 = 0;
@ -207,8 +208,8 @@ void PPU::Sprite::reset() {
regs.priority2 = 0; regs.priority2 = 0;
regs.priority3 = 0; regs.priority3 = 0;
regs.time_over = 0; regs.time_over = false;
regs.range_over = 0; regs.range_over = false;
output.main.palette = 0; output.main.palette = 0;
output.main.priority = 0; output.main.priority = 0;

View File

@ -38,8 +38,8 @@ class Sprite {
bool sub_enable; bool sub_enable;
bool interlace; bool interlace;
uint8 base_size; uint3 base_size;
uint8 nameselect; uint2 nameselect;
uint16 tiledata_addr; uint16 tiledata_addr;
uint8 first_sprite; uint8 first_sprite;
@ -61,6 +61,7 @@ class Sprite {
//list.cpp //list.cpp
void update(unsigned addr, uint8 data); void update(unsigned addr, uint8 data);
void synchronize();
//sprite.cpp //sprite.cpp
void address_reset(); void address_reset();

View File

@ -108,52 +108,52 @@ void PPU::Window::test(
} }
void PPU::Window::reset() { void PPU::Window::reset() {
regs.bg1_one_enable = false; regs.bg1_one_enable = random(false);
regs.bg1_one_invert = false; regs.bg1_one_invert = random(false);
regs.bg1_two_enable = false; regs.bg1_two_enable = random(false);
regs.bg1_two_invert = false; regs.bg1_two_invert = random(false);
regs.bg2_one_enable = false; regs.bg2_one_enable = random(false);
regs.bg2_one_invert = false; regs.bg2_one_invert = random(false);
regs.bg2_two_enable = false; regs.bg2_two_enable = random(false);
regs.bg2_two_invert = false; regs.bg2_two_invert = random(false);
regs.bg3_one_enable = false; regs.bg3_one_enable = random(false);
regs.bg3_one_invert = false; regs.bg3_one_invert = random(false);
regs.bg3_two_enable = false; regs.bg3_two_enable = random(false);
regs.bg3_two_invert = false; regs.bg3_two_invert = random(false);
regs.bg4_one_enable = false; regs.bg4_one_enable = random(false);
regs.bg4_one_invert = false; regs.bg4_one_invert = random(false);
regs.bg4_two_enable = false; regs.bg4_two_enable = random(false);
regs.bg4_two_invert = false; regs.bg4_two_invert = random(false);
regs.oam_one_enable = false; regs.oam_one_enable = random(false);
regs.oam_one_invert = false; regs.oam_one_invert = random(false);
regs.oam_two_enable = false; regs.oam_two_enable = random(false);
regs.oam_two_invert = false; regs.oam_two_invert = random(false);
regs.col_one_enable = false; regs.col_one_enable = random(false);
regs.col_one_invert = false; regs.col_one_invert = random(false);
regs.col_two_enable = false; regs.col_two_enable = random(false);
regs.col_two_invert = false; regs.col_two_invert = random(false);
regs.one_left = 0; regs.one_left = random(0x00);
regs.one_right = 0; regs.one_right = random(0x00);
regs.two_left = 0; regs.two_left = random(0x00);
regs.two_right = 0; regs.two_right = random(0x00);
regs.bg1_mask = 0; regs.bg1_mask = random(0);
regs.bg2_mask = 0; regs.bg2_mask = random(0);
regs.bg3_mask = 0; regs.bg3_mask = random(0);
regs.bg4_mask = 0; regs.bg4_mask = random(0);
regs.oam_mask = 0; regs.oam_mask = random(0);
regs.col_mask = 0; regs.col_mask = random(0);
regs.bg1_main_enable = 0; regs.bg1_main_enable = random(false);
regs.bg1_sub_enable = 0; regs.bg1_sub_enable = random(false);
regs.bg2_main_enable = 0; regs.bg2_main_enable = random(false);
regs.bg2_sub_enable = 0; regs.bg2_sub_enable = random(false);
regs.bg3_main_enable = 0; regs.bg3_main_enable = random(false);
regs.bg3_sub_enable = 0; regs.bg3_sub_enable = random(false);
regs.bg4_main_enable = 0; regs.bg4_main_enable = random(false);
regs.bg4_sub_enable = 0; regs.bg4_sub_enable = random(false);
regs.oam_main_enable = 0; regs.oam_main_enable = random(false);
regs.oam_sub_enable = 0; regs.oam_sub_enable = random(false);
regs.col_main_mask = 0; regs.col_main_mask = random(0);
regs.col_sub_mask = 0; regs.col_sub_mask = random(0);
output.main.color_enable = 0; output.main.color_enable = 0;
output.sub.color_enable = 0; output.sub.color_enable = 0;

View File

@ -35,12 +35,12 @@ class Window {
uint8 two_left; uint8 two_left;
uint8 two_right; uint8 two_right;
uint8 bg1_mask; uint2 bg1_mask;
uint8 bg2_mask; uint2 bg2_mask;
uint8 bg3_mask; uint2 bg3_mask;
uint8 bg4_mask; uint2 bg4_mask;
uint8 oam_mask; uint2 oam_mask;
uint8 col_mask; uint2 col_mask;
bool bg1_main_enable; bool bg1_main_enable;
bool bg1_sub_enable; bool bg1_sub_enable;
@ -53,8 +53,8 @@ class Window {
bool oam_main_enable; bool oam_main_enable;
bool oam_sub_enable; bool oam_sub_enable;
uint8 col_main_mask; uint2 col_main_mask;
uint8 col_sub_mask; uint2 col_sub_mask;
} regs; } regs;
struct Output { struct Output {

View File

@ -1,7 +1,7 @@
namespace SNES { namespace SNES {
namespace Info { namespace Info {
static const char Name[] = "bsnes"; static const char Name[] = "bsnes";
static const char Version[] = "077.04"; static const char Version[] = "077.05";
static const unsigned SerializerVersion = 19; static const unsigned SerializerVersion = 19;
} }
} }

View File

@ -148,7 +148,7 @@ void System::unload() {
} }
void System::power() { void System::power() {
random.seed(0x62797575); random.seed((unsigned)time(0));
region = config.region; region = config.region;
expansion = config.expansion_port; expansion = config.expansion_port;

View File

@ -55,11 +55,8 @@ void Video::update() {
uint16_t *data = (uint16_t*)ppu.output; uint16_t *data = (uint16_t*)ppu.output;
if(ppu.interlace() && ppu.field()) data += 512; if(ppu.interlace() && ppu.field()) data += 512;
unsigned width = 256;
unsigned height = !ppu.overscan() ? 224 : 239;
if(frame_hires) { if(frame_hires) {
width <<= 1;
//normalize line widths //normalize line widths
for(unsigned y = 0; y < 240; y++) { for(unsigned y = 0; y < 240; y++) {
if(line_width[y] == 512) continue; if(line_width[y] == 512) continue;
@ -70,11 +67,7 @@ void Video::update() {
} }
} }
if(frame_interlace) { system.interface->video_refresh(ppu.output, 256 << frame_hires, 240 << frame_interlace);
height <<= 1;
}
system.interface->video_refresh(ppu.output + 1024, width, height);
frame_hires = false; frame_hires = false;
frame_interlace = false; frame_interlace = false;

View File

@ -111,7 +111,7 @@ bool Cartridge::loadCartridge(SNES::MappedRAM &memory, string &XML, const char *
fp.close(); fp.close();
filemap patch(string(nall::basename(filename), ".ups"), filemap::mode::read); filemap patch(string(nall::basename(filename), ".ups"), filemap::mode::read);
if(patch.opened()) { if(patch.open()) {
unsigned targetSize; unsigned targetSize;
ups patcher; ups patcher;
if(patcher.apply(patch.data(), patch.size(), data, size, (uint8_t*)0, targetSize) == ups::result::target_too_small) { if(patcher.apply(patch.data(), patch.size(), data, size, (uint8_t*)0, targetSize) == ups::result::target_too_small) {

16
bsnes/ui/input/hotkeys.hpp Executable file
View File

@ -0,0 +1,16 @@
struct HotkeysGeneral : Controller {
DigitalInput stateSave;
DigitalInput stateLoad;
DigitalInput stateDecrement;
DigitalInput stateIncrement;
DigitalInput fullscreenToggle;
DigitalInput mouseCaptureToggle;
DigitalInput pauseToggle;
DigitalInput fastForward;
DigitalInput power;
DigitalInput reset;
void create(const char *deviceName, const char *configName);
} hotkeysGeneral;
struct Hotkeys : ControllerPort {
} hotkeys;

View File

@ -79,30 +79,30 @@ void Filter::render(uint32_t *output, unsigned outpitch, const uint16_t *input,
} }
void Interface::video_refresh(const uint16_t *data, unsigned width, unsigned height) { void Interface::video_refresh(const uint16_t *data, unsigned width, unsigned height) {
bool interlace = (height >= 240); bool interlace = SNES::ppu.interlace();
bool overscan = (height == 239 || height == 478); bool overscan = SNES::ppu.overscan();
unsigned inpitch = interlace ? 1024 : 2048; unsigned inpitch = interlace ? 1024 : 2048;
uint32_t *buffer; //always ignore blank scanline 0
unsigned outpitch; data += 1024;
height -= 1 << interlace;
if(config.video.region == 0 && (height == 239 || height == 478)) { if(config.video.region == 0) {
//NTSC overscan compensation (center image, remove 15 lines) //NTSC overscan compensation
data += 7 * 1024; height -= 15 << interlace;
if(height == 239) height = 224; if(overscan == true ) data += 7 * 1024;
if(height == 478) height = 448;
} }
if(config.video.region == 1 && (height == 224 || height == 448)) { if(config.video.region == 1) {
//PAL underscan compensation (center image, add 15 lines) //PAL underscan compensation
data -= 7 * 1024; if(overscan == false) data -= 7 * 1024;
if(height == 224) height = 239;
if(height == 448) height = 478;
} }
unsigned outwidth = width, outheight = height; unsigned outwidth = width, outheight = height;
filter.size(outwidth, outheight); filter.size(outwidth, outheight);
uint32_t *buffer;
unsigned outpitch;
if(video.lock(buffer, outpitch, outwidth, outheight)) { if(video.lock(buffer, outpitch, outwidth, outheight)) {
filter.render(buffer, outpitch, data, inpitch, width, height); filter.render(buffer, outpitch, data, inpitch, width, height);
video.unlock(); video.unlock();