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:
Tim Allen 2010-09-24 23:15:21 +10:00
parent 8a91c95002
commit d0d8c2a921
15 changed files with 83 additions and 152 deletions

View File

@ -1,7 +1,7 @@
include nall/Makefile
snes := snes
profile := performance
ui := ui-phoenix
profile := accuracy
ui := ui-qt
# compiler
c := $(compiler) -std=gnu99

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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;

View File

@ -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);
}
}

View File

@ -64,6 +64,7 @@ class Sprite {
//sprite.cpp
void address_reset();
void set_first_sprite();
void frame();
void scanline();
void run();

View File

@ -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;

View File

@ -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);

View File

@ -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() {
}

View File

@ -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) {

View File

@ -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;