mirror of https://github.com/bsnes-emu/bsnes.git
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:
parent
721e0b1762
commit
378b78dad7
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
);
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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 };
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in New Issue