mirror of https://github.com/bsnes-emu/bsnes.git
Update to v082r32 release.
byuu says: Added delay to MMC1 register writes, to fix Bill & Ted's Godawful Adventure. Fixed up MMC5 RAM+fill mode, and added EXRAM mode support (8x8 tiles/attributes.) Just Breed is fully playable now. MMC5 is a total pain in the ass, the documentation on it is just terrible. I basically just tried seven hundred variations until something worked. I still need to add MMC5 vertical split screen (for one single game's attract screen, ugh), and the extra sound channels. Would like to rework the NES APU first. Since the pulse channels are identical sans sweep, it'd be nice to just inherit those and mask out the sweep register bit writes. So that probably won't make it into the first release, at least. Still, overall I think it'll be an impressive showing of complex mappers for a first release: MMC3, MMC5, VRC6 and 5B. The latter two with full audio. The only other really, really hard bit is the VRC7 audio, supposedly.
This commit is contained in:
parent
4c47cc203f
commit
b8d607d16b
|
@ -27,6 +27,10 @@ enum class Revision : unsigned {
|
|||
|
||||
MMC1 mmc1;
|
||||
|
||||
void main() {
|
||||
return mmc1.main();
|
||||
}
|
||||
|
||||
unsigned ram_addr(unsigned addr) {
|
||||
unsigned bank = 0;
|
||||
if(revision == Revision::SOROM) bank = (mmc1.chr_bank[0] & 0x08) >> 3;
|
||||
|
|
|
@ -9,6 +9,7 @@ enum class Revision : unsigned {
|
|||
MMC1C,
|
||||
} revision;
|
||||
|
||||
unsigned writedelay;
|
||||
unsigned shiftaddr;
|
||||
unsigned shiftdata;
|
||||
|
||||
|
@ -20,6 +21,17 @@ uint5 chr_bank[2];
|
|||
bool ram_disable;
|
||||
uint4 prg_bank;
|
||||
|
||||
void main() {
|
||||
while(true) {
|
||||
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
||||
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||||
}
|
||||
|
||||
if(writedelay) writedelay--;
|
||||
tick();
|
||||
}
|
||||
}
|
||||
|
||||
unsigned prg_addr(unsigned addr) {
|
||||
bool region = addr & 0x4000;
|
||||
unsigned bank = (prg_bank & ~1) + region;
|
||||
|
@ -49,6 +61,9 @@ unsigned ciram_addr(unsigned addr) {
|
|||
}
|
||||
|
||||
void mmio_write(unsigned addr, uint8 data) {
|
||||
if(writedelay) return;
|
||||
writedelay = 2;
|
||||
|
||||
if(data & 0x80) {
|
||||
shiftaddr = 0;
|
||||
prg_size = 1;
|
||||
|
@ -87,6 +102,7 @@ void power() {
|
|||
}
|
||||
|
||||
void reset() {
|
||||
writedelay = 0;
|
||||
shiftaddr = 0;
|
||||
shiftdata = 0;
|
||||
|
||||
|
@ -101,6 +117,7 @@ void reset() {
|
|||
}
|
||||
|
||||
void serialize(serializer &s) {
|
||||
s.integer(writedelay);
|
||||
s.integer(shiftaddr);
|
||||
s.integer(shiftdata);
|
||||
|
||||
|
|
|
@ -51,6 +51,9 @@ uint16 chr_access[4];
|
|||
bool chr_active;
|
||||
bool sprite_8x16;
|
||||
|
||||
uint8 exbank;
|
||||
uint8 exattr;
|
||||
|
||||
void main() {
|
||||
while(true) {
|
||||
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
||||
|
@ -92,14 +95,17 @@ uint8 prg_access(bool write, unsigned addr, uint8 data = 0x00) {
|
|||
addr &= 0x1fff;
|
||||
}
|
||||
|
||||
bool rom = bank & 0x80;
|
||||
bank &= 0x7f;
|
||||
|
||||
if(write == false) {
|
||||
if(bank & 0x80) {
|
||||
if(rom) {
|
||||
return board.prgrom.read((bank << 13) | addr);
|
||||
} else {
|
||||
board.prgram.read((bank << 13) | addr);
|
||||
return board.prgram.read((bank << 13) | addr);
|
||||
}
|
||||
} else {
|
||||
if(bank & 0x80) {
|
||||
if(rom) {
|
||||
board.prgrom.write((bank << 13) | addr, data);
|
||||
} else {
|
||||
if(prgram_write_protect[0] == 2 && prgram_write_protect[1] == 1) {
|
||||
|
@ -112,7 +118,7 @@ uint8 prg_access(bool write, unsigned addr, uint8 data = 0x00) {
|
|||
|
||||
uint8 prg_read(unsigned addr) {
|
||||
if((addr & 0xfc00) == 0x5c00) {
|
||||
if(exram_mode & 2) return exram[addr & 0x03ff];
|
||||
if(exram_mode >= 2) return exram[addr & 0x03ff];
|
||||
return cpu.mdr();
|
||||
}
|
||||
|
||||
|
@ -133,6 +139,8 @@ uint8 prg_read(unsigned addr) {
|
|||
|
||||
void prg_write(unsigned addr, uint8 data) {
|
||||
if((addr & 0xfc00) == 0x5c00) {
|
||||
//writes 0x00 *during* Vblank (not during screen rendering ...)
|
||||
if(exram_mode == 0 || exram_mode == 1) exram[addr & 0x03ff] = in_frame ? data : 0x00;
|
||||
if(exram_mode == 2) exram[addr & 0x03ff] = data;
|
||||
return;
|
||||
}
|
||||
|
@ -320,6 +328,15 @@ void scanline() {
|
|||
cpu_cycle_counter = 0;
|
||||
}
|
||||
|
||||
uint8 ciram_read(unsigned addr) {
|
||||
switch(nametable_mode[(addr >> 10) & 3]) {
|
||||
case 0: return ppu.ciram_read(0x0000 | (addr & 0x03ff));
|
||||
case 1: return ppu.ciram_read(0x0400 | (addr & 0x03ff));
|
||||
case 2: return exram_mode < 2 ? exram[addr & 0x03ff] : 0x00;
|
||||
case 3: return (hcounter & 2) == 0 ? fillmode_tile : (uint8)fillmode_color;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 chr_read(unsigned addr) {
|
||||
chr_access[0] = chr_access[1];
|
||||
chr_access[1] = chr_access[2];
|
||||
|
@ -332,35 +349,49 @@ uint8 chr_read(unsigned addr) {
|
|||
&& (chr_access[2] & 0x2000)
|
||||
&& (chr_access[3] & 0x2000)) scanline();
|
||||
|
||||
unsigned lx = hcounter;
|
||||
hcounter += 2;
|
||||
if(in_frame == false) {
|
||||
if(addr & 0x2000) return ciram_read(addr);
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
if(addr & 0x2000) {
|
||||
switch(nametable_mode[(addr >> 10) & 3]) {
|
||||
case 0: return ppu.ciram_read(0x0000 | (addr & 0x03ff));
|
||||
case 1: return ppu.ciram_read(0x0400 | (addr & 0x03ff));
|
||||
case 2: return (exram_mode < 2) ? exram[addr & 0x03ff] : 0x00;
|
||||
case 3: return fillmode_tile;
|
||||
unsigned mode = nametable_mode[(addr >> 10) & 3];
|
||||
uint8 result = 0x00;
|
||||
|
||||
if((hcounter & 7) == 0) {
|
||||
result = ciram_read(addr);
|
||||
|
||||
exbank = (chr_bank_hi << 6) | (exram[addr & 0x03ff] & 0x3f);
|
||||
exattr = exram[addr & 0x03ff] >> 6;
|
||||
exattr |= exattr << 2;
|
||||
exattr |= exattr << 4;
|
||||
} else if((hcounter & 7) == 2) {
|
||||
result = ciram_read(addr);
|
||||
|
||||
if((hcounter < 256 || hcounter >= 320) && exram_mode == 1) {
|
||||
result = exattr;
|
||||
}
|
||||
} else {
|
||||
if(sprite_8x16 == false) {
|
||||
result = board.chrrom.read(chr_active ? chr_bg_addr(addr) : chr_sprite_addr(addr));
|
||||
}
|
||||
else if(hcounter < 256) result = board.chrrom.read(chr_bg_addr(addr));
|
||||
else if(hcounter < 320) result = board.chrrom.read(chr_sprite_addr(addr));
|
||||
else /* hcounter < 340*/result = board.chrrom.read(chr_bg_addr(addr));
|
||||
|
||||
if((hcounter < 256 || hcounter >= 320) && exram_mode == 1) {
|
||||
result = board.chrrom.read(exbank * 0x1000 + addr);
|
||||
}
|
||||
}
|
||||
|
||||
if(sprite_8x16 == false) {
|
||||
return board.chrrom.read(chr_active ? chr_bg_addr(addr) : chr_sprite_addr(addr));
|
||||
}
|
||||
|
||||
if(lx < 256) return board.chrrom.read(chr_bg_addr(addr));
|
||||
if(lx < 320) return board.chrrom.read(chr_sprite_addr(addr));
|
||||
/* lx < 340*/return board.chrrom.read(chr_bg_addr(addr));
|
||||
hcounter += 2;
|
||||
return result;
|
||||
}
|
||||
|
||||
void chr_write(unsigned addr, uint8 data) {
|
||||
if(addr & 0x2000) {
|
||||
switch(nametable_mode[(addr >> 10) & 3]) {
|
||||
case 0: return ppu.ciram_write(0x0000 | (addr & 0x03ff), data);
|
||||
case 1: return ppu.ciram_write(0x0400 | (addr & 0x03ff), data);
|
||||
case 2: if(exram_mode < 2) exram[addr & 0x03ff] = data; return;
|
||||
case 3: fillmode_tile = data; return;
|
||||
}
|
||||
unsigned mode = nametable_mode[(addr >> 10) & 3];
|
||||
if(mode == 0) ppu.ciram_write(0x0000 | (addr & 0x03ff), data);
|
||||
if(mode == 1) ppu.ciram_write(0x0400 | (addr & 0x03ff), data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -406,6 +437,9 @@ void reset() {
|
|||
for(auto &n : chr_access) n = 0;
|
||||
chr_active = 0;
|
||||
sprite_8x16 = 0;
|
||||
|
||||
exbank = 0;
|
||||
exattr = 0;
|
||||
}
|
||||
|
||||
void serialize(serializer &s) {
|
||||
|
@ -444,6 +478,9 @@ void serialize(serializer &s) {
|
|||
for(auto &n : chr_access) s.integer(n);
|
||||
s.integer(chr_active);
|
||||
s.integer(sprite_8x16);
|
||||
|
||||
s.integer(exbank);
|
||||
s.integer(exattr);
|
||||
}
|
||||
|
||||
MMC5(Board &board) : Chip(board) {
|
||||
|
|
|
@ -12,6 +12,7 @@ void CPU::Main() {
|
|||
}
|
||||
|
||||
void CPU::main() {
|
||||
//trace = true;
|
||||
//FILE *fp = fopen("/home/byuu/Desktop/log.txt", "wb");
|
||||
|
||||
unsigned lpc = 0xffff;
|
||||
|
@ -111,14 +112,10 @@ void CPU::ram_write(uint16 addr, uint8 data) {
|
|||
uint8 CPU::read(uint16 addr) {
|
||||
if(addr == 0x4016) {
|
||||
return (mdr() & 0xc0) | input.data(0);
|
||||
// if(status.controller_port0 >= 8) return (mdr() & 0xc0) | 1;
|
||||
// return interface->inputPoll(0, 0u, status.controller_port0++);
|
||||
}
|
||||
|
||||
if(addr == 0x4017) {
|
||||
return (mdr() & 0xc0) | input.data(1);
|
||||
// if(status.controller_port1 >= 8) return (mdr() & 0xc0) | 1;
|
||||
// return interface->inputPoll(1, 0u, status.controller_port1++);
|
||||
}
|
||||
|
||||
return apu.read(addr);
|
||||
|
@ -132,11 +129,6 @@ void CPU::write(uint16 addr, uint8 data) {
|
|||
|
||||
if(addr == 0x4016) {
|
||||
input.latch(data & 0x01);
|
||||
// status.controller_latch = data & 0x01;
|
||||
// if(status.controller_latch) {
|
||||
// status.controller_port0 = 0;
|
||||
// status.controller_port1 = 0;
|
||||
// }
|
||||
}
|
||||
|
||||
return apu.write(addr, data);
|
||||
|
|
|
@ -49,7 +49,7 @@ Application::Application(int argc, char **argv) {
|
|||
inputManager = new InputManager;
|
||||
utility = new Utility;
|
||||
|
||||
title = "bsnes v082.31";
|
||||
title = "bsnes v082.32";
|
||||
|
||||
string fontFamily = Intrinsics::platform() == Intrinsics::Platform::Windows ? "Tahoma, " : "Sans, ";
|
||||
normalFont = { fontFamily, "8" };
|
||||
|
|
Loading…
Reference in New Issue