mirror of https://github.com/bsnes-emu/bsnes.git
Update to v068r24 release.
(there was no r23 release posted to the WIP thread) byuu says: Fixes OAM latchdata for all 3 cores and CGRAM address invalidation for the accuracy core (the only one that really does it because it needs cycle PPU timing.) Also removes the OAM/CGRAM read/write functions to put them inside the actual MMIO functions. Easier to handle all the special cases that way. VRAM is a bit more annoying since there's two read and two write functions. This should fix battletech/mechwarrior 3050 palette at least.
This commit is contained in:
parent
8a91c95002
commit
d0d8c2a921
|
@ -1,7 +1,7 @@
|
|||
include nall/Makefile
|
||||
snes := snes
|
||||
profile := performance
|
||||
ui := ui-phoenix
|
||||
profile := accuracy
|
||||
ui := ui-qt
|
||||
|
||||
# compiler
|
||||
c := $(compiler) -std=gnu99
|
||||
|
|
|
@ -37,11 +37,11 @@ void PPU::mmio_w2103(uint8 data) {
|
|||
|
||||
//OAMDATA
|
||||
void PPU::mmio_w2104(uint8 data) {
|
||||
if((regs.oam_addr & 1) == 0) regs.oam_latchdata = data;
|
||||
|
||||
if(regs.oam_addr & 0x0200) {
|
||||
oam_mmio_write(regs.oam_addr, data);
|
||||
} else if((regs.oam_addr & 1) == 0) {
|
||||
regs.oam_latchdata = data;
|
||||
} else {
|
||||
} else if((regs.oam_addr & 1) == 1) {
|
||||
oam_mmio_write((regs.oam_addr & ~1) + 0, regs.oam_latchdata);
|
||||
oam_mmio_write((regs.oam_addr & ~1) + 1, data);
|
||||
}
|
||||
|
|
|
@ -311,11 +311,10 @@ void PPU::mmio_write(unsigned addr, uint8 data) {
|
|||
}
|
||||
|
||||
case 0x2104: { //OAMDATA
|
||||
if((regs.oam_addr & 1) == 0) regs.oam_latchdata = data;
|
||||
if(regs.oam_addr & 0x0200) {
|
||||
oam_write(regs.oam_addr, data);
|
||||
} else if((regs.oam_addr & 1) == 0) {
|
||||
regs.oam_latchdata = data;
|
||||
} else {
|
||||
} else if((regs.oam_addr & 1) == 1) {
|
||||
oam_write((regs.oam_addr & ~1) + 0, regs.oam_latchdata);
|
||||
oam_write((regs.oam_addr & ~1) + 1, data);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,17 @@
|
|||
#ifdef PPU_CPP
|
||||
|
||||
bool PPU::interlace() const {
|
||||
return display.interlace;
|
||||
}
|
||||
|
||||
bool PPU::overscan() const {
|
||||
return display.overscan;
|
||||
}
|
||||
|
||||
bool PPU::hires() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void PPU::latch_counters() {
|
||||
cpu.synchronize_ppu();
|
||||
regs.hcounter = hdot();
|
||||
|
@ -31,45 +43,6 @@ void PPU::vram_write(unsigned addr, uint8 data) {
|
|||
}
|
||||
}
|
||||
|
||||
uint8 PPU::oam_read(unsigned addr) {
|
||||
if(!regs.display_disable && vcounter() < (!regs.overscan ? 225 : 240)) addr = regs.ioamaddr;
|
||||
if(addr & 0x0200) addr &= 0x021f;
|
||||
return memory::oam[addr];
|
||||
}
|
||||
|
||||
void PPU::oam_write(unsigned addr, uint8 data) {
|
||||
if(!regs.display_disable && vcounter() < (!regs.overscan ? 225 : 240)) addr = regs.ioamaddr;
|
||||
if(addr & 0x0200) addr &= 0x021f;
|
||||
memory::oam[addr] = data;
|
||||
oam.update(addr, data);
|
||||
}
|
||||
|
||||
uint8 PPU::cgram_read(unsigned addr) {
|
||||
if(!regs.display_disable && vcounter() < (!regs.overscan ? 225 : 240)) {
|
||||
if(hcounter() >= 128 && hcounter() < 1096) addr = 0x0000;
|
||||
}
|
||||
return memory::cgram[addr];
|
||||
}
|
||||
|
||||
void PPU::cgram_write(unsigned addr, uint8 data) {
|
||||
if(!regs.display_disable && vcounter() < (!regs.overscan ? 225 : 240)) {
|
||||
if(hcounter() >= 128 && hcounter() < 1096) addr = 0x0000;
|
||||
}
|
||||
memory::cgram[addr] = data;
|
||||
}
|
||||
|
||||
bool PPU::interlace() const {
|
||||
return display.interlace;
|
||||
}
|
||||
|
||||
bool PPU::overscan() const {
|
||||
return display.overscan;
|
||||
}
|
||||
|
||||
bool PPU::hires() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void PPU::mmio_update_video_mode() {
|
||||
switch(regs.bgmode) {
|
||||
case 0: {
|
||||
|
@ -184,32 +157,32 @@ void PPU::mmio_w2101(uint8 data) {
|
|||
|
||||
//OAMADDL
|
||||
void PPU::mmio_w2102(uint8 data) {
|
||||
regs.oam_baseaddr &= 0x0100;
|
||||
regs.oam_baseaddr |= (data << 0);
|
||||
regs.oam_baseaddr = (regs.oam_baseaddr & 0x0200) | (data << 1);
|
||||
oam.address_reset();
|
||||
}
|
||||
|
||||
//OAMADDH
|
||||
void PPU::mmio_w2103(uint8 data) {
|
||||
regs.oam_priority = data & 0x80;
|
||||
regs.oam_baseaddr &= 0x00ff;
|
||||
regs.oam_baseaddr |= (data & 1) << 8;
|
||||
regs.oam_baseaddr = ((data & 0x01) << 9) | (regs.oam_baseaddr & 0x01fe);
|
||||
oam.address_reset();
|
||||
}
|
||||
|
||||
//OAMDATA
|
||||
void PPU::mmio_w2104(uint8 data) {
|
||||
if(regs.oam_addr & 0x0200) {
|
||||
oam_write(regs.oam_addr, data);
|
||||
} else if((regs.oam_addr & 1) == 0) {
|
||||
regs.oam_latchdata = data;
|
||||
} else {
|
||||
oam_write((regs.oam_addr & ~1) + 0, regs.oam_latchdata);
|
||||
oam_write((regs.oam_addr & ~1) + 1, data);
|
||||
}
|
||||
bool latch = regs.oam_addr & 1;
|
||||
uint10 addr = regs.oam_addr++;
|
||||
if(regs.display_disable == false && vcounter() < (!regs.overscan ? 225 : 240)) addr = regs.oam_iaddr;
|
||||
if(addr & 0x0200) addr &= 0x021f;
|
||||
|
||||
regs.oam_addr = (regs.oam_addr + 1) & 0x03ff;
|
||||
oam.regs.first_sprite = (regs.oam_priority == false ? 0 : (regs.oam_addr >> 2) & 127);
|
||||
if(latch == 0) regs.oam_latchdata = data;
|
||||
if(addr & 0x0200) {
|
||||
oam.update(addr, data);
|
||||
} else if(latch == 1) {
|
||||
oam.update((addr & ~1) + 0, regs.oam_latchdata);
|
||||
oam.update((addr & ~1) + 1, data);
|
||||
}
|
||||
oam.set_first_sprite();
|
||||
}
|
||||
|
||||
//BGMODE
|
||||
|
@ -416,13 +389,19 @@ void PPU::mmio_w2121(uint8 data) {
|
|||
|
||||
//CGDATA
|
||||
void PPU::mmio_w2122(uint8 data) {
|
||||
if((regs.cgram_addr & 1) == 0) {
|
||||
bool latch = regs.cgram_addr & 1;
|
||||
uint9 addr = regs.cgram_addr++;
|
||||
if(regs.display_disable == false
|
||||
&& vcounter() > 0 && vcounter() < (!regs.overscan ? 225 : 240)
|
||||
&& hcounter() >= 88 && hcounter() < 1096
|
||||
) addr = regs.cgram_iaddr;
|
||||
|
||||
if(latch == 0) {
|
||||
regs.cgram_latchdata = data;
|
||||
} else {
|
||||
cgram_write((regs.cgram_addr & ~1) + 0, regs.cgram_latchdata);
|
||||
cgram_write((regs.cgram_addr & ~1) + 1, data & 0x7f);
|
||||
memory::cgram[(addr & ~1) + 0] = regs.cgram_latchdata;
|
||||
memory::cgram[(addr & ~1) + 1] = data & 0x7f;
|
||||
}
|
||||
regs.cgram_addr = (regs.cgram_addr + 1) & 0x01ff;
|
||||
}
|
||||
|
||||
//W12SEL
|
||||
|
@ -597,9 +576,12 @@ uint8 PPU::mmio_r2137() {
|
|||
|
||||
//OAMDATAREAD
|
||||
uint8 PPU::mmio_r2138() {
|
||||
regs.ppu1_mdr = oam_read(regs.oam_addr);
|
||||
regs.oam_addr = (regs.oam_addr + 1) & 0x03ff;
|
||||
oam.regs.first_sprite = (regs.oam_priority == false ? 0 : (regs.oam_addr >> 2) & 127);
|
||||
uint10 addr = regs.oam_addr++;
|
||||
if(regs.display_disable == false && vcounter() < (!regs.overscan ? 225 : 240)) addr = regs.oam_iaddr;
|
||||
if(addr & 0x0200) addr &= 0x021f;
|
||||
|
||||
regs.ppu1_mdr = memory::oam[addr];
|
||||
oam.set_first_sprite();
|
||||
return regs.ppu1_mdr;
|
||||
}
|
||||
|
||||
|
@ -631,20 +613,26 @@ uint8 PPU::mmio_r213a() {
|
|||
|
||||
//CGDATAREAD
|
||||
uint8 PPU::mmio_r213b() {
|
||||
if((regs.cgram_addr & 1) == 0) {
|
||||
regs.ppu2_mdr = cgram_read(regs.cgram_addr) & 0xff;
|
||||
bool latch = regs.cgram_addr & 1;
|
||||
uint9 addr = regs.cgram_addr++;
|
||||
if(regs.display_disable == false
|
||||
&& vcounter() > 0 && vcounter() < (!regs.overscan ? 225 : 240)
|
||||
&& hcounter() >= 88 && hcounter() < 1096
|
||||
) addr = regs.cgram_iaddr;
|
||||
|
||||
if(latch == 0) {
|
||||
regs.ppu2_mdr = memory::cgram[addr];
|
||||
} else {
|
||||
regs.ppu2_mdr &= 0x80;
|
||||
regs.ppu2_mdr |= cgram_read(regs.cgram_addr) & 0x7f;
|
||||
regs.ppu2_mdr |= memory::cgram[addr];
|
||||
}
|
||||
regs.cgram_addr = (regs.cgram_addr + 1) & 0x01ff;
|
||||
return regs.ppu2_mdr;
|
||||
}
|
||||
|
||||
//OPHCT
|
||||
uint8 PPU::mmio_r213c() {
|
||||
if(regs.latch_hcounter == 0) {
|
||||
regs.ppu2_mdr = regs.hcounter & 0xff;
|
||||
regs.ppu2_mdr = (regs.hcounter >> 0);
|
||||
} else {
|
||||
regs.ppu2_mdr &= 0xfe;
|
||||
regs.ppu2_mdr |= (regs.hcounter >> 8) & 1;
|
||||
|
@ -656,7 +644,7 @@ uint8 PPU::mmio_r213c() {
|
|||
//OPVCT
|
||||
uint8 PPU::mmio_r213d() {
|
||||
if(regs.latch_vcounter == 0) {
|
||||
regs.ppu2_mdr = regs.vcounter & 0xff;
|
||||
regs.ppu2_mdr = (regs.vcounter >> 0);
|
||||
} else {
|
||||
regs.ppu2_mdr &= 0xfe;
|
||||
regs.ppu2_mdr |= (regs.vcounter >> 8) & 1;
|
||||
|
@ -705,8 +693,8 @@ void PPU::mmio_reset() {
|
|||
regs.latch_hcounter = 0;
|
||||
regs.latch_vcounter = 0;
|
||||
|
||||
regs.ioamaddr = 0;
|
||||
regs.icgramaddr = 0;
|
||||
regs.oam_iaddr = 0x0000;
|
||||
regs.cgram_iaddr = 0x00;
|
||||
|
||||
//$2100 INIDISP
|
||||
regs.display_disable = true;
|
||||
|
|
|
@ -11,8 +11,8 @@ struct {
|
|||
bool latch_hcounter;
|
||||
bool latch_vcounter;
|
||||
|
||||
uint16 ioamaddr;
|
||||
uint16 icgramaddr;
|
||||
uint10 oam_iaddr;
|
||||
uint9 cgram_iaddr;
|
||||
|
||||
//$2100 INIDISP
|
||||
bool display_disable;
|
||||
|
@ -20,8 +20,8 @@ struct {
|
|||
|
||||
//$2102 OAMADDL
|
||||
//$2103 OAMADDH
|
||||
uint16 oam_baseaddr;
|
||||
uint16 oam_addr;
|
||||
uint10 oam_baseaddr;
|
||||
uint10 oam_addr;
|
||||
bool oam_priority;
|
||||
|
||||
//$2105 BGMODE
|
||||
|
@ -67,7 +67,7 @@ struct {
|
|||
uint16 m7y;
|
||||
|
||||
//$2121 CGADD
|
||||
uint16 cgram_addr;
|
||||
uint9 cgram_addr;
|
||||
|
||||
//$2133 SETINI
|
||||
bool mode7_extbg;
|
||||
|
@ -83,16 +83,9 @@ struct {
|
|||
} regs;
|
||||
|
||||
uint16 get_vram_address();
|
||||
|
||||
uint8 vram_read(unsigned addr);
|
||||
void vram_write(unsigned addr, uint8 data);
|
||||
|
||||
uint8 oam_read(unsigned addr);
|
||||
void oam_write(unsigned addr, uint8 data);
|
||||
|
||||
uint8 cgram_read(unsigned addr);
|
||||
void cgram_write(unsigned addr, uint8 data);
|
||||
|
||||
void mmio_update_video_mode();
|
||||
|
||||
void mmio_w2100(uint8); //INIDISP
|
||||
|
|
|
@ -172,6 +172,7 @@ uint16 PPU::Screen::addsub(unsigned x, unsigned y, bool halve) {
|
|||
|
||||
uint16 PPU::Screen::get_color(unsigned palette) {
|
||||
palette <<= 1;
|
||||
self.regs.cgram_iaddr = palette;
|
||||
return memory::cgram[palette + 0] + (memory::cgram[palette + 1] << 8);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,8 +34,8 @@ void PPU::serialize(serializer &s) {
|
|||
s.integer(regs.latch_hcounter);
|
||||
s.integer(regs.latch_vcounter);
|
||||
|
||||
s.integer(regs.ioamaddr);
|
||||
s.integer(regs.icgramaddr);
|
||||
s.integer(regs.oam_iaddr);
|
||||
s.integer(regs.cgram_iaddr);
|
||||
|
||||
s.integer(regs.display_disable);
|
||||
s.integer(regs.display_brightness);
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifdef PPU_CPP
|
||||
|
||||
void PPU::Sprite::update(unsigned addr, uint8 data) {
|
||||
memory::oam[addr] = data;
|
||||
|
||||
if(addr < 0x0200) {
|
||||
unsigned n = addr >> 2;
|
||||
addr &= 3;
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
#include "list.cpp"
|
||||
|
||||
void PPU::Sprite::address_reset() {
|
||||
self.regs.oam_addr = self.regs.oam_baseaddr << 1;
|
||||
self.regs.oam_addr = self.regs.oam_baseaddr;
|
||||
set_first_sprite();
|
||||
}
|
||||
|
||||
void PPU::Sprite::set_first_sprite() {
|
||||
regs.first_sprite = (self.regs.oam_priority == false ? 0 : (self.regs.oam_addr >> 2) & 127);
|
||||
}
|
||||
|
||||
|
@ -37,7 +41,7 @@ void PPU::Sprite::scanline() {
|
|||
}
|
||||
|
||||
if(t.item_count > 0 && oam_item[t.item_count - 1] != 0xff) {
|
||||
ppu.regs.ioamaddr = 0x0200 + (oam_item[t.item_count - 1] >> 2);
|
||||
ppu.regs.oam_iaddr = 0x0200 + (oam_item[t.item_count - 1] >> 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@ class Sprite {
|
|||
|
||||
//sprite.cpp
|
||||
void address_reset();
|
||||
void set_first_sprite();
|
||||
void frame();
|
||||
void scanline();
|
||||
void run();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
namespace SNES {
|
||||
namespace Info {
|
||||
static const char Name[] = "bsnes";
|
||||
static const char Version[] = "068.22";
|
||||
static const char Version[] = "068.24";
|
||||
static const unsigned SerializerVersion = 13;
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ namespace SNES {
|
|||
|
||||
typedef uint_t<2> uint2;
|
||||
typedef uint_t<3> uint3;
|
||||
typedef uint_t<9> uint9;
|
||||
typedef uint_t<10> uint10;
|
||||
typedef uint_t<17> uint17;
|
||||
typedef uint_t<24> uint24;
|
||||
|
|
|
@ -69,7 +69,7 @@ int Application::main(int &argc, char **argv) {
|
|||
CoInitialize(0);
|
||||
#endif
|
||||
|
||||
initargs(argc, argv); //ensure argv[]s are in UTF-8 format
|
||||
initialize_arguments(argc, argv); //ensure argv[]s are in UTF-8 format
|
||||
initPaths(argv[0]);
|
||||
locateFile(configFilename = "bsnes.cfg", true);
|
||||
locateFile(styleSheetFilename = "style.qss", false);
|
||||
|
|
|
@ -1,17 +1,3 @@
|
|||
char* userpath(char *path) {
|
||||
*path = 0;
|
||||
struct passwd *userinfo = getpwuid(getuid());
|
||||
if(userinfo) strcpy(path, userinfo->pw_dir);
|
||||
return path;
|
||||
}
|
||||
|
||||
char *getcwd(char *path) {
|
||||
return getcwd(path, PATH_MAX);
|
||||
}
|
||||
|
||||
void initargs(int &argc, char **&argv) {
|
||||
}
|
||||
|
||||
void supressScreenSaver() {
|
||||
}
|
||||
|
||||
|
|
|
@ -1,35 +1,5 @@
|
|||
#include <nall/utf8.hpp>
|
||||
|
||||
char* realpath(const char *filename, char *resolvedname) {
|
||||
wchar_t fn[_MAX_PATH] = L"";
|
||||
_wfullpath(fn, nall::utf16_t(filename), _MAX_PATH);
|
||||
strcpy(resolvedname, nall::utf8_t(fn));
|
||||
return resolvedname;
|
||||
}
|
||||
|
||||
char* userpath(char *path) {
|
||||
wchar_t fp[_MAX_PATH] = L"";
|
||||
SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, fp);
|
||||
strcpy(path, nall::utf8_t(fp));
|
||||
return path;
|
||||
}
|
||||
|
||||
char* getcwd(char *path) {
|
||||
wchar_t fp[_MAX_PATH] = L"";
|
||||
_wgetcwd(fp, _MAX_PATH);
|
||||
strcpy(path, nall::utf8_t(fp));
|
||||
return path;
|
||||
}
|
||||
|
||||
void initargs(int &argc, char **&argv) {
|
||||
wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
|
||||
argv = new char*[argc];
|
||||
for(unsigned i = 0; i < argc; i++) {
|
||||
argv[i] = new char[_MAX_PATH];
|
||||
strcpy(argv[i], nall::utf8_t(wargv[i]));
|
||||
}
|
||||
}
|
||||
|
||||
bool Application::App::winEventFilter(MSG *msg, long *result) {
|
||||
//supress screen saver from activating during gameplay
|
||||
if(msg->message == WM_SYSCOMMAND) {
|
||||
|
|
|
@ -14,20 +14,6 @@ struct LibXtst : public library {
|
|||
}
|
||||
} libXtst;
|
||||
|
||||
char* userpath(char *path) {
|
||||
*path = 0;
|
||||
struct passwd *userinfo = getpwuid(getuid());
|
||||
if(userinfo) strcpy(path, userinfo->pw_dir);
|
||||
return path;
|
||||
}
|
||||
|
||||
char *getcwd(char *path) {
|
||||
return getcwd(path, PATH_MAX);
|
||||
}
|
||||
|
||||
void initargs(int &argc, char **&argv) {
|
||||
}
|
||||
|
||||
void supressScreenSaver() {
|
||||
if(!libXtst.XTestFakeKeyEvent) return;
|
||||
|
||||
|
|
Loading…
Reference in New Issue