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
bsnes
|
@ -27,6 +27,10 @@ enum class Revision : unsigned {
|
||||||
|
|
||||||
MMC1 mmc1;
|
MMC1 mmc1;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
return mmc1.main();
|
||||||
|
}
|
||||||
|
|
||||||
unsigned ram_addr(unsigned addr) {
|
unsigned ram_addr(unsigned addr) {
|
||||||
unsigned bank = 0;
|
unsigned bank = 0;
|
||||||
if(revision == Revision::SOROM) bank = (mmc1.chr_bank[0] & 0x08) >> 3;
|
if(revision == Revision::SOROM) bank = (mmc1.chr_bank[0] & 0x08) >> 3;
|
||||||
|
|
|
@ -9,6 +9,7 @@ enum class Revision : unsigned {
|
||||||
MMC1C,
|
MMC1C,
|
||||||
} revision;
|
} revision;
|
||||||
|
|
||||||
|
unsigned writedelay;
|
||||||
unsigned shiftaddr;
|
unsigned shiftaddr;
|
||||||
unsigned shiftdata;
|
unsigned shiftdata;
|
||||||
|
|
||||||
|
@ -20,6 +21,17 @@ uint5 chr_bank[2];
|
||||||
bool ram_disable;
|
bool ram_disable;
|
||||||
uint4 prg_bank;
|
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) {
|
unsigned prg_addr(unsigned addr) {
|
||||||
bool region = addr & 0x4000;
|
bool region = addr & 0x4000;
|
||||||
unsigned bank = (prg_bank & ~1) + region;
|
unsigned bank = (prg_bank & ~1) + region;
|
||||||
|
@ -49,6 +61,9 @@ unsigned ciram_addr(unsigned addr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void mmio_write(unsigned addr, uint8 data) {
|
void mmio_write(unsigned addr, uint8 data) {
|
||||||
|
if(writedelay) return;
|
||||||
|
writedelay = 2;
|
||||||
|
|
||||||
if(data & 0x80) {
|
if(data & 0x80) {
|
||||||
shiftaddr = 0;
|
shiftaddr = 0;
|
||||||
prg_size = 1;
|
prg_size = 1;
|
||||||
|
@ -87,6 +102,7 @@ void power() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
|
writedelay = 0;
|
||||||
shiftaddr = 0;
|
shiftaddr = 0;
|
||||||
shiftdata = 0;
|
shiftdata = 0;
|
||||||
|
|
||||||
|
@ -101,6 +117,7 @@ void reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void serialize(serializer &s) {
|
void serialize(serializer &s) {
|
||||||
|
s.integer(writedelay);
|
||||||
s.integer(shiftaddr);
|
s.integer(shiftaddr);
|
||||||
s.integer(shiftdata);
|
s.integer(shiftdata);
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,9 @@ uint16 chr_access[4];
|
||||||
bool chr_active;
|
bool chr_active;
|
||||||
bool sprite_8x16;
|
bool sprite_8x16;
|
||||||
|
|
||||||
|
uint8 exbank;
|
||||||
|
uint8 exattr;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
while(true) {
|
while(true) {
|
||||||
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
||||||
|
@ -92,14 +95,17 @@ uint8 prg_access(bool write, unsigned addr, uint8 data = 0x00) {
|
||||||
addr &= 0x1fff;
|
addr &= 0x1fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool rom = bank & 0x80;
|
||||||
|
bank &= 0x7f;
|
||||||
|
|
||||||
if(write == false) {
|
if(write == false) {
|
||||||
if(bank & 0x80) {
|
if(rom) {
|
||||||
return board.prgrom.read((bank << 13) | addr);
|
return board.prgrom.read((bank << 13) | addr);
|
||||||
} else {
|
} else {
|
||||||
board.prgram.read((bank << 13) | addr);
|
return board.prgram.read((bank << 13) | addr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(bank & 0x80) {
|
if(rom) {
|
||||||
board.prgrom.write((bank << 13) | addr, data);
|
board.prgrom.write((bank << 13) | addr, data);
|
||||||
} else {
|
} else {
|
||||||
if(prgram_write_protect[0] == 2 && prgram_write_protect[1] == 1) {
|
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) {
|
uint8 prg_read(unsigned addr) {
|
||||||
if((addr & 0xfc00) == 0x5c00) {
|
if((addr & 0xfc00) == 0x5c00) {
|
||||||
if(exram_mode & 2) return exram[addr & 0x03ff];
|
if(exram_mode >= 2) return exram[addr & 0x03ff];
|
||||||
return cpu.mdr();
|
return cpu.mdr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,6 +139,8 @@ uint8 prg_read(unsigned addr) {
|
||||||
|
|
||||||
void prg_write(unsigned addr, uint8 data) {
|
void prg_write(unsigned addr, uint8 data) {
|
||||||
if((addr & 0xfc00) == 0x5c00) {
|
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;
|
if(exram_mode == 2) exram[addr & 0x03ff] = data;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -320,6 +328,15 @@ void scanline() {
|
||||||
cpu_cycle_counter = 0;
|
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) {
|
uint8 chr_read(unsigned addr) {
|
||||||
chr_access[0] = chr_access[1];
|
chr_access[0] = chr_access[1];
|
||||||
chr_access[1] = chr_access[2];
|
chr_access[1] = chr_access[2];
|
||||||
|
@ -332,35 +349,49 @@ uint8 chr_read(unsigned addr) {
|
||||||
&& (chr_access[2] & 0x2000)
|
&& (chr_access[2] & 0x2000)
|
||||||
&& (chr_access[3] & 0x2000)) scanline();
|
&& (chr_access[3] & 0x2000)) scanline();
|
||||||
|
|
||||||
unsigned lx = hcounter;
|
if(in_frame == false) {
|
||||||
hcounter += 2;
|
if(addr & 0x2000) return ciram_read(addr);
|
||||||
|
return 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
if(addr & 0x2000) {
|
unsigned mode = nametable_mode[(addr >> 10) & 3];
|
||||||
switch(nametable_mode[(addr >> 10) & 3]) {
|
uint8 result = 0x00;
|
||||||
case 0: return ppu.ciram_read(0x0000 | (addr & 0x03ff));
|
|
||||||
case 1: return ppu.ciram_read(0x0400 | (addr & 0x03ff));
|
if((hcounter & 7) == 0) {
|
||||||
case 2: return (exram_mode < 2) ? exram[addr & 0x03ff] : 0x00;
|
result = ciram_read(addr);
|
||||||
case 3: return fillmode_tile;
|
|
||||||
|
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) {
|
hcounter += 2;
|
||||||
return board.chrrom.read(chr_active ? chr_bg_addr(addr) : chr_sprite_addr(addr));
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void chr_write(unsigned addr, uint8 data) {
|
void chr_write(unsigned addr, uint8 data) {
|
||||||
if(addr & 0x2000) {
|
if(addr & 0x2000) {
|
||||||
switch(nametable_mode[(addr >> 10) & 3]) {
|
unsigned mode = nametable_mode[(addr >> 10) & 3];
|
||||||
case 0: return ppu.ciram_write(0x0000 | (addr & 0x03ff), data);
|
if(mode == 0) ppu.ciram_write(0x0000 | (addr & 0x03ff), data);
|
||||||
case 1: return ppu.ciram_write(0x0400 | (addr & 0x03ff), data);
|
if(mode == 1) ppu.ciram_write(0x0400 | (addr & 0x03ff), data);
|
||||||
case 2: if(exram_mode < 2) exram[addr & 0x03ff] = data; return;
|
|
||||||
case 3: fillmode_tile = data; return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,6 +437,9 @@ void reset() {
|
||||||
for(auto &n : chr_access) n = 0;
|
for(auto &n : chr_access) n = 0;
|
||||||
chr_active = 0;
|
chr_active = 0;
|
||||||
sprite_8x16 = 0;
|
sprite_8x16 = 0;
|
||||||
|
|
||||||
|
exbank = 0;
|
||||||
|
exattr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void serialize(serializer &s) {
|
void serialize(serializer &s) {
|
||||||
|
@ -444,6 +478,9 @@ void serialize(serializer &s) {
|
||||||
for(auto &n : chr_access) s.integer(n);
|
for(auto &n : chr_access) s.integer(n);
|
||||||
s.integer(chr_active);
|
s.integer(chr_active);
|
||||||
s.integer(sprite_8x16);
|
s.integer(sprite_8x16);
|
||||||
|
|
||||||
|
s.integer(exbank);
|
||||||
|
s.integer(exattr);
|
||||||
}
|
}
|
||||||
|
|
||||||
MMC5(Board &board) : Chip(board) {
|
MMC5(Board &board) : Chip(board) {
|
||||||
|
|
|
@ -12,6 +12,7 @@ void CPU::Main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPU::main() {
|
void CPU::main() {
|
||||||
|
//trace = true;
|
||||||
//FILE *fp = fopen("/home/byuu/Desktop/log.txt", "wb");
|
//FILE *fp = fopen("/home/byuu/Desktop/log.txt", "wb");
|
||||||
|
|
||||||
unsigned lpc = 0xffff;
|
unsigned lpc = 0xffff;
|
||||||
|
@ -111,14 +112,10 @@ void CPU::ram_write(uint16 addr, uint8 data) {
|
||||||
uint8 CPU::read(uint16 addr) {
|
uint8 CPU::read(uint16 addr) {
|
||||||
if(addr == 0x4016) {
|
if(addr == 0x4016) {
|
||||||
return (mdr() & 0xc0) | input.data(0);
|
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) {
|
if(addr == 0x4017) {
|
||||||
return (mdr() & 0xc0) | input.data(1);
|
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);
|
return apu.read(addr);
|
||||||
|
@ -132,11 +129,6 @@ void CPU::write(uint16 addr, uint8 data) {
|
||||||
|
|
||||||
if(addr == 0x4016) {
|
if(addr == 0x4016) {
|
||||||
input.latch(data & 0x01);
|
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);
|
return apu.write(addr, data);
|
||||||
|
|
|
@ -49,7 +49,7 @@ Application::Application(int argc, char **argv) {
|
||||||
inputManager = new InputManager;
|
inputManager = new InputManager;
|
||||||
utility = new Utility;
|
utility = new Utility;
|
||||||
|
|
||||||
title = "bsnes v082.31";
|
title = "bsnes v082.32";
|
||||||
|
|
||||||
string fontFamily = Intrinsics::platform() == Intrinsics::Platform::Windows ? "Tahoma, " : "Sans, ";
|
string fontFamily = Intrinsics::platform() == Intrinsics::Platform::Windows ? "Tahoma, " : "Sans, ";
|
||||||
normalFont = { fontFamily, "8" };
|
normalFont = { fontFamily, "8" };
|
||||||
|
|
Loading…
Reference in New Issue