mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
vsnes.cpp: working sound + "improved" graphics in Vs. SMB bootleg sets (#7360)
* vsnes.cpp: Improvements to Vs SMB bootleg sets based on kevtris' schematics/video. * video/ppu2c0x.cpp: Add 2C04 PPU clone device and use the real palette ROMs for the bootlegs. * video/ppu2c0x.cpp: Implement most PPU behavior differences for VS System bootlegs. * video/ppu2c0x.cpp: add the 2c04 clone's delayed sprite rendering.
This commit is contained in:
parent
0ff27cf174
commit
58ef849d18
@ -35,15 +35,16 @@
|
||||
//**************************************************************************
|
||||
|
||||
// devices
|
||||
DEFINE_DEVICE_TYPE(PPU_2C02, ppu2c02_device, "ppu2c02", "2C02 PPU")
|
||||
DEFINE_DEVICE_TYPE(PPU_2C03B, ppu2c03b_device, "ppu2c03b", "2C03B PPC")
|
||||
DEFINE_DEVICE_TYPE(PPU_2C04, ppu2c04_device, "ppu2c04", "2C04 PPU")
|
||||
DEFINE_DEVICE_TYPE(PPU_2C07, ppu2c07_device, "ppu2c07", "2C07 PPU")
|
||||
DEFINE_DEVICE_TYPE(PPU_PALC, ppupalc_device, "ppupalc", "Generic PAL Clone PPU")
|
||||
DEFINE_DEVICE_TYPE(PPU_2C05_01, ppu2c05_01_device, "ppu2c05_01", "2C05_01 PPU")
|
||||
DEFINE_DEVICE_TYPE(PPU_2C05_02, ppu2c05_02_device, "ppu2c05_02", "2C05_02 PPU")
|
||||
DEFINE_DEVICE_TYPE(PPU_2C05_03, ppu2c05_03_device, "ppu2c05_03", "2C05_03 PPU")
|
||||
DEFINE_DEVICE_TYPE(PPU_2C05_04, ppu2c05_04_device, "ppu2c05_04", "2C05_04 PPU")
|
||||
DEFINE_DEVICE_TYPE(PPU_2C02, ppu2c02_device, "ppu2c02", "2C02 PPU")
|
||||
DEFINE_DEVICE_TYPE(PPU_2C03B, ppu2c03b_device, "ppu2c03b", "2C03B PPC")
|
||||
DEFINE_DEVICE_TYPE(PPU_2C04, ppu2c04_device, "ppu2c04", "2C04 PPU")
|
||||
DEFINE_DEVICE_TYPE(PPU_2C07, ppu2c07_device, "ppu2c07", "2C07 PPU")
|
||||
DEFINE_DEVICE_TYPE(PPU_PALC, ppupalc_device, "ppupalc", "Generic PAL Clone PPU")
|
||||
DEFINE_DEVICE_TYPE(PPU_2C05_01, ppu2c05_01_device, "ppu2c05_01", "2C05_01 PPU")
|
||||
DEFINE_DEVICE_TYPE(PPU_2C05_02, ppu2c05_02_device, "ppu2c05_02", "2C05_02 PPU")
|
||||
DEFINE_DEVICE_TYPE(PPU_2C05_03, ppu2c05_03_device, "ppu2c05_03", "2C05_03 PPU")
|
||||
DEFINE_DEVICE_TYPE(PPU_2C05_04, ppu2c05_04_device, "ppu2c05_04", "2C05_04 PPU")
|
||||
DEFINE_DEVICE_TYPE(PPU_2C04C, ppu2c04_clone_device, "ppu2c04c", "2C04 Clone PPU")
|
||||
|
||||
|
||||
// default address map
|
||||
@ -99,6 +100,7 @@ ppu2c0x_device::ppu2c0x_device(const machine_config& mconfig, device_type type,
|
||||
m_back_color(0),
|
||||
m_refresh_data(0),
|
||||
m_x_fine(0),
|
||||
m_toggle(0),
|
||||
m_tilecount(0),
|
||||
m_latch(*this),
|
||||
m_scanline_callback_proc(*this),
|
||||
@ -106,7 +108,6 @@ ppu2c0x_device::ppu2c0x_device(const machine_config& mconfig, device_type type,
|
||||
m_vidaccess_callback_proc(*this),
|
||||
m_int_callback(*this),
|
||||
m_refresh_latch(0),
|
||||
m_toggle(0),
|
||||
m_add(1),
|
||||
m_videomem_addr(0),
|
||||
m_data_latch(0),
|
||||
@ -197,6 +198,17 @@ ppu2c05_04_device::ppu2c05_04_device(const machine_config& mconfig, const char*
|
||||
m_security_value = 0x1b;
|
||||
}
|
||||
|
||||
// Vs. Unisystem (Super Mario Bros. bootlegs)
|
||||
ppu2c04_clone_device::ppu2c04_clone_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) :
|
||||
ppu2c0x_device(mconfig, PPU_2C04C, tag, owner, clock),
|
||||
m_palette_data(*this, "palette", 0x100)
|
||||
{
|
||||
m_scanlines_per_frame = VS_CLONE_SCANLINES_PER_FRAME;
|
||||
m_vblank_first_scanline = VBLANK_FIRST_SCANLINE_VS_CLONE;
|
||||
|
||||
// background and sprites are always enabled; monochrome and color emphasis aren't supported
|
||||
m_regs[PPU_CONTROL1] = ~(PPU_CONTROL1_COLOR_EMPHASIS | PPU_CONTROL1_DISPLAY_MONO);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
@ -259,6 +271,26 @@ void ppu2c0x_device::device_start()
|
||||
save_item(NAME(m_palette_ram));
|
||||
}
|
||||
|
||||
void ppu2c04_clone_device::device_start()
|
||||
{
|
||||
ppu2c0x_device::device_start();
|
||||
|
||||
/* this PPU clone draws sprites into a frame buffer before displaying them,
|
||||
causing sprite rendering to be one frame behind tile/background rendering
|
||||
(mainly noticeable during scrolling)
|
||||
to simulate that, we can just have a secondary OAM buffer and swap them
|
||||
at the end of each frame.
|
||||
|
||||
(theoretically this can cause the wrong sprite tiles to be drawn for
|
||||
one frame after changing CHR banks, but the Vs. SMB bootlegs that use
|
||||
this clone hardware don't actually have CHR bank switching anyway.
|
||||
also generally affects PPU-side read timings involving the OAM, but
|
||||
this still doesn't seem to matter for Vs. SMB specifically)
|
||||
*/
|
||||
m_spritebuf = make_unique_clear<uint8_t[]>(SPRITERAM_SIZE);
|
||||
save_pointer(NAME(m_spritebuf), SPRITERAM_SIZE);
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
// INLINE HELPERS
|
||||
//**************************************************************************
|
||||
@ -445,6 +477,24 @@ void ppu2c0x_rgb_device::init_palette_tables()
|
||||
}
|
||||
}
|
||||
|
||||
void ppu2c04_clone_device::init_palette_tables()
|
||||
{
|
||||
/* clone HW doesn't use color emphasis bits.
|
||||
however, it does have two separate palettes: colors 0-63 for background, and 64-127 for sprites
|
||||
(although the tile and sprite colors are identical in the Vs. SMB bootleg ROMs)
|
||||
*/
|
||||
for (int color_num = 0; color_num < 64*2; color_num++)
|
||||
{
|
||||
/* A7 line on palette ROMs is always high, color bits are in reverse order */
|
||||
u8 color = m_palette_data[color_num | 0x80];
|
||||
int R = bitswap<3>(color, 0, 1, 2);
|
||||
int G = bitswap<3>(color, 3, 4, 5);
|
||||
int B = bitswap<2>(color, 6, 7);
|
||||
|
||||
m_nespens[color_num] = (pal3bit(R) << 16) | (pal3bit(G) << 8) | pal2bit(B);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* PPU Initialization and Disposal
|
||||
@ -704,6 +754,15 @@ void ppu2c0x_device::draw_background(uint8_t* line_priority)
|
||||
}
|
||||
}
|
||||
|
||||
void ppu2c04_clone_device::draw_background(uint8_t* line_priority)
|
||||
{
|
||||
// nametable selection is ignored below the hardwired scroll split position
|
||||
if (m_scanline < 31)
|
||||
m_refresh_data &= ~0x0c00;
|
||||
|
||||
ppu2c0x_device::draw_background(line_priority);
|
||||
}
|
||||
|
||||
void ppu2c0x_device::draw_back_pen(uint32_t* dst, int back_pen)
|
||||
{
|
||||
*dst = m_nespens[back_pen];
|
||||
@ -757,6 +816,17 @@ void ppu2c0x_device::draw_sprite_pixel(int sprite_xpos, int color, int pixel, ui
|
||||
bitmap.pix(m_scanline, sprite_xpos + pixel) = pix;
|
||||
}
|
||||
|
||||
void ppu2c04_clone_device::draw_sprite_pixel(int sprite_xpos, int color, int pixel, uint8_t pixel_data, bitmap_rgb32 &bitmap)
|
||||
{
|
||||
/* clone PPU clips sprites at the screen edges */
|
||||
if ((sprite_xpos + pixel < 8) || (sprite_xpos + pixel) >= (VISIBLE_SCREEN_WIDTH - 6))
|
||||
return;
|
||||
|
||||
uint16_t palval = m_palette_ram[((4 * color) | pixel_data) & 0x1f];
|
||||
uint32_t pix = m_nespens[palval | 0x40];
|
||||
bitmap.pix(m_scanline, sprite_xpos + pixel) = pix;
|
||||
}
|
||||
|
||||
void ppu2c0x_device::read_extra_sprite_bits(int sprite_index)
|
||||
{
|
||||
// needed for some clones
|
||||
@ -953,6 +1023,19 @@ void ppu2c0x_device::draw_sprites(uint8_t* line_priority)
|
||||
}
|
||||
}
|
||||
|
||||
void ppu2c04_clone_device::draw_sprites(uint8_t *line_priority)
|
||||
{
|
||||
ppu2c0x_device::draw_sprites(line_priority);
|
||||
|
||||
if (m_scanline == BOTTOM_VISIBLE_SCANLINE)
|
||||
{
|
||||
/* this frame's sprite buffer is cleared after being displayed
|
||||
and the other one that was filled this frame will be displayed next frame */
|
||||
m_spriteram.swap(m_spritebuf);
|
||||
memset(m_spritebuf.get(), 0, SPRITERAM_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Scanline Rendering and Update
|
||||
@ -1185,6 +1268,23 @@ uint8_t ppu2c0x_device::read(offs_t offset)
|
||||
return m_data_latch;
|
||||
}
|
||||
|
||||
uint8_t ppu2c04_clone_device::read(offs_t offset)
|
||||
{
|
||||
switch (offset & 7)
|
||||
{
|
||||
case PPU_STATUS: /* 2 */
|
||||
// $2002 on this clone only contains the sprite 0 hit flag,
|
||||
// and it's hardwired to trigger after a specific scanline, not based on actual sprite positions
|
||||
if (m_scanline < 31 || m_scanline >= (m_vblank_first_scanline - 1))
|
||||
return ~PPU_STATUS_SPRITE0_HIT;
|
||||
return 0xff;
|
||||
|
||||
case PPU_SPRITE_DATA: /* 4 */
|
||||
return m_spritebuf[m_regs[PPU_SPRITE_ADDRESS]];
|
||||
}
|
||||
|
||||
return ppu2c0x_device::read(offset);
|
||||
}
|
||||
|
||||
/*************************************
|
||||
*
|
||||
@ -1324,6 +1424,49 @@ void ppu2c0x_device::write(offs_t offset, uint8_t data)
|
||||
m_data_latch = data;
|
||||
}
|
||||
|
||||
void ppu2c04_clone_device::write(offs_t offset, uint8_t data)
|
||||
{
|
||||
switch (offset & 7)
|
||||
{
|
||||
case PPU_CONTROL0: /* 0 */
|
||||
data &= (0x01 | PPU_CONTROL0_INC | PPU_CONTROL0_NMI); /* other bits of $2000 are ignored by this clone */
|
||||
data |= PPU_CONTROL0_CHR_SELECT;
|
||||
break;
|
||||
|
||||
case PPU_CONTROL1: /* 1 */
|
||||
case PPU_SPRITE_ADDRESS: /* 3 */
|
||||
return; /* $2001 and $2003 do nothing on this clone */
|
||||
|
||||
case PPU_SPRITE_DATA: /* 4 */
|
||||
m_spritebuf[m_regs[PPU_SPRITE_ADDRESS]] = data;
|
||||
m_regs[PPU_SPRITE_ADDRESS] = (m_regs[PPU_SPRITE_ADDRESS] + 1) & 0xff;
|
||||
return;
|
||||
|
||||
case PPU_SCROLL: /* 5 */
|
||||
if (m_toggle)
|
||||
data = 0; /* no vertical scroll */
|
||||
break;
|
||||
|
||||
case PPU_ADDRESS: /* 6 */
|
||||
/* $2006 doesn't affect scroll latching */
|
||||
if (m_toggle)
|
||||
{
|
||||
/* second write */
|
||||
set_vram_dest((get_vram_dest() & 0xff00) | data);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* first write */
|
||||
set_vram_dest((get_vram_dest() & 0x00ff) | (data << 8));
|
||||
}
|
||||
|
||||
m_toggle ^= 1;
|
||||
return;
|
||||
}
|
||||
|
||||
ppu2c0x_device::write(offset, data);
|
||||
}
|
||||
|
||||
uint16_t ppu2c0x_device::get_vram_dest()
|
||||
{
|
||||
return m_videomem_addr;
|
||||
|
@ -53,14 +53,17 @@ public:
|
||||
|
||||
enum
|
||||
{
|
||||
NTSC_SCANLINES_PER_FRAME = 262,
|
||||
PAL_SCANLINES_PER_FRAME = 312,
|
||||
NTSC_SCANLINES_PER_FRAME = 262,
|
||||
PAL_SCANLINES_PER_FRAME = 312,
|
||||
VS_CLONE_SCANLINES_PER_FRAME = 280,
|
||||
|
||||
BOTTOM_VISIBLE_SCANLINE = 239,
|
||||
VBLANK_FIRST_SCANLINE = 241,
|
||||
VBLANK_FIRST_SCANLINE_PALC = 291,
|
||||
VBLANK_LAST_SCANLINE_NTSC = 260,
|
||||
VBLANK_LAST_SCANLINE_PAL = 310
|
||||
BOTTOM_VISIBLE_SCANLINE = 239,
|
||||
VBLANK_FIRST_SCANLINE = 241,
|
||||
VBLANK_FIRST_SCANLINE_PALC = 291,
|
||||
VBLANK_FIRST_SCANLINE_VS_CLONE = 240,
|
||||
VBLANK_LAST_SCANLINE_NTSC = 260,
|
||||
VBLANK_LAST_SCANLINE_PAL = 310,
|
||||
VBLANK_LAST_SCANLINE_VS_CLONE = 279
|
||||
|
||||
// Both the scanline immediately before and immediately after VBLANK
|
||||
// are non-rendering and non-vblank.
|
||||
@ -207,6 +210,7 @@ protected:
|
||||
int m_back_color; /* background color */
|
||||
int m_refresh_data; /* refresh-related */
|
||||
int m_x_fine; /* refresh-related */
|
||||
int m_toggle; /* used to latch hi-lo scroll */
|
||||
int m_tilecount; /* MMC5 can change attributes to subsets of the 34 visible tiles */
|
||||
latch_delegate m_latch;
|
||||
|
||||
@ -228,7 +232,6 @@ private:
|
||||
devcb_write_line m_int_callback; /* nmi access callback from interface */
|
||||
|
||||
int m_refresh_latch; /* refresh-related */
|
||||
int m_toggle; /* used to latch hi-lo scroll */
|
||||
int m_add; /* vram increment amount */
|
||||
int m_videomem_addr; /* videomem address pointer */
|
||||
int m_data_latch; /* latched videomem data */
|
||||
@ -300,17 +303,39 @@ public:
|
||||
ppu2c05_04_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
|
||||
};
|
||||
|
||||
class ppu2c04_clone_device : public ppu2c0x_device {
|
||||
public:
|
||||
ppu2c04_clone_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
|
||||
|
||||
virtual uint8_t read(offs_t offset) override;
|
||||
virtual void write(offs_t offset, uint8_t data) override;
|
||||
|
||||
virtual void draw_background(uint8_t *line_priority) override;
|
||||
virtual void draw_sprite_pixel(int sprite_xpos, int color, int pixel, uint8_t pixel_data, bitmap_rgb32 &bitmap) override;
|
||||
virtual void draw_sprites(uint8_t *line_priority) override;
|
||||
|
||||
virtual void init_palette_tables() override;
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
|
||||
private:
|
||||
required_region_ptr<uint8_t> m_palette_data;
|
||||
|
||||
std::unique_ptr<uint8_t[]> m_spritebuf; /* buffered sprite ram for next frame */
|
||||
};
|
||||
|
||||
// device type definition
|
||||
//extern const device_type PPU_2C0X;
|
||||
DECLARE_DEVICE_TYPE(PPU_2C02, ppu2c02_device) // NTSC NES
|
||||
DECLARE_DEVICE_TYPE(PPU_2C03B, ppu2c03b_device) // Playchoice 10
|
||||
DECLARE_DEVICE_TYPE(PPU_2C04, ppu2c04_device) // Vs. Unisystem
|
||||
DECLARE_DEVICE_TYPE(PPU_2C07, ppu2c07_device) // PAL NES
|
||||
DECLARE_DEVICE_TYPE(PPU_PALC, ppupalc_device) // PAL Clones
|
||||
DECLARE_DEVICE_TYPE(PPU_2C05_01, ppu2c05_01_device) // Vs. Unisystem (Ninja Jajamaru Kun)
|
||||
DECLARE_DEVICE_TYPE(PPU_2C05_02, ppu2c05_02_device) // Vs. Unisystem (Mighty Bomb Jack)
|
||||
DECLARE_DEVICE_TYPE(PPU_2C05_03, ppu2c05_03_device) // Vs. Unisystem (Gumshoe)
|
||||
DECLARE_DEVICE_TYPE(PPU_2C05_04, ppu2c05_04_device) // Vs. Unisystem (Top Gun)
|
||||
DECLARE_DEVICE_TYPE(PPU_2C02, ppu2c02_device) // NTSC NES
|
||||
DECLARE_DEVICE_TYPE(PPU_2C03B, ppu2c03b_device) // Playchoice 10
|
||||
DECLARE_DEVICE_TYPE(PPU_2C04, ppu2c04_device) // Vs. Unisystem
|
||||
DECLARE_DEVICE_TYPE(PPU_2C07, ppu2c07_device) // PAL NES
|
||||
DECLARE_DEVICE_TYPE(PPU_PALC, ppupalc_device) // PAL Clones
|
||||
DECLARE_DEVICE_TYPE(PPU_2C05_01, ppu2c05_01_device) // Vs. Unisystem (Ninja Jajamaru Kun)
|
||||
DECLARE_DEVICE_TYPE(PPU_2C05_02, ppu2c05_02_device) // Vs. Unisystem (Mighty Bomb Jack)
|
||||
DECLARE_DEVICE_TYPE(PPU_2C05_03, ppu2c05_03_device) // Vs. Unisystem (Gumshoe)
|
||||
DECLARE_DEVICE_TYPE(PPU_2C05_04, ppu2c05_04_device) // Vs. Unisystem (Top Gun)
|
||||
DECLARE_DEVICE_TYPE(PPU_2C04C, ppu2c04_clone_device) // Vs. Unisystem (Super Mario Bros. bootlegs)
|
||||
|
||||
#endif // MAME_VIDEO_PPU2C0X_H
|
||||
|
@ -221,16 +221,17 @@ void vsnes_state::vsnes_cpu2_map(address_map &map)
|
||||
|
||||
|
||||
|
||||
uint8_t vsnes_state::vsnes_bootleg_z80_address_r()
|
||||
uint8_t vsnes_state::vsnes_bootleg_z80_address_r(offs_t offset)
|
||||
{
|
||||
// NMI routine uses the value read here as the low part of an offset from 0x2000 to store a value read at 0x4000
|
||||
// before reading 0x6000 and returning
|
||||
if (!(offset & 1))
|
||||
{
|
||||
m_subcpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
|
||||
m_maincpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
|
||||
}
|
||||
|
||||
// can't really see how to get sound this way tho, maybe the unused rom is acting as lookup table to convert
|
||||
// PSG write offsets to addresses to offsets for use here?
|
||||
//printf("Z80 read offs %x\n", m_bootleg_sound_offset);
|
||||
m_subcpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
|
||||
return m_bootleg_sound_offset;
|
||||
return 0xf0 | m_bootleg_sound_offset;
|
||||
}
|
||||
|
||||
void vsnes_state::bootleg_sound_write(offs_t offset, uint8_t data)
|
||||
@ -238,12 +239,15 @@ void vsnes_state::bootleg_sound_write(offs_t offset, uint8_t data)
|
||||
m_bootleg_sound_offset = offset & 0xf;
|
||||
m_bootleg_sound_data = data;
|
||||
m_subcpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE);
|
||||
m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
|
||||
}
|
||||
|
||||
uint8_t vsnes_state::vsnes_bootleg_z80_data_r()
|
||||
{
|
||||
//printf("Z80 read data %02x\n", m_bootleg_sound_data);
|
||||
m_bootleg_latched_scanline = m_ppu1->get_current_scanline();
|
||||
m_subcpu->set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE);
|
||||
|
||||
return m_bootleg_sound_data;
|
||||
}
|
||||
|
||||
@ -271,20 +275,14 @@ void vsnes_state::vsnes_cpu1_bootleg_map(address_map &map)
|
||||
{
|
||||
map(0x0000, 0x07ff).mirror(0x1800).ram().share("work_ram");
|
||||
map(0x2000, 0x3fff).rw(m_ppu1, FUNC(ppu2c0x_device::read), FUNC(ppu2c0x_device::write));
|
||||
map(0x4000, 0x4017).w(FUNC(vsnes_state::bootleg_sound_write));
|
||||
map(0x4014, 0x4014).w(FUNC(vsnes_state::sprite_dma_0_w));
|
||||
map(0x4000, 0x400f).w(FUNC(vsnes_state::bootleg_sound_write));
|
||||
map(0x4016, 0x4016).rw(FUNC(vsnes_state::vsnes_in0_r), FUNC(vsnes_state::vsnes_in0_w));
|
||||
map(0x4017, 0x4017).r(FUNC(vsnes_state::vsnes_in1_r)); /* IN1 - input port 2 / PSG second control register */
|
||||
map(0x4020, 0x4020).rw(FUNC(vsnes_state::vsnes_coin_counter_r), FUNC(vsnes_state::vsnes_coin_counter_w));
|
||||
map(0x4020, 0x4020).w(FUNC(vsnes_state::vsnes_coin_counter_w));
|
||||
map(0x6000, 0x7fff).bankrw("extra1");
|
||||
map(0x8000, 0xffff).rom();
|
||||
}
|
||||
|
||||
uint8_t vsnes_state::vsnes_bootleg_z80_latch_r()
|
||||
{
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
// from kevtris' schematics, 2 74LS139s do the Z80 address decoding.
|
||||
// A13 = 0, A14 = 0 is ROM
|
||||
// A13 = 1, A14 = 0 is RAM
|
||||
@ -1846,36 +1844,32 @@ void vsnes_state::vsdual_pi(machine_config &config)
|
||||
void vsnes_state::vsnes_bootleg(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
M6502(config, m_maincpu, XTAL(16'000'000)/4); // 4mhz? seems too high but flickers badly otherwise, issue elsewhere?
|
||||
M6502(config, m_maincpu, XTAL(16'000'000)/8);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &vsnes_state::vsnes_cpu1_bootleg_map);
|
||||
/* some carts also trigger IRQs */
|
||||
MCFG_MACHINE_RESET_OVERRIDE(vsnes_state,vsnes)
|
||||
MCFG_MACHINE_START_OVERRIDE(vsnes_state,vsnes)
|
||||
MCFG_MACHINE_START_OVERRIDE(vsnes_state,bootleg)
|
||||
|
||||
Z80(config, m_subcpu, XTAL(16'000'000)/4); /* ? MHz */ // Z8400APS-Z80CPU
|
||||
Z80(config, m_subcpu, XTAL(16'000'000)/8); // Z8400APS-Z80CPU
|
||||
m_subcpu->set_addrmap(AS_PROGRAM, &vsnes_state::vsnes_bootleg_z80_map);
|
||||
m_subcpu->set_vblank_int("screen1", FUNC(vsnes_state::irq0_line_assert));
|
||||
|
||||
/* video hardware */
|
||||
screen_device &screen1(SCREEN(config, "screen1", SCREEN_TYPE_RASTER));
|
||||
screen1.set_refresh_hz(60);
|
||||
screen1.set_size(32*8, 262);
|
||||
screen1.set_refresh_hz(56.69);
|
||||
screen1.set_size(32*8, 280);
|
||||
screen1.set_visarea(0*8, 32*8-1, 0*8, 30*8-1);
|
||||
screen1.set_screen_update("ppu1", FUNC(ppu2c0x_device::screen_update));
|
||||
|
||||
PPU_2C04(config, m_ppu1);
|
||||
PPU_2C04C(config, m_ppu1);
|
||||
m_ppu1->set_cpu_tag(m_maincpu);
|
||||
m_ppu1->set_screen("screen1");
|
||||
m_ppu1->int_callback().set_inputline(m_maincpu, INPUT_LINE_NMI);
|
||||
m_ppu1->use_sprite_write_limitation_disable(); // bootleg seems to need this - code to set the sprite address is replaced with complete copy loops??
|
||||
|
||||
/* sound hardware */
|
||||
SPEAKER(config, "mono").front_center();
|
||||
|
||||
// PCB has 2, code accesses 3? which 2 really exist?
|
||||
SN76489(config, "sn1", XTAL(16'000'000)/4).add_route(ALL_OUTPUTS, "mono", 0.50);
|
||||
SN76489(config, "sn1", XTAL(16'000'000)/8).add_route(ALL_OUTPUTS, "mono", 0.50); // one runs at 2 MHz, other runs at 4 MHz
|
||||
SN76489(config, "sn2", XTAL(16'000'000)/4).add_route(ALL_OUTPUTS, "mono", 0.50);
|
||||
SN76489(config, "sn3", XTAL(16'000'000)/4).add_route(ALL_OUTPUTS, "mono", 0.50);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@ -1961,7 +1955,7 @@ ROM_START( suprmriobl )
|
||||
ROM_REGION( 0x10000, "sub", 0 ) /* Z80 memory */
|
||||
ROM_LOAD( "1.bin", 0x0000, 0x2000, CRC(9e3557f2) SHA1(11a0de2c0154f7ac120d9774cb5d1051e0156822) )
|
||||
|
||||
ROM_REGION( 0x10000, "unk", 0 ) /* first half is some sort of table */
|
||||
ROM_REGION( 0x10000, "unk", 0 ) /* Table used by clone PPU for sprite flipping, etc. */
|
||||
ROM_LOAD( "3.bin", 0x0000, 0x8000, CRC(67a467f9) SHA1(61cd1db7cd52faa31153b89f6b98c9b78bf4ca4f) )
|
||||
|
||||
ROM_REGION( 0x4000, "gfx1", 0 ) /* PPU memory */
|
||||
@ -1969,9 +1963,9 @@ ROM_START( suprmriobl )
|
||||
ROM_LOAD( "5.bin", 0x2000, 0x2000, CRC(15506b86) SHA1(69ecf7a3cc8bf719c1581ec7c0d68798817d416f) )
|
||||
|
||||
/* this set has some extra files compared to "suprmriobl2", they probably exist on that pcb too though */
|
||||
ROM_REGION( 0x200, "proms", 0 )
|
||||
ROM_LOAD( "prom6301.1", 0x000, 0x100, CRC(a31dc330) SHA1(b652003f7e252bac3bdb19412839c2f03af7f8b8) )
|
||||
ROM_LOAD( "prom6301.2", 0x100, 0x100, CRC(019c6141) SHA1(fdeda4dea6506807a3324fa941f0684208aa3b4b) )
|
||||
ROM_REGION( 0x100, "ppu1:palette", 0 )
|
||||
ROM_LOAD_NIB_HIGH( "prom6301.1", 0x000, 0x100, CRC(a31dc330) SHA1(b652003f7e252bac3bdb19412839c2f03af7f8b8) )
|
||||
ROM_LOAD_NIB_LOW ( "prom6301.2", 0x000, 0x100, CRC(019c6141) SHA1(fdeda4dea6506807a3324fa941f0684208aa3b4b) )
|
||||
|
||||
ROM_REGION( 0x4000, "pals", 0 )
|
||||
ROM_LOAD( "pal16l8.1", 0x000, 0x104, CRC(bd76fb53) SHA1(2d0634e8edb3289a103719466465e9777606086e) )
|
||||
@ -1982,7 +1976,8 @@ ROM_START( suprmriobl )
|
||||
ROM_LOAD( "pal16r8.6", 0x000, 0x104, CRC(bd76fb53) SHA1(2d0634e8edb3289a103719466465e9777606086e) )
|
||||
ROM_LOAD( "pal16r8a.7", 0x000, 0x104, CRC(bd76fb53) SHA1(2d0634e8edb3289a103719466465e9777606086e) )
|
||||
|
||||
PALETTE_2C04_0004("ppu1:palette")
|
||||
ROM_REGION(0x0100, "epld", 0)
|
||||
ROM_LOAD("ep1200.bin", 0x000, 0x100, NO_DUMP) // Not dumped
|
||||
ROM_END
|
||||
|
||||
ROM_START( suprmriobl2 )
|
||||
@ -1992,48 +1987,28 @@ ROM_START( suprmriobl2 )
|
||||
ROM_REGION( 0x10000, "sub", 0 ) /* Z80 memory */
|
||||
ROM_LOAD( "1-2764.bin", 0x0000, 0x2000, CRC(95856e07) SHA1(c681cfdb656e687bc59080df56c9c38e13be4bb8) )
|
||||
|
||||
ROM_REGION( 0x10000, "unk", 0 ) /* first half is some sort of table */
|
||||
ROM_REGION( 0x10000, "unk", 0 ) /* Table used by clone PPU for sprite flipping, etc. */
|
||||
ROM_LOAD( "3-27256.bin", 0x0000, 0x8000, CRC(67a467f9) SHA1(61cd1db7cd52faa31153b89f6b98c9b78bf4ca4f) )
|
||||
|
||||
ROM_REGION( 0x4000, "gfx1", 0 ) /* PPU memory */
|
||||
ROM_LOAD( "2-2764.bin", 0x0000, 0x2000, CRC(42418d40) SHA1(22ab61589742cfa4cc6856f7205d7b4b8310bc4d) )
|
||||
ROM_LOAD( "5-2764.bin", 0x2000, 0x2000, CRC(15506b86) SHA1(69ecf7a3cc8bf719c1581ec7c0d68798817d416f) )
|
||||
|
||||
PALETTE_2C04_0004("ppu1:palette")
|
||||
ROM_END
|
||||
ROM_REGION(0x100, "ppu1:palette", 0)
|
||||
ROM_LOAD_NIB_HIGH( "prom6301.1", 0x000, 0x100, BAD_DUMP CRC(a31dc330) SHA1(b652003f7e252bac3bdb19412839c2f03af7f8b8) ) // Not from this PCB
|
||||
ROM_LOAD_NIB_LOW ( "prom6301.2", 0x000, 0x100, BAD_DUMP CRC(019c6141) SHA1(fdeda4dea6506807a3324fa941f0684208aa3b4b) ) // Not from this PCB
|
||||
|
||||
ROM_START( suprmriobl3 )
|
||||
ROM_REGION( 0x10000, "maincpu", 0 ) // 6502 memory
|
||||
ROM_LOAD( "sm_4.bin", 0x8000, 0x8000, CRC(663b1753) SHA1(b0d2057c4545f2d6534cafb16086826c8ba49f5a) )
|
||||
ROM_REGION(0x4000, "pals", 0)
|
||||
ROM_LOAD("pal16l8.1", 0x000, 0x104, BAD_DUMP CRC(bd76fb53) SHA1(2d0634e8edb3289a103719466465e9777606086e)) // Not from this PCB
|
||||
ROM_LOAD("pal16r6a.2", 0x000, 0x104, NO_DUMP)
|
||||
ROM_LOAD("pal16r8.3", 0x000, 0x104, BAD_DUMP CRC(bd76fb53) SHA1(2d0634e8edb3289a103719466465e9777606086e)) // Not from this PCB
|
||||
ROM_LOAD("pal16l8.4", 0x000, 0x104, BAD_DUMP CRC(6f6de82d) SHA1(3d59b222d25457b2f89b559409721db37d6a81d8)) // Not from this PCB
|
||||
ROM_LOAD("pal16r6.5", 0x000, 0x104, BAD_DUMP CRC(ceff7c7c) SHA1(52fd344c591478469369cd0862d1facfe23e12fb)) // Not from this PCB
|
||||
ROM_LOAD("pal16r8.6", 0x000, 0x104, BAD_DUMP CRC(bd76fb53) SHA1(2d0634e8edb3289a103719466465e9777606086e)) // Not from this PCB
|
||||
ROM_LOAD("pal16r8a.7", 0x000, 0x104, BAD_DUMP CRC(bd76fb53) SHA1(2d0634e8edb3289a103719466465e9777606086e)) // Not from this PCB
|
||||
|
||||
ROM_REGION( 0x10000, "sub", 0 ) // Z80 memory
|
||||
ROM_LOAD( "sm_1.bin", 0x0000, 0x2000, CRC(7f6dda4a) SHA1(0e92a1255ce13ae1215b531f268cd4874e20d611) )
|
||||
|
||||
ROM_REGION( 0x10000, "unk", 0 ) // First half is some sort of table
|
||||
ROM_LOAD( "sm_3.bin", 0x0000, 0x8000, CRC(67a467f9) SHA1(61cd1db7cd52faa31153b89f6b98c9b78bf4ca4f) )
|
||||
|
||||
ROM_REGION( 0x4000, "gfx1", 0 ) // PPU memory
|
||||
ROM_LOAD( "sm_2.bin", 0x0000, 0x2000, CRC(a5f771d1) SHA1(b3f916700035d5556cca009ab83300fb662a868f) )
|
||||
ROM_LOAD( "sm_5.bin", 0x2000, 0x2000, CRC(a08903ca) SHA1(7ecec519ac973168a84505ddede4f248b554fd85) )
|
||||
|
||||
/* this set has some extra files compared to "suprmriobl2", they probably exist on that pcb too though */
|
||||
ROM_REGION( 0x200, "proms", 0 )
|
||||
ROM_LOAD( "prom6301.1", 0x000, 0x100, BAD_DUMP CRC(a31dc330) SHA1(b652003f7e252bac3bdb19412839c2f03af7f8b8) ) // Not from this PCB
|
||||
ROM_LOAD( "prom6301.2", 0x100, 0x100, BAD_DUMP CRC(019c6141) SHA1(fdeda4dea6506807a3324fa941f0684208aa3b4b) ) // Not from this PCB
|
||||
|
||||
ROM_REGION( 0x4000, "pals", 0 )
|
||||
ROM_LOAD( "pal16l8.1", 0x000, 0x104, BAD_DUMP CRC(bd76fb53) SHA1(2d0634e8edb3289a103719466465e9777606086e) ) // Not from this PCB
|
||||
ROM_LOAD( "pal16r6a.2", 0x000, 0x104, NO_DUMP )
|
||||
ROM_LOAD( "pal16r8.3", 0x000, 0x104, BAD_DUMP CRC(bd76fb53) SHA1(2d0634e8edb3289a103719466465e9777606086e) ) // Not from this PCB
|
||||
ROM_LOAD( "pal16l8.4", 0x000, 0x104, BAD_DUMP CRC(6f6de82d) SHA1(3d59b222d25457b2f89b559409721db37d6a81d8) ) // Not from this PCB
|
||||
ROM_LOAD( "pal16r6.5", 0x000, 0x104, BAD_DUMP CRC(ceff7c7c) SHA1(52fd344c591478469369cd0862d1facfe23e12fb) ) // Not from this PCB
|
||||
ROM_LOAD( "pal16r8.6", 0x000, 0x104, BAD_DUMP CRC(bd76fb53) SHA1(2d0634e8edb3289a103719466465e9777606086e) ) // Not from this PCB
|
||||
ROM_LOAD( "pal16r8a.7", 0x000, 0x104, BAD_DUMP CRC(bd76fb53) SHA1(2d0634e8edb3289a103719466465e9777606086e) ) // Not from this PCB
|
||||
|
||||
ROM_REGION( 0x0100, "epld", 0 )
|
||||
ROM_LOAD( "ep1200.bin", 0x000, 0x100, NO_DUMP ) // Not dumped
|
||||
|
||||
PALETTE_2C04_0004("ppu1:palette") // Not from this PCB
|
||||
ROM_REGION(0x0100, "epld", 0)
|
||||
ROM_LOAD("ep1200.bin", 0x000, 0x100, NO_DUMP) // Not dumped
|
||||
ROM_END
|
||||
|
||||
ROM_START( skatekds )
|
||||
@ -2880,9 +2855,8 @@ GAME( 1986, rbibb, 0, vsnes, rbibb, vsnes_state, init_rbib
|
||||
GAME( 1986, rbibba, rbibb, vsnes, rbibb, vsnes_state, init_rbibb, ROT0, "Namco", "Vs. Atari R.B.I. Baseball (set 2)", 0 )
|
||||
GAME( 1986, suprmrio, 0, vsnes, suprmrio, vsnes_state, init_vsnormal, ROT0, "Nintendo", "Vs. Super Mario Bros. (set SM4-4 E)", 0 )
|
||||
GAME( 1986, suprmrioa,suprmrio, vsnes, suprmrio, vsnes_state, init_vsnormal, ROT0, "Nintendo", "Vs. Super Mario Bros. (set ?, harder)", 0 )
|
||||
GAME( 1986, suprmriobl,suprmrio, vsnes_bootleg, suprmrio, vsnes_state, init_vsnormal, ROT0, "bootleg", "Vs. Super Mario Bros. (bootleg with Z80, set 1)", MACHINE_NOT_WORKING ) // timer starts at 200(!)
|
||||
GAME( 1986, suprmriobl2,suprmrio,vsnes_bootleg, suprmrio, vsnes_state, init_vsnormal, ROT0, "bootleg", "Vs. Super Mario Bros. (bootleg with Z80, set 2)", MACHINE_NOT_WORKING ) // timer starts at 300
|
||||
GAME( 1986, suprmriobl3,suprmrio,vsnes_bootleg, suprmrio, vsnes_state, init_vsnormal, ROT0, "bootleg", "Vs. Super Mario Bros. (bootleg with Z80, set 3)", MACHINE_NOT_WORKING ) // timer starts at 300
|
||||
GAME( 1986, suprmriobl,suprmrio, vsnes_bootleg, suprmrio, vsnes_state, init_bootleg, ROT0, "bootleg", "Vs. Super Mario Bros. (bootleg with Z80, set 1)", 0) // timer starts at 200(!)
|
||||
GAME( 1986, suprmriobl2,suprmrio,vsnes_bootleg, suprmrio, vsnes_state, init_bootleg, ROT0, "bootleg", "Vs. Super Mario Bros. (bootleg with Z80, set 2)", 0) // timer starts at 300
|
||||
GAME( 1988, skatekds, suprmrio, vsnes, suprmrio, vsnes_state, init_vsnormal, ROT0, "hack (Two-Bit Score)", "Vs. Skate Kids. (Graphic hack of Super Mario Bros.)", 0 )
|
||||
GAME( 1985, vsskykid, 0, vsnes, vsskykid, vsnes_state, init_MMC3, ROT0, "Namco", "Vs. Super SkyKid", 0 )
|
||||
GAME( 1987, tkoboxng, 0, vsnes, tkoboxng, vsnes_state, init_tkoboxng, ROT0, "Namco / Data East USA", "Vs. T.K.O. Boxing", 0 )
|
||||
|
@ -44,6 +44,7 @@ public:
|
||||
void init_platoon();
|
||||
void init_rbibb();
|
||||
void init_vsdual();
|
||||
void init_bootleg();
|
||||
|
||||
private:
|
||||
required_device<cpu_device> m_maincpu;
|
||||
@ -99,15 +100,17 @@ private:
|
||||
DECLARE_MACHINE_RESET(vsnes);
|
||||
DECLARE_MACHINE_START(vsdual);
|
||||
DECLARE_MACHINE_RESET(vsdual);
|
||||
DECLARE_MACHINE_START(bootleg);
|
||||
void v_set_videorom_bank( int start, int count, int vrom_start_bank );
|
||||
void mapper4_set_prg( );
|
||||
void mapper4_set_chr( );
|
||||
void mapper4_irq( int scanline, int vblank, int blanked );
|
||||
|
||||
uint8_t vsnes_bootleg_z80_latch_r();
|
||||
void bootleg_sound_write(offs_t offset, uint8_t data);
|
||||
uint8_t vsnes_bootleg_z80_data_r();
|
||||
uint8_t vsnes_bootleg_z80_address_r();
|
||||
uint8_t vsnes_bootleg_z80_address_r(offs_t offset);
|
||||
void vsnes_bootleg_scanline(int scanline, int vblank, int blanked);
|
||||
uint8_t vsnes_bootleg_ppudata();
|
||||
|
||||
void vsnes_bootleg_z80_map(address_map &map);
|
||||
void vsnes_cpu1_bootleg_map(address_map &map);
|
||||
@ -122,6 +125,7 @@ private:
|
||||
std::unique_ptr<uint8_t[]> m_vram;
|
||||
uint8_t* m_vrom[2];
|
||||
std::unique_ptr<uint8_t[]> m_nt_ram[2];
|
||||
memory_bank* m_bank_vrom[8];
|
||||
uint8_t* m_nt_page[2][4];
|
||||
uint32_t m_vrom_size[2];
|
||||
int m_vrom_banks;
|
||||
@ -146,4 +150,5 @@ private:
|
||||
|
||||
uint8_t m_bootleg_sound_offset;
|
||||
uint8_t m_bootleg_sound_data;
|
||||
int m_bootleg_latched_scanline;
|
||||
};
|
||||
|
@ -179,7 +179,7 @@ void vsnes_state::v_set_videorom_bank( int start, int count, int vrom_start_ban
|
||||
/* count determines the size of the area mapped */
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
membank(chr_banknames[i + start])->set_entry(vrom_start_bank + i);
|
||||
m_bank_vrom[i + start]->set_entry(vrom_start_bank + i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -219,7 +219,8 @@ MACHINE_START_MEMBER(vsnes_state,vsnes)
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
ppu1_space.install_read_bank(0x0400 * i, 0x0400 * i + 0x03ff, chr_banknames[i]);
|
||||
membank(chr_banknames[i])->configure_entries(0, m_vrom_banks, m_vrom[0], 0x400);
|
||||
m_bank_vrom[i] = membank(chr_banknames[i]);
|
||||
m_bank_vrom[i]->configure_entries(0, m_vrom_banks, m_vrom[0], 0x400);
|
||||
}
|
||||
v_set_videorom_bank(0, 8, 0);
|
||||
}
|
||||
@ -255,10 +256,34 @@ MACHINE_START_MEMBER(vsnes_state,vsdual)
|
||||
m_ppu1->space(AS_PROGRAM).install_read_bank(0x0000, 0x1fff, "bank2");
|
||||
// read only!
|
||||
m_ppu2->space(AS_PROGRAM).install_read_bank(0x0000, 0x1fff, "bank3");
|
||||
membank("bank2")->configure_entries(0, m_vrom_size[0] / 0x2000, m_vrom[0], 0x2000);
|
||||
membank("bank3")->configure_entries(0, m_vrom_size[1] / 0x2000, m_vrom[1], 0x2000);
|
||||
membank("bank2")->set_entry(0);
|
||||
membank("bank3")->set_entry(0);
|
||||
m_bank_vrom[0] = membank("bank2");
|
||||
m_bank_vrom[1] = membank("bank3");
|
||||
m_bank_vrom[0]->configure_entries(0, m_vrom_size[0] / 0x2000, m_vrom[0], 0x2000);
|
||||
m_bank_vrom[1]->configure_entries(0, m_vrom_size[1] / 0x2000, m_vrom[1], 0x2000);
|
||||
m_bank_vrom[0]->set_entry(0);
|
||||
m_bank_vrom[1]->set_entry(0);
|
||||
}
|
||||
|
||||
MACHINE_START_MEMBER(vsnes_state, bootleg)
|
||||
{
|
||||
address_space &ppu1_space = m_ppu1->space(AS_PROGRAM);
|
||||
|
||||
/* establish nametable ram */
|
||||
m_nt_ram[0] = std::make_unique<uint8_t[]>(0x1000);
|
||||
/* set mirroring */
|
||||
v_set_mirroring(0, PPU_MIRROR_VERT);
|
||||
|
||||
ppu1_space.install_readwrite_handler(0x2000, 0x3eff, read8sm_delegate(*this, FUNC(vsnes_state::vsnes_nt0_r)), write8sm_delegate(*this, FUNC(vsnes_state::vsnes_nt0_w)));
|
||||
|
||||
m_vrom[0] = m_gfx1_rom->base();
|
||||
m_vrom_size[0] = m_gfx1_rom->bytes();
|
||||
m_vrom_banks = m_vrom_size[0] / 0x2000;
|
||||
|
||||
/* establish chr banks */
|
||||
m_ppu1->space(AS_PROGRAM).install_read_bank(0x0000, 0x1fff, "bank2");
|
||||
m_bank_vrom[0] = membank("bank2");
|
||||
m_bank_vrom[0]->configure_entries(0, m_vrom_banks, m_vrom[0], 0x2000);
|
||||
m_bank_vrom[0]->set_entry(0);
|
||||
}
|
||||
|
||||
/*************************************
|
||||
@ -1017,7 +1042,7 @@ void vsnes_state::init_bnglngby()
|
||||
void vsnes_state::vsdual_vrom_banking_main(uint8_t data)
|
||||
{
|
||||
/* switch vrom */
|
||||
membank("bank2")->set_entry(BIT(data, 2));
|
||||
m_bank_vrom[0]->set_entry(BIT(data, 2));
|
||||
|
||||
/* bit 1 ( data & 2 ) triggers irq on the other cpu */
|
||||
m_subcpu->set_input_line(0, (data & 2) ? CLEAR_LINE : ASSERT_LINE);
|
||||
@ -1029,7 +1054,7 @@ void vsnes_state::vsdual_vrom_banking_main(uint8_t data)
|
||||
void vsnes_state::vsdual_vrom_banking_sub(uint8_t data)
|
||||
{
|
||||
/* switch vrom */
|
||||
membank("bank3")->set_entry(BIT(data, 2));
|
||||
m_bank_vrom[1]->set_entry(BIT(data, 2));
|
||||
|
||||
/* bit 1 ( data & 2 ) triggers irq on the other cpu */
|
||||
m_maincpu->set_input_line(0, (data & 2) ? CLEAR_LINE : ASSERT_LINE);
|
||||
@ -1050,3 +1075,38 @@ void vsnes_state::init_vsdual()
|
||||
m_maincpu->space(AS_PROGRAM).install_ram(0x6000, 0x7fff, &prg[0x6000]);
|
||||
m_subcpu->space(AS_PROGRAM).install_ram(0x6000, 0x7fff, &prg[0x6000]);
|
||||
}
|
||||
|
||||
/**********************************************************************************/
|
||||
/* Vs. Super Mario Bros (Bootleg) */
|
||||
|
||||
void vsnes_state::vsnes_bootleg_scanline(int scanline, int vblank, int blanked)
|
||||
{
|
||||
// Z80 IRQ is controlled by two factors:
|
||||
// - bit 6 of current (next) scanline number
|
||||
// - bit 6 of latched scanline number from Z80 reading $4000
|
||||
if (!(m_bootleg_latched_scanline & 0x40))
|
||||
{
|
||||
m_subcpu->set_input_line(INPUT_LINE_IRQ0, ((scanline + 1) & 0x40) ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t vsnes_state::vsnes_bootleg_ppudata()
|
||||
{
|
||||
// CPU always reads higher CHR ROM banks from $2007, PPU always reads lower ones
|
||||
m_bank_vrom[0]->set_entry(1);
|
||||
uint8_t data = m_ppu1->read(0x2007);
|
||||
m_bank_vrom[0]->set_entry(0);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void vsnes_state::init_bootleg()
|
||||
{
|
||||
m_bootleg_sound_offset = 0;
|
||||
m_bootleg_sound_data = 0;
|
||||
m_bootleg_latched_scanline = 0;
|
||||
|
||||
m_ppu1->set_scanline_callback(*this, FUNC(vsnes_state::vsnes_bootleg_scanline));
|
||||
|
||||
m_maincpu->space(AS_PROGRAM).install_read_handler(0x2007, 0x2007, read8smo_delegate(*this, FUNC(vsnes_state::vsnes_bootleg_ppudata)));
|
||||
}
|
||||
|
@ -41455,7 +41455,6 @@ suprmrio // (c) 1986 Nintendo
|
||||
suprmrioa // (c) 1986 Nintendo
|
||||
suprmriobl // bootleg
|
||||
suprmriobl2 // bootleg
|
||||
suprmriobl3 // bootleg
|
||||
supxevs // (c) 1986 Nintendo
|
||||
tkoboxng // (c) 1987 Data East
|
||||
topgun // (c) 1987 Konami
|
||||
|
Loading…
Reference in New Issue
Block a user