From fe30addeaf0d2b9f322e19f8f3278b55c4440807 Mon Sep 17 00:00:00 2001 From: 0kmg <9137159+0kmg@users.noreply.github.com> Date: Sat, 13 Aug 2022 04:57:54 -0800 Subject: [PATCH] nintendo/playch10.cpp: Merged playch10 source files. (#10214) * Added finders for joystick and gun inputs. * Fixed some bad masks (sprite DMA write and Pin-Bot). * Made color PROM loading more concise. * Removed pc_1942 imperfect graphics flag. It looks as bad as it should. * Various other minor cleanups. --- src/mame/nintendo/playch10.cpp | 1169 +++++++++++++++++++++++++++++- src/mame/nintendo/playch10.h | 197 ----- src/mame/nintendo/playch10_m.cpp | 862 ---------------------- src/mame/nintendo/playch10_v.cpp | 142 ---- 4 files changed, 1151 insertions(+), 1219 deletions(-) delete mode 100644 src/mame/nintendo/playch10.h delete mode 100644 src/mame/nintendo/playch10_m.cpp delete mode 100644 src/mame/nintendo/playch10_v.cpp diff --git a/src/mame/nintendo/playch10.cpp b/src/mame/nintendo/playch10.cpp index e9b8eff8e00..f68e6193570 100644 --- a/src/mame/nintendo/playch10.cpp +++ b/src/mame/nintendo/playch10.cpp @@ -289,19 +289,338 @@ Notes & Todo: ***************************************************************************/ #include "emu.h" -#include "playch10.h" +#include "bus/nes_ctrl/zapper_sensor.h" +#include "cpu/m6502/n2a03.h" #include "cpu/z80/z80.h" #include "machine/74259.h" #include "machine/rp5h01.h" #include "machine/nvram.h" +#include "video/ppu2c0x.h" +#include "emupal.h" #include "screen.h" #include "speaker.h" +#include "tilemap.h" #include "playch10.lh" +namespace { + +class playch10_state : public driver_device +{ +public: + playch10_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_cartcpu(*this, "cart") + , m_ppu(*this, "ppu") + , m_rp5h01(*this, "rp5h01") + , m_ram_8w(*this, "ram_8w") + , m_videoram(*this, "videoram") + , m_gfxdecode(*this, "gfxdecode") + , m_sensor(*this, "sensor") + , m_in(*this, "P%u", 1U) + , m_gunx(*this, "GUNX") + , m_guny(*this, "GUNY") + , m_nt_page(*this, "nt_page%u", 0U) + , m_prg_banks(*this, "prg%u", 0U) + , m_prg_view(*this, "prg_view") + , m_vrom_region(*this, "gfx2") + , m_timedigits(*this, "digit_%u", 0U) + { + } + + void playch10(machine_config &config); + void playch10_a(machine_config &config); + void playch10_b(machine_config &config); + void playch10_c(machine_config &config); + void playch10_d(machine_config &config); + void playch10_d2(machine_config &config); + void playch10_e(machine_config &config); + void playch10_f(machine_config &config); + void playch10_f2(machine_config &config); + void playch10_g(machine_config &config); + void playch10_h(machine_config &config); + void playch10_i(machine_config &config); + void playch10_k(machine_config &config); + + void init_playch10(); + void init_pc_gun(); + void init_pcaboard(); + void init_pcbboard(); + void init_pccboard(); + void init_pcdboard(); + void init_pceboard(); + void init_pcfboard(); + void init_pcgboard(); + void init_pcgboard_type2(); + void init_pchboard(); + void init_pciboard(); + void init_pckboard(); + void init_pc_hrz(); + + DECLARE_READ_LINE_MEMBER(int_detect_r); + +private: + DECLARE_WRITE_LINE_MEMBER(up8w_w); + u8 ram_8w_r(offs_t offset); + void ram_8w_w(offs_t offset, u8 data); + void sprite_dma_w(address_space &space, u8 data); + void time_w(offs_t offset, u8 data); + DECLARE_WRITE_LINE_MEMBER(sdcs_w); + DECLARE_WRITE_LINE_MEMBER(cntrl_mask_w); + DECLARE_WRITE_LINE_MEMBER(disp_mask_w); + DECLARE_WRITE_LINE_MEMBER(sound_mask_w); + DECLARE_WRITE_LINE_MEMBER(nmi_enable_w); + DECLARE_WRITE_LINE_MEMBER(dog_di_w); + DECLARE_WRITE_LINE_MEMBER(ppu_reset_w); + u8 pc10_detectclr_r(); + void cart_sel_w(u8 data); + u8 pc10_prot_r(); + void pc10_prot_w(u8 data); + void pc10_in0_w(u8 data); + u8 pc10_in0_r(); + u8 pc10_in1_r(); + void pc10_chr_w(offs_t offset, u8 data); + u8 pc10_chr_r(offs_t offset); + void mmc1_rom_switch_w(offs_t offset, u8 data); + void aboard_vrom_switch_w(u8 data); + void bboard_rom_switch_w(u8 data); + void cboard_vrom_switch_w(u8 data); + void eboard_rom_switch_w(offs_t offset, u8 data); + void gboard_rom_switch_w(offs_t offset, u8 data); + void hboard_rom_switch_w(offs_t offset, u8 data); + void iboard_rom_switch_w(u8 data); + void playch10_videoram_w(offs_t offset, u8 data); + + TILE_GET_INFO_MEMBER(get_bg_tile_info); + + void bios_io_map(address_map &map); + void bios_map(address_map &map); + void ppu_map(address_map &map); + void cart_map(address_map &map); + void cart_a_map(address_map &map); + void cart_b_map(address_map &map); + void cart_c_map(address_map &map); + void cart_d_map(address_map &map); + void cart_d2_map(address_map &map); + void cart_e_map(address_map &map); + void cart_f_map(address_map &map); + void cart_f2_map(address_map &map); + void cart_g_map(address_map &map); + void cart_h_map(address_map &map); + void cart_i_map(address_map &map); + void cart_k_map(address_map &map); + + virtual void machine_start() override; + virtual void machine_reset() override; + virtual void video_start() override; + + struct chr_bank + { + int writable = 0; // 1 for RAM, 0 for ROM + u8* chr = nullptr; // direct access to the memory + }; + + void playch10_palette(palette_device &palette) const; + DECLARE_WRITE_LINE_MEMBER(vblank_irq); + + void pc10_set_videorom_bank(int first, int count, int bank, int size); + void set_videoram_bank(int first, int count, int bank, int size); + void gboard_scanline_cb(int scanline, bool vblank, bool blanked); + DECLARE_WRITE_LINE_MEMBER(int_detect_w); + void mapper9_latch(offs_t offset); + void pc10_set_mirroring(int mirroring); + + u32 screen_update_playch10_top(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); + u32 screen_update_playch10_bottom(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); + u32 screen_update_playch10_single(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); + + required_device m_maincpu; + required_device m_cartcpu; + required_device m_ppu; + optional_device m_rp5h01; + + required_shared_ptr m_ram_8w; + required_shared_ptr m_videoram; + required_device m_gfxdecode; + required_device m_sensor; + + required_ioport_array<2> m_in; + optional_ioport m_gunx; + optional_ioport m_guny; + + required_memory_bank_array<4> m_nt_page; + std::unique_ptr m_nt_ram; + std::unique_ptr m_cart_nt_ram; + + void init_prg_banking(); + void prg32(int bank); + void prg16(int slot, int bank); + void prg8(int slot, int bank); + memory_bank_array_creator<4> m_prg_banks; + memory_view m_prg_view; + int m_prg_chunks = 0; + + optional_memory_region m_vrom_region; + + output_finder<4> m_timedigits; + + int m_up_8w = 0; + int m_pc10_nmi_enable = 0; + int m_pc10_dog_di = 0; + int m_pc10_sdcs = 0; + int m_pc10_dispmask = 0; + int m_pc10_int_detect = 0; + int m_pc10_game_mode = 0; + int m_pc10_dispmask_old = 0; + int m_pc10_gun_controller = 0; + int m_cart_sel = 0; + int m_cntrl_mask = 0; + int m_input_latch[2]{}; + int m_mirroring = 0; + int m_MMC2_bank[4]{}; + int m_MMC2_bank_latch[2]{}; + u8* m_vrom = nullptr; + std::unique_ptr m_vram; + chr_bank m_chr_page[8]; + int m_mmc1_shiftreg = 0; + int m_mmc1_shiftcount = 0; + int m_gboard_banks[2]{}; + int m_gboard_command = 0; + int m_IRQ_count = 0; + u8 m_IRQ_count_latch = 0; + int m_IRQ_enable = 0; + int m_pc10_bios = 0; + tilemap_t *m_bg_tilemap = nullptr; +}; + + +/*************************************************************************** + + PlayChoice-10 Video Hardware + +***************************************************************************/ + +void playch10_state::playch10_videoram_w(offs_t offset, u8 data) +{ + if (m_pc10_sdcs) + { + m_videoram[offset] = data; + m_bg_tilemap->mark_tile_dirty(offset / 2); + } +} + +void playch10_state::playch10_palette(palette_device &palette) const +{ + static constexpr u8 coeff[4] = { 0x0e, 0x1f, 0x43, 0x8f }; + const u8 *color_prom = memregion("proms")->base(); + + for (int i = 0; i < 256; i++) + { + for (int j = 0, r = 0, g = 0, b = 0; j < 4; j++) + { + r += coeff[j] * BIT(color_prom[0], j); + g += coeff[j] * BIT(color_prom[256], j); + b += coeff[j] * BIT(color_prom[2 * 256], j); + palette.set_pen_color(i, rgb_t(r, g, b)); + } + + color_prom++; + } +} + +WRITE_LINE_MEMBER(playch10_state::int_detect_w) +{ + if (state) + m_pc10_int_detect = 1; +} + +TILE_GET_INFO_MEMBER(playch10_state::get_bg_tile_info) +{ + u8 *videoram = m_videoram; + int offs = tile_index * 2; + int code = videoram[offs] + ((videoram[offs + 1] & 0x07) << 8); + int color = (videoram[offs + 1] >> 3) & 0x1f; + + tileinfo.set(0, code, color, 0); +} + +void playch10_state::video_start() +{ + const u8 *bios = memregion("maincpu")->base(); + m_pc10_bios = (bios[3] == 0x2a) ? 1 : 2; + + m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(playch10_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, + 8, 8, 32, 32); +} + +/*************************************************************************** + + Display refresh + +***************************************************************************/ + +u32 playch10_state::screen_update_playch10_single(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + rectangle top_monitor = screen.visible_area(); + + top_monitor.max_y = (top_monitor.max_y - top_monitor.min_y) / 2; + + if (m_pc10_dispmask_old != m_pc10_dispmask) + { + m_pc10_dispmask_old = m_pc10_dispmask; + + if (m_pc10_dispmask) + m_pc10_game_mode ^= 1; + } + + if (m_pc10_game_mode) + // render the ppu + m_ppu->render(bitmap, 0, 0, 0, 0, cliprect); + else + { + // When the bios is accessing vram, the video circuitry can't access it + if (!m_pc10_sdcs) + m_bg_tilemap->draw(screen, bitmap, top_monitor, 0, 0); + } + + return 0; +} + +u32 playch10_state::screen_update_playch10_top(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + // Single Monitor version + if (m_pc10_bios != 1) + return screen_update_playch10_single(screen, bitmap, cliprect); + + // When the bios is accessing vram, the video circuitry can't access it + if (!m_pc10_sdcs) + m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0); + else + bitmap.fill(0, cliprect); + + return 0; +} + +u32 playch10_state::screen_update_playch10_bottom(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + // Single Monitor version + if (m_pc10_bios != 1) + return screen_update_playch10_single(screen, bitmap, cliprect); + + if (!m_pc10_dispmask) + // render the ppu + m_ppu->render(bitmap, 0, 0, 0, 0, cliprect); + else + bitmap.fill(0, cliprect); + + return 0; +} + + //****************************************************************************** @@ -310,38 +629,850 @@ WRITE_LINE_MEMBER(playch10_state::up8w_w) m_up_8w = state; } -uint8_t playch10_state::ram_8w_r(offs_t offset) +u8 playch10_state::ram_8w_r(offs_t offset) { - if ( offset >= 0x400 && m_up_8w ) - return m_ram_8w[offset]; - - return m_ram_8w[offset & 0x3ff]; + if (!m_up_8w) + offset &= 0x3ff; + return m_ram_8w[offset]; } -void playch10_state::ram_8w_w(offs_t offset, uint8_t data) +void playch10_state::ram_8w_w(offs_t offset, u8 data) { - if ( offset >= 0x400 && m_up_8w ) - m_ram_8w[offset] = data; - else - m_ram_8w[offset & 0x3ff] = data; + if (!m_up_8w) + offset &= 0x3ff; + m_ram_8w[offset] = data; } -void playch10_state::sprite_dma_w(address_space &space, uint8_t data) +void playch10_state::sprite_dma_w(address_space &space, u8 data) { - int source = ( data & 7 ); - m_ppu->spriteram_dma(space, source); + m_ppu->spriteram_dma(space, data); } // Only used in single monitor bios -void playch10_state::time_w(offs_t offset, uint8_t data) +void playch10_state::time_w(offs_t offset, u8 data) { - constexpr static uint8_t DIGIT_MAP[16] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7c, 0x07, 0x7f, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + constexpr static u8 DIGIT_MAP[16] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7c, 0x07, 0x7f, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; m_timedigits[offset] = DIGIT_MAP[data & 0x0f]; } +/************************************* + * + * Init machine + * + *************************************/ + +void playch10_state::machine_reset() +{ + m_pc10_int_detect = 0; + + m_pc10_game_mode = 0; + m_pc10_dispmask_old = 0; + + m_input_latch[0] = m_input_latch[1] = 0; + + // variables used only in MMC2 game (mapper 9) + m_MMC2_bank[0] = m_MMC2_bank[1] = m_MMC2_bank[2] = m_MMC2_bank[3] = 0; + m_MMC2_bank_latch[0] = m_MMC2_bank_latch[1] = 0xfe; + + // reset the security chip + m_rp5h01->enable_w(1); + m_rp5h01->enable_w(0); + m_rp5h01->reset_w(0); + m_rp5h01->reset_w(1); + + pc10_set_mirroring(m_mirroring); +} + +void playch10_state::machine_start() +{ + m_timedigits.resolve(); + + m_vrom = m_vrom_region ? m_vrom_region->base() : nullptr; + + // sanity check: make sure PRG/CHR sizes are powers of 2 and big enough + int len = memregion("prg")->bytes(); + assert(!(len & (len - 1)) && len >= 0x8000); + if (m_vrom) + { + len = m_vrom_region->bytes(); + assert(!(len & (len - 1)) && len >= 0x2000); + } + + // allocate 2K of nametable ram here + // this is on the main board and does not belong to the cart board + m_nt_ram = std::make_unique(0x800); + + for (int i = 0; i < 4; i++) + if (m_cart_nt_ram && i >= 2) // extra cart RAM for 4 screen mirroring + m_nt_page[i]->configure_entries(0, 2, m_cart_nt_ram.get(), 0x400); + else + m_nt_page[i]->configure_entries(0, 2, m_nt_ram.get(), 0x400); + + if (m_vram) + set_videoram_bank(0, 8, 0, 8); + else + pc10_set_videorom_bank(0, 8, 0, 8); +} + +/************************************* + * + * BIOS ports handling + * + *************************************/ + +READ_LINE_MEMBER(playch10_state::int_detect_r) +{ + return ~m_pc10_int_detect & 1; +} + +WRITE_LINE_MEMBER(playch10_state::sdcs_w) +{ + /* + Hooked to CLR on LS194A - Sheet 2, bottom left. + Drives character and color code to 0. + It's used to keep the screen black during redraws. + Also hooked to the video sram. Prevent writes. + */ + m_pc10_sdcs = !state; +} + +WRITE_LINE_MEMBER(playch10_state::cntrl_mask_w) +{ + m_cntrl_mask = !state; +} + +WRITE_LINE_MEMBER(playch10_state::disp_mask_w) +{ + m_pc10_dispmask = !state; +} + +WRITE_LINE_MEMBER(playch10_state::sound_mask_w) +{ + machine().sound().system_mute(!state); +} + +WRITE_LINE_MEMBER(playch10_state::nmi_enable_w) +{ + m_pc10_nmi_enable = state; +} + +WRITE_LINE_MEMBER(playch10_state::dog_di_w) +{ + m_pc10_dog_di = state; +} + +WRITE_LINE_MEMBER(playch10_state::ppu_reset_w) +{ + if (state) + m_ppu->reset(); +} + +u8 playch10_state::pc10_detectclr_r() +{ + m_pc10_int_detect = 0; + + return 0; +} + +void playch10_state::cart_sel_w(u8 data) +{ + m_cart_sel = data; +} + + +/************************************* + * + * RP5H01 handling + * + *************************************/ + +u8 playch10_state::pc10_prot_r() +{ + int data = 0xe7; + + // we only support a single cart connected at slot 0 + if (m_cart_sel == 0) + { + data |= (~m_rp5h01->counter_r() << 4) & 0x10; // D4 + data |= (m_rp5h01->data_r() << 3) & 0x08; // D3 + } + return data; +} + +void playch10_state::pc10_prot_w(u8 data) +{ + // we only support a single cart connected at slot 0 + if (m_cart_sel == 0) + { + m_rp5h01->test_w(data & 0x10); // D4 + m_rp5h01->clock_w(data & 0x08); // D3 + m_rp5h01->reset_w(~data & 0x01); // D0 + } +} + +/************************************* + * + * Input Ports + * + *************************************/ + +void playch10_state::pc10_in0_w(u8 data) +{ + // Toggling bit 0 high then low resets both controllers + if (data & 1) + return; + + // load up the latches + for (int i = 0; i < 2; i++) + m_input_latch[i] = m_in[i]->read(); + + // apply any masking from the BIOS + if (m_cntrl_mask) + { + // mask out select and start + m_input_latch[0] &= ~0x0c; + } +} + +u8 playch10_state::pc10_in0_r() +{ + int ret = m_input_latch[0] & 1; + + // shift + m_input_latch[0] >>= 1; + + // some games expect bit 6 to be set because the last entry on the data bus shows up + // in the unused upper 3 bits, so typically a read from $4016 leaves 0x40 there. + ret |= 0x40; + + return ret; +} + +u8 playch10_state::pc10_in1_r() +{ + int ret = m_input_latch[1] & 1; + + // shift + m_input_latch[1] >>= 1; + + // do the gun thing + if (m_pc10_gun_controller) + { + int trigger = m_in[0]->read(); + + if (!m_sensor->detect_light(m_gunx->read(), m_guny->read())) + ret |= 0x08; + + // now, add the trigger if not masked + if (!m_cntrl_mask) + ret |= (trigger & 2) << 3; + } + + // some games expect bit 6 to be set because the last entry on the data bus shows up + // in the unused upper 3 bits, so typically a read from $4016 leaves 0x40 there. + ret |= 0x40; + + return ret; +} +/************************************* + * + * PPU External bus handlers + * + *************************************/ + +void playch10_state::pc10_chr_w(offs_t offset, u8 data) +{ + int bank = BIT(offset, 10, 3); + if (m_chr_page[bank].writable) + m_chr_page[bank].chr[offset & 0x3ff] = data; +} + +u8 playch10_state::pc10_chr_r(offs_t offset) +{ + int bank = BIT(offset, 10, 3); + return m_chr_page[bank].chr[offset & 0x3ff]; +} + +void playch10_state::pc10_set_mirroring(int mirroring) +{ + int bit = mirroring == PPU_MIRROR_HORZ || mirroring == PPU_MIRROR_HIGH; + + switch (mirroring) + { + case PPU_MIRROR_LOW: + case PPU_MIRROR_HIGH: + for (int i = 0; i < 4; i++) + m_nt_page[i]->set_entry(bit); + break; + case PPU_MIRROR_HORZ: + case PPU_MIRROR_VERT: + case PPU_MIRROR_4SCREEN: + default: + for (int i = 0; i < 4; i++) + m_nt_page[i]->set_entry(BIT(i, bit)); + break; + } +} + + +void playch10_state::pc10_set_videorom_bank(int first, int count, int bank, int size) +{ + // first = first bank to map + // count = number of 1K banks to map + // bank = index of the bank + // size = size of indexed banks (in KB) + // note that this follows the original PPU banking and might be overly complex + + // yeah, this is probably a horrible assumption to make + // but the driver is 100% consistant + + if (!m_vrom) // do nothing if there is no CHR ROM to bank + return; + + int len = m_vrom_region->bytes(); + len /= 0x400; // convert to KB + len /= size; // convert to bank resolution + len--; // convert to mask + bank &= len; // should be the right mask + + for (int i = 0; i < count; i++) + { + m_chr_page[i + first].writable = 0; + m_chr_page[i + first].chr = m_vrom + (i * 0x400) + (bank * size * 0x400); + } +} + +void playch10_state::set_videoram_bank(int first, int count, int bank, int size) +{ + // first = first bank to map + // count = number of 1K banks to map + // bank = index of the bank + // size = size of indexed banks (in KB) + // note that this follows the original PPU banking and might be overly complex + + // assumes 8K of vram + // need 8K to fill address space + // only pinbot (8k) banks at all + + for (int i = 0; i < count; i++) + { + m_chr_page[i + first].writable = 1; + m_chr_page[i + first].chr = m_vram.get() + (((i * 0x400) + (bank * size * 0x400)) & 0x1fff); + } +} + +/************************************* + * + * Common init for all games + * + *************************************/ + +void playch10_state::init_playch10() +{ + m_vram = nullptr; + + // set the controller to default + m_pc10_gun_controller = 0; + + // default mirroring + m_mirroring = PPU_MIRROR_VERT; +} + +/********************************************************************************** + * + * Game and Board-specific initialization + * + **********************************************************************************/ + +// Gun games + +void playch10_state::init_pc_gun() +{ + // common init + init_playch10(); + + // set the control type + m_pc10_gun_controller = 1; +} + +// Horizontal mirroring + +void playch10_state::init_pc_hrz() +{ + // common init + init_playch10(); + + // setup mirroring + m_mirroring = PPU_MIRROR_HORZ; +} + +// Init for games that bank PRG memory + +void playch10_state::init_prg_banking() +{ + // common init + init_playch10(); + + u8 *base = memregion("prg")->base(); + m_prg_chunks = memregion("prg")->bytes() / 0x2000; + + for (int i = 0; i < 4; i++) + { + m_prg_banks[i]->configure_entries(0, m_prg_chunks, base, 0x2000); + m_prg_banks[i]->set_entry(m_prg_chunks - 4 + i); + } + + m_prg_view.select(0); +} + +// safe banking helpers (only work when PRG size is a power of 2) + +void playch10_state::prg32(int bank) +{ + bank = (bank << 2) & (m_prg_chunks - 1); + + for (int i = 0; i < 4; i++) + m_prg_banks[i]->set_entry(bank + i); +} + +void playch10_state::prg16(int slot, int bank) +{ + bank = (bank << 1) & (m_prg_chunks - 1); + slot = (slot & 1) << 1; + + for (int i = 0; i < 2; i++) + m_prg_banks[slot + i]->set_entry(bank + i); +} + +void playch10_state::prg8(int slot, int bank) +{ + m_prg_banks[slot & 0x03]->set_entry(bank & (m_prg_chunks - 1)); +} + +// MMC1 mapper, used by D, F, and K boards + +void playch10_state::mmc1_rom_switch_w(offs_t offset, u8 data) +{ + static int size16k, switchlow, vrom4k; + + // reset mapper + if (data & 0x80) + { + m_mmc1_shiftreg = m_mmc1_shiftcount = 0; + + size16k = 1; + switchlow = 1; + vrom4k = 0; + + return; + } + + // update shift register + m_mmc1_shiftreg = (m_mmc1_shiftreg >> 1) | (data & 1) << 4; + m_mmc1_shiftcount = (m_mmc1_shiftcount + 1) % 5; + + // are we done shifting? + if (!m_mmc1_shiftcount) + { + // apply data to registers + switch (BIT(offset, 13, 2)) + { + case 0: // mirroring and options + { + static constexpr u8 mirr[4] = { + PPU_MIRROR_LOW, PPU_MIRROR_HIGH, PPU_MIRROR_VERT, PPU_MIRROR_HORZ + }; + + pc10_set_mirroring(mirr[m_mmc1_shiftreg & 0x03]); + + vrom4k = m_mmc1_shiftreg & 0x10; + size16k = m_mmc1_shiftreg & 0x08; + switchlow = m_mmc1_shiftreg & 0x04; + break; + } + + case 1: // video rom banking - bank 0 - 4k or 8k + if (m_vram) + set_videoram_bank(0, (vrom4k) ? 4 : 8, m_mmc1_shiftreg & 0x1f, 4); + else + pc10_set_videorom_bank(0, (vrom4k) ? 4 : 8, m_mmc1_shiftreg & 0x1f, 4); + break; + + case 2: // video rom banking - bank 1 - 4k only + if (vrom4k) + { + if (m_vram) + set_videoram_bank(0, (vrom4k) ? 4 : 8, m_mmc1_shiftreg & 0x1f, 4); + else + pc10_set_videorom_bank(4, 4, m_mmc1_shiftreg & 0x1f, 4); + } + break; + + case 3: // program banking + if (size16k) + prg16(!switchlow, m_mmc1_shiftreg); + else + prg32(m_mmc1_shiftreg >> 1); + break; + } + } +} + +//********************************************************************************** +// A Board games (Track & Field, Gradius) + +void playch10_state::aboard_vrom_switch_w(u8 data) +{ + pc10_set_videorom_bank(0, 8, data & 0x03, 8); +} + +void playch10_state::init_pcaboard() +{ + // common init + init_playch10(); +} + +//********************************************************************************** +// B Board games (Contra, Rush N' Attach, Pro Wrestling) + +void playch10_state::bboard_rom_switch_w(u8 data) +{ + prg16(0, data); +} + +void playch10_state::init_pcbboard() +{ + // point program banks to last 32K + init_prg_banking(); + + // allocate vram + m_vram = std::make_unique(0x2000); +} + +//********************************************************************************** +// C Board games (The Goonies) + +void playch10_state::cboard_vrom_switch_w(u8 data) +{ + pc10_set_videorom_bank(0, 8, BIT(data, 1), 8); +} + +void playch10_state::init_pccboard() +{ + // common init + init_playch10(); +} + +//********************************************************************************** +// D Board games (Rad Racer, Metroid) + +void playch10_state::init_pcdboard() +{ + // point program banks to last 32K + init_prg_banking(); + + // allocate vram + m_vram = std::make_unique(0x2000); +} + +//********************************************************************************** +// E Board (MMC2) games (Mike Tyson's Punchout) + +// callback for the ppu_latch +void playch10_state::mapper9_latch(offs_t offset) +{ + if((offset & 0x1ff0) == 0x0fd0 && m_MMC2_bank_latch[0] != 0xfd) + { + m_MMC2_bank_latch[0] = 0xfd; + pc10_set_videorom_bank(0, 4, m_MMC2_bank[0], 4); + } + else if((offset & 0x1ff0) == 0x0fe0 && m_MMC2_bank_latch[0] != 0xfe) + { + m_MMC2_bank_latch[0] = 0xfe; + pc10_set_videorom_bank(0, 4, m_MMC2_bank[1], 4); + } + else if((offset & 0x1ff0) == 0x1fd0 && m_MMC2_bank_latch[1] != 0xfd) + { + m_MMC2_bank_latch[1] = 0xfd; + pc10_set_videorom_bank(4, 4, m_MMC2_bank[2], 4); + } + else if((offset & 0x1ff0) == 0x1fe0 && m_MMC2_bank_latch[1] != 0xfe) + { + m_MMC2_bank_latch[1] = 0xfe; + pc10_set_videorom_bank(4, 4, m_MMC2_bank[3], 4); + } +} + +void playch10_state::eboard_rom_switch_w(offs_t offset, u8 data) +{ + // a variation of mapper 9 on a nes + switch (offset & 0x7000) + { + case 0x2000: // code bank switching + prg8(0, data); + break; + + case 0x3000: // gfx bank 0 - 4k + m_MMC2_bank[0] = data; + if (m_MMC2_bank_latch[0] == 0xfd) + pc10_set_videorom_bank(0, 4, data, 4); + break; + + case 0x4000: // gfx bank 0 - 4k + m_MMC2_bank[1] = data; + if (m_MMC2_bank_latch[0] == 0xfe) + pc10_set_videorom_bank(0, 4, data, 4); + break; + + case 0x5000: // gfx bank 1 - 4k + m_MMC2_bank[2] = data; + if (m_MMC2_bank_latch[1] == 0xfd) + pc10_set_videorom_bank(4, 4, data, 4); + break; + + case 0x6000: // gfx bank 1 - 4k + m_MMC2_bank[3] = data; + if (m_MMC2_bank_latch[1] == 0xfe) + pc10_set_videorom_bank(4, 4, data, 4); + break; + + case 0x7000: // mirroring + pc10_set_mirroring(data & 1 ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT); + break; + } +} + +void playch10_state::init_pceboard() +{ + // point program banks to last 32K + init_prg_banking(); + + // ppu_latch callback + m_ppu->set_latch(*this, FUNC(playch10_state::mapper9_latch)); +} + +//********************************************************************************** +// F Board games (Ninja Gaiden, Double Dragon) + +void playch10_state::init_pcfboard() +{ + // point program banks to last 32K + init_prg_banking(); +} + +//********************************************************************************** +// G Board (MMC3) games (Super Mario Bros. 3, etc) + +void playch10_state::gboard_scanline_cb(int scanline, bool vblank, bool blanked) +{ + if (scanline < ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE) + { + int priorCount = m_IRQ_count; + if (m_IRQ_count) + m_IRQ_count--; + else + m_IRQ_count = m_IRQ_count_latch; + + if (m_IRQ_enable && !blanked && !m_IRQ_count && priorCount) // according to blargg the latter should be present as well, but it breaks Rampart and Joe & Mac US: they probably use the alt irq! + { + m_cartcpu->set_input_line(0, ASSERT_LINE); + } + } +} + +void playch10_state::gboard_rom_switch_w(offs_t offset, u8 data) +{ + switch (offset & 0x6001) + { + case 0x0000: + { + m_gboard_command = data; + + // reset the flippable banks + int flip = BIT(m_gboard_command, 6) << 1; + prg8(0 ^ flip, m_gboard_banks[0]); + prg8(2 ^ flip, m_prg_chunks - 2); + + break; + } + + case 0x0001: + { + u8 cmd = m_gboard_command & 0x07; + int page = (m_gboard_command & 0x80) >> 5; + + switch (cmd) + { + case 0: // char banking + case 1: // char banking + data &= 0xfe; + page ^= cmd << 1; + pc10_set_videorom_bank(page, 2, data, 1); + break; + + case 2: // char banking + case 3: // char banking + case 4: // char banking + case 5: // char banking + page ^= cmd + 2; + pc10_set_videorom_bank(page, 1, data, 1); + break; + + case 6: // program banking + { + m_gboard_banks[0] = data; + + int flip = BIT(m_gboard_command, 6) << 1; + prg8(0 ^ flip, m_gboard_banks[0]); + prg8(2 ^ flip, m_prg_chunks - 2); + break; + } + + case 7: // program banking - mid bank + m_gboard_banks[1] = data; + prg8(1, m_gboard_banks[1]); + break; + } + break; + } + + case 0x2000: // mirroring + if (m_mirroring != PPU_MIRROR_4SCREEN) + pc10_set_mirroring((data & 1) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT); + break; + + case 0x2001: // enable ram at $6000 + // ignored - we always enable it + break; + + case 0x4000: // scanline counter + m_IRQ_count_latch = data; + break; + + case 0x4001: // scanline latch + m_IRQ_count = 0; + break; + + case 0x6000: // disable irqs + m_IRQ_enable = 0; + m_cartcpu->set_input_line(0, CLEAR_LINE); + break; + + case 0x6001: // enable irqs + m_IRQ_enable = 1; + break; + } +} + +void playch10_state::init_pcgboard() +{ + // point program banks to last 32K + init_prg_banking(); + + m_gboard_banks[0] = 0x1e; + m_gboard_banks[1] = 0x1f; + m_gboard_command = 0; + m_IRQ_enable = 0; + m_IRQ_count = m_IRQ_count_latch = 0; + + m_ppu->set_scanline_callback(*this, FUNC(playch10_state::gboard_scanline_cb)); +} + +void playch10_state::init_pcgboard_type2() +{ + // common init + init_pcgboard(); + + // enable 4 screen mirroring + // 2K on the cart board, in addition to the 2K on the main board + m_cart_nt_ram = std::make_unique(0x800); + m_mirroring = PPU_MIRROR_4SCREEN; +} + +//********************************************************************************** +// H Board games (PinBot) + +void playch10_state::hboard_rom_switch_w(offs_t offset, u8 data) +{ + switch (offset & 0x6001) + { + case 0x0001: + { + u8 cmd = m_gboard_command & 0x07; + int page = (m_gboard_command & 0x80) >> 5; + + switch (cmd) + { + case 0: // char banking + case 1: // char banking + data &= 0xfe; + page ^= (cmd << 1); + if (data & 0x40) + set_videoram_bank(page, 2, data, 1); + else + pc10_set_videorom_bank(page, 2, data, 1); + return; + + case 2: // char banking + case 3: // char banking + case 4: // char banking + case 5: // char banking + page ^= cmd + 2; + if (data & 0x40) + set_videoram_bank(page, 1, data, 1); + else + pc10_set_videorom_bank(page, 1, data, 1); + return; + } + } + } + + gboard_rom_switch_w(offset,data); +} + +void playch10_state::init_pchboard() +{ + // common init + init_pcgboard(); + + // allocate vram + m_vram = std::make_unique(0x2000); +} + +//********************************************************************************** +// i Board games (Captain Sky Hawk, Solar Jetman) + +void playch10_state::iboard_rom_switch_w(u8 data) +{ + prg32(data); + + pc10_set_mirroring(BIT(data, 4) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW); +} + +void playch10_state::init_pciboard() +{ + // point program banks to last 32K + init_prg_banking(); + + m_mirroring = PPU_MIRROR_LOW; + + // allocate vram + m_vram = std::make_unique(0x2000); +} + +//********************************************************************************** +// K Board games (Mario Open Golf) + +void playch10_state::init_pckboard() +{ + // later board but similar to D boards, i.e. MMC1 + 8K VRAM + init_pcdboard(); +} + + //****************************************************************************** // BIOS @@ -933,7 +2064,7 @@ void playch10_state::playch10_k(machine_config &config) ROM_LOAD_BIOS( 3, "pch1-c__8m_e-1.8m", 0x02000, 0x2000, CRC(c1232eee) SHA1(beaf9fa2d091a3c7f70c51e966d885b1f9f0935f) ) \ ROM_LOAD_BIOS( 3, "pch1-c__8p_e-1.8p", 0x04000, 0x2000, CRC(30c15e23) SHA1(69166afdb2fe827c7f1919cdf4197caccbd961fa) ) \ \ - ROM_REGION( 0x0300, "proms", 0 ) \ + ROM_REGION( 0x0300, "proms", ROMREGION_INVERT ) \ ROM_LOAD( "pch1-c-6f.82s129an.6f", 0x0000, 0x0100, CRC(e5414ca3) SHA1(d2878411cda84ffe0afb2e538a67457f51bebffb) ) \ ROM_LOAD( "pch1-c-6e.82s129an.6e", 0x0100, 0x0100, CRC(a2625c6e) SHA1(a448b47c9289902e26a3d3c4c7d5a7968c385e81) ) \ ROM_LOAD( "pch1-c-6d.82s129an.6d", 0x0200, 0x0100, CRC(1213ebd4) SHA1(0ad386fc3eab5e53c0288ad1de33639a9e461b7c) ) \ @@ -1836,6 +2967,8 @@ ROM_START( playch10 ) ROM_REGION( 0x10000, "prg", ROMREGION_ERASE00 ) ROM_END +} // anonymous namespace + /******************************************************************************/ @@ -1859,7 +2992,7 @@ GAME( 1984, pc_golf, playch10, playch10, playch10, playch10_state, init_pc_hr GAME( 1985, pc_kngfu, playch10, playch10, playch10, playch10_state, init_playch10, ROT0, "Irem (Nintendo license)", "Kung Fu (PlayChoice-10)", 0 ) GAME( 1985, pc_smb, playch10, playch10, playch10, playch10_state, init_playch10, ROT0, "Nintendo", "Super Mario Bros. (PlayChoice-10)", 0 ) GAME( 1986, pc_vball, playch10, playch10, playch10, playch10_state, init_playch10, ROT0, "Nintendo", "Volley Ball (PlayChoice-10)", 0 ) -GAME( 1987, pc_1942, playch10, playch10, playch10, playch10_state, init_pc_hrz, ROT0, "Capcom", "1942 (PlayChoice-10)", MACHINE_IMPERFECT_GRAPHICS ) +GAME( 1987, pc_1942, playch10, playch10, playch10, playch10_state, init_pc_hrz, ROT0, "Capcom", "1942 (PlayChoice-10)", 0 ) // Gun Games GAME( 1984, pc_duckh, playch10, playch10, playc10g, playch10_state, init_pc_gun, ROT0, "Nintendo", "Duck Hunt (PlayChoice-10)", 0 ) diff --git a/src/mame/nintendo/playch10.h b/src/mame/nintendo/playch10.h deleted file mode 100644 index 4ffb240bc49..00000000000 --- a/src/mame/nintendo/playch10.h +++ /dev/null @@ -1,197 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ernesto Corvi,Brad Oliver -#ifndef MAME_INCLUDES_PLAYCH10_H -#define MAME_INCLUDES_PLAYCH10_H - -#pragma once - -#include "bus/nes_ctrl/zapper_sensor.h" -#include "cpu/m6502/n2a03.h" -#include "machine/rp5h01.h" -#include "video/ppu2c0x.h" -#include "emupal.h" -#include "tilemap.h" - -class playch10_state : public driver_device -{ -public: - playch10_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag) - , m_maincpu(*this, "maincpu") - , m_cartcpu(*this, "cart") - , m_ppu(*this, "ppu") - , m_rp5h01(*this, "rp5h01") - , m_ram_8w(*this, "ram_8w") - , m_videoram(*this, "videoram") - , m_gfxdecode(*this, "gfxdecode") - , m_sensor(*this, "sensor") - , m_nt_page(*this, "nt_page%u", 0U) - , m_prg_banks(*this, "prg%u", 0U) - , m_prg_view(*this, "prg_view") - , m_vrom_region(*this, "gfx2") - , m_timedigits(*this, "digit_%u", 0U) - { - } - - void playch10(machine_config &config); - void playch10_a(machine_config &config); - void playch10_b(machine_config &config); - void playch10_c(machine_config &config); - void playch10_d(machine_config &config); - void playch10_d2(machine_config &config); - void playch10_e(machine_config &config); - void playch10_f(machine_config &config); - void playch10_f2(machine_config &config); - void playch10_g(machine_config &config); - void playch10_h(machine_config &config); - void playch10_i(machine_config &config); - void playch10_k(machine_config &config); - - void init_playch10(); - void init_pc_gun(); - void init_pcaboard(); - void init_pcbboard(); - void init_pccboard(); - void init_pcdboard(); - void init_pceboard(); - void init_pcfboard(); - void init_pcgboard(); - void init_pcgboard_type2(); - void init_pchboard(); - void init_pciboard(); - void init_pckboard(); - void init_pc_hrz(); - - DECLARE_READ_LINE_MEMBER(int_detect_r); - -private: - DECLARE_WRITE_LINE_MEMBER(up8w_w); - uint8_t ram_8w_r(offs_t offset); - void ram_8w_w(offs_t offset, uint8_t data); - void sprite_dma_w(address_space &space, uint8_t data); - void time_w(offs_t offset, uint8_t data); - DECLARE_WRITE_LINE_MEMBER(sdcs_w); - DECLARE_WRITE_LINE_MEMBER(cntrl_mask_w); - DECLARE_WRITE_LINE_MEMBER(disp_mask_w); - DECLARE_WRITE_LINE_MEMBER(sound_mask_w); - DECLARE_WRITE_LINE_MEMBER(nmi_enable_w); - DECLARE_WRITE_LINE_MEMBER(dog_di_w); - DECLARE_WRITE_LINE_MEMBER(ppu_reset_w); - uint8_t pc10_detectclr_r(); - void cart_sel_w(uint8_t data); - uint8_t pc10_prot_r(); - void pc10_prot_w(uint8_t data); - void pc10_in0_w(uint8_t data); - uint8_t pc10_in0_r(); - uint8_t pc10_in1_r(); - void pc10_chr_w(offs_t offset, uint8_t data); - uint8_t pc10_chr_r(offs_t offset); - void mmc1_rom_switch_w(offs_t offset, uint8_t data); - void aboard_vrom_switch_w(uint8_t data); - void bboard_rom_switch_w(uint8_t data); - void cboard_vrom_switch_w(uint8_t data); - void eboard_rom_switch_w(offs_t offset, uint8_t data); - void gboard_rom_switch_w(offs_t offset, uint8_t data); - void hboard_rom_switch_w(offs_t offset, uint8_t data); - void iboard_rom_switch_w(uint8_t data); - void playch10_videoram_w(offs_t offset, uint8_t data); - - TILE_GET_INFO_MEMBER(get_bg_tile_info); - - void bios_io_map(address_map &map); - void bios_map(address_map &map); - void ppu_map(address_map &map); - void cart_map(address_map &map); - void cart_a_map(address_map &map); - void cart_b_map(address_map &map); - void cart_c_map(address_map &map); - void cart_d_map(address_map &map); - void cart_d2_map(address_map &map); - void cart_e_map(address_map &map); - void cart_f_map(address_map &map); - void cart_f2_map(address_map &map); - void cart_g_map(address_map &map); - void cart_h_map(address_map &map); - void cart_i_map(address_map &map); - void cart_k_map(address_map &map); - - virtual void machine_start() override; - virtual void machine_reset() override; - virtual void video_start() override; - - struct chr_bank - { - int writable = 0; // 1 for RAM, 0 for ROM - uint8_t* chr = nullptr; // direct access to the memory - }; - - void playch10_palette(palette_device &palette) const; - DECLARE_WRITE_LINE_MEMBER(vblank_irq); - - void pc10_set_videorom_bank(int first, int count, int bank, int size); - void set_videoram_bank(int first, int count, int bank, int size); - void gboard_scanline_cb(int scanline, bool vblank, bool blanked); - DECLARE_WRITE_LINE_MEMBER(int_detect_w); - void mapper9_latch(offs_t offset); - void pc10_set_mirroring(int mirroring); - - uint32_t screen_update_playch10_top(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - uint32_t screen_update_playch10_bottom(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - uint32_t screen_update_playch10_single(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - - required_device m_maincpu; - required_device m_cartcpu; - required_device m_ppu; - optional_device m_rp5h01; - - required_shared_ptr m_ram_8w; - required_shared_ptr m_videoram; - required_device m_gfxdecode; - required_device m_sensor; - - required_memory_bank_array<4> m_nt_page; - std::unique_ptr m_nt_ram; - std::unique_ptr m_cart_nt_ram; - - void init_prg_banking(); - void prg32(int bank); - void prg16(int slot, int bank); - void prg8(int slot, int bank); - memory_bank_array_creator<4> m_prg_banks; - memory_view m_prg_view; - int m_prg_chunks = 0; - - optional_memory_region m_vrom_region; - - output_finder<4> m_timedigits; - - int m_up_8w = 0; - int m_pc10_nmi_enable = 0; - int m_pc10_dog_di = 0; - int m_pc10_sdcs = 0; - int m_pc10_dispmask = 0; - int m_pc10_int_detect = 0; - int m_pc10_game_mode = 0; - int m_pc10_dispmask_old = 0; - int m_pc10_gun_controller = 0; - int m_cart_sel = 0; - int m_cntrl_mask = 0; - int m_input_latch[2]{}; - int m_mirroring = 0; - int m_MMC2_bank[4]{}; - int m_MMC2_bank_latch[2]{}; - uint8_t* m_vrom = nullptr; - std::unique_ptr m_vram; - chr_bank m_chr_page[8]; - int m_mmc1_shiftreg = 0; - int m_mmc1_shiftcount = 0; - int m_gboard_banks[2]{}; - int m_gboard_command = 0; - int m_IRQ_count = 0; - uint8_t m_IRQ_count_latch = 0; - int m_IRQ_enable = 0; - int m_pc10_bios = 0; - tilemap_t *m_bg_tilemap = nullptr; -}; - -#endif // MAME_INCLUDES_PLAYCH10_H diff --git a/src/mame/nintendo/playch10_m.cpp b/src/mame/nintendo/playch10_m.cpp deleted file mode 100644 index eaea15a1708..00000000000 --- a/src/mame/nintendo/playch10_m.cpp +++ /dev/null @@ -1,862 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ernesto Corvi,Brad Oliver - -#include "emu.h" -#include "screen.h" -#include "playch10.h" - -#include "video/ppu2c0x.h" - - -/************************************* - * - * Init machine - * - *************************************/ - -void playch10_state::machine_reset() -{ - m_pc10_int_detect = 0; - - m_pc10_game_mode = 0; - m_pc10_dispmask_old = 0; - - m_input_latch[0] = m_input_latch[1] = 0; - - /* variables used only in MMC2 game (mapper 9) */ - m_MMC2_bank[0] = m_MMC2_bank[1] = m_MMC2_bank[2] = m_MMC2_bank[3] = 0; - m_MMC2_bank_latch[0] = m_MMC2_bank_latch[1] = 0xfe; - - /* reset the security chip */ - m_rp5h01->enable_w(1); - m_rp5h01->enable_w(0); - m_rp5h01->reset_w(0); - m_rp5h01->reset_w(1); - - pc10_set_mirroring(m_mirroring); -} - -void playch10_state::machine_start() -{ - m_timedigits.resolve(); - - m_vrom = (m_vrom_region != nullptr) ? m_vrom_region->base() : nullptr; - - // allocate 2K of nametable ram here - // this is on the main board and does not belong to the cart board - m_nt_ram = std::make_unique(0x800); - - for (int i = 0; i < 4; i++) - if (m_cart_nt_ram != nullptr && i >= 2) // extra cart RAM for 4 screen mirroring - m_nt_page[i]->configure_entries(0, 2, m_cart_nt_ram.get(), 0x400); - else - m_nt_page[i]->configure_entries(0, 2, m_nt_ram.get(), 0x400); - - if (m_vram != nullptr) - set_videoram_bank(0, 8, 0, 8); - else - pc10_set_videorom_bank(0, 8, 0, 8); -} - -/************************************* - * - * BIOS ports handling - * - *************************************/ - -READ_LINE_MEMBER(playch10_state::int_detect_r) -{ - return ~m_pc10_int_detect & 1; -} - -WRITE_LINE_MEMBER(playch10_state::sdcs_w) -{ - /* - Hooked to CLR on LS194A - Sheet 2, bottom left. - Drives character and color code to 0. - It's used to keep the screen black during redraws. - Also hooked to the video sram. Prevent writes. - */ - m_pc10_sdcs = !state; -} - -WRITE_LINE_MEMBER(playch10_state::cntrl_mask_w) -{ - m_cntrl_mask = !state; -} - -WRITE_LINE_MEMBER(playch10_state::disp_mask_w) -{ - m_pc10_dispmask = !state; -} - -WRITE_LINE_MEMBER(playch10_state::sound_mask_w) -{ - machine().sound().system_mute(!state); -} - -WRITE_LINE_MEMBER(playch10_state::nmi_enable_w) -{ - m_pc10_nmi_enable = state; -} - -WRITE_LINE_MEMBER(playch10_state::dog_di_w) -{ - m_pc10_dog_di = state; -} - -WRITE_LINE_MEMBER(playch10_state::ppu_reset_w) -{ - if (state) - m_ppu->reset(); -} - -uint8_t playch10_state::pc10_detectclr_r() -{ - m_pc10_int_detect = 0; - - return 0; -} - -void playch10_state::cart_sel_w(uint8_t data) -{ - m_cart_sel = data; -} - - -/************************************* - * - * RP5H01 handling - * - *************************************/ - -uint8_t playch10_state::pc10_prot_r() -{ - int data = 0xe7; - - /* we only support a single cart connected at slot 0 */ - if (m_cart_sel == 0) - { - data |= ((~m_rp5h01->counter_r()) << 4) & 0x10; /* D4 */ - data |= (m_rp5h01->data_r() << 3) & 0x08; /* D3 */ - } - return data; -} - -void playch10_state::pc10_prot_w(uint8_t data) -{ - /* we only support a single cart connected at slot 0 */ - if (m_cart_sel == 0) - { - m_rp5h01->test_w(data & 0x10); /* D4 */ - m_rp5h01->clock_w(data & 0x08); /* D3 */ - m_rp5h01->reset_w(~data & 0x01); /* D0 */ - } -} - -/************************************* - * - * Input Ports - * - *************************************/ - -void playch10_state::pc10_in0_w(uint8_t data) -{ - /* Toggling bit 0 high then low resets both controllers */ - if (data & 1) - return; - - /* load up the latches */ - m_input_latch[0] = ioport("P1")->read(); - m_input_latch[1] = ioport("P2")->read(); - - /* apply any masking from the BIOS */ - if (m_cntrl_mask) - { - /* mask out select and start */ - m_input_latch[0] &= ~0x0c; - } -} - -uint8_t playch10_state::pc10_in0_r() -{ - int ret = (m_input_latch[0]) & 1; - - /* shift */ - m_input_latch[0] >>= 1; - - /* some games expect bit 6 to be set because the last entry on the data bus shows up */ - /* in the unused upper 3 bits, so typically a read from $4016 leaves 0x40 there. */ - ret |= 0x40; - - return ret; -} - -uint8_t playch10_state::pc10_in1_r() -{ - int ret = m_input_latch[1] & 1; - - // shift - m_input_latch[1] >>= 1; - - // do the gun thing - if (m_pc10_gun_controller) - { - int trigger = ioport("P1")->read(); - - if (!m_sensor->detect_light(ioport("GUNX")->read(), ioport("GUNY")->read())) - ret |= 0x08; - - // now, add the trigger if not masked - if (!m_cntrl_mask) - ret |= (trigger & 2) << 3; - } - - // some games expect bit 6 to be set because the last entry on the data bus shows up - // in the unused upper 3 bits, so typically a read from $4016 leaves 0x40 there. - ret |= 0x40; - - return ret; -} -/************************************* - * - * PPU External bus handlers - * - *************************************/ - -void playch10_state::pc10_chr_w(offs_t offset, uint8_t data) -{ - int bank = offset >> 10; - if (m_chr_page[bank].writable) - { - m_chr_page[bank].chr[offset & 0x3ff] = data; - } -} - -uint8_t playch10_state::pc10_chr_r(offs_t offset) -{ - int bank = offset >> 10; - return m_chr_page[bank].chr[offset & 0x3ff]; -} - -void playch10_state::pc10_set_mirroring(int mirroring) -{ - switch (mirroring) - { - case PPU_MIRROR_LOW: - for (int i = 0; i < 4; i++) - m_nt_page[i]->set_entry(0); - break; - case PPU_MIRROR_HIGH: - for (int i = 0; i < 4; i++) - m_nt_page[i]->set_entry(1); - break; - case PPU_MIRROR_HORZ: - for (int i = 0; i < 4; i++) - m_nt_page[i]->set_entry(BIT(i, 1)); - break; - case PPU_MIRROR_VERT: - case PPU_MIRROR_4SCREEN: - default: - for (int i = 0; i < 4; i++) - m_nt_page[i]->set_entry(i & 1); - break; - } -} - -/* SIZE MAPPINGS *\ - * old new * - * 512 8 * - * 256 4 * - * 128 2 * - * 64 1 * -\*****************/ - -void playch10_state::pc10_set_videorom_bank(int first, int count, int bank, int size) -{ - int i, len; - /* first = first bank to map */ - /* count = number of 1K banks to map */ - /* bank = index of the bank */ - /* size = size of indexed banks (in KB) */ - /* note that this follows the original PPU banking and might be overly complex */ - - /* yeah, this is probably a horrible assumption to make.*/ - /* but the driver is 100% consistant */ - - if (memregion("gfx2")) // playch10 bios doesn't have gfx2 - len = memregion("gfx2")->bytes(); - else - len = memregion("gfx1")->bytes(); - - len /= 0x400; // convert to KB - len /= size; // convert to bank resolution - len--; // convert to mask - bank &= len; // should be the right mask - - for (i = 0; i < count; i++) - { - m_chr_page[i + first].writable = 0; - m_chr_page[i + first].chr = m_vrom + (i * 0x400) + (bank * size * 0x400); - } -} - -void playch10_state::set_videoram_bank(int first, int count, int bank, int size) -{ - int i; - /* first = first bank to map */ - /* count = number of 1K banks to map */ - /* bank = index of the bank */ - /* size = size of indexed banks (in KB) */ - /* note that this follows the original PPU banking and might be overly complex */ - - /* assumes 8K of vram */ - /* need 8K to fill address space */ - /* only pinbot (8k) banks at all */ - - for (i = 0; i < count; i++) - { - m_chr_page[i + first].writable = 1; - m_chr_page[i + first].chr = m_vram.get() + (((i * 0x400) + (bank * size * 0x400)) & 0x1fff); - } -} - -/************************************* - * - * Common init for all games - * - *************************************/ - -void playch10_state::init_playch10() -{ - m_vram = nullptr; - - // set the controller to default - m_pc10_gun_controller = 0; - - // default mirroring - m_mirroring = PPU_MIRROR_VERT; -} - -/********************************************************************************** - * - * Game and Board-specific initialization - * - **********************************************************************************/ - -// Gun games - -void playch10_state::init_pc_gun() -{ - // common init - init_playch10(); - - // set the control type - m_pc10_gun_controller = 1; -} - -// Horizontal mirroring - -void playch10_state::init_pc_hrz() -{ - // common init - init_playch10(); - - // setup mirroring - m_mirroring = PPU_MIRROR_HORZ; -} - -// Init for games that bank PRG memory - -void playch10_state::init_prg_banking() -{ - // common init - init_playch10(); - - u8 *base = memregion("prg")->base(); - m_prg_chunks = memregion("prg")->bytes() / 0x2000; - - for (int i = 0; i < 4; i++) - { - m_prg_banks[i]->configure_entries(0, m_prg_chunks, base, 0x2000); - m_prg_banks[i]->set_entry(m_prg_chunks - 4 + i); - } - - m_prg_view.select(0); -} - -// safe banking helpers (only work when PRG size is a power of 2) - -void playch10_state::prg32(int bank) -{ - bank = (bank << 2) & (m_prg_chunks - 1); - - for (int i = 0; i < 4; i++) - m_prg_banks[i]->set_entry(bank + i); -} - -void playch10_state::prg16(int slot, int bank) -{ - bank = (bank << 1) & (m_prg_chunks - 1); - slot = (slot & 1) << 1; - - for (int i = 0; i < 2; i++) - m_prg_banks[slot + i]->set_entry(bank + i); -} - -void playch10_state::prg8(int slot, int bank) -{ - m_prg_banks[slot & 0x03]->set_entry(bank & (m_prg_chunks - 1)); -} - -// MMC1 mapper, used by D, F, and K boards - -void playch10_state::mmc1_rom_switch_w(offs_t offset, uint8_t data) -{ - static int size16k, switchlow, vrom4k; - - /* reset mapper */ - if (data & 0x80) - { - m_mmc1_shiftreg = m_mmc1_shiftcount = 0; - - size16k = 1; - switchlow = 1; - vrom4k = 0; - - return; - } - - /* see if we need to clock in data */ - if (m_mmc1_shiftcount < 5) - { - m_mmc1_shiftreg >>= 1; - m_mmc1_shiftreg |= (data & 1) << 4; - m_mmc1_shiftcount++; - } - - /* are we done shifting? */ - if (m_mmc1_shiftcount == 5) - { - /* reset count */ - m_mmc1_shiftcount = 0; - - /* apply data to registers */ - switch (BIT(offset, 13, 2)) - { - case 0: /* mirroring and options */ - { - int _mirroring; - - vrom4k = m_mmc1_shiftreg & 0x10; - size16k = m_mmc1_shiftreg & 0x08; - switchlow = m_mmc1_shiftreg & 0x04; - - switch (m_mmc1_shiftreg & 3) - { - case 0: - _mirroring = PPU_MIRROR_LOW; - break; - - case 1: - _mirroring = PPU_MIRROR_HIGH; - break; - - case 2: - _mirroring = PPU_MIRROR_VERT; - break; - - default: - case 3: - _mirroring = PPU_MIRROR_HORZ; - break; - } - - /* apply mirroring */ - pc10_set_mirroring(_mirroring); - } - break; - - case 1: /* video rom banking - bank 0 - 4k or 8k */ - if (m_vram) - set_videoram_bank(0, (vrom4k) ? 4 : 8, (m_mmc1_shiftreg & 0x1f), 4); - else - pc10_set_videorom_bank(0, (vrom4k) ? 4 : 8, (m_mmc1_shiftreg & 0x1f), 4); - break; - - case 2: /* video rom banking - bank 1 - 4k only */ - if (vrom4k) - { - if (m_vram) - set_videoram_bank(0, (vrom4k) ? 4 : 8, (m_mmc1_shiftreg & 0x1f), 4); - else - pc10_set_videorom_bank(4, 4, (m_mmc1_shiftreg & 0x1f), 4); - } - break; - - case 3: /* program banking */ - if (size16k) - prg16(!switchlow, m_mmc1_shiftreg); - else - prg32(m_mmc1_shiftreg >> 1); - break; - } - } -} - -//********************************************************************************** -// A Board games (Track & Field, Gradius) - -void playch10_state::aboard_vrom_switch_w(uint8_t data) -{ - pc10_set_videorom_bank(0, 8, (data & 3), 8); -} - -void playch10_state::init_pcaboard() -{ - // common init - init_playch10(); -} - -//********************************************************************************** -// B Board games (Contra, Rush N' Attach, Pro Wrestling) - -void playch10_state::bboard_rom_switch_w(uint8_t data) -{ - prg16(0, data); -} - -void playch10_state::init_pcbboard() -{ - // point program banks to last 32K - init_prg_banking(); - - // allocate vram - m_vram = std::make_unique(0x2000); -} - -//********************************************************************************** -// C Board games (The Goonies) - -void playch10_state::cboard_vrom_switch_w(uint8_t data) -{ - pc10_set_videorom_bank(0, 8, BIT(data, 1), 8); -} - -void playch10_state::init_pccboard() -{ - // common init - init_playch10(); -} - -//********************************************************************************** -// D Board games (Rad Racer, Metroid) - -void playch10_state::init_pcdboard() -{ - // point program banks to last 32K - init_prg_banking(); - - // allocate vram - m_vram = std::make_unique(0x2000); -} - -//********************************************************************************** -// E Board (MMC2) games (Mike Tyson's Punchout) - -// callback for the ppu_latch -void playch10_state::mapper9_latch(offs_t offset) -{ - if((offset & 0x1ff0) == 0x0fd0 && m_MMC2_bank_latch[0] != 0xfd) - { - m_MMC2_bank_latch[0] = 0xfd; - pc10_set_videorom_bank(0, 4, m_MMC2_bank[0], 4); - } - else if((offset & 0x1ff0) == 0x0fe0 && m_MMC2_bank_latch[0] != 0xfe) - { - m_MMC2_bank_latch[0] = 0xfe; - pc10_set_videorom_bank(0, 4, m_MMC2_bank[1], 4); - } - else if((offset & 0x1ff0) == 0x1fd0 && m_MMC2_bank_latch[1] != 0xfd) - { - m_MMC2_bank_latch[1] = 0xfd; - pc10_set_videorom_bank(4, 4, m_MMC2_bank[2], 4); - } - else if((offset & 0x1ff0) == 0x1fe0 && m_MMC2_bank_latch[1] != 0xfe) - { - m_MMC2_bank_latch[1] = 0xfe; - pc10_set_videorom_bank(4, 4, m_MMC2_bank[3], 4); - } -} - -void playch10_state::eboard_rom_switch_w(offs_t offset, uint8_t data) -{ - /* a variation of mapper 9 on a nes */ - switch (offset & 0x7000) - { - case 0x2000: /* code bank switching */ - prg8(0, data); - break; - - case 0x3000: /* gfx bank 0 - 4k */ - m_MMC2_bank[0] = data; - if (m_MMC2_bank_latch[0] == 0xfd) - pc10_set_videorom_bank(0, 4, data, 4); - break; - - case 0x4000: /* gfx bank 0 - 4k */ - m_MMC2_bank[1] = data; - if (m_MMC2_bank_latch[0] == 0xfe) - pc10_set_videorom_bank(0, 4, data, 4); - break; - - case 0x5000: /* gfx bank 1 - 4k */ - m_MMC2_bank[2] = data; - if (m_MMC2_bank_latch[1] == 0xfd) - pc10_set_videorom_bank(4, 4, data, 4); - break; - - case 0x6000: /* gfx bank 1 - 4k */ - m_MMC2_bank[3] = data; - if (m_MMC2_bank_latch[1] == 0xfe) - pc10_set_videorom_bank(4, 4, data, 4); - break; - - case 0x7000: /* mirroring */ - pc10_set_mirroring(data & 1 ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT); - - break; - } -} - -void playch10_state::init_pceboard() -{ - // point program banks to last 32K - init_prg_banking(); - - // ppu_latch callback - m_ppu->set_latch(*this, FUNC(playch10_state::mapper9_latch)); -} - -//********************************************************************************** -// F Board games (Ninja Gaiden, Double Dragon) - -void playch10_state::init_pcfboard() -{ - // point program banks to last 32K - init_prg_banking(); -} - -//********************************************************************************** -// G Board (MMC3) games (Super Mario Bros. 3, etc) - -void playch10_state::gboard_scanline_cb(int scanline, bool vblank, bool blanked) -{ - if (scanline < ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE) - { - int priorCount = m_IRQ_count; - if (m_IRQ_count == 0) - m_IRQ_count = m_IRQ_count_latch; - else - m_IRQ_count--; - - if (m_IRQ_enable && !blanked && (m_IRQ_count == 0) && priorCount) // according to blargg the latter should be present as well, but it breaks Rampart and Joe & Mac US: they probably use the alt irq! - { - m_cartcpu->set_input_line(0, ASSERT_LINE); - } - } -} - -void playch10_state::gboard_rom_switch_w(offs_t offset, uint8_t data) -{ - switch (offset & 0x6001) - { - case 0x0000: - m_gboard_command = data; - { - // reset the flippable banks - int flip = BIT(m_gboard_command, 6) << 1; - prg8(0 ^ flip, m_gboard_banks[0]); - prg8(2 ^ flip, m_prg_chunks - 2); - } - break; - - case 0x0001: - { - uint8_t cmd = m_gboard_command & 0x07; - int page = (m_gboard_command & 0x80) >> 5; - - switch (cmd) - { - case 0: /* char banking */ - case 1: /* char banking */ - data &= 0xfe; - page ^= (cmd << 1); - pc10_set_videorom_bank(page, 2, data, 1); - break; - - case 2: /* char banking */ - case 3: /* char banking */ - case 4: /* char banking */ - case 5: /* char banking */ - page ^= cmd + 2; - pc10_set_videorom_bank(page, 1, data, 1); - break; - - case 6: /* program banking */ - { - m_gboard_banks[0] = data; - - int flip = BIT(m_gboard_command, 6) << 1; - prg8(0 ^ flip, m_gboard_banks[0]); - prg8(2 ^ flip, m_prg_chunks - 2); - } - break; - - case 7: // program banking - mid bank - m_gboard_banks[1] = data; - prg8(1, m_gboard_banks[1]); - break; - } - } - break; - - case 0x2000: /* mirroring */ - if (m_mirroring != PPU_MIRROR_4SCREEN) - pc10_set_mirroring((data & 1) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT); - break; - - case 0x2001: /* enable ram at $6000 */ - /* ignored - we always enable it */ - break; - - case 0x4000: /* scanline counter */ - m_IRQ_count_latch = data; - break; - - case 0x4001: /* scanline latch */ - m_IRQ_count = 0; - break; - - case 0x6000: /* disable irqs */ - m_IRQ_enable = 0; - m_cartcpu->set_input_line(0, CLEAR_LINE); - break; - - case 0x6001: /* enable irqs */ - m_IRQ_enable = 1; - break; - } -} - -void playch10_state::init_pcgboard() -{ - // point program banks to last 32K - init_prg_banking(); - - m_gboard_banks[0] = 0x1e; - m_gboard_banks[1] = 0x1f; - m_gboard_command = 0; - m_IRQ_enable = 0; - m_IRQ_count = m_IRQ_count_latch = 0; - - m_ppu->set_scanline_callback(*this, FUNC(playch10_state::gboard_scanline_cb)); -} - -void playch10_state::init_pcgboard_type2() -{ - // common init - init_pcgboard(); - - // enable 4 screen mirroring - // 2K on the cart board, in addition to the 2K on the main board - m_cart_nt_ram = std::make_unique(0x800); - m_mirroring = PPU_MIRROR_4SCREEN; -} - -//********************************************************************************** -// H Board games (PinBot) - -void playch10_state::hboard_rom_switch_w(offs_t offset, uint8_t data) -{ - switch (offset & 0x7001) - { - case 0x0001: - { - uint8_t cmd = m_gboard_command & 0x07; - int page = (m_gboard_command & 0x80) >> 5; - - switch (cmd) - { - case 0: // char banking - case 1: // char banking - data &= 0xfe; - page ^= (cmd << 1); - if (data & 0x40) - { - set_videoram_bank(page, 2, data, 1); - } - else - { - pc10_set_videorom_bank(page, 2, data, 1); - } - return; - - case 2: // char banking - case 3: // char banking - case 4: // char banking - case 5: // char banking - page ^= cmd + 2; - if (data & 0x40) - { - set_videoram_bank(page, 1, data, 1); - } - else - { - pc10_set_videorom_bank(page, 1, data, 1); - } - return; - } - } - }; - gboard_rom_switch_w(offset,data); -} - -void playch10_state::init_pchboard() -{ - // common init - init_pcgboard(); - - // allocate vram - m_vram = std::make_unique(0x2000); -} - -//********************************************************************************** -// i Board games (Captain Sky Hawk, Solar Jetman) - -void playch10_state::iboard_rom_switch_w(uint8_t data) -{ - prg32(data); - - pc10_set_mirroring(BIT(data, 4) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW); -} - -void playch10_state::init_pciboard() -{ - // point program banks to last 32K - init_prg_banking(); - - m_mirroring = PPU_MIRROR_LOW; - - // allocate vram - m_vram = std::make_unique(0x2000); -} - -//********************************************************************************** -// K Board games (Mario Open Golf) - -void playch10_state::init_pckboard() -{ - // later board but similar to D boards, i.e. MMC1 + 8K VRAM - init_pcdboard(); -} diff --git a/src/mame/nintendo/playch10_v.cpp b/src/mame/nintendo/playch10_v.cpp deleted file mode 100644 index 2b13085cda4..00000000000 --- a/src/mame/nintendo/playch10_v.cpp +++ /dev/null @@ -1,142 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ernesto Corvi,Brad Oliver -#include "emu.h" -#include "playch10.h" -#include "video/ppu2c0x.h" - -#include "screen.h" - - -void playch10_state::playch10_videoram_w(offs_t offset, uint8_t data) -{ - if (m_pc10_sdcs) - { - m_videoram[offset] = data; - m_bg_tilemap->mark_tile_dirty(offset / 2); - } -} - -void playch10_state::playch10_palette(palette_device &palette) const -{ - const uint8_t *color_prom = memregion("proms")->base(); - - for (int i = 0; i < 256; i++) - { - int bit0, bit1, bit2, bit3; - - // red component - bit0 = BIT(~color_prom[0], 0); - bit1 = BIT(~color_prom[0], 1); - bit2 = BIT(~color_prom[0], 2); - bit3 = BIT(~color_prom[0], 3); - - int const r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; - - // green component - bit0 = BIT(~color_prom[256], 0); - bit1 = BIT(~color_prom[256], 1); - bit2 = BIT(~color_prom[256], 2); - bit3 = BIT(~color_prom[256], 3); - - int const g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; - - // blue component - bit0 = BIT(~color_prom[2 * 256], 0); - bit1 = BIT(~color_prom[2 * 256], 1); - bit2 = BIT(~color_prom[2 * 256], 2); - bit3 = BIT(~color_prom[2 * 256], 3); - - int const b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3; - - palette.set_pen_color(i, rgb_t(r, g, b)); - - color_prom++; - } -} - -WRITE_LINE_MEMBER(playch10_state::int_detect_w) -{ - if (state) - m_pc10_int_detect = 1; -} - -TILE_GET_INFO_MEMBER(playch10_state::get_bg_tile_info) -{ - uint8_t *videoram = m_videoram; - int offs = tile_index * 2; - int code = videoram[offs] + ((videoram[offs + 1] & 0x07) << 8); - int color = (videoram[offs + 1] >> 3) & 0x1f; - - tileinfo.set(0, code, color, 0); -} - -void playch10_state::video_start() -{ - const uint8_t *bios = memregion("maincpu")->base(); - m_pc10_bios = (bios[3] == 0x2a) ? 1 : 2; - - m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(playch10_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, - 8, 8, 32, 32); -} - -/*************************************************************************** - - Display refresh - -***************************************************************************/ - -uint32_t playch10_state::screen_update_playch10_single(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - rectangle top_monitor = screen.visible_area(); - - top_monitor.max_y = (top_monitor.max_y - top_monitor.min_y) / 2; - - if (m_pc10_dispmask_old != m_pc10_dispmask) - { - m_pc10_dispmask_old = m_pc10_dispmask; - - if (m_pc10_dispmask) - m_pc10_game_mode ^= 1; - } - - if (m_pc10_game_mode) - /* render the ppu */ - m_ppu->render(bitmap, 0, 0, 0, 0, cliprect); - else - { - /* When the bios is accessing vram, the video circuitry can't access it */ - if (!m_pc10_sdcs) - m_bg_tilemap->draw(screen, bitmap, top_monitor, 0, 0); - } - return 0; -} - -uint32_t playch10_state::screen_update_playch10_top(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - /* Single Monitor version */ - if (m_pc10_bios != 1) - return screen_update_playch10_single(screen, bitmap, cliprect); - - /* When the bios is accessing vram, the video circuitry can't access it */ - if (!m_pc10_sdcs) - m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0); - else - bitmap.fill(0, cliprect); - - return 0; -} - -uint32_t playch10_state::screen_update_playch10_bottom(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - /* Single Monitor version */ - if (m_pc10_bios != 1) - return screen_update_playch10_single(screen, bitmap, cliprect); - - if (!m_pc10_dispmask) - /* render the ppu */ - m_ppu->render(bitmap, 0, 0, 0, 0, cliprect); - else - bitmap.fill(0, cliprect); - - return 0; -}