mirror of
https://github.com/holub/mame
synced 2025-04-20 15:32:45 +03:00
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.
This commit is contained in:
parent
41e1c7d3a2
commit
fe30addeaf
File diff suppressed because it is too large
Load Diff
@ -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<cpu_device> m_maincpu;
|
||||
required_device<n2a03_device> m_cartcpu;
|
||||
required_device<ppu2c0x_device> m_ppu;
|
||||
optional_device<rp5h01_device> m_rp5h01;
|
||||
|
||||
required_shared_ptr<uint8_t> m_ram_8w;
|
||||
required_shared_ptr<uint8_t> m_videoram;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<nes_zapper_sensor_device> m_sensor;
|
||||
|
||||
required_memory_bank_array<4> m_nt_page;
|
||||
std::unique_ptr<u8[]> m_nt_ram;
|
||||
std::unique_ptr<u8[]> 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<uint8_t[]> 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
|
@ -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<u8[]>(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<uint8_t[]>(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<uint8_t[]>(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<u8[]>(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<uint8_t[]>(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<uint8_t[]>(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();
|
||||
}
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user