Added two TV Games (not working), and improved SPG110 SoC emulation. (#13153)

* machine/spg110.cpp: Improved interrupt emulation.
* machine/spg110_video.cpp: Hooked up Y flip, cleaned up code, updated comments.

New systems marked not working
-------------------------------
JAKKS Pacific Inc / HotGen Ltd Bob the Builder - Project: Build It (JAKKS Pacific TV Game) (JUN 2 2006 14:42:01) [David Haywood, TeamEurope]
JAKKS Pacific Inc / Digital Eclipse EA Sports Classics: NHL 95 & FIFA Soccer 96 (JAKKS Pacific TV Game) [David Haywood, TeamEurope]
This commit is contained in:
mamehaze 2025-01-02 15:46:30 +00:00 committed by GitHub
parent 026836d8cf
commit a278e24cfd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 576 additions and 359 deletions

View File

@ -30,8 +30,7 @@ spg110_device::spg110_device(const machine_config &mconfig, device_type type, co
m_portb_in(*this, 0),
m_portc_in(*this, 0),
m_adc_in(*this, 0x0fff),
m_chip_sel(*this),
m_is_spiderman(false)
m_chip_sel(*this)
{
}
@ -46,14 +45,47 @@ void spg110_device::videoirq_w(int state)
set_state_unsynced(UNSP_IRQ0_LINE, state);
}
void spg110_device::timerirq_w(int state)
{
set_state_unsynced(UNSP_IRQ3_LINE, state);
}
void spg110_device::uartirq_w(int state)
{
set_state_unsynced(UNSP_IRQ4_LINE, state);
}
void spg110_device::extirq_w(int state)
{
// External Int1 is IRQ4 (was 5 on SPG2xx)
// External Int2 is IRQ2 (was 5 on SPG2xx)
set_state_unsynced(UNSP_IRQ4_LINE, state);
}
void spg110_device::ffreq1_w(int state)
{
set_state_unsynced(UNSP_IRQ5_LINE, state);
}
void spg110_device::ffreq2_w(int state)
{
set_state_unsynced(UNSP_IRQ6_LINE, state);
}
// notes about IRQ differences from 2xx
//
// TMB1 / TMB2 are IRQ7 (same as SPG2xx)
// Key Change is IRQ4 (was 7 on SPG2xx)
// LVD (Low Voltage Reset) is IRQ6 (doesn't exist on SPG2xx?)
// ADC is IRQ1 (was 3 on SPG2xx)
//
// on SPG2xx 0x3D2E can redirect any other interrupt to the FIQ
// on SPG110 FIQ is always from SPUIRQ (sound)
//
// on SPG2xx SPU_Ch_Irq (sound) is IRQ1, and SPU_Env_Irq / SPU_Beat_Irq is IRQ4
// SPU_Ch_Irq / SPU_Env_Irq and SPU_Beat_Irq don't exist on SPG110? (assume SPU_Ch_Irq is SPUIRQ?)
//
// SPG2xx has SPI Interrupt on IRQ3, no SPI interrupt on SPG110?
void spg110_device::configure_spg_io(spg2xx_io_device* io)
{
@ -69,9 +101,9 @@ void spg110_device::configure_spg_io(spg2xx_io_device* io)
io->adc_in<3>().set(FUNC(spg110_device::adc_r<3>));
io->chip_select().set(FUNC(spg110_device::cs_w));
// io->pal_read_callback().set(FUNC(spg110_device::get_pal_r));
// io->write_timer_irq_callback().set(FUNC(spg110_device::timerirq_w));
// io->write_uart_adc_irq_callback().set(FUNC(spg110_device::uartirq_w));
// io->write_external_irq_callback().set(FUNC(spg110_device::extirq_w));
io->write_timer_irq_callback().set(FUNC(spg110_device::timerirq_w));
io->write_uart_adc_irq_callback().set(FUNC(spg110_device::uartirq_w));
io->write_external_irq_callback().set(FUNC(spg110_device::extirq_w));
io->write_ffrq_tmr1_irq_callback().set(FUNC(spg110_device::ffreq1_w));
io->write_ffrq_tmr2_irq_callback().set(FUNC(spg110_device::ffreq2_w));
}
@ -112,49 +144,48 @@ void spg110_device::internal_map(address_map &map)
map(0x002010, 0x002015).rw(m_spg_video, FUNC(spg110_video_device::tmap0_regs_r), FUNC(spg110_video_device::tmap0_regs_w));
map(0x002016, 0x00201b).rw(m_spg_video, FUNC(spg110_video_device::tmap1_regs_r), FUNC(spg110_video_device::tmap1_regs_w));
#if 1 // more vregs?
map(0x00201c, 0x00201c).w(m_spg_video, FUNC(spg110_video_device::spg110_201c_w));
map(0x00201c, 0x00201c).w(m_spg_video, FUNC(spg110_video_device::vcomp_val_201c_w)); // P_VComp_Value (vertical compression)
map(0x002020, 0x002020).w(m_spg_video, FUNC(spg110_video_device::spg110_2020_w));
map(0x002020, 0x002027).w(m_spg_video, FUNC(spg110_video_device::segment_202x_w)); // P_Segment0-7 (tilebases)
map(0x002028, 0x002028).rw(m_spg_video, FUNC(spg110_video_device::adr_mode_2028_r), FUNC(spg110_video_device::adr_mode_2028_w)); // P_Adr_mode
map(0x002029, 0x002029).rw(m_spg_video, FUNC(spg110_video_device::ext_bus_2029_r), FUNC(spg110_video_device::ext_bus_2029_w)); // P_Ext_Bus
// 0x202a // P_Blending
map(0x002028, 0x002028).rw(m_spg_video, FUNC(spg110_video_device::spg110_2028_r), FUNC(spg110_video_device::spg110_2028_w));
map(0x002029, 0x002029).rw(m_spg_video, FUNC(spg110_video_device::spg110_2029_r), FUNC(spg110_video_device::spg110_2029_w));
// 0x2030 // P_Eff_color
map(0x002031, 0x002031).w(m_spg_video, FUNC(spg110_video_device::win_mask_1_2031_w)); // P_Win_mask1 - sometimes 14a?
map(0x002032, 0x002032).w(m_spg_video, FUNC(spg110_video_device::win_mask_2_2032_w)); // P_Win_mask2 - always 14a?
map(0x002033, 0x002033).w(m_spg_video, FUNC(spg110_video_device::win_attribute_w)); // P_Win_attrribute
map(0x002034, 0x002034).w(m_spg_video, FUNC(spg110_video_device::win_mask_3_2034_w)); // P_Win_mask3
map(0x002035, 0x002035).w(m_spg_video, FUNC(spg110_video_device::win_mask_4_2035_w)); // P_Win_mask4
map(0x002036, 0x002036).w(m_spg_video, FUNC(spg110_video_device::irq_tm_v_2036_w)); // P_IRQTMV
map(0x002037, 0x002037).rw(m_spg_video, FUNC(spg110_video_device::irq_tm_h_2037_r), FUNC(spg110_video_device::irq_tm_h_2037_w)); // P_IRQTMH
// 0x2038 // P_Effect_color (not the same as 2030)
map(0x002039, 0x002039).w(m_spg_video, FUNC(spg110_video_device::effect_control_2039_w)); // P_Effect_control
// 0x203a // P_Mix_offset
// 0x203b // P_Fan_effect_th
map(0x00203c, 0x00203c).w(m_spg_video, FUNC(spg110_video_device::huereference_203c_w)); // P_203C_HueRefer (should be set based on PAL/NTSC)
map(0x00203d, 0x00203d).w(m_spg_video, FUNC(spg110_video_device::lum_adjust_203d_w)); // P_Lum_Adjust
// 0x203e // P_LPVPosition
// 0x203f // P_LPHPosition
map(0x002031, 0x002031).w(m_spg_video, FUNC(spg110_video_device::spg110_2031_w)); // sometimes 14a?
map(0x002032, 0x002032).w(m_spg_video, FUNC(spg110_video_device::spg110_2032_w)); // always 14a?
map(0x002033, 0x002033).w(m_spg_video, FUNC(spg110_video_device::spg110_2033_w));
map(0x002034, 0x002034).w(m_spg_video, FUNC(spg110_video_device::spg110_2034_w));
map(0x002035, 0x002035).w(m_spg_video, FUNC(spg110_video_device::spg110_2035_w));
map(0x002036, 0x002036).w(m_spg_video, FUNC(spg110_video_device::spg110_2036_w)); // possible scroll register?
map(0x002037, 0x002037).rw(m_spg_video, FUNC(spg110_video_device::spg110_2037_r), FUNC(spg110_video_device::spg110_2037_w));
map(0x002042, 0x002042).rw(m_spg_video, FUNC(spg110_video_device::sp_control_2042_r),FUNC(spg110_video_device::sp_control_2042_w)); // P_Sp_control
map(0x002039, 0x002039).w(m_spg_video, FUNC(spg110_video_device::spg110_2039_w));
map(0x002045, 0x002045).w(m_spg_video, FUNC(spg110_video_device::spg110_2045_w)); // not documented?
map(0x00203c, 0x00203c).w(m_spg_video, FUNC(spg110_video_device::spg110_203c_w));
map(0x002050, 0x00205f).ram().w(m_spg_video, FUNC(spg110_video_device::transparent_color_205x_w)).share("spg_video:palctrlram"); // P_Trptcolor0 - 15
map(0x00203d, 0x00203d).w(m_spg_video, FUNC(spg110_video_device::spg110_203d_w)); // possible scroll register?
map(0x002060, 0x002060).w(m_spg_video, FUNC(spg110_video_device::dma_dst_2060_w)); // P_DMA_Target_adr
map(0x002061, 0x002061).w(m_spg_video, FUNC(spg110_video_device::dma_dst_seg_2061_w)); // P_DMA_Target_seg
map(0x002062, 0x002062).rw(m_spg_video, FUNC(spg110_video_device::dma_len_status_2062_r),FUNC(spg110_video_device::dma_len_trigger_2062_w)); // P_DMA_numbr
map(0x002063, 0x002063).rw(m_spg_video, FUNC(spg110_video_device::spg110_2063_r),FUNC(spg110_video_device::spg110_2063_w)); // P_DMA_control - Video IRQ source / ack (3 different things checked here instead of 2 on spg2xx?)
map(0x002064, 0x002064).w(m_spg_video, FUNC(spg110_video_device::dma_dst_step_2064_w)); // P_DMA_Target_step
map(0x002065, 0x002065).rw(m_spg_video, FUNC(spg110_video_device::dma_manual_2065_r), FUNC(spg110_video_device::dma_manual_2065_w)); // P_DMA_data
map(0x002066, 0x002066).w(m_spg_video, FUNC(spg110_video_device::dma_source_2066_w)); // P_DMA_Source_adr
map(0x002067, 0x002067).w(m_spg_video, FUNC(spg110_video_device::dma_source_seg_2067_w)); // P_DMA_Source_seg
map(0x002068, 0x002068).rw(m_spg_video, FUNC(spg110_video_device::dma_src_step_2068_r), FUNC(spg110_video_device::dma_src_step_2068_w)); // P_DMA_Source_step
map(0x002042, 0x002042).rw(m_spg_video, FUNC(spg110_video_device::spg110_2042_r),FUNC(spg110_video_device::spg110_2042_w));
map(0x002045, 0x002045).w(m_spg_video, FUNC(spg110_video_device::spg110_2045_w));
#endif
// seems to be 16 entries for.. something? on jak_capb these seem connected to the palette DMA operations, 0x2050 for 0x8000, 0x2051 for 0x8020, 0x2052 for 0x8040 etc. maybe 1 bit per pen?
map(0x002050, 0x00205f).ram().w(m_spg_video, FUNC(spg110_video_device::spg110_205x_w)).share("spg_video:palctrlram");
// everything (dma? and interrupt flag?!)
map(0x002060, 0x002060).w(m_spg_video, FUNC(spg110_video_device::dma_dst_w));
map(0x002061, 0x002061).w(m_spg_video, FUNC(spg110_video_device::dma_unk_2061_w));
map(0x002062, 0x002062).rw(m_spg_video, FUNC(spg110_video_device::dma_len_status_r),FUNC(spg110_video_device::dma_len_trigger_w));
map(0x002063, 0x002063).rw(m_spg_video, FUNC(spg110_video_device::spg110_2063_r),FUNC(spg110_video_device::spg110_2063_w)); // Video IRQ source / ack (3 different things checked here instead of 2 on spg2xx?)
map(0x002064, 0x002064).w(m_spg_video, FUNC(spg110_video_device::dma_dst_step_w));
map(0x002065, 0x002065).rw(m_spg_video, FUNC(spg110_video_device::dma_manual_r), FUNC(spg110_video_device::dma_manual_w));
map(0x002066, 0x002066).w(m_spg_video, FUNC(spg110_video_device::dma_src_w));
map(0x002067, 0x002067).w(m_spg_video, FUNC(spg110_video_device::dma_unk_2067_w));
map(0x002068, 0x002068).w(m_spg_video, FUNC(spg110_video_device::dma_src_step_w));
map(0x002100, 0x0021ff).ram(); // jak_spdmo only
map(0x002200, 0x0022ff).ram(); // looks like per-pen brightness or similar? strange because palette isn't memory mapped here (maybe rowscroll?)
map(0x002100, 0x0021ff).ram(); // P_Tx_Hvoffset0 - P_Tx_Hvoffset255 // rowscroll table
map(0x002200, 0x0022ff).ram(); // P_HComp_Value0 - P_HComp_Value255 // horizontal compression table
/// sound registers? seems to be 8 long entries, only uses up to 0x7f? (register mapping seems similar to spg2xx, maybe with less channels?)
map(0x003000, 0x00307f).rw(m_spg_audio, FUNC(spg110_audio_device::audio_r), FUNC(spg110_audio_device::audio_w));
@ -162,7 +193,6 @@ void spg110_device::internal_map(address_map &map)
map(0x003100, 0x00310f).rw(m_spg_audio, FUNC(spg110_audio_device::audio_ctrl_r), FUNC(spg2xx_audio_device::audio_ctrl_w));
// 0032xx looks like it could be the same as 003d00 on spg2xx
map(0x003200, 0x00322f).rw(m_spg_io, FUNC(spg2xx_io_device::io_r), FUNC(spg2xx_io_device::io_w));
}
@ -171,6 +201,4 @@ void spg110_device::internal_map(address_map &map)
void spg110_device::device_reset()
{
unsp_device::device_reset();
m_spg_video->set_video_irq_spidman(m_is_spiderman);
}

View File

@ -26,8 +26,6 @@ public:
m_screen.set_tag(std::forward<T>(screen_tag));
}
void set_video_irq_spidman(bool is_spiderman) { m_is_spiderman = is_spiderman; }
auto porta_out() { return m_porta_out.bind(); }
auto portb_out() { return m_portb_out.bind(); }
auto portc_out() { return m_portc_out.bind(); }
@ -79,6 +77,9 @@ private:
void portb_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) { m_portb_out(offset, data, mem_mask); }
void portc_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) { m_portc_out(offset, data, mem_mask); }
void timerirq_w(int state);
void uartirq_w(int state);
void extirq_w(int state);
void ffreq1_w(int state);
void ffreq2_w(int state);
@ -88,7 +89,6 @@ private:
void configure_spg_io(spg2xx_io_device* io);
void videoirq_w(int state);
bool m_is_spiderman;
};
DECLARE_DEVICE_TYPE(SPG110, spg110_device)

View File

@ -38,17 +38,12 @@ void spg110_video_device::draw(const rectangle &cliprect, uint32_t line, uint32_
uint32_t nc = (bpp + 1) << 1;
switch (bpp)
{
case 0x03: pal = 0; break; // 8 bpp
case 0x02: pal &=0x03; break; // 6 bpp
case 0x01: break; // 4 bpp
case 0x00: break; // 2 bpp
}
uint32_t palette_offset = pal;
palette_offset <<= nc;
if (bpp == 3)
palette_offset = 0;
palette_offset <<= 4;
uint32_t bits_per_row = nc * w / 16;
uint32_t words_per_tile = bits_per_row * h;
@ -81,7 +76,7 @@ void spg110_video_device::draw(const rectangle &cliprect, uint32_t line, uint32_
}
nbits -= nc;
uint32_t pal = palette_offset + (bits >> 16);
uint8_t pennum = (palette_offset + (bits >> 16));
bits &= 0xffff;
xx &= 0x01ff;
@ -92,14 +87,14 @@ void spg110_video_device::draw(const rectangle &cliprect, uint32_t line, uint32_
{
int pix_index = xx + y_index;
const pen_t *pens = m_palette->pens();
uint32_t paldata = pens[pal];
uint32_t paldata = pens[pennum];
int transmap = m_palctrlram[(pal & 0xf0)>>4];
int transmap = m_palctrlram[(pennum & 0xf0)>>4];
bool trans = false;
if (transmap & 0x10) // maybe values other than 0x010 have other meanings, like blending?
if ((pal & 0x0f) == (transmap & 0xf))
if ((pennum & 0x0f) == (transmap & 0xf))
trans = true;
if (!trans)
@ -129,11 +124,12 @@ void spg110_video_device::draw_page(const rectangle &cliprect, uint32_t scanline
// {
// return;
// }
uint8_t bpp = attr & 0x03;
uint32_t tile_h = 8 << ((attr & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT);
uint32_t tile_w = 8 << ((attr & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT);
uint8_t bpp = (attr & 0x0003);
// flip 0x000c
uint32_t tile_w = 8 << ((attr & 0x0030) >> PAGE_TILE_WIDTH_SHIFT);
uint32_t tile_h = 8 << ((attr & 0x00c0) >> PAGE_TILE_HEIGHT_SHIFT);
uint8_t pal = (attr & 0x0f00)>>8;
uint8_t pri = (attr & 0x3000)>>12;
uint32_t tile_count_x = 512 / tile_w;
@ -151,9 +147,8 @@ void spg110_video_device::draw_page(const rectangle &cliprect, uint32_t scanline
if (!tile)
continue;
uint8_t pal = 0x000;
uint8_t pri = 0x00;
bool flip_x = false;
bool flip_y = false;
if (!(ctrl & 0x0002)) // 'regset'
{
@ -167,15 +162,17 @@ void spg110_video_device::draw_page(const rectangle &cliprect, uint32_t scanline
pal = extra_attribute & 0x0f;
pri = (extra_attribute & 0x30) >> 4;
flip_x = extra_attribute & 0x40;
flip_y = extra_attribute & 0x80;
}
const uint32_t yflipmask = flip_y ? tile_h - 1 : 0;
if (pri == priority)
{
if (flip_x)
draw<FlipXOn>(cliprect, tile_scanline, xx, yy, ctrl, bitmap_addr, tile, 0, pal, tile_h, tile_w, bpp);
draw<FlipXOn>(cliprect, tile_scanline, xx, yy, ctrl, bitmap_addr, tile, yflipmask, pal, tile_h, tile_w, bpp);
else
draw<FlipXOff>(cliprect, tile_scanline, xx, yy, ctrl, bitmap_addr, tile, 0, pal, tile_h, tile_w, bpp);
draw<FlipXOff>(cliprect, tile_scanline, xx, yy, ctrl, bitmap_addr, tile, yflipmask, pal, tile_h, tile_w, bpp);
}
}
@ -184,7 +181,6 @@ void spg110_video_device::draw_page(const rectangle &cliprect, uint32_t scanline
void spg110_video_device::draw_sprite(const rectangle &cliprect, uint32_t scanline, int priority, uint32_t base_addr)
{
// m_sprtileno tttt tttt tttt tttt t = tile number (all bits?)
// m_sprattr1 xxxx xxxx yyyy yyyy x = low x bits, y = low y bits
// m_sprattr2 YXzz pppp hhww fFbb X = high x bit, z = priority, p = palette, h = height, w = width, f = flipy, F = flipx, b = bpp, Y = high y bit
@ -196,7 +192,7 @@ void spg110_video_device::draw_sprite(const rectangle &cliprect, uint32_t scanli
return;
}
uint32_t bitmap_addr = 0x40 * m_tilebase;
uint32_t bitmap_addr = 0x40 * m_tilebase[0];
uint16_t attr1 = m_sprattr1[base_addr];
uint16_t attr2 = m_sprattr2[base_addr];
@ -212,8 +208,8 @@ void spg110_video_device::draw_sprite(const rectangle &cliprect, uint32_t scanli
if (!(attr2 & 0x8000))
y+= 0x100;
const uint32_t h = 8 << ((attr2 & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT);
const uint32_t w = 8 << ((attr2 & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT);
const uint32_t h = 8 << ((attr2 & 0x00c0) >> PAGE_TILE_HEIGHT_SHIFT);
const uint32_t w = 8 << ((attr2 & 0x0030) >> PAGE_TILE_WIDTH_SHIFT);
// if (!(m_video_regs[0x42] & SPRITE_COORD_TL_MASK))
// {
@ -243,7 +239,7 @@ void spg110_video_device::draw_sprite(const rectangle &cliprect, uint32_t scanli
//bool blend = (attr & 0x4000);
const uint8_t bpp = attr2 & 0x0003;
const uint32_t yflipmask = flip_y ? h - 1 : 0;
const uint32_t palette_offset = (attr2 & 0x0f00) >> 8;
uint32_t palette_offset = (attr2 & 0x0f00) >> 8;
if (pri == priority)
{
@ -341,88 +337,214 @@ device_memory_interface::space_config_vector spg110_video_device::memory_space_c
}
// irq source or similar?
/* 0x2063 P_DMA_control
despite the name this address is more IRQ control than DMA, although there are some DMA flags in here
bit15 bit14 bit13 bit12 bit11 bit10 bit9 bit8 bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
(unused) (unused) (unused) (unused) DMA_Busy wrtS readS testmd extsrc (unused) VDO_IRQ_Flag VDO_IRQ_EN BLK_IRQ_Flag BLK_IRQ_EN DMA_IRQ_Flag DMA_IRQ_EN
DMA_Busy - 0 = free, 1 = busy
wrtS - used when writing 0x2065
readS - used when reading 0x2065
testmd - memory dump mode, causes data from dma_dst to be read in 0x2065?
extsrc - 0 = work RAM, 1 = External Memory
VDO_IRQ_Flag (aka TMc or VDO_IRQ) - Positional IRQ Status / Clear IRQ on write
VDO_IRQ_EN (aka Tme) - Positional IRQ Enable
BLK_IRQ_Flag - VBlank IRQ Status / Clear IRQ on write
BLK_IRQ_EN - VBlank IRQ Enable
DMA_IRQ_Flag - DMA IRQ Status / Clear IRQ on write (can also be cleared by starting a new DMA)
DMA_IRQ_EN - DMA IRQ Enable
NOTE: if an IRQ flag is active when the IRQ Enable is turned on the IRQ will be taken
writing 0 to IRQ enable does not clear IRQ flag
by default:
BLK IRQ is asserted during the Vblank period, and deasserted when it ends
DMA IRQ is asserted at the end of a DMA, and deasserted when a new one starts
VDO IRQ is asserted when screen position in 2036 / 2037 is hit (has to be manually deasserted?)
*/
uint16_t spg110_video_device::spg110_2063_r()
{
// checks for bits 0x20 and 0x08 in the IRQ function (all IRQs point to the same place)
// TODO these need to be handled properly
uint8_t readS = 1;
uint8_t wrtS = 1;
uint8_t testmd = 0;
uint8_t extsrc = 0;
// HACK! jak_spdo checks for 0x400 or 0x200 starting some of the games
return m_video_irq_status | 0x0600; /* | 0x0002; */
uint16_t ret = 0;
ret |= m_dma_irq_enable ? 0x0001 : 0x0000;
ret |= m_dma_irq_flag ? 0x0002 : 0x0000;
ret |= m_blk_irq_enable ? 0x0004 : 0x0000;
ret |= m_blk_irq_flag ? 0x0008 : 0x0000;
ret |= m_vdo_irq_enable ? 0x0010 : 0x0000;
ret |= m_vdo_irq_flag ? 0x0020 : 0x0000;
// 0x0040 unused
ret |= extsrc ? 0x0080 : 0x0000;
ret |= testmd ? 0x0100 : 0x0000;
ret |= readS ? 0x0200 : 0x0000;
ret |= wrtS ? 0x0400 : 0x0000;
ret |= m_dma_busy ? 0x0800 : 0x0000;
// 0x1000 unused
// 0x2000 unused
// 0x4000 unused
// 0x8000 unused
return ret;
}
void spg110_video_device::spg110_2063_w(uint16_t data)
{
// writes 0x28, probably clears the IRQ / IRQ sources? 0x63 is the same offset for this in spg2xx but bits used seem to be different
const uint16_t old = m_video_irq_enable & m_video_irq_status;
m_video_irq_status &= ~data;
const uint16_t changed = old ^ (m_video_irq_enable & m_video_irq_status);
if (changed)
check_video_irq();
m_dma_irq_enable = data & 0x01;
m_blk_irq_enable = data & 0x04;
m_vdo_irq_enable = data & 0x10;
if (data & 0x02)
m_dma_irq_flag = 0;
if (data & 0x08)
m_blk_irq_flag = 0;
if (data & 0x20)
m_vdo_irq_flag = 0;
// still need to handle wrtS, readS, testmd, extsrc
update_video_irqs();
}
void spg110_video_device::spg110_201c_w(uint16_t data) { logerror("%s: 201c: %04x\n", machine().describe_context(), data); } // during startup text only
void spg110_video_device::spg110_2020_w(offs_t offset, uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_tilebase); logerror("%s: 2020: %04x\n", machine().describe_context(), data); } // confirmed as tile base, seems to apply to both layers and sprites, unlike spg2xx which has separate registers
void spg110_video_device::update_video_irqs()
{
bool irq_on = false;
void spg110_video_device::spg110_2028_w(uint16_t data) { logerror("%s: 2028: %04x\n", machine().describe_context(), data); } // startup
uint16_t spg110_video_device::spg110_2028_r() { return 0x0000; }
if ((m_blk_irq_enable) && (m_blk_irq_flag))
irq_on = true;
void spg110_video_device::spg110_2029_w(uint16_t data) { logerror("%s: 2029: %04x\n", machine().describe_context(), data); } // 0006, 0008 on startup
uint16_t spg110_video_device::spg110_2029_r() { return 0x0000; }
if ((m_dma_irq_enable) && (m_dma_irq_flag))
irq_on = true;
void spg110_video_device::spg110_2031_w(uint16_t data) { logerror("%s: 2031: %04x\n", machine().describe_context(), data); } // 014a or 0000 when ball is in trap
void spg110_video_device::spg110_2032_w(uint16_t data) { logerror("%s: 2032: %04x\n", machine().describe_context(), data); } // 014a most of the time, 0000 very rarely
void spg110_video_device::spg110_2033_w(uint16_t data) { logerror("%s: 2033: %04x\n", machine().describe_context(), data); } // changes, situational, eg when pausing
void spg110_video_device::spg110_2034_w(uint16_t data) { logerror("%s: 2034: %04x\n", machine().describe_context(), data); } // 0141 on every scene transition
void spg110_video_device::spg110_2035_w(uint16_t data) { logerror("%s: 2035: %04x\n", machine().describe_context(), data); } // 0141 on every scene transition
void spg110_video_device::spg110_2036_w(offs_t offset, uint16_t data, uint16_t mem_mask) { logerror("%s: 2036: %04x\n", machine().describe_context(), data); COMBINE_DATA(&m_2036_scroll); } // seems related to ball y position, not scrolling (possibly shadow sprite related?)
if ((m_vdo_irq_enable) && (m_vdo_irq_flag))
irq_on = true;
uint16_t spg110_video_device::spg110_2037_r() { return 0x0000; } // added to something from the PRNG
void spg110_video_device::spg110_2037_w(uint16_t data) { logerror("%s: 2037: %04x\n", machine().describe_context(), data); } // 0126 (always?)
void spg110_video_device::spg110_2039_w(uint16_t data) { logerror("%s: 2039: %04x\n", machine().describe_context(), data); } // 0803 on every scene transition
void spg110_video_device::spg110_203c_w(uint16_t data) { logerror("%s: 203c: %04x\n", machine().describe_context(), data); } // 0006 on startup, twice
void spg110_video_device::spg110_203d_w(uint16_t data) { logerror("%s: 203d: %04x\n", machine().describe_context(), data); } // changes, usually between scenes
uint16_t spg110_video_device::spg110_2042_r() { return 0x0000; }
void spg110_video_device::spg110_2042_w(uint16_t data) { logerror("%s: 2042: %04x\n", machine().describe_context(), data); } // sets bit 0x0004, masks with 0xfffb etc.
void spg110_video_device::spg110_2045_w(uint16_t data) { logerror("%s: 2045: %04x\n", machine().describe_context(), data); } // 0006 on startup, once
m_video_irq_cb(irq_on ? ASSERT_LINE : CLEAR_LINE);
}
void spg110_video_device::spg110_205x_w(offs_t offset, uint16_t data, uint16_t mem_mask)
void spg110_video_device::vcomp_val_201c_w(uint16_t data) { logerror("%s: vcomp_val_201c_w: %04x\n", machine().describe_context(), data); } // during startup text only
void spg110_video_device::segment_202x_w(offs_t offset, uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_tilebase[offset]); logerror("%s: segment/tilebase write: %02x %04x\n", machine().describe_context(), offset, data); } // confirmed as tile base, seems to apply to both layers and sprites, unlike spg2xx which has separate registers
void spg110_video_device::adr_mode_2028_w(uint16_t data) { logerror("%s: adr_mode_2028_w: %04x\n", machine().describe_context(), data); } // startup
uint16_t spg110_video_device::adr_mode_2028_r() { return 0x0000; }
void spg110_video_device::ext_bus_2029_w(uint16_t data) { logerror("%s: ext_bus_2029_w: %04x\n", machine().describe_context(), data); } // 0006, 0008 on startup
uint16_t spg110_video_device::ext_bus_2029_r() { return 0x0000; }
void spg110_video_device::win_mask_1_2031_w(uint16_t data) { logerror("%s: win_mask_1_2031_w: %04x\n", machine().describe_context(), data); } // 014a or 0000 when ball is in trap
void spg110_video_device::win_mask_2_2032_w(uint16_t data) { logerror("%s: win_mask_2_2032_w: %04x\n", machine().describe_context(), data); } // 014a most of the time, 0000 very rarely
void spg110_video_device::win_attribute_w(uint16_t data) { logerror("%s: win_attribute_w: %04x\n", machine().describe_context(), data); } // changes, situational, eg when pausing
void spg110_video_device::win_mask_3_2034_w(uint16_t data) { logerror("%s: win_mask_3_2034_w: %04x\n", machine().describe_context(), data); } // 0141 on every scene transition
void spg110_video_device::win_mask_4_2035_w(uint16_t data) { logerror("%s: win_mask_4_2035_w: %04x\n", machine().describe_context(), data); } // 0141 on every scene transition
void spg110_video_device::irq_tm_v_2036_w(uint16_t data)
{
// used for scanline raster effects, including ball shadow in capb
m_tm_v_2036 = data & 0x1ff;
update_raster_interrupt_timer();
}
uint16_t spg110_video_device::irq_tm_h_2037_r()
{
// added to value from the PRNG for some random number generation cases
// should this return the *current* horizontal position? or the register value written?
return m_screen->hpos();
}
void spg110_video_device::irq_tm_h_2037_w(uint16_t data)
{
// horizontal position for the scanline IRQ
m_tm_h_2037 = data & 0x1ff;
update_raster_interrupt_timer();
}
void spg110_video_device::effect_control_2039_w(uint16_t data)
{
// 0803 on every scene transition
logerror("%s: effect_control_2039_w: %04x\n", machine().describe_context(), data);
}
void spg110_video_device::huereference_203c_w(uint16_t data)
{
// 0006 on startup, twice
logerror("%s: huereference_203c_w: %04x\n", machine().describe_context(), data);
}
void spg110_video_device::lum_adjust_203d_w(uint16_t data)
{
// changes, usually between scenes (brightness)
logerror("%s: lum_adjust_203d_w: %04x\n", machine().describe_context(), data);
}
uint16_t spg110_video_device::sp_control_2042_r()
{
return 0x0000;
}
void spg110_video_device::sp_control_2042_w(uint16_t data)
{
// sets bit 0x0004, masks with 0xfffb etc.
logerror("%s: sp_control_2042_w: %04x\n", machine().describe_context(), data);
}
void spg110_video_device::spg110_2045_w(uint16_t data)
{
// 0006 on startup, once
logerror("%s: spg110_2045_w: %04x\n", machine().describe_context(), data);
}
void spg110_video_device::transparent_color_205x_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
COMBINE_DATA(&m_palctrlram[offset]);
}
void spg110_video_device::dma_dst_seg_2061_w(offs_t offset, uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_dma_dst_seg); }
void spg110_video_device::dma_dst_step_2064_w(offs_t offset, uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_dma_dst_step); }
void spg110_video_device::dma_source_seg_2067_w(offs_t offset, uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_dma_src_seg); }
void spg110_video_device::dma_src_step_2068_w(offs_t offset, uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_dma_src_step); }
uint16_t spg110_video_device::dma_src_step_2068_r(offs_t offset, uint16_t mem_mask) { return m_dma_src_step; }
void spg110_video_device::dma_unk_2061_w(offs_t offset, uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_dma_unk_2061); }
void spg110_video_device::dma_dst_step_w(offs_t offset, uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_dma_dst_step); }
void spg110_video_device::dma_unk_2067_w(offs_t offset, uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_dma_src_high); }
void spg110_video_device::dma_src_step_w(offs_t offset, uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_dma_src_step); }
void spg110_video_device::dma_dst_2060_w(offs_t offset, uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_dma_dst); }
void spg110_video_device::dma_source_2066_w(offs_t offset, uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_dma_src); }
void spg110_video_device::dma_dst_w(offs_t offset, uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_dma_dst); }
void spg110_video_device::dma_src_w(offs_t offset, uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_dma_src); }
void spg110_video_device::dma_len_trigger_w(uint16_t data)
void spg110_video_device::dma_len_trigger_2062_w(uint16_t data)
{
int length = data & 0x1fff;
m_dma_irq_flag = 0;
m_dma_busy = 1;
update_video_irqs();
// this is presumably a counter that underflows to 0x1fff, because that's what the wait loop waits for?
logerror("%s: (trigger len) %04x with values (unk) %04x (dststep) %04x (srchigh) %04x (src step) %04x | (dst) %04x (src) %04x\n", machine().describe_context(), data, m_dma_unk_2061, m_dma_dst_step, m_dma_src_high, m_dma_src_step, m_dma_dst, m_dma_src);
logerror("%s: (trigger len) %04x with values (dstseg) %04x (dststep) %04x (srchigh) %04x (src step) %04x | (dst) %04x (src) %04x\n", machine().describe_context(), data, m_dma_dst_seg, m_dma_dst_step, m_dma_src_seg, m_dma_src_step, m_dma_dst, m_dma_src);
/*
if (m_dma_unk_2061 != 0x0000)
if (m_dma_dst_seg != 0x0000)
{
logerror("unknown DMA params are not zero!\n");
}
*/
int source = m_dma_src | m_dma_src_high << 16;
int source = m_dma_src | m_dma_src_seg << 16;
int dest = m_dma_dst;
// bits 0xc000 are 'DMABANK'
// the use of other bits change slightly depending on them, for example
// palette tranfsers only use the bottom 8 bits of dest, jak_bobb relies on this or bridge pieces have no palette
if ((m_dma_dst & 0xc000) == 0x4000)
dest &= 0x40ff;
for (int i = 0; i < length; i++)
{
address_space &mem = m_cpu->space(AS_PROGRAM);
@ -435,38 +557,28 @@ void spg110_video_device::dma_len_trigger_w(uint16_t data)
}
// not sure, spiderman would suggest that some of these need to reset (unless a missing IRQ clears them)
m_dma_unk_2061 = 0;
m_dma_dst_seg = 0;
//m_dma_dst_step = 0; // conyteni says no
m_dma_src_high = 0;
m_dma_src_seg = 0;
//m_dma_src_step = 0; // conyteni says no
m_dma_dst = 0;
m_dma_src = 0;
m_dma_dst = dest;
m_dma_src = source;
// HACK: it really seems this interrupt status is related to the DMA, but jak_capb doesn't ack it, so must also be a way to disable it?
if (m_is_spiderman)
{
const int i = 0x0002;
if (m_video_irq_enable & 1)
{
m_video_irq_status |= i;
check_video_irq();
}
}
m_dma_timer->adjust(attotime::from_usec(20));
}
void spg110_video_device::dma_manual_w(uint16_t data)
void spg110_video_device::dma_manual_2065_w(uint16_t data)
{
this->space(0).write_word(m_dma_dst * 2, data, 0xffff);
}
uint16_t spg110_video_device::dma_manual_r()
uint16_t spg110_video_device::dma_manual_2065_r()
{
uint16_t val = this->space(0).read_word(m_dma_dst * 2);
return val;
}
uint16_t spg110_video_device::dma_len_status_r()
uint16_t spg110_video_device::dma_len_status_2062_r()
{
return 0x1fff; // DMA related?
}
@ -490,8 +602,6 @@ void spg110_video_device::tilemap_write_regs(int which, uint16_t* regs, int regn
break;
case 0x2: // Page Attributes
// 'priority' can't be priority here as it is on spg2xx, or the scores in attract will be behind the table, it really seems to be per attribute bit instead
logerror("video_w: Page %d Attributes = %04x (Priority:%d, Palette:%d, VSize:%d, HSize:%d, FlipY:%d, FlipX:%d, BPP:%d)\n", which, data
, (data >> 12) & 3, (data >> 8) & 15, 8 << ((data >> 6) & 3), 8 << ((data >> 4) & 3), BIT(data, 3), BIT(data, 2), 2 * ((data & 3) + 1));
regs[regno] = data;
@ -530,14 +640,13 @@ void spg110_video_device::tmap1_regs_w(offs_t offset, uint16_t data)
// this seems to be a different, non-cpu mapped space only accessible via the DMA?
void spg110_video_device::map_video(address_map &map)
{
// are these addresses hardcoded, or can they move (in which case tilemap system isn't really suitable)
map(0x00000, 0x03fff).ram(); // 2fff?
map(0x00000, 0x02fff).ram();
map(0x04000, 0x041ff).ram().share("sprtileno"); // seems to be 3 blocks, almost certainly spritelist
map(0x04000, 0x041ff).ram().share("sprtileno");
map(0x04200, 0x043ff).ram().share("sprattr1");
map(0x04400, 0x045ff).ram().share("sprattr2");
map(0x08000, 0x081ff).ram().w(FUNC(spg110_video_device::palette_w)).share("palram"); // palette format unknown
map(0x08000, 0x081ff).ram().w(FUNC(spg110_video_device::palette_w)).share("palram");
}
// Not used, for reference
@ -690,26 +799,43 @@ void spg110_video_device::device_start()
{
save_item(NAME(m_dma_src_step));
save_item(NAME(m_dma_dst_step));
save_item(NAME(m_dma_unk_2061));
save_item(NAME(m_dma_src_high));
save_item(NAME(m_dma_dst_seg));
save_item(NAME(m_dma_src_seg));
save_item(NAME(m_dma_dst));
save_item(NAME(m_dma_src));
save_item(NAME(m_bg_scrollx));
save_item(NAME(m_bg_scrolly));
save_item(NAME(m_2036_scroll));
save_item(NAME(m_tm_v_2036));
save_item(NAME(m_tm_h_2037));
save_item(NAME(m_blk_irq_enable));
save_item(NAME(m_blk_irq_flag));
save_item(NAME(m_dma_irq_enable));
save_item(NAME(m_dma_irq_flag));
save_item(NAME(m_vdo_irq_enable));
save_item(NAME(m_vdo_irq_flag));
save_item(NAME(m_dma_busy));
m_screenpos_timer = timer_alloc(FUNC(spg110_video_device::screenpos_hit), this);
m_screenpos_timer->adjust(attotime::never);
m_dma_timer = timer_alloc(FUNC(spg110_video_device::dma_done), this);
m_dma_timer->adjust(attotime::never);
}
void spg110_video_device::device_reset()
{
m_dma_src_step = 0;
m_dma_dst_step = 0;
m_dma_unk_2061 = 0;
m_dma_src_high = 0;
m_dma_dst_seg = 0;
m_dma_src_seg = 0;
m_dma_dst = 0;
m_dma_src = 0;
m_bg_scrollx = 0;
m_bg_scrolly = 0;
m_2036_scroll = 0;
m_tm_v_2036 = 0xffff;
m_tm_h_2037 = 0xffff;
std::fill(std::begin(tmap0_regs), std::end(tmap0_regs), 0);
std::fill(std::begin(tmap1_regs), std::end(tmap1_regs), 0);
@ -717,6 +843,45 @@ void spg110_video_device::device_reset()
// is there actually an enable register here?
m_video_irq_enable = 0xffff;
m_video_irq_status = 0x0000;
m_blk_irq_enable = 0;
m_blk_irq_flag = 0;
m_dma_irq_enable = 0;
m_dma_irq_flag = 0;
m_vdo_irq_enable = 0;
m_vdo_irq_flag = 0;
m_dma_busy = 0;
}
TIMER_CALLBACK_MEMBER(spg110_video_device::dma_done)
{
m_dma_irq_flag = 1;
m_dma_busy = 0;
update_video_irqs();
m_dma_timer->adjust(attotime::never);
}
void spg110_video_device::update_raster_interrupt_timer()
{
if (m_tm_h_2037 < 320 && m_tm_v_2036 < 240)
{
m_screenpos_timer->adjust(m_screen->time_until_pos(m_tm_v_2036, m_tm_h_2037));
}
else
m_screenpos_timer->adjust(attotime::never);
}
TIMER_CALLBACK_MEMBER(spg110_video_device::screenpos_hit)
{
m_vdo_irq_flag = 1;
update_video_irqs();
m_screen->update_partial(m_screen->vpos());
// fire again (based on spg2xx logic)
m_screenpos_timer->adjust(m_screen->time_until_pos(m_tm_v_2036, m_tm_h_2037));
}
void spg110_video_device::palette_w(offs_t offset, uint16_t data, uint16_t mem_mask)
@ -727,27 +892,27 @@ void spg110_video_device::palette_w(offs_t offset, uint16_t data, uint16_t mem_m
uint32_t spg110_video_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
memset(&m_screenbuf[320 * cliprect.min_y], 0, 4 * 320 * ((cliprect.max_y - cliprect.min_y) + 1));
const uint32_t page1_addr = 0x40 * m_tilebase;//0x40 * m_video_regs[0x20];
const uint32_t page2_addr = 0x40 * m_tilebase;//0x40 * m_video_regs[0x21];
uint16_t *page1_regs = tmap0_regs;
uint16_t *page2_regs = tmap1_regs;
const pen_t *pens = m_palette->pens();
const uint32_t page1_addr = 0x40 * m_tilebase[0];
const uint32_t page2_addr = 0x40 * m_tilebase[0];
for (uint32_t scanline = (uint32_t)cliprect.min_y; scanline <= (uint32_t)cliprect.max_y; scanline++)
{
for (int x = cliprect.min_x; x <= cliprect.max_x; x++)
m_screenbuf[(320 * scanline) + x] = pens[0];
for (int i = 0; i < 4; i++)
{
draw_page(cliprect, scanline, i, page2_addr, page2_regs);
draw_page(cliprect, scanline, i, page1_addr, page1_regs);
draw_page(cliprect, scanline, i, page1_addr, tmap0_regs);
draw_page(cliprect, scanline, i, page2_addr, tmap1_regs);
draw_sprites(cliprect, scanline, i);
}
}
for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
{
uint32_t *dest = &bitmap.pix(y, cliprect.min_x);
const uint32_t *src = &m_screenbuf[cliprect.min_x + 320 * y];
uint32_t* dest = &bitmap.pix(y, cliprect.min_x);
const uint32_t* src = &m_screenbuf[cliprect.min_x + 320 * y];
std::copy_n(src, cliprect.width(), dest);
}
@ -756,23 +921,6 @@ uint32_t spg110_video_device::screen_update(screen_device &screen, bitmap_rgb32
void spg110_video_device::vblank(int state)
{
const int i = 0x0008;
if (!state)
{
m_video_irq_status &= ~i;
check_video_irq();
return;
}
if (m_video_irq_enable & 1)
{
m_video_irq_status |= i;
check_video_irq();
}
}
void spg110_video_device::check_video_irq()
{
m_video_irq_cb((m_video_irq_status & m_video_irq_enable) ? ASSERT_LINE : CLEAR_LINE);
m_blk_irq_flag = state;
update_video_irqs();
}

View File

@ -27,58 +27,57 @@ public:
m_screen.set_tag(std::forward<U>(screen_tag));
}
void set_video_irq_spidman(bool is_spiderman) { m_is_spiderman = is_spiderman; }
void map_video(address_map &map) ATTR_COLD;
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
void vblank(int state);
void spg110_201c_w(uint16_t data);
void spg110_2020_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void vcomp_val_201c_w(uint16_t data);
void segment_202x_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void spg110_2028_w(uint16_t data);
void spg110_2029_w(uint16_t data);
void adr_mode_2028_w(uint16_t data);
void ext_bus_2029_w(uint16_t data);
uint16_t spg110_2028_r();
uint16_t spg110_2029_r();
uint16_t adr_mode_2028_r();
uint16_t ext_bus_2029_r();
void spg110_2031_w(uint16_t data);
void spg110_2032_w(uint16_t data);
void spg110_2033_w(uint16_t data);
void spg110_2034_w(uint16_t data);
void spg110_2035_w(uint16_t data);
void spg110_2036_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void spg110_2037_w(uint16_t data);
void spg110_2039_w(uint16_t data);
void win_mask_1_2031_w(uint16_t data);
void win_mask_2_2032_w(uint16_t data);
void win_attribute_w(uint16_t data);
void win_mask_3_2034_w(uint16_t data);
void win_mask_4_2035_w(uint16_t data);
void irq_tm_v_2036_w(uint16_t data);
void irq_tm_h_2037_w(uint16_t data);
void effect_control_2039_w(uint16_t data);
void spg110_203c_w(uint16_t data);
void spg110_203d_w(uint16_t data);
void huereference_203c_w(uint16_t data);
void lum_adjust_203d_w(uint16_t data);
void spg110_2042_w(uint16_t data);
void sp_control_2042_w(uint16_t data);
void spg110_2045_w(uint16_t data);
void spg110_205x_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void transparent_color_205x_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
uint16_t spg110_2037_r();
uint16_t spg110_2042_r();
uint16_t irq_tm_h_2037_r();
uint16_t sp_control_2042_r();
void dma_dst_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void dma_unk_2061_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void dma_len_trigger_w(uint16_t data);
void dma_dst_2060_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void dma_dst_seg_2061_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void dma_len_trigger_2062_w(uint16_t data);
void spg110_2063_w(uint16_t data);
void dma_dst_step_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void dma_src_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void dma_unk_2067_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void dma_src_step_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void dma_dst_step_2064_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void dma_source_2066_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void dma_source_seg_2067_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void dma_src_step_2068_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
uint16_t dma_src_step_2068_r(offs_t offset, uint16_t mem_mask);
uint16_t dma_len_status_r();
uint16_t dma_len_status_2062_r();
uint16_t spg110_2063_r();
uint16_t dma_manual_r();
void dma_manual_w(uint16_t data);
uint16_t dma_manual_2065_r();
void dma_manual_2065_w(uint16_t data);
uint16_t tmap0_regs_r(offs_t offset);
uint16_t tmap1_regs_r(offs_t offset);
@ -105,9 +104,7 @@ private:
PAGE_PRIORITY_FLAG_MASK = 0x3000,
PAGE_PRIORITY_FLAG_SHIFT = 12,
PAGE_TILE_HEIGHT_MASK = 0x00c0,
PAGE_TILE_HEIGHT_SHIFT = 6,
PAGE_TILE_WIDTH_MASK = 0x0030,
PAGE_TILE_WIDTH_SHIFT = 4,
TILE_X_FLIP = 0x0004,
@ -140,21 +137,21 @@ private:
uint16_t m_dma_src_step;
uint16_t m_dma_dst_step;
uint16_t m_dma_unk_2061;
uint16_t m_dma_src_high;
uint16_t m_dma_dst_seg;
uint16_t m_dma_src_seg;
uint16_t m_dma_dst;
uint16_t m_dma_src;
uint16_t m_bg_scrollx;
uint16_t m_bg_scrolly;
uint16_t m_2036_scroll;
uint16_t m_tm_v_2036;
uint16_t m_tm_h_2037;
uint16_t m_tilebase;
uint16_t m_tilebase[8];
uint16_t m_video_irq_enable;
uint16_t m_video_irq_status;
void check_video_irq();
void tilemap_write_regs(int which, uint16_t* regs, int regno, uint16_t data);
@ -164,8 +161,28 @@ private:
void draw_sprite(const rectangle &cliprect, uint32_t scanline, int priority, uint32_t base_addr);
void draw_sprites(const rectangle &cliprect, uint32_t scanline, int priority);
void update_raster_interrupt_timer();
TIMER_CALLBACK_MEMBER(screenpos_hit);
TIMER_CALLBACK_MEMBER(dma_done);
void update_video_irqs();
uint8_t m_blk_irq_enable;
uint8_t m_blk_irq_flag;
uint8_t m_dma_irq_enable;
uint8_t m_dma_irq_flag;
uint8_t m_vdo_irq_enable;
uint8_t m_vdo_irq_flag;
uint8_t m_dma_busy;
emu_timer *m_screenpos_timer;
emu_timer *m_dma_timer;
uint32_t m_screenbuf[320 * 240];
bool m_is_spiderman;
devcb_write_line m_video_irq_cb;
};

View File

@ -45930,12 +45930,14 @@ pi_stry
pi_stry2
@source:tvgames/spg110.cpp
conyfght
conyping //
conyteni //
easports
jak_bobb
jak_capb //
jak_spdmo //
jak_spdmoa
conyteni //
conyping //
conyfght
sstarkar
@source:tvgames/spg29x.cpp

View File

@ -12,10 +12,10 @@
Conny TV Virtual Tennis
Conny Ping Pong
Conny TV Virtual Fighter
JAKKS EA Sports (NHL 95 + Fifa 96) (EU)
assumed:
JAKKS EA Sports (NHL 95 + Madden 95) (US)
JAKKS EA Sports (NHL 95 + Fifa 96) (US)
JAKKS Bob the Builder
JAKKS Disney (original release)
@ -27,7 +27,10 @@
#include "bus/generic/carts.h"
#include "cpu/unsp/unsp.h"
#include "machine/nvram.h"
#include "machine/spg110.h"
#include "screen.h"
#include "softlist_dev.h"
#include "speaker.h"
@ -45,7 +48,7 @@ public:
{ }
void spg110_base(machine_config &config);
void spg110_spdmo(machine_config& config);
void spg110_base_pal(machine_config &config);
ioport_value plunger_r();
@ -56,6 +59,18 @@ protected:
virtual void mem_map(address_map &map) ATTR_COLD;
};
class spg110_easports_game_state : public spg110_game_state
{
public:
spg110_easports_game_state(const machine_config &mconfig, device_type type, const char *tag) :
spg110_game_state(mconfig, type, tag)
{ }
void easports_pal(machine_config &config);
private:
virtual void mem_map(address_map &map) override ATTR_COLD;
};
class spg110_sstarkar_game_state : public spg110_game_state
{
public:
@ -64,7 +79,7 @@ public:
m_cart(*this, "cartslot"),
m_cartrom(*this, "cartrom")
{ }
public:
void sstarkar(machine_config &config);
protected:
@ -92,6 +107,14 @@ void spg110_sstarkar_game_state::mem_map_cart(address_map &map)
map(0x004000, 0x0fffff).bankr("cartrom");
}
void spg110_easports_game_state::mem_map(address_map &map)
{
//map(0x001000, 0x007fff).ram(); // ??
map(0x004000, 0x2fffff).rom().region("maincpu", 0x8000);
map(0x3e0000, 0x3effff).ram().share("nvram"); // size? is all of it backed up?
map(0x3f0000, 0x3fffff).ram(); // seems to only be used for GFX data
}
static INPUT_PORTS_START( jak_capb )
PORT_START("PA")
@ -254,129 +277,8 @@ ioport_value spg110_game_state::plunger_r()
}
static INPUT_PORTS_START( jak_spdmo )
PORT_START("PA")
PORT_BIT( 0x001f, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("Menu / Pause")
PORT_BIT( 0x00c0, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_BUTTON4 )
PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_BUTTON3 )
PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_BUTTON2 )
PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_BUTTON1 )
PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_NAME("Joypad Right")
PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_NAME("Joypad Left")
PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_NAME("Joypad Down")
PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_NAME("Joypad Up")
PORT_START("PB")
PORT_DIPNAME( 0x0001, 0x0000, "PB" )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0001, DEF_STR( On ) )
PORT_DIPNAME( 0x0002, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0002, DEF_STR( On ) )
PORT_DIPNAME( 0x0004, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0004, DEF_STR( On ) )
PORT_DIPNAME( 0x0008, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0008, DEF_STR( On ) )
PORT_DIPNAME( 0x0010, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0010, DEF_STR( On ) )
PORT_DIPNAME( 0x0020, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0020, DEF_STR( On ) )
PORT_DIPNAME( 0x0040, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0040, DEF_STR( On ) )
PORT_DIPNAME( 0x0080, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0080, DEF_STR( On ) )
PORT_DIPNAME( 0x0100, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0100, DEF_STR( On ) )
PORT_DIPNAME( 0x0200, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0200, DEF_STR( On ) )
PORT_DIPNAME( 0x0400, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0400, DEF_STR( On ) )
PORT_DIPNAME( 0x0800, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0800, DEF_STR( On ) )
PORT_DIPNAME( 0x1000, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x1000, DEF_STR( On ) )
PORT_DIPNAME( 0x2000, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x2000, DEF_STR( On ) )
PORT_DIPNAME( 0x4000, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x4000, DEF_STR( On ) )
PORT_DIPNAME( 0x8000, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x8000, DEF_STR( On ) )
PORT_START("PC")
PORT_DIPNAME( 0x0001, 0x0000, "PC" )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0001, DEF_STR( On ) )
PORT_DIPNAME( 0x0002, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0002, DEF_STR( On ) )
PORT_DIPNAME( 0x0004, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0004, DEF_STR( On ) )
PORT_DIPNAME( 0x0008, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0008, DEF_STR( On ) )
PORT_DIPNAME( 0x0010, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0010, DEF_STR( On ) )
PORT_DIPNAME( 0x0020, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0020, DEF_STR( On ) )
PORT_DIPNAME( 0x0040, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0040, DEF_STR( On ) )
PORT_DIPNAME( 0x0080, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0080, DEF_STR( On ) )
PORT_DIPNAME( 0x0100, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0100, DEF_STR( On ) )
PORT_DIPNAME( 0x0200, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0200, DEF_STR( On ) )
PORT_DIPNAME( 0x0400, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0400, DEF_STR( On ) )
PORT_DIPNAME( 0x0800, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0800, DEF_STR( On ) )
PORT_DIPNAME( 0x1000, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x1000, DEF_STR( On ) )
PORT_DIPNAME( 0x2000, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x2000, DEF_STR( On ) )
PORT_DIPNAME( 0x4000, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x4000, DEF_STR( On ) )
PORT_DIPNAME( 0x8000, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x8000, DEF_STR( On ) )
PORT_START("JOYX")
PORT_START("JOYY")
INPUT_PORTS_END
static INPUT_PORTS_START( conyteni )
static INPUT_PORTS_START( spg110_base )
PORT_START("PA")
PORT_DIPNAME( 0x0001, 0x0000, "PA" )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
@ -431,15 +333,27 @@ static INPUT_PORTS_START( conyteni )
PORT_DIPNAME( 0x0001, 0x0000, "PB" )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0001, DEF_STR( On ) )
PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Console Back")
PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Console Enter")
PORT_DIPNAME( 0x0002, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0002, DEF_STR( On ) )
PORT_DIPNAME( 0x0004, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0004, DEF_STR( On ) )
PORT_DIPNAME( 0x0008, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0008, DEF_STR( On ) )
PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_NAME("Console Right")
PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_NAME("Console Down")
PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_NAME("Console Left")
PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_NAME("Console Up")
PORT_DIPNAME( 0x0010, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0010, DEF_STR( On ) )
PORT_DIPNAME( 0x0020, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0020, DEF_STR( On ) )
PORT_DIPNAME( 0x0040, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0040, DEF_STR( On ) )
PORT_DIPNAME( 0x0080, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0080, DEF_STR( On ) )
PORT_DIPNAME( 0x0100, 0x0000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0100, DEF_STR( On ) )
@ -518,7 +432,82 @@ static INPUT_PORTS_START( conyteni )
PORT_START("JOYX")
PORT_START("JOYY")
INPUT_PORTS_END
static INPUT_PORTS_START( jak_spdmo )
PORT_INCLUDE( spg110_base )
PORT_MODIFY("PA")
PORT_BIT( 0x001f, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("Menu / Pause")
PORT_BIT( 0x00c0, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_BUTTON4 )
PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_BUTTON3 )
PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_BUTTON2 )
PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_BUTTON1 )
PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_NAME("Joypad Right")
PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_NAME("Joypad Left")
PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_NAME("Joypad Down")
PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_NAME("Joypad Up")
INPUT_PORTS_END
static INPUT_PORTS_START( jak_bobb )
PORT_INCLUDE( spg110_base )
PORT_MODIFY("PA")
PORT_BIT( 0x001f, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("Menu / Pause")
PORT_BIT( 0x00c0, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_BUTTON1 )
// not technically a joystick, so 2 opposing buttons could be pressed, but maps where Joystick usually maps
// using PORT_16WAY for now like ksys573.cpp
PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_NAME("Right / Blue") PORT_16WAY
PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_NAME("Left / Green") PORT_16WAY
PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_NAME("Down / Red") PORT_16WAY
PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_NAME("Up / Yellow") PORT_16WAY
INPUT_PORTS_END
static INPUT_PORTS_START( easports )
PORT_INCLUDE( spg110_base )
PORT_MODIFY("PA")
// not all units had 2 control pads
// hold right and button 2 (B) on startup for ROM test
PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2)
PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2)
PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2)
PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(2)
PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_PLAYER(2) // START
PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(2) // B
PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(2) // A
PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_PLAYER(2) // C
PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_PLAYER(1) // START
PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(1) // B
PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(1) // A
PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_PLAYER(1) // C
PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1)
PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1)
PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1)
PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(1)
PORT_MODIFY("PC") // different configurations were hardwired, this can't be changed by the user
PORT_CONFNAME(0x01, 0x00, "Pad Configuration")
PORT_CONFSETTING(0x01, "Single")
PORT_CONFSETTING(0x00, "Double")
INPUT_PORTS_END
static INPUT_PORTS_START( conyteni )
PORT_INCLUDE( spg110_base )
PORT_MODIFY("PB")
PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Console Back")
PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Console Enter")
PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_NAME("Console Right")
PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_NAME("Console Down")
PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_NAME("Console Left")
PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_NAME("Console Up")
INPUT_PORTS_END
void spg110_game_state::spg110_base(machine_config &config)
@ -544,13 +533,21 @@ void spg110_game_state::spg110_base(machine_config &config)
m_maincpu->add_route(ALL_OUTPUTS, "rspeaker", 0.5);
}
void spg110_game_state::spg110_spdmo(machine_config& config)
void spg110_game_state::spg110_base_pal(machine_config &config)
{
spg110_base(config);
m_maincpu->set_video_irq_spidman(true);
m_screen->set_refresh_hz(50);
}
void spg110_easports_game_state::easports_pal(machine_config &config)
{
spg110_base_pal(config);
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
}
void spg110_sstarkar_game_state::machine_start()
{
// if there's a cart, override the standard mapping
@ -603,6 +600,25 @@ ROM_START( jak_spdmoa )
ROM_LOAD16_WORD_SWAP( "spiderman.bin", 0x000000, 0x200000, CRC(b2a5a55a) SHA1(93c87ac0387997b753d4f0fb894a0dd02138b460) )
ROM_END
ROM_START( jak_bobb )
ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 )
ROM_LOAD16_WORD_SWAP( "bob.bin", 0x000000, 0x400000, CRC(16b0b39f) SHA1(43a45e5346d108a9ec1b672fa727e97722b4eaa1) )
ROM_END
ROM_START( easports )
ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 )
ROM_LOAD16_WORD_SWAP( "ea.u3", 0x000000, 0x400000, CRC(d750089e) SHA1(426f04c3d841103d434a892561db55ade684db54) )
ROM_LOAD16_WORD_SWAP( "ea.u4", 0x400000, 0x200000, CRC(20a63445) SHA1(8c3383a353638c7d6b795d15a751275043eacbd0) )
ROM_REGION( 0x20000, "nvram", ROMREGION_ERASE00 )
// There is a coin style battery backing up at least some of the RAM.
// The games seems to fail to initialize it properly first time, resulting in a hang shortly after
// selecting a game. Provide a default (at least for now)
// Random default fills, All 1, or All 0 do not work in this case
ROM_LOAD( "nvram", 0x000000, 0x20000, CRC(bfcbd206) SHA1(0f5b730679762547a0658c2cd0d4fa5169b857af) )
ROM_END
ROM_START( conyteni )
ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 )
ROM_LOAD16_WORD_SWAP( "tennis_m29w160eb.bin", 0x000000, 0x200000, CRC(70050f17) SHA1(929f0d8599b7380b5994684424bb91063c4f6569) )
@ -635,8 +651,11 @@ ROM_END
// JAKKS Pacific Inc TV games
CONS( 2004, jak_capb, 0, 0, spg110_base, jak_capb, spg110_game_state, empty_init, "JAKKS Pacific Inc / HotGen Ltd", "Classic Arcade Pinball (JAKKS Pacific TV Game)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )
CONS( 2004, jak_spdmo, jak_spdm, 0, spg110_spdmo, jak_spdmo, spg110_game_state, empty_init, "JAKKS Pacific Inc / Digital Eclipse", "Spider-Man (JAKKS Pacific TV Game) (older hardware, set 1)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS ) // this is the smaller more 'square' style joystick that was originally released before the GameKey slot was added.
CONS( 2004, jak_spdmoa,jak_spdm, 0, spg110_spdmo, jak_spdmo, spg110_game_state, empty_init, "JAKKS Pacific Inc / Digital Eclipse", "Spider-Man (JAKKS Pacific TV Game) (older hardware, set 2)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS ) // this is the resdesigned stick, but before the GameKey release
CONS( 2004, jak_spdmo, jak_spdm, 0, spg110_base, jak_spdmo, spg110_game_state, empty_init, "JAKKS Pacific Inc / Digital Eclipse", "Spider-Man (JAKKS Pacific TV Game) (older hardware, set 1)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS ) // this is the smaller more 'square' style joystick that was originally released before the GameKey slot was added.
CONS( 2004, jak_spdmoa,jak_spdm, 0, spg110_base, jak_spdmo, spg110_game_state, empty_init, "JAKKS Pacific Inc / Digital Eclipse", "Spider-Man (JAKKS Pacific TV Game) (older hardware, set 2)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS ) // this is the resdesigned stick, but before the GameKey release
// has Game-Key strings in test mode even if there were no SPG110 Game-Key units at all
CONS( 2006, jak_bobb, 0, 0, spg110_base, jak_bobb, spg110_game_state, empty_init, "JAKKS Pacific Inc / HotGen Ltd", "Bob the Builder - Project: Build It (JAKKS Pacific TV Game) (JUN 2 2006 14:42:01)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )
// this was sold by SDW Games for the US market, ROM not yet verified to be the same, also appears in some multigames?
CONS( 2003, conyteni, 0, 0, spg110_base, conyteni, spg110_game_state, empty_init, "Conny", "TV Virtual Tennis", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS ) // needs motion inputs, and video fixes, setting to PAL
@ -650,3 +669,6 @@ CONS( 200?, conyfght, 0, 0, spg110_base, conyteni, spg110_game_state, e
// The unit contains no BIOS ROM, was sold by Taikee as Singing Star Karaoke, but also by Imaginarium / ItsMagical in Spain as Karao Kids. Cartridges are compatible.
CONS( 200?, sstarkar, 0, 0, sstarkar, conyteni, spg110_sstarkar_game_state, empty_init, "Taikee", "Singing Star Karaoke (World) / Karao Kids (Spain)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS ) // "ItsMagical" brand from Imaginarium
CONS( 2004, easports, 0, 0, easports_pal, easports, spg110_easports_game_state, empty_init, "JAKKS Pacific Inc / Digital Eclipse", "EA Sports Classics: NHL 95 & FIFA Soccer 96 (JAKKS Pacific TV Game)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )
// US release has Madden instead of FIFA