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
snes := snes
gameboy := gameboy
profile := compatibility
profile := accuracy
ui := ui
# debugger

View File

@ -21,7 +21,7 @@ namespace nall {
public:
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_); }
void close() { return p_close(); }
unsigned size() const { return p_size; }
@ -42,7 +42,7 @@ namespace nall {
HANDLE p_filehandle, p_maphandle;
bool p_opened() const {
bool p_open() const {
return p_handle;
}
@ -128,7 +128,7 @@ namespace nall {
int p_fd;
bool p_opened() const {
bool p_open() const {
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() {
Font &font = this->font();
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) {

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() {
Font &font = this->font();
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) {

View File

@ -1,7 +1,7 @@
Geometry pLineEdit::minimumGeometry() {
Font &font = this->font();
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) {

View File

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

View File

@ -96,13 +96,16 @@ inline void PPU::render_line_output() {
}
} else {
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)];
*ptr++ = (prev + curr - ((prev ^ curr) & 0x0421)) >> 1;
prev = curr;
*ptr++ = curr; //(prev + curr - ((prev ^ curr) & 0x0421)) >> 1;
//prev = curr;
curr = luma[get_pixel_normal(x)];
*ptr++ = (prev + curr - ((prev ^ curr) & 0x0421)) >> 1;
prev = curr;
*ptr++ = curr; //(prev + curr - ((prev ^ curr) & 0x0421)) >> 1;
//prev = curr;
}
}
}

View File

@ -247,7 +247,7 @@ void NECDSP::init() {
void NECDSP::load() {
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() {
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() {

View File

@ -14,7 +14,7 @@ void SRTC::init() {
void SRTC::load() {
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() {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -14,9 +14,9 @@ class Screen {
bool oam_color_enable;
bool back_color_enable;
uint8 color_b;
uint8 color_g;
uint8 color_r;
uint5 color_b;
uint5 color_g;
uint5 color_r;
} regs;
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 {
if(size == 0) {
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].size = 0;
}
synchronize();
t.x = 0;
t.y = 0;
@ -193,13 +194,13 @@ void PPU::Sprite::reset() {
}
}
regs.main_enable = 0;
regs.sub_enable = 0;
regs.interlace = 0;
regs.main_enable = random(false);
regs.sub_enable = random(false);
regs.interlace = random(false);
regs.base_size = 0;
regs.nameselect = 0;
regs.tiledata_addr = 0;
regs.base_size = random(0);
regs.nameselect = random(0);
regs.tiledata_addr = random(0x0000);
regs.first_sprite = 0;
regs.priority0 = 0;
@ -207,8 +208,8 @@ void PPU::Sprite::reset() {
regs.priority2 = 0;
regs.priority3 = 0;
regs.time_over = 0;
regs.range_over = 0;
regs.time_over = false;
regs.range_over = false;
output.main.palette = 0;
output.main.priority = 0;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -111,7 +111,7 @@ bool Cartridge::loadCartridge(SNES::MappedRAM &memory, string &XML, const char *
fp.close();
filemap patch(string(nall::basename(filename), ".ups"), filemap::mode::read);
if(patch.opened()) {
if(patch.open()) {
unsigned targetSize;
ups patcher;
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) {
bool interlace = (height >= 240);
bool overscan = (height == 239 || height == 478);
bool interlace = SNES::ppu.interlace();
bool overscan = SNES::ppu.overscan();
unsigned inpitch = interlace ? 1024 : 2048;
uint32_t *buffer;
unsigned outpitch;
//always ignore blank scanline 0
data += 1024;
height -= 1 << interlace;
if(config.video.region == 0 && (height == 239 || height == 478)) {
//NTSC overscan compensation (center image, remove 15 lines)
data += 7 * 1024;
if(height == 239) height = 224;
if(height == 478) height = 448;
if(config.video.region == 0) {
//NTSC overscan compensation
height -= 15 << interlace;
if(overscan == true ) data += 7 * 1024;
}
if(config.video.region == 1 && (height == 224 || height == 448)) {
//PAL underscan compensation (center image, add 15 lines)
data -= 7 * 1024;
if(height == 224) height = 239;
if(height == 448) height = 478;
if(config.video.region == 1) {
//PAL underscan compensation
if(overscan == false) data -= 7 * 1024;
}
unsigned outwidth = width, outheight = height;
filter.size(outwidth, outheight);
uint32_t *buffer;
unsigned outpitch;
if(video.lock(buffer, outpitch, outwidth, outheight)) {
filter.render(buffer, outpitch, data, inpitch, width, height);
video.unlock();