nes: Improve MMC5 extended attributes

- mmc5: Use ExRAM byte from nametable area to select palette bank
- ppu2c0x: Fix order of nametable/attribute reads
This commit is contained in:
AJR 2019-04-12 08:39:16 -04:00
parent 106990d8c9
commit cb514ba0f1
4 changed files with 253 additions and 243 deletions

View File

@ -33620,7 +33620,7 @@
</part> </part>
</software> </software>
<software name="simcity" supported="partial"> <software name="simcity">
<description>SimCity (USA, Prototype)</description> <description>SimCity (USA, Prototype)</description>
<year>1991</year> <year>1991</year>
<publisher>Nintendo</publisher> <publisher>Nintendo</publisher>

View File

@ -45,7 +45,7 @@ nes_exrom_device::nes_exrom_device(const machine_config &mconfig, const char *ta
: nes_nrom_device(mconfig, NES_EXROM, tag, owner, clock), m_irq_count(0) : nes_nrom_device(mconfig, NES_EXROM, tag, owner, clock), m_irq_count(0)
, m_irq_status(0), m_irq_enable(0), m_mult1(0), m_mult2(0), m_mmc5_scanline(0), m_vrom_page_a(0), m_vrom_page_b(0), m_floodtile(0), m_floodattr(0) , m_irq_status(0), m_irq_enable(0), m_mult1(0), m_mult2(0), m_mmc5_scanline(0), m_vrom_page_a(0), m_vrom_page_b(0), m_floodtile(0), m_floodattr(0)
, m_prg_mode(0), m_chr_mode(0), m_wram_protect_1(0), m_wram_protect_2(0), m_exram_control(0), m_wram_base(0), m_last_chr(0), m_ex1_chr(0) , m_prg_mode(0), m_chr_mode(0), m_wram_protect_1(0), m_wram_protect_2(0), m_exram_control(0), m_wram_base(0), m_last_chr(0), m_ex1_chr(0)
, m_split_chr(0), m_ex1_bank(0), m_high_chr(0), m_split_scr(0), m_split_rev(0), m_split_ctrl(0), m_split_yst(0), m_split_bank(0), m_vcount(0) , m_split_chr(0), m_ex1_bank(0), m_ex1_attrib(0), m_high_chr(0), m_split_scr(0), m_split_rev(0), m_split_ctrl(0), m_split_yst(0), m_split_bank(0), m_vcount(0)
, m_ppu(*this, ":ppu") // FIXME: this dependency should not exist , m_ppu(*this, ":ppu") // FIXME: this dependency should not exist
, m_sound(*this, "mmc5snd") // FIXME: this is a hack, it should be separated device, similar not same as NES APU!!! , m_sound(*this, "mmc5snd") // FIXME: this is a hack, it should be separated device, similar not same as NES APU!!!
{ {
@ -81,6 +81,7 @@ void nes_exrom_device::device_start()
save_item(NAME(m_prg_regs)); save_item(NAME(m_prg_regs));
save_item(NAME(m_prg_ram_mapped)); save_item(NAME(m_prg_ram_mapped));
save_item(NAME(m_ex1_bank)); save_item(NAME(m_ex1_bank));
save_item(NAME(m_ex1_attrib));
save_item(NAME(m_high_chr)); save_item(NAME(m_high_chr));
save_item(NAME(m_split_scr)); save_item(NAME(m_split_scr));
save_item(NAME(m_split_rev)); save_item(NAME(m_split_rev));
@ -124,6 +125,7 @@ void nes_exrom_device::pcb_reset()
m_ex1_chr = 0; m_ex1_chr = 0;
m_split_chr = 0; m_split_chr = 0;
m_ex1_bank = 0; m_ex1_bank = 0;
m_ex1_attrib = 0;
m_vcount = 0; m_vcount = 0;
for (auto & elem : m_vrom_bank) for (auto & elem : m_vrom_bank)
@ -330,11 +332,12 @@ uint8_t nes_exrom_device::nt_r(offs_t offset)
if (m_exram_control == 1) if (m_exram_control == 1)
{ {
if ((offset & 0x3ff) >= 0x3c0) if ((offset & 0x3ff) >= 0x3c0)
return m_mmc5_attrib[(m_exram[offset & 0x3ff] >> 6) & 0x03]; return m_ex1_attrib;
else // in this case, we write Ex1 CHR bank, but then access NT normally! else if (!machine().side_effects_disabled()) // in this case, we write Ex1 CHR bank, but then access NT normally!
{ {
m_ex1_chr = 1; m_ex1_chr = 1;
m_ex1_bank = (m_exram[offset & 0x3ff] & 0x3f) | (m_high_chr << 6); m_ex1_bank = (m_exram[offset & 0x3ff] & 0x3f) | (m_high_chr << 6);
m_ex1_attrib = m_mmc5_attrib[(m_exram[offset & 0x3ff] >> 6) & 0x03];
} }
} }
return m_nt_access[page][offset & 0x3ff]; return m_nt_access[page][offset & 0x3ff];
@ -371,7 +374,7 @@ inline uint8_t nes_exrom_device::base_chr_r(int bank, uint32_t offset)
if (bank < 8) if (bank < 8)
helper = ((m_vrom_bank[bank | 7] & 0xff) * 0x2000) + (offset & 0x1fff); helper = ((m_vrom_bank[bank | 7] & 0xff) * 0x2000) + (offset & 0x1fff);
else else
helper = ((m_vrom_bank[bank | 3] & 0xff) * 0x2000) + (offset & 0xfff); helper = ((m_vrom_bank[bank | 3] & 0xff) * 0x2000) + (offset & 0x1fff);
break; break;
case 1: case 1:
helper = ((m_vrom_bank[bank | 3] & 0xff) * 0x1000) + (offset & 0xfff); helper = ((m_vrom_bank[bank | 3] & 0xff) * 0x1000) + (offset & 0xfff);
@ -446,16 +449,21 @@ uint8_t nes_exrom_device::read_l(offs_t offset)
{ {
case 0x1204: case 0x1204:
value = m_irq_status; value = m_irq_status;
if (!machine().side_effects_disabled())
{
m_irq_status &= ~0x80; m_irq_status &= ~0x80;
set_irq_line(CLEAR_LINE); set_irq_line(CLEAR_LINE);
}
return value; return value;
case 0x1205: case 0x1205:
return (m_mult1 * m_mult2) & 0xff; return (m_mult1 * m_mult2) & 0xff;
case 0x1206: case 0x1206:
return ((m_mult1 * m_mult2) & 0xff00) >> 8; return ((m_mult1 * m_mult2) & 0xff00) >> 8;
default: default:
if (!machine().side_effects_disabled())
logerror("MMC5 uncaught read, offset: %04x\n", offset + 0x4100); logerror("MMC5 uncaught read, offset: %04x\n", offset + 0x4100);
return get_open_bus(); return get_open_bus();
} }
@ -508,6 +516,7 @@ void nes_exrom_device::write_l(offs_t offset, uint8_t data)
m_wram_protect_1 = data & 0x03; m_wram_protect_1 = data & 0x03;
LOG_MMC(("MMC5 vram protect 1: %02x\n", data)); LOG_MMC(("MMC5 vram protect 1: %02x\n", data));
break; break;
case 0x1103: case 0x1103:
m_wram_protect_2 = data & 0x03; m_wram_protect_2 = data & 0x03;
LOG_MMC(("MMC5 vram protect 2: %02x\n", data)); LOG_MMC(("MMC5 vram protect 2: %02x\n", data));
@ -538,7 +547,6 @@ void nes_exrom_device::write_l(offs_t offset, uint8_t data)
m_wram_base = data & 0x07; m_wram_base = data & 0x07;
break; break;
case 0x1114: case 0x1114:
case 0x1115: case 0x1115:
case 0x1116: case 0x1116:
@ -578,7 +586,6 @@ void nes_exrom_device::write_l(offs_t offset, uint8_t data)
m_split_chr = 0; m_split_chr = 0;
break; break;
case 0x1200: case 0x1200:
// in EX2 and EX3 modes, no split screen // in EX2 and EX3 modes, no split screen
m_split_scr = BIT(data, 7); m_split_scr = BIT(data, 7);
@ -599,13 +606,16 @@ void nes_exrom_device::write_l(offs_t offset, uint8_t data)
m_irq_count = data; m_irq_count = data;
LOG_MMC(("MMC5 irq scanline: %d\n", m_irq_count)); LOG_MMC(("MMC5 irq scanline: %d\n", m_irq_count));
break; break;
case 0x1204: case 0x1204:
m_irq_enable = data & 0x80; m_irq_enable = data & 0x80;
LOG_MMC(("MMC5 irq enable: %02x\n", data)); LOG_MMC(("MMC5 irq enable: %02x\n", data));
break; break;
case 0x1205: case 0x1205:
m_mult1 = data; m_mult1 = data;
break; break;
case 0x1206: case 0x1206:
m_mult2 = data; m_mult2 = data;
break; break;

View File

@ -75,6 +75,7 @@ protected:
uint8_t m_prg_ram_mapped[4]; uint8_t m_prg_ram_mapped[4];
uint8_t m_ex1_bank; uint8_t m_ex1_bank;
uint8_t m_ex1_attrib;
uint8_t m_high_chr; // $5130 uint8_t m_high_chr; // $5130

View File

@ -676,6 +676,9 @@ void ppu2c0x_device::draw_background(uint8_t *line_priority)
index1 = tile_index + x; index1 = tile_index + x;
// page2 is the output of the nametable read (this section is the FIRST read per tile!)
page2 = readbyte(index1);
// this is attribute table stuff! (actually read 2 in PPUspeak)! // this is attribute table stuff! (actually read 2 in PPUspeak)!
/* Figure out which byte in the color table to use */ /* Figure out which byte in the color table to use */
pos = ((index1 & 0x380) >> 4) | ((index1 & 0x1f) >> 2); pos = ((index1 & 0x380) >> 4) | ((index1 & 0x1f) >> 2);
@ -686,10 +689,6 @@ void ppu2c0x_device::draw_background(uint8_t *line_priority)
/* figure out which bits in the color table to use */ /* figure out which bits in the color table to use */
color_bits = ((index1 & 0x40) >> 4) + (index1 & 0x02); color_bits = ((index1 & 0x40) >> 4) + (index1 & 0x02);
// page2 is the output of the nametable read (this section is the FIRST read per tile!)
address = index1 & 0x3ff;
page2 = readbyte(index1);
// 27/12/2002 // 27/12/2002
if (!m_latch.isnull()) if (!m_latch.isnull())
m_latch((m_tile_page << 10) | (page2 << 4)); m_latch((m_tile_page << 10) | (page2 << 4));