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:
0kmg 2022-08-13 04:57:54 -08:00 committed by GitHub
parent 41e1c7d3a2
commit fe30addeaf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 1151 additions and 1219 deletions

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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