diff --git a/hash/nes.xml b/hash/nes.xml index 0b5137f1157..b72f86955a3 100644 --- a/hash/nes.xml +++ b/hash/nes.xml @@ -33620,7 +33620,7 @@ - + SimCity (USA, Prototype) 1991 Nintendo diff --git a/src/devices/bus/nes/mmc5.cpp b/src/devices/bus/nes/mmc5.cpp index 0cceec064d2..171af3c86e9 100644 --- a/src/devices/bus/nes/mmc5.cpp +++ b/src/devices/bus/nes/mmc5.cpp @@ -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) , 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_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_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_ram_mapped)); save_item(NAME(m_ex1_bank)); + save_item(NAME(m_ex1_attrib)); save_item(NAME(m_high_chr)); save_item(NAME(m_split_scr)); save_item(NAME(m_split_rev)); @@ -124,6 +125,7 @@ void nes_exrom_device::pcb_reset() m_ex1_chr = 0; m_split_chr = 0; m_ex1_bank = 0; + m_ex1_attrib = 0; m_vcount = 0; for (auto & elem : m_vrom_bank) @@ -167,70 +169,70 @@ void nes_exrom_device::update_prg() switch (m_prg_mode) { - case 0: // 32k banks - bank3 = m_prg_regs[3] >> 2; - prg32(bank3); - break; + case 0: // 32k banks + bank3 = m_prg_regs[3] >> 2; + prg32(bank3); + break; - case 1: // 16k banks - bank1 = m_prg_regs[1] >> 1; - bank3 = m_prg_regs[3] >> 1; + case 1: // 16k banks + bank1 = m_prg_regs[1] >> 1; + bank3 = m_prg_regs[3] >> 1; - if (m_prg_ram_mapped[1]) - { - m_ram_hi_banks[0] = ((bank1 << 1) & 0x07); - m_ram_hi_banks[1] = ((bank1 << 1) & 0x07) | 1; - } - else - prg16_89ab(bank1); + if (m_prg_ram_mapped[1]) + { + m_ram_hi_banks[0] = ((bank1 << 1) & 0x07); + m_ram_hi_banks[1] = ((bank1 << 1) & 0x07) | 1; + } + else + prg16_89ab(bank1); - prg16_cdef(bank3); - break; + prg16_cdef(bank3); + break; - case 2: // 16k-8k banks - bank1 = m_prg_regs[1] >> 1; - bank2 = m_prg_regs[2]; - bank3 = m_prg_regs[3]; + case 2: // 16k-8k banks + bank1 = m_prg_regs[1] >> 1; + bank2 = m_prg_regs[2]; + bank3 = m_prg_regs[3]; - if (m_prg_ram_mapped[1]) - { - m_ram_hi_banks[0] = ((bank1 << 1) & 0x07); - m_ram_hi_banks[1] = ((bank1 << 1) & 0x07) | 1; - } - else - prg16_89ab(bank1); + if (m_prg_ram_mapped[1]) + { + m_ram_hi_banks[0] = ((bank1 << 1) & 0x07); + m_ram_hi_banks[1] = ((bank1 << 1) & 0x07) | 1; + } + else + prg16_89ab(bank1); - if (m_prg_ram_mapped[2]) - m_ram_hi_banks[2] = (bank2 & 0x07); - else - prg8_cd(bank2); + if (m_prg_ram_mapped[2]) + m_ram_hi_banks[2] = (bank2 & 0x07); + else + prg8_cd(bank2); - prg8_ef(bank3); - break; + prg8_ef(bank3); + break; - case 3: // 8k banks - bank0 = m_prg_regs[0]; - bank1 = m_prg_regs[1]; - bank2 = m_prg_regs[2]; - bank3 = m_prg_regs[3]; + case 3: // 8k banks + bank0 = m_prg_regs[0]; + bank1 = m_prg_regs[1]; + bank2 = m_prg_regs[2]; + bank3 = m_prg_regs[3]; - if (m_prg_ram_mapped[0]) - m_ram_hi_banks[0] = (bank0 & 0x07); - else - prg8_89(bank0); + if (m_prg_ram_mapped[0]) + m_ram_hi_banks[0] = (bank0 & 0x07); + else + prg8_89(bank0); - if (m_prg_ram_mapped[1]) - m_ram_hi_banks[1] = (bank1 & 0x07); - else - prg8_ab(bank1); + if (m_prg_ram_mapped[1]) + m_ram_hi_banks[1] = (bank1 & 0x07); + else + prg8_ab(bank1); - if (m_prg_ram_mapped[2]) - m_ram_hi_banks[2] = (bank2 & 0x07); - else - prg8_cd(bank2); + if (m_prg_ram_mapped[2]) + m_ram_hi_banks[2] = (bank2 & 0x07); + else + prg8_cd(bank2); - prg8_ef(bank3); - break; + prg8_ef(bank3); + break; } } @@ -258,20 +260,20 @@ void nes_exrom_device::set_mirror(int page, int src) { switch (src) { - case 0: - set_nt_page(page, CIRAM, 0, 1); - break; - case 1: - set_nt_page(page, CIRAM, 1, 1); - break; - case 2: - set_nt_page(page, EXRAM, 0, 1); - break; - case 3: - set_nt_page(page, MMC5FILL, 0, 0); - break; - default: - fatalerror("This should never happen\n"); + case 0: + set_nt_page(page, CIRAM, 0, 1); + break; + case 1: + set_nt_page(page, CIRAM, 1, 1); + break; + case 2: + set_nt_page(page, EXRAM, 0, 1); + break; + case 3: + set_nt_page(page, MMC5FILL, 0, 0); + break; + default: + fatalerror("This should never happen\n"); } } @@ -295,49 +297,50 @@ uint8_t nes_exrom_device::nt_r(offs_t offset) switch (m_nt_src[page]) { - case MMC5FILL: + case MMC5FILL: + if ((offset & 0x3ff) >= 0x3c0) + return m_floodattr; + return m_floodtile; + + case EXRAM: + // to investigate: can split screen affect this too? + if (!BIT(m_exram_control, 1)) + return m_exram[offset & 0x3ff]; + else + return 0x00; + + case CIRAM: + default: + // Uchuu Keibitai SDF uses extensively split screen for its intro, + // but it does not work yet + if (m_split_scr && !(m_exram_control & 0x02) && in_split()) + { + int tile = m_ppu->get_tilenum(); + if ((offset & 0x3ff) >= 0x3c0) - return m_floodattr; - return m_floodtile; - - case EXRAM: - // to investigate: can split screen affect this too? - if (!BIT(m_exram_control, 1)) - return m_exram[offset & 0x3ff]; + { + int pos = (((m_split_yst + m_vcount) & ~0x1f) | (tile & 0x1f)) >> 2; + return m_exram[0x3c0 | pos]; + } else - return 0x00; - - case CIRAM: - default: - // Uchuu Keibitai SDF uses extensively split screen for its intro, - // but it does not work yet - if (m_split_scr && !(m_exram_control & 0x02) && in_split()) { - int tile = m_ppu->get_tilenum(); - - if ((offset & 0x3ff) >= 0x3c0) - { - int pos = (((m_split_yst + m_vcount) & ~0x1f) | (tile & 0x1f)) >> 2; - return m_exram[0x3c0 | pos]; - } - else - { - int pos = (((m_split_yst + m_vcount) & 0xf8) << 2) | (tile & 0x1f); - return m_exram[pos]; - } + int pos = (((m_split_yst + m_vcount) & 0xf8) << 2) | (tile & 0x1f); + return m_exram[pos]; } + } - if (m_exram_control == 1) + if (m_exram_control == 1) + { + if ((offset & 0x3ff) >= 0x3c0) + return m_ex1_attrib; + else if (!machine().side_effects_disabled()) // in this case, we write Ex1 CHR bank, but then access NT normally! { - if ((offset & 0x3ff) >= 0x3c0) - return m_mmc5_attrib[(m_exram[offset & 0x3ff] >> 6) & 0x03]; - else // in this case, we write Ex1 CHR bank, but then access NT normally! - { - m_ex1_chr = 1; - m_ex1_bank = (m_exram[offset & 0x3ff] & 0x3f) | (m_high_chr << 6); - } + m_ex1_chr = 1; + 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]; } } @@ -350,14 +353,14 @@ void nes_exrom_device::nt_w(offs_t offset, uint8_t data) switch (m_nt_src[page]) { - case EXRAM: - m_exram[offset & 0x3ff] = data; - break; + case EXRAM: + m_exram[offset & 0x3ff] = data; + break; - case CIRAM: - default: - m_nt_access[page][offset & 0x3ff] = data; - break; + case CIRAM: + default: + m_nt_access[page][offset & 0x3ff] = data; + break; } } @@ -367,21 +370,21 @@ inline uint8_t nes_exrom_device::base_chr_r(int bank, uint32_t offset) switch (m_chr_mode) { - case 0: - if (bank < 8) - helper = ((m_vrom_bank[bank | 7] & 0xff) * 0x2000) + (offset & 0x1fff); - else - helper = ((m_vrom_bank[bank | 3] & 0xff) * 0x2000) + (offset & 0xfff); - break; - case 1: - helper = ((m_vrom_bank[bank | 3] & 0xff) * 0x1000) + (offset & 0xfff); - break; - case 2: - helper = (m_vrom_bank[bank | 1] * 0x800) + (offset & 0x7ff); - break; - case 3: - helper = (m_vrom_bank[bank] * 0x400) + (offset & 0x3ff); - break; + case 0: + if (bank < 8) + helper = ((m_vrom_bank[bank | 7] & 0xff) * 0x2000) + (offset & 0x1fff); + else + helper = ((m_vrom_bank[bank | 3] & 0xff) * 0x2000) + (offset & 0x1fff); + break; + case 1: + helper = ((m_vrom_bank[bank | 3] & 0xff) * 0x1000) + (offset & 0xfff); + break; + case 2: + helper = (m_vrom_bank[bank | 1] * 0x800) + (offset & 0x7ff); + break; + case 3: + helper = (m_vrom_bank[bank] * 0x400) + (offset & 0x3ff); + break; } return m_vrom[helper & (m_vrom_size - 1)]; @@ -444,20 +447,25 @@ uint8_t nes_exrom_device::read_l(offs_t offset) switch (offset) { - case 0x1204: - value = m_irq_status; + case 0x1204: + value = m_irq_status; + if (!machine().side_effects_disabled()) + { m_irq_status &= ~0x80; set_irq_line(CLEAR_LINE); - return value; + } + return value; - case 0x1205: - return (m_mult1 * m_mult2) & 0xff; - case 0x1206: - return ((m_mult1 * m_mult2) & 0xff00) >> 8; + case 0x1205: + return (m_mult1 * m_mult2) & 0xff; - default: + case 0x1206: + return ((m_mult1 * m_mult2) & 0xff00) >> 8; + + default: + if (!machine().side_effects_disabled()) logerror("MMC5 uncaught read, offset: %04x\n", offset + 0x4100); - return get_open_bus(); + return get_open_bus(); } } @@ -491,128 +499,130 @@ void nes_exrom_device::write_l(offs_t offset, uint8_t data) switch (offset) { - case 0x1100: - m_prg_mode = data & 0x03; - update_prg(); - //LOG_MMC(("MMC5 rom bank mode: %02x\n", data)); - break; + case 0x1100: + m_prg_mode = data & 0x03; + update_prg(); + //LOG_MMC(("MMC5 rom bank mode: %02x\n", data)); + break; - case 0x1101: - m_chr_mode = data & 0x03; - m_ex1_chr = 0; - m_split_chr = 0; - //LOG_MMC(("MMC5 vrom bank mode: %02x\n", data)); - break; + case 0x1101: + m_chr_mode = data & 0x03; + m_ex1_chr = 0; + m_split_chr = 0; + //LOG_MMC(("MMC5 vrom bank mode: %02x\n", data)); + break; - case 0x1102: - m_wram_protect_1 = data & 0x03; - LOG_MMC(("MMC5 vram protect 1: %02x\n", data)); - break; - case 0x1103: - m_wram_protect_2 = data & 0x03; - LOG_MMC(("MMC5 vram protect 2: %02x\n", data)); - break; + case 0x1102: + m_wram_protect_1 = data & 0x03; + LOG_MMC(("MMC5 vram protect 1: %02x\n", data)); + break; - case 0x1104: // Extra VRAM (EXRAM) - m_exram_control = data & 0x03; - LOG_MMC(("MMC5 exram control: %02x\n", data)); - break; + case 0x1103: + m_wram_protect_2 = data & 0x03; + LOG_MMC(("MMC5 vram protect 2: %02x\n", data)); + break; - case 0x1105: - set_mirror(0, (data & 0x03) >> 0); - set_mirror(1, (data & 0x0c) >> 2); - set_mirror(2, (data & 0x30) >> 4); - set_mirror(3, (data & 0xc0) >> 6); - break; + case 0x1104: // Extra VRAM (EXRAM) + m_exram_control = data & 0x03; + LOG_MMC(("MMC5 exram control: %02x\n", data)); + break; - case 0x1106: - m_floodtile = data; - break; + case 0x1105: + set_mirror(0, (data & 0x03) >> 0); + set_mirror(1, (data & 0x0c) >> 2); + set_mirror(2, (data & 0x30) >> 4); + set_mirror(3, (data & 0xc0) >> 6); + break; - case 0x1107: - m_floodattr = m_mmc5_attrib[data & 3]; - break; + case 0x1106: + m_floodtile = data; + break; - case 0x1113: - LOG_MMC(("MMC5 mid RAM bank select: %02x\n", data & 0x07)); - m_wram_base = data & 0x07; - break; + case 0x1107: + m_floodattr = m_mmc5_attrib[data & 3]; + break; + case 0x1113: + LOG_MMC(("MMC5 mid RAM bank select: %02x\n", data & 0x07)); + m_wram_base = data & 0x07; + break; - case 0x1114: - case 0x1115: - case 0x1116: - case 0x1117: - m_prg_regs[offset & 3] = data & 0x7f; - m_prg_ram_mapped[offset & 3] = !BIT(data, 7); // m_prg_ram_mapped[3] is not used, in fact! - update_prg(); - break; + case 0x1114: + case 0x1115: + case 0x1116: + case 0x1117: + m_prg_regs[offset & 3] = data & 0x7f; + m_prg_ram_mapped[offset & 3] = !BIT(data, 7); // m_prg_ram_mapped[3] is not used, in fact! + update_prg(); + break; - case 0x1120: - case 0x1121: - case 0x1122: - case 0x1123: - case 0x1124: - case 0x1125: - case 0x1126: - case 0x1127: - m_vrom_bank[offset & 0x07] = data | (m_high_chr << 8); - m_last_chr = LAST_CHR_REG_A; - m_ex1_chr = 0; - m_split_chr = 0; - break; + case 0x1120: + case 0x1121: + case 0x1122: + case 0x1123: + case 0x1124: + case 0x1125: + case 0x1126: + case 0x1127: + m_vrom_bank[offset & 0x07] = data | (m_high_chr << 8); + m_last_chr = LAST_CHR_REG_A; + m_ex1_chr = 0; + m_split_chr = 0; + break; - case 0x1128: - case 0x1129: - case 0x112a: - case 0x112b: - m_vrom_bank[offset & 0x0f] = data | (m_high_chr << 8); - m_last_chr = LAST_CHR_REG_B; - m_ex1_chr = 0; - m_split_chr = 0; - break; + case 0x1128: + case 0x1129: + case 0x112a: + case 0x112b: + m_vrom_bank[offset & 0x0f] = data | (m_high_chr << 8); + m_last_chr = LAST_CHR_REG_B; + m_ex1_chr = 0; + m_split_chr = 0; + break; - case 0x1130: - m_high_chr = data & 0x03; - m_ex1_chr = 0; - m_split_chr = 0; - break; + case 0x1130: + m_high_chr = data & 0x03; + m_ex1_chr = 0; + m_split_chr = 0; + break; + case 0x1200: + // in EX2 and EX3 modes, no split screen + m_split_scr = BIT(data, 7); + m_split_rev = BIT(data, 6); + m_split_ctrl = data & 0x1f; + break; - case 0x1200: - // in EX2 and EX3 modes, no split screen - m_split_scr = BIT(data, 7); - m_split_rev = BIT(data, 6); - m_split_ctrl = data & 0x1f; - break; + case 0x1201: + m_split_yst = (data >= 240) ? data - 16 : data; + break; - case 0x1201: - m_split_yst = (data >= 240) ? data - 16 : data; - break; + case 0x1202: + m_split_bank = data; + m_split_chr = 1; + break; - case 0x1202: - m_split_bank = data; - m_split_chr = 1; - break; + case 0x1203: + m_irq_count = data; + LOG_MMC(("MMC5 irq scanline: %d\n", m_irq_count)); + break; - case 0x1203: - m_irq_count = data; - LOG_MMC(("MMC5 irq scanline: %d\n", m_irq_count)); - break; - case 0x1204: - m_irq_enable = data & 0x80; - LOG_MMC(("MMC5 irq enable: %02x\n", data)); - break; - case 0x1205: - m_mult1 = data; - break; - case 0x1206: - m_mult2 = data; - break; + case 0x1204: + m_irq_enable = data & 0x80; + LOG_MMC(("MMC5 irq enable: %02x\n", data)); + break; - default: - logerror("MMC5 uncaught write, offset: %04x, data: %02x\n", offset + 0x4100, data); - break; + case 0x1205: + m_mult1 = data; + break; + + case 0x1206: + m_mult2 = data; + break; + + default: + logerror("MMC5 uncaught write, offset: %04x, data: %02x\n", offset + 0x4100, data); + break; } } diff --git a/src/devices/bus/nes/mmc5.h b/src/devices/bus/nes/mmc5.h index 86914fec177..27a9709cafd 100644 --- a/src/devices/bus/nes/mmc5.h +++ b/src/devices/bus/nes/mmc5.h @@ -75,6 +75,7 @@ protected: uint8_t m_prg_ram_mapped[4]; uint8_t m_ex1_bank; + uint8_t m_ex1_attrib; uint8_t m_high_chr; // $5130 diff --git a/src/devices/video/ppu2c0x.cpp b/src/devices/video/ppu2c0x.cpp index f82055140b7..f97c91d381b 100644 --- a/src/devices/video/ppu2c0x.cpp +++ b/src/devices/video/ppu2c0x.cpp @@ -676,6 +676,9 @@ void ppu2c0x_device::draw_background(uint8_t *line_priority) 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)! /* Figure out which byte in the color table to use */ 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 */ 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 if (!m_latch.isnull()) m_latch((m_tile_page << 10) | (page2 << 4));