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:
Tim Allen 2011-10-08 18:34:16 +11:00
parent 4c47cc203f
commit b8d607d16b
5 changed files with 85 additions and 35 deletions

View File

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

View File

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

View File

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

View File

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

View File

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