continued study of later unsp20 type SoCs used by JAKKS titles (nw) (#6091)

* experiments with the unsp20 based stuff (nw)

* some notes (nw)

* notes (nw)

* NAND type notes (nw)

* only copy needed boot code (nw)

* document (nw)

* more notes etc. (nw)

* kill debug statement (nw)

* typo (nw)

* some readback (nw)

* (nw)
This commit is contained in:
David Haywood 2019-12-24 20:37:00 +00:00 committed by R. Belmont
parent ad34f923c3
commit 3ed061acaa
8 changed files with 467 additions and 150 deletions

View File

@ -60,7 +60,7 @@ void unsp_12_device::execute_exxx_group(uint16_t op)
return;
case 0x03:
fatalerror("UNSP: unknown opcode invb Rd,offset (%04x) at %04x\n", op, UNSP_LPC);
m_core->m_r[rd] ^= (1 << offset);
return;
}
return;

View File

@ -37,28 +37,63 @@ generalplus_gpac800_device::generalplus_gpac800_device(const machine_config &mco
// **************************************** SYSTEM DMA device *************************************************
uint16_t sunplus_gcm394_base_device::read_dma_params(int channel, int offset)
{
uint16_t retdata = m_dma_params[offset][channel];
LOGMASKED(LOG_GCM394_SYSDMA, "%s:sunplus_gcm394_base_device::read_dma_params (channel %01x) %01x returning %04x\n", machine().describe_context(), channel, offset, retdata);
return retdata;
}
void sunplus_gcm394_base_device::write_dma_params(int channel, int offset, uint16_t data)
{
m_dma_params[offset][channel] = data;
LOGMASKED(LOG_GCM394_SYSDMA, "%s:sunplus_gcm394_base_device::write_dma_params (channel %01x) %01x %04x\n", machine().describe_context(), channel, offset, data);
}
READ16_MEMBER(sunplus_gcm394_base_device::system_dma_params_channel0_r)
{
return read_dma_params(0, offset);
}
WRITE16_MEMBER(sunplus_gcm394_base_device::system_dma_params_channel0_w)
{
write_dma_params(0, offset, data);
}
READ16_MEMBER(sunplus_gcm394_base_device::system_dma_params_channel1_r)
{
return read_dma_params(1, offset);
}
WRITE16_MEMBER(sunplus_gcm394_base_device::system_dma_params_channel1_w)
{
write_dma_params(1, offset, data);
}
READ16_MEMBER(sunplus_gcm394_base_device::system_dma_status_r)
{
LOGMASKED(LOG_GCM394_SYSDMA, "%s:sunplus_gcm394_base_device::system_dma_status_r (7abf)\n", machine().describe_context());
return 0x0001;
// bit 0 = channel 0 ready
// bit 1 = channel 1 ready
return 0x0003;
}
WRITE16_MEMBER(sunplus_gcm394_base_device::system_dma_params_w)
void sunplus_gcm394_base_device::trigger_systemm_dma(address_space &space, int channel, uint16_t data)
{
m_dma_params[offset] = data;
LOGMASKED(LOG_GCM394_SYSDMA, "%s:sunplus_gcm394_base_device::sys_dma_params_w %01x %04x\n", machine().describe_context(), offset, data);
}
WRITE16_MEMBER(sunplus_gcm394_base_device::system_dma_trigger_w)
{
uint16_t mode = m_dma_params[0];
uint32_t source = m_dma_params[1] | (m_dma_params[4] << 16);
uint32_t dest = m_dma_params[2] | (m_dma_params[5] << 16) ;
uint32_t length = m_dma_params[3] | (m_dma_params[6] << 16);
uint16_t mode = m_dma_params[0][channel];
uint32_t source = m_dma_params[1][channel] | (m_dma_params[4][channel] << 16);
uint32_t dest = m_dma_params[2][channel] | (m_dma_params[5][channel] << 16) ;
uint32_t length = m_dma_params[3][channel] | (m_dma_params[6][channel] << 16);
LOGMASKED(LOG_GCM394_SYSDMA, "%s:possible DMA operation (7abf) (trigger %04x) with params mode:%04x source:%08x (word offset) dest:%08x (word offset) length:%08x (words)\n", machine().describe_context(), data, mode, source, dest, length );
if (source >= 0x20000)
if ((source&0x0fffffff) >= 0x20000)
LOGMASKED(LOG_GCM394_SYSDMA, " likely transfer from ROM %08x - %08x\n", (source - 0x20000) * 2, (source - 0x20000) * 2 + (length * 2)- 1);
// wrlshunt transfers ROM to RAM, all RAM write addresses have 0x800000 in the destination set
@ -67,7 +102,41 @@ WRITE16_MEMBER(sunplus_gcm394_base_device::system_dma_trigger_w)
// mode 0x0009 == regular copy? (smartfp does 2 copies like this after the initial clears, source definitely points at a correctly sized data structure)
// what does having bit 0x4000 on mode set mean? (first transfer on wrlshunt - maybe an IRQ disable?)
if ((mode == 0x0089) || (mode == 0x0009) || (mode == 0x4009))
if (mode == 0x1089) // 8-bit no increment mode, counter is in bytes? used for DMA from NAND (first writes 0x1088 then does an OR with 0x0001)
{
address_space& mem = this->space(AS_PROGRAM);
source &= 0x0fffffff;
for (int i = 0; i < length/2; i++)
{
uint16_t val1 = mem.read_word(source);
uint16_t val2 = mem.read_word(source);
//printf("val1 %04x val2 %04x\n", val1, val2);
uint16_t val = (val2 << 8) | val1;
m_space_write_cb(space, dest, val);
dest += 1;
}
// HACKS to get into service mode for debugging
// note, these patch the code copied to SRAM so the 'PROGRAM ROM' check fails (it passes otherwise)
if (mem.read_word(0x3f368) == 0x4840)
mem.write_word(0x3f368, 0x4841); // cars 2 IRQ? wait hack
if (mem.read_word(0x4368c) == 0x4846)
mem.write_word(0x4368c, 0x4840); // cars 2 force service mode
if (mem.read_word(0x4d8d4) == 0x4840)
mem.write_word(0x4d8d4, 0x4841); // golden tee IRQ? wait hack
if (mem.read_word(0x34410) == 0x4846)
mem.write_word(0x34410, 0x4840); // golden tee force service mode
}
else if ((mode == 0x0089) || (mode == 0x0009) || (mode == 0x4009))
{
for (int i = 0; i < length; i++)
{
@ -105,10 +174,16 @@ WRITE16_MEMBER(sunplus_gcm394_base_device::system_dma_trigger_w)
LOGMASKED(LOG_GCM394_SYSDMA, "unhandled!\n");
}
m_dma_params[0] = m_dma_params[1] = m_dma_params[2] = m_dma_params[3] = m_dma_params[4] = m_dma_params[5] = m_dma_params[6] = 0x0000;
m_dma_params[0][channel] = m_dma_params[1][channel] = m_dma_params[2][channel] = m_dma_params[3][channel] = m_dma_params[4][channel] = m_dma_params[5][channel] = m_dma_params[6][channel] = 0x0000;
//machine().debug_break();
}
WRITE16_MEMBER(sunplus_gcm394_base_device::system_dma_trigger_w)
{
if (data & 0x01) trigger_systemm_dma(space, 0, data);
if (data & 0x02) trigger_systemm_dma(space, 1, data);
}
// **************************************** 78xx region with some handling *************************************************
@ -142,39 +217,60 @@ WRITE16_MEMBER(sunplus_gcm394_base_device::unkarea_7803_w) { LOGMASKED(LOG_GCM39
WRITE16_MEMBER(sunplus_gcm394_base_device::unkarea_7807_w) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7807_w %04x\n", machine().describe_context(), data); m_7807 = data; }
// this gets stored / modified / restored before certain memory accesses (in practical terms it just seems to flip from 0/1) maybe it changes the memory mapping (as 7820 seems to)
READ16_MEMBER(sunplus_gcm394_base_device::unkarea_7810_r)
WRITE16_MEMBER(sunplus_gcm394_base_device::waitmode_enter_780c_w)
{
LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7810_r\n", machine().describe_context());
return m_7810;
// LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::waitmode_enter_780c_w %04x\n", machine().describe_context(), data);
// must be followed by 6 nops to ensure wait mode is entered
}
WRITE16_MEMBER(sunplus_gcm394_base_device::unkarea_7810_w)
// this gets stored / modified / restored before certain memory accesses (
// used extensively during SDRAM checks in jak_gtg and jak_car2
READ16_MEMBER(sunplus_gcm394_base_device::membankswitch_7810_r)
{
LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7810_w %04x\n", machine().describe_context(), data);
m_7810 = data;
// LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::membankswitch_7810_r\n", machine().describe_context());
return m_membankswitch_7810;
}
WRITE16_MEMBER(sunplus_gcm394_base_device::membankswitch_7810_w)
{
// if (m_membankswitch_7810 != data)
// LOGMASKED(LOG_GCM394,"%s:sunplus_gcm394_base_device::membankswitch_7810_w %04x\n", machine().describe_context(), data);
popmessage("bankswitch %04x -> %04x", m_membankswitch_7810, data);
m_membankswitch_7810 = data;
}
WRITE16_MEMBER(sunplus_gcm394_base_device::unkarea_7816_w) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7816_w %04x\n", machine().describe_context(), data); m_7816 = data; }
WRITE16_MEMBER(sunplus_gcm394_base_device::unkarea_7817_w) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7817_w %04x\n", machine().describe_context(), data); m_7817 = data; }
WRITE16_MEMBER(sunplus_gcm394_base_device::unkarea_7820_w)
WRITE16_MEMBER(sunplus_gcm394_base_device::chipselect_csx_memory_device_control_w)
{
LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7820_w (Rom Mapping control?) %04x\n", machine().describe_context(), data);
m_7820 = data;
m_mapping_write_cb(data);
}
LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::chipselect_csx_memory_device_control_w %04x (782x registers offset %d)\n", machine().describe_context(), data, offset);
m_782x[offset] = data;
if (offset == 0)
m_mapping_write_cb(data);
static const char* const md[] =
{
"(00) ROM / SRAM",
"(01) ROM / SRAM",
"(10) NOR FLASH",
"(11) NAND FLASH",
};
uint8_t cs_wait = data & 0x000f;
uint8_t cs_warat = (data & 0x0030)>>4;
uint8_t cs_md = (data & 0x00c0)>>6;
int cs_size = (data & 0xff00)>>8;
logerror("CS%d set to size: %02x (%08x words) md: %01x %s warat: %01x wait: %01x\n", offset, cs_size, (cs_size+1)*0x10000, cs_md, md[cs_md], cs_warat, cs_wait);
WRITE16_MEMBER(sunplus_gcm394_base_device::unkarea_7821_w)
{
LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7821_w %04x\n", machine().describe_context(), data); m_7821 = data;
}
// these seem to be related to the above but don't change after startup. maybe it's how different devices see memory?
WRITE16_MEMBER(sunplus_gcm394_base_device::unkarea_7822_w) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7822_w %04x\n", machine().describe_context(), data); m_7822 = data; }
WRITE16_MEMBER(sunplus_gcm394_base_device::unkarea_7823_w) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7823_w %04x\n", machine().describe_context(), data); m_7823 = data; }
WRITE16_MEMBER(sunplus_gcm394_base_device::unkarea_7824_w) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7824_w %04x\n", machine().describe_context(), data); m_7824 = data; }
WRITE16_MEMBER(sunplus_gcm394_base_device::unkarea_7835_w) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7835_w %04x\n", machine().describe_context(), data); m_7835 = data; }
@ -357,18 +453,18 @@ void sunplus_gcm394_base_device::gcm394_internal_map(address_map &map)
map(0x007016, 0x00701b).rw(m_spg_video, FUNC(gcm394_base_video_device::tmap1_regs_r), FUNC(gcm394_base_video_device::tmap1_regs_w));
// tilebase LSBs
map(0x007020, 0x007020).w(m_spg_video, FUNC(gcm394_base_video_device::tmap0_tilebase_lsb_w)); // tilebase, written with other tmap0 regs
map(0x007021, 0x007021).w(m_spg_video, FUNC(gcm394_base_video_device::tmap1_tilebase_lsb_w)); // tilebase, written with other tmap1 regs
map(0x007022, 0x007022).w(m_spg_video, FUNC(gcm394_base_video_device::sprite_7022_gfxbase_lsb_w)); // sprite tilebase written as 7022, 702d and 7042 group
map(0x007020, 0x007020).rw(m_spg_video, FUNC(gcm394_base_video_device::tmap0_tilebase_lsb_r), FUNC(gcm394_base_video_device::tmap0_tilebase_lsb_w)); // tilebase, written with other tmap0 regs
map(0x007021, 0x007021).rw(m_spg_video, FUNC(gcm394_base_video_device::tmap1_tilebase_lsb_r), FUNC(gcm394_base_video_device::tmap1_tilebase_lsb_w)); // tilebase, written with other tmap1 regs
map(0x007022, 0x007022).rw(m_spg_video, FUNC(gcm394_base_video_device::sprite_7022_gfxbase_lsb_r), FUNC(gcm394_base_video_device::sprite_7022_gfxbase_lsb_w)); // sprite tilebase written as 7022, 702d and 7042 group
map(0x007023, 0x007023).w(m_spg_video, FUNC(gcm394_base_video_device::unk_vid1_gfxbase_lsb_w)); // written with other unknown_video_device1 regs (roz layer or line layer?)
map(0x007024, 0x007024).w(m_spg_video, FUNC(gcm394_base_video_device::unk_vid2_gfxbase_lsb_w)); // written with other unknown_video_device2 regs (roz layer or line layer?)
map(0x00702a, 0x00702a).w(m_spg_video, FUNC(gcm394_base_video_device::video_702a_w)); // blend level control
// tilebase MSBs
map(0x00702b, 0x00702b).w(m_spg_video, FUNC(gcm394_base_video_device::tmap0_tilebase_msb_w)); // written with other tmap0 regs
map(0x00702c, 0x00702c).w(m_spg_video, FUNC(gcm394_base_video_device::tmap1_tilebase_msb_w)); // written with other tmap1 regs
map(0x00702d, 0x00702d).w(m_spg_video, FUNC(gcm394_base_video_device::sprite_702d_gfxbase_msb_w)); // sprites, written as 7022, 702d and 7042 group
map(0x00702b, 0x00702b).rw(m_spg_video, FUNC(gcm394_base_video_device::tmap0_tilebase_msb_r), FUNC(gcm394_base_video_device::tmap0_tilebase_msb_w)); // written with other tmap0 regs
map(0x00702c, 0x00702c).rw(m_spg_video, FUNC(gcm394_base_video_device::tmap1_tilebase_msb_r), FUNC(gcm394_base_video_device::tmap1_tilebase_msb_w)); // written with other tmap1 regs
map(0x00702d, 0x00702d).rw(m_spg_video, FUNC(gcm394_base_video_device::sprite_702d_gfxbase_msb_r), FUNC(gcm394_base_video_device::sprite_702d_gfxbase_msb_w)); // sprites, written as 7022, 702d and 7042 group
map(0x00702e, 0x00702e).w(m_spg_video, FUNC(gcm394_base_video_device::unk_vid1_gfxbase_msb_w)); // written with other unknown_video_device1 regs (roz layer or line layer?)
map(0x00702f, 0x00702f).w(m_spg_video, FUNC(gcm394_base_video_device::unk_vid2_gfxbase_msb_w)); // written with other unknown_video_device2 regs (roz layer or line layer?)
@ -418,80 +514,131 @@ void sunplus_gcm394_base_device::gcm394_internal_map(address_map &map)
map(0x007400, 0x0077ff).rw(m_spg_video, FUNC(gcm394_base_video_device::spriteram_r), FUNC(gcm394_base_video_device::spriteram_w));
// ######################################################################################################################################################################################
// 78xx region = io + other?
// 78xx region = system regs?
// ######################################################################################################################################################################################
map(0x007803, 0x007803).rw(FUNC(sunplus_gcm394_base_device::unkarea_7803_r), FUNC(sunplus_gcm394_base_device::unkarea_7803_w));
map(0x007807, 0x007807).w(FUNC(sunplus_gcm394_base_device::unkarea_7807_w));
// 7808
// 780a
map(0x00780c, 0x00780c).w(FUNC(sunplus_gcm394_base_device::waitmode_enter_780c_w));
map(0x00780f, 0x00780f).r(FUNC(sunplus_gcm394_base_device::unkarea_780f_status_r));
map(0x007810, 0x007810).rw(FUNC(sunplus_gcm394_base_device::unkarea_7810_r), FUNC(sunplus_gcm394_base_device::unkarea_7810_w));
map(0x007810, 0x007810).rw(FUNC(sunplus_gcm394_base_device::membankswitch_7810_r), FUNC(sunplus_gcm394_base_device::membankswitch_7810_w)); // 7810 Bank Switch Control Register (P_BankSwitch_Ctrl) (maybe)
map(0x007819, 0x007819).rw(FUNC(sunplus_gcm394_base_device::unkarea_7819_r), FUNC(sunplus_gcm394_base_device::unkarea_7819_w));
map(0x007816, 0x007816).w(FUNC(sunplus_gcm394_base_device::unkarea_7816_w));
map(0x007817, 0x007817).w(FUNC(sunplus_gcm394_base_device::unkarea_7817_w));
// wrlshunt | smartfp
map(0x007820, 0x007820).w(FUNC(sunplus_gcm394_base_device::unkarea_7820_w)); // 7f8a (7f8a before DMA from ROM to RAM, 008a after DMA from ROM to RAM) | 3f04
map(0x007821, 0x007821).w(FUNC(sunplus_gcm394_base_device::unkarea_7821_w)); // 7f47 | 0044
map(0x007822, 0x007822).w(FUNC(sunplus_gcm394_base_device::unkarea_7822_w)); // 0047 | 1f44
map(0x007823, 0x007823).w(FUNC(sunplus_gcm394_base_device::unkarea_7823_w)); // 0047 | 0044
map(0x007824, 0x007824).w(FUNC(sunplus_gcm394_base_device::unkarea_7824_w)); // 0047 | 0044
// ######################################################################################################################################################################################
// 782x region = memory config / control
// ######################################################################################################################################################################################
// wrlshunt | smartfp
map(0x007820, 0x007824).w(FUNC(sunplus_gcm394_base_device::chipselect_csx_memory_device_control_w)); // 7f8a (7f8a before DMA from ROM to RAM, 008a after DMA from ROM to RAM) | 3f04 7820 Chip Select (CS0) Memory Device Control (P_MC50_Ctrl)
// 7f47 | 0044 7821 Chip Select (CS1) Memory Device Control (P_MC51_Ctrl)
// 0047 | 1f44 7822 Chip Select (CS2) Memory Device Control (P_MC52_Ctrl)
// 0047 | 0044 7823 Chip Select (CS3) Memory Device Control (P_MC53_Ctrl)
// 0047 | 0044 7824 Chip Select (CS4) Memory Device Control (P_MC54_Ctrl)
map(0x00782d, 0x00782d).rw(FUNC(sunplus_gcm394_base_device::unkarea_782d_r), FUNC(sunplus_gcm394_base_device::unkarea_782d_w)); // on startup
// 782f
map(0x007835, 0x007835).w(FUNC(sunplus_gcm394_base_device::unkarea_7835_w));
map(0x007860, 0x007860).rw(FUNC(sunplus_gcm394_base_device::ioarea_7860_porta_r), FUNC(sunplus_gcm394_base_device::ioarea_7860_porta_w));
// 783a
// 783b
// 783c
// 783d
// 783e
map(0x007861, 0x007861).r(FUNC(sunplus_gcm394_base_device::unkarea_7861_r));
map(0x007862, 0x007862).rw(FUNC(sunplus_gcm394_base_device::unkarea_7862_r), FUNC(sunplus_gcm394_base_device::unkarea_7862_w));
map(0x007863, 0x007863).rw(FUNC(sunplus_gcm394_base_device::unkarea_7863_r), FUNC(sunplus_gcm394_base_device::unkarea_7863_w));
// 7841
map(0x007868, 0x007868).r(FUNC(sunplus_gcm394_base_device::unkarea_7868_r)); // on startup
// ######################################################################################################################################################################################
// 786x - 787x - IO related?
// ######################################################################################################################################################################################
map(0x007870, 0x007870).rw(FUNC(sunplus_gcm394_base_device::ioarea_7870_portb_r) ,FUNC(sunplus_gcm394_base_device::ioarea_7870_portb_w));
map(0x007860, 0x007860).rw(FUNC(sunplus_gcm394_base_device::ioarea_7860_porta_r), FUNC(sunplus_gcm394_base_device::ioarea_7860_porta_w)); // 7860 I/O PortA Data Register
map(0x007861, 0x007861).r(FUNC(sunplus_gcm394_base_device::unkarea_7861_r)); // 7861 I/O PortA Buffer Register
map(0x007862, 0x007862).rw(FUNC(sunplus_gcm394_base_device::unkarea_7862_r), FUNC(sunplus_gcm394_base_device::unkarea_7862_w)); // 7862 I/O PortA Direction Register
map(0x007863, 0x007863).rw(FUNC(sunplus_gcm394_base_device::unkarea_7863_r), FUNC(sunplus_gcm394_base_device::unkarea_7863_w)); // 7863 I/O PortA Attribute Register
map(0x007871, 0x007871).r(FUNC(sunplus_gcm394_base_device::unkarea_7871_r));
map(0x007872, 0x007872).rw(FUNC(sunplus_gcm394_base_device::unkarea_7872_r), FUNC(sunplus_gcm394_base_device::unkarea_7872_w));
map(0x007873, 0x007873).rw(FUNC(sunplus_gcm394_base_device::unkarea_7873_r), FUNC(sunplus_gcm394_base_device::unkarea_7873_w));
map(0x007868, 0x007868).r(FUNC(sunplus_gcm394_base_device::unkarea_7868_r)); // on startup // 7868 I/O PortB Data Register
// 7869 I/O PortB Buffer Register
// 786a I/O PortB Direction Register
// 786b I/O PortB Attribute Register
// 786a I/O PortB Direction Register
// 786c I/O PortB Latch / Wakeup
map(0x007870, 0x007870).rw(FUNC(sunplus_gcm394_base_device::ioarea_7870_portb_r) ,FUNC(sunplus_gcm394_base_device::ioarea_7870_portb_w)); // 7870 I/O PortC Data Register
map(0x007871, 0x007871).r(FUNC(sunplus_gcm394_base_device::unkarea_7871_r)); // 7871 I/O PortC Buffer Register
map(0x007872, 0x007872).rw(FUNC(sunplus_gcm394_base_device::unkarea_7872_r), FUNC(sunplus_gcm394_base_device::unkarea_7872_w)); // 7872 I/O PortC Direction Register
map(0x007873, 0x007873).rw(FUNC(sunplus_gcm394_base_device::unkarea_7873_r), FUNC(sunplus_gcm394_base_device::unkarea_7873_w)); // 7873 I/O PortC Attribute Register
// 7874 (data 0x1249)
// 787c (data 0x1249)
// 787e (data 0x1249)
// 7878 I/O PortD Data Register
// 7879 I/O PortD Buffer Register
// 787a I/O PortD Direction Register
// 787b I/O PortD Attribute Register
// ######################################################################################################################################################################################
// 788x - more IO?
// ######################################################################################################################################################################################
// 7880
map(0x007882, 0x007882).rw(FUNC(sunplus_gcm394_base_device::unkarea_7882_r), FUNC(sunplus_gcm394_base_device::unkarea_7882_w));
map(0x007883, 0x007883).rw(FUNC(sunplus_gcm394_base_device::unkarea_7883_r), FUNC(sunplus_gcm394_base_device::unkarea_7883_w));
map(0x0078a0, 0x0078a0).rw(FUNC(sunplus_gcm394_base_device::unkarea_78a0_r), FUNC(sunplus_gcm394_base_device::unkarea_78a0_w));
// 0x7888 (data 0x1249)
// ######################################################################################################################################################################################
// 78ax - interrupt controller?
// ######################################################################################################################################################################################
map(0x0078a0, 0x0078a0).rw(FUNC(sunplus_gcm394_base_device::unkarea_78a0_r), FUNC(sunplus_gcm394_base_device::unkarea_78a0_w));
map(0x0078a1, 0x0078a1).r(FUNC(sunplus_gcm394_base_device::unkarea_78a1_r));
map(0x0078a4, 0x0078a4).w(FUNC(sunplus_gcm394_base_device::unkarea_78a4_w));
map(0x0078a5, 0x0078a5).w(FUNC(sunplus_gcm394_base_device::unkarea_78a5_w));
map(0x0078a6, 0x0078a6).w(FUNC(sunplus_gcm394_base_device::unkarea_78a6_w));
map(0x0078a8, 0x0078a8).w(FUNC(sunplus_gcm394_base_device::unkarea_78a8_w));
map(0x0078a8, 0x0078a8).w(FUNC(sunplus_gcm394_base_device::unkarea_78a8_w));
map(0x0078b0, 0x0078b0).w(FUNC(sunplus_gcm394_base_device::unkarea_78b0_w));
map(0x0078b1, 0x0078b1).w(FUNC(sunplus_gcm394_base_device::unkarea_78b1_w));
// ######################################################################################################################################################################################
// 78bx - timer control?
// ######################################################################################################################################################################################
map(0x0078b2, 0x0078b2).r(FUNC(sunplus_gcm394_base_device::unkarea_78b2_r));
map(0x0078b2, 0x0078b2).w(FUNC(sunplus_gcm394_base_device::unkarea_78b2_w));
map(0x0078b0, 0x0078b0).w(FUNC(sunplus_gcm394_base_device::unkarea_78b0_w)); // 78b0 TimeBase A Control Register (P_TimeBaseA_Ctrl)
map(0x0078b1, 0x0078b1).w(FUNC(sunplus_gcm394_base_device::unkarea_78b1_w)); // 78b1 TimeBase B Control Register (P_TimeBaseB_Ctrl)
map(0x0078b2, 0x0078b2).rw(FUNC(sunplus_gcm394_base_device::unkarea_78b2_r), FUNC(sunplus_gcm394_base_device::unkarea_78b2_w)); // 78b2 TimeBase C Control Register (P_TimeBaseC_Ctrl)
map(0x0078b8, 0x0078b8).w(FUNC(sunplus_gcm394_base_device::unkarea_78b8_w));
map(0x0078b8, 0x0078b8).w(FUNC(sunplus_gcm394_base_device::unkarea_78b8_w)); // 78b8 TimeBase Counter Reset Register (P_TimeBase_Reset)
// ######################################################################################################################################################################################
// 78fx - unknown
// ######################################################################################################################################################################################
map(0x0078f0, 0x0078f0).w(FUNC(sunplus_gcm394_base_device::unkarea_78f0_w));
map(0x0078fb, 0x0078fb).r(FUNC(sunplus_gcm394_base_device::unkarea_78fb_status_r));
// ######################################################################################################################################################################################
// 79xx region = timers?
// 79xx - misc?
// ######################################################################################################################################################################################
// possible rtc?
map(0x007934, 0x007934).rw(FUNC(sunplus_gcm394_base_device::unkarea_7934_r), FUNC(sunplus_gcm394_base_device::unkarea_7934_w));
map(0x007935, 0x007935).rw(FUNC(sunplus_gcm394_base_device::unkarea_7935_r), FUNC(sunplus_gcm394_base_device::unkarea_7935_w));
map(0x007936, 0x007936).rw(FUNC(sunplus_gcm394_base_device::unkarea_7936_r), FUNC(sunplus_gcm394_base_device::unkarea_7936_w));
// possible adc?
map(0x007960, 0x007960).w(FUNC(sunplus_gcm394_base_device::unkarea_7960_w));
map(0x007961, 0x007961).rw(FUNC(sunplus_gcm394_base_device::unkarea_7961_r), FUNC(sunplus_gcm394_base_device::unkarea_7961_w));
@ -499,7 +646,13 @@ void sunplus_gcm394_base_device::gcm394_internal_map(address_map &map)
// 7axx region = system (including dma)
// ######################################################################################################################################################################################
map(0x007a80, 0x007a86).w(FUNC(sunplus_gcm394_base_device::system_dma_params_w));
map(0x007a3a, 0x007a3a).r(FUNC(sunplus_gcm394_base_device::system_7a3a_r));
map(0x007a80, 0x007a86).rw(FUNC(sunplus_gcm394_base_device::system_dma_params_channel0_r), FUNC(sunplus_gcm394_base_device::system_dma_params_channel0_w));
map(0x007a88, 0x007a8e).rw(FUNC(sunplus_gcm394_base_device::system_dma_params_channel1_r), FUNC(sunplus_gcm394_base_device::system_dma_params_channel1_w)); // jak_tsm writes here
// 7abe - written with DMA stuff (source type for each channel so that device handles timings properly?)
map(0x007abf, 0x007abf).rw(FUNC(sunplus_gcm394_base_device::system_dma_status_r), FUNC(sunplus_gcm394_base_device::system_dma_trigger_w));
// ######################################################################################################################################################################################
@ -518,25 +671,53 @@ READ16_MEMBER(generalplus_gpac800_device::unkarea_7850_r)
READ16_MEMBER(generalplus_gpac800_device::unkarea_7854_r)
{
m_testval ^= 1;
logerror("%s:sunplus_gcm394_base_device::unkarea_7854_r\n", machine().describe_context());
//logerror("%s:sunplus_gcm394_base_device::unkarea_7854_r\n", machine().describe_context());
// jak_tsm code looks for various 'magic values'
if (m_testval == 1)
return 0x98;
else
return 0x79;
if (m_nandcommand == 0x90) // read ident
{
m_testval ^= 1;
if (m_testval == 0)
return 0x73;
else
return 0x98;
}
else if (m_nandcommand == 0x00) // read data
{
//uint8_t d
uint32_t nandaddress = (m_flash_addr_high << 16) | m_flash_addr_low;
uint8_t data = m_nand_read_cb((nandaddress * 2) + m_curblockaddr);
//printf("reading nand byte %02x\n", data);
m_curblockaddr++;
return data;
}
else if (m_nandcommand == 0x70) // read status
{
return 0xffff;
}
return 0x00;
}
// 7998
WRITE16_MEMBER(generalplus_gpac800_device::nand_command_w)
{
logerror("%s:sunplus_gcm394_base_device::nand_command_w %04x\n", machine().describe_context(), data);
m_nandcommand = data;
}
WRITE16_MEMBER(generalplus_gpac800_device::flash_addr_low_w)
{
//logerror("%s:sunplus_gcm394_base_device::flash_addr_low_w %04x\n", machine().describe_context(), data);
m_flash_addr_low = data;
m_curblockaddr = 0;
}
WRITE16_MEMBER(generalplus_gpac800_device::flash_addr_high_w)
@ -546,7 +727,10 @@ WRITE16_MEMBER(generalplus_gpac800_device::flash_addr_high_w)
uint32_t address = (m_flash_addr_high << 16) | m_flash_addr_low;
logerror("%s: flash address is now %08x\n", machine().describe_context(), address);
m_curblockaddr = 0;
}
@ -561,13 +745,12 @@ void generalplus_gpac800_device::gpac800_internal_map(address_map& map)
//
// this should be the NAND device, as the games attempt to do a DMA operation with '7854' as the source, and the target
// as the RAM location where code needs to end up before jumping to it
map(0x007850, 0x007850).r(FUNC(generalplus_gpac800_device::unkarea_7850_r)); // 'device ready' status flag?
map(0x007852, 0x007852).w(FUNC(generalplus_gpac800_device::flash_addr_low_w));
map(0x007853, 0x007853).w(FUNC(generalplus_gpac800_device::flash_addr_high_w));
map(0x007854, 0x007854).r(FUNC(generalplus_gpac800_device::unkarea_7854_r)); // data read port (timing appears to be important)
map(0x007850, 0x007850).r(FUNC(generalplus_gpac800_device::unkarea_7850_r)); // NAND Control Reg
map(0x007851, 0x007851).w(FUNC(generalplus_gpac800_device::nand_command_w)); // NAND Command Reg
map(0x007852, 0x007852).w(FUNC(generalplus_gpac800_device::flash_addr_low_w)); // NAND Low Address Reg
map(0x007853, 0x007853).w(FUNC(generalplus_gpac800_device::flash_addr_high_w)); // NAND High Address Reg
map(0x007854, 0x007854).r(FUNC(generalplus_gpac800_device::unkarea_7854_r)); // NAND Data Reg
// map(0x007855, 0x007855).w(FUNC(generalplus_gpac800_device::nand_dma_ctrl_w)); // NAND DMA / INT Control
}
void sunplus_gcm394_base_device::device_start()
@ -584,6 +767,7 @@ void sunplus_gcm394_base_device::device_start()
m_space_write_cb.resolve();
m_mapping_write_cb.resolve();
m_nand_read_cb.resolve_safe(0);
m_unk_timer = timer_alloc(0);
m_unk_timer->adjust(attotime::never);
@ -593,9 +777,12 @@ void sunplus_gcm394_base_device::device_reset()
{
unsp_20_device::device_reset();
for (int i = 0; i < 7; i++)
for (int j = 0; j < 2; j++)
{
m_dma_params[i] = 0x0000;
for (int i = 0; i < 7; i++)
{
m_dma_params[i][j] = 0x0000;
}
}
// 78xx unknown
@ -605,18 +792,18 @@ void sunplus_gcm394_base_device::device_reset()
m_7807 = 0x0000;
m_7810 = 0x0000;
m_membankswitch_7810 = 0x0000;
m_7816 = 0x0000;
m_7817 = 0x0000;
m_7819 = 0x0000;
m_7820 = 0x0000;
m_7821 = 0x0000;
m_7822 = 0x0000;
m_7823 = 0x0000;
m_7824 = 0x0000;
m_782x[0] = 0x0000;
m_782x[1] = 0x0000;
m_782x[2] = 0x0000;
m_782x[3] = 0x0000;
m_782x[4] = 0x0000;
m_7835 = 0x0000;

View File

@ -35,6 +35,7 @@ public:
m_porta_in(*this),
m_portb_in(*this),
m_porta_out(*this),
m_nand_read_cb(*this),
m_space_read_cb(*this),
m_space_write_cb(*this),
m_mapping_write_cb(*this)
@ -52,6 +53,7 @@ public:
auto space_write_callback() { return m_space_write_cb.bind(); }
auto mapping_write_callback() { return m_mapping_write_cb.bind(); }
auto nand_read_callback() { return m_nand_read_cb.bind(); }
DECLARE_WRITE_LINE_MEMBER(vblank) { m_spg_video->vblank(state); }
@ -75,14 +77,14 @@ protected:
devcb_write16 m_porta_out;
uint16_t m_dma_params[7];
uint16_t m_dma_params[7][2];
// unk 78xx
uint16_t m_7803;
uint16_t m_7807;
uint16_t m_7810;
uint16_t m_membankswitch_7810;
uint16_t m_7816;
uint16_t m_7817;
@ -90,11 +92,7 @@ protected:
uint16_t m_7819;
uint16_t m_7820;
uint16_t m_7821;
uint16_t m_7822;
uint16_t m_7823;
uint16_t m_7824;
uint16_t m_782x[5];
uint16_t m_782d;
@ -143,6 +141,8 @@ protected:
uint16_t m_7960;
uint16_t m_7961;
devcb_read16 m_nand_read_cb;
private:
devcb_read16 m_space_read_cb;
devcb_write16 m_space_write_cb;
@ -150,11 +150,17 @@ private:
DECLARE_READ16_MEMBER(unk_r);
DECLARE_WRITE16_MEMBER(unk_w);
void write_dma_params(int channel, int offset, uint16_t data);
uint16_t read_dma_params(int channel, int offset);
void trigger_systemm_dma(address_space &space, int channel, uint16_t data);
DECLARE_WRITE16_MEMBER(system_dma_params_w);
DECLARE_WRITE16_MEMBER(system_dma_trigger_w);
DECLARE_READ16_MEMBER(system_dma_params_channel0_r);
DECLARE_WRITE16_MEMBER(system_dma_params_channel0_w);
DECLARE_READ16_MEMBER(system_dma_params_channel1_r);
DECLARE_WRITE16_MEMBER(system_dma_params_channel1_w);
DECLARE_READ16_MEMBER(system_dma_status_r);
DECLARE_WRITE16_MEMBER(system_dma_trigger_w);
DECLARE_READ16_MEMBER(unkarea_780f_status_r);
DECLARE_READ16_MEMBER(unkarea_78fb_status_r);
@ -164,8 +170,10 @@ private:
DECLARE_WRITE16_MEMBER(unkarea_7807_w);
DECLARE_READ16_MEMBER(unkarea_7810_r);
DECLARE_WRITE16_MEMBER(unkarea_7810_w);
DECLARE_WRITE16_MEMBER(waitmode_enter_780c_w);
DECLARE_READ16_MEMBER(membankswitch_7810_r);
DECLARE_WRITE16_MEMBER(membankswitch_7810_w);
DECLARE_WRITE16_MEMBER(unkarea_7816_w);
DECLARE_WRITE16_MEMBER(unkarea_7817_w);
@ -173,11 +181,7 @@ private:
DECLARE_READ16_MEMBER(unkarea_7819_r);
DECLARE_WRITE16_MEMBER(unkarea_7819_w);
DECLARE_WRITE16_MEMBER(unkarea_7820_w);
DECLARE_WRITE16_MEMBER(unkarea_7821_w);
DECLARE_WRITE16_MEMBER(unkarea_7822_w);
DECLARE_WRITE16_MEMBER(unkarea_7823_w);
DECLARE_WRITE16_MEMBER(unkarea_7824_w);
DECLARE_WRITE16_MEMBER(chipselect_csx_memory_device_control_w);
DECLARE_WRITE16_MEMBER(unkarea_7835_w);
@ -249,6 +253,11 @@ private:
DECLARE_WRITE_LINE_MEMBER(videoirq_w);
DECLARE_WRITE_LINE_MEMBER(audioirq_w);
DECLARE_READ16_MEMBER(system_7a3a_r)
{
return machine().rand();
}
void checkirq6();
emu_timer *m_unk_timer;
@ -299,14 +308,20 @@ private:
DECLARE_READ16_MEMBER(unkarea_7850_r);
DECLARE_READ16_MEMBER(unkarea_7854_r);
DECLARE_WRITE16_MEMBER(nand_command_w);
DECLARE_WRITE16_MEMBER(flash_addr_low_w);
DECLARE_WRITE16_MEMBER(flash_addr_high_w);
int m_testval;
uint16_t m_nandcommand;
uint16_t m_flash_addr_low;
uint16_t m_flash_addr_high;
int m_curblockaddr;
};

View File

@ -31,6 +31,7 @@ gcm394_base_video_device::gcm394_base_video_device(const machine_config &mconfig
, m_palette(*this, "palette")
, m_gfxdecode(*this, "gfxdecode")
, m_space_read_cb(*this)
, m_global_y_mask(0x1ff)
{
}
@ -301,9 +302,9 @@ void gcm394_base_video_device::draw(const rectangle &cliprect, uint32_t line, ui
uint32_t nbits = 0;
uint32_t y = line;
int yy = (yoff + y) & 0x1ff;
if (yy >= 0x01c0)
yy -= 0x0200;
int yy = (yoff + y);// &0x1ff;
//if (yy >= 0x01c0)
// yy -= 0x0200;
if (yy > cliprect.max_y || yy < 0)
return;
@ -355,9 +356,9 @@ void gcm394_base_video_device::draw(const rectangle &cliprect, uint32_t line, ui
if (RowScroll)
xx -= 0;// (int16_t)m_scrollram[yy & 0x1ff];
xx &= 0x01ff;
if (xx >= 0x01c0)
xx -= 0x0200;
//xx &= 0x01ff;
//if (xx >= 0x01c0)
// xx -= 0x0200;
if (xx >= 0 && xx <= cliprect.max_x)
{
@ -408,17 +409,22 @@ void gcm394_base_video_device::draw_page(const rectangle &cliprect, uint32_t sca
uint32_t tile_h = 8 << ((attr_reg & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT);
uint32_t tile_w = 8 << ((attr_reg & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT);
uint32_t tile_count_x = 512 / tile_w;
int total_width = 512;
uint32_t bitmap_y = (scanline + yscroll) & 0xff;
if ((attr_reg >> 14) & 0x2)
total_width = 1024;
uint32_t tile_count_x = total_width / tile_w;
uint32_t bitmap_y = (scanline + yscroll);// &0xff;
uint32_t y0 = bitmap_y / tile_h;
uint32_t tile_scanline = bitmap_y % tile_h;
uint32_t tile_address = tile_count_x * y0;
for (uint32_t x0 = 0; x0 < tile_count_x; x0++, tile_address++)
{
uint32_t yy = ((tile_h * y0 - yscroll + 0x10) & 0xff) - 0x10;
uint32_t xx = (tile_w * x0 - xscroll) & 0x1ff;
uint32_t yy = ((tile_h * y0 - yscroll + 0x10) & m_global_y_mask) - 0x10;
uint32_t xx = (tile_w * x0 - xscroll);// &0x1ff;
uint32_t tile = (ctrl_reg & PAGE_WALLPAPER_MASK) ? space.read_word(tilemap) : space.read_word(tilemap + tile_address);
uint16_t palette = (ctrl_reg & PAGE_WALLPAPER_MASK) ? space.read_word(palette_map) : space.read_word(palette_map + tile_address / 2);
@ -694,6 +700,11 @@ WRITE16_MEMBER(gcm394_base_video_device::tmap0_regs_w)
write_tmap_regs(0, m_tmap0_regs, offset, data);
}
READ16_MEMBER(gcm394_base_video_device::tmap0_tilebase_lsb_r)
{
return m_page0_addr_lsb;
}
WRITE16_MEMBER(gcm394_base_video_device::tmap0_tilebase_lsb_w)
{
LOGMASKED(LOG_GCM394_TMAP, "%s:gcm394_base_video_device::tmap0_tilebase_lsb_w %04x\n", machine().describe_context(), data);
@ -701,6 +712,11 @@ WRITE16_MEMBER(gcm394_base_video_device::tmap0_tilebase_lsb_w)
LOGMASKED(LOG_GCM394_TMAP, "\t(tmap0 tilegfxbase is now %04x%04x)\n", m_page0_addr_msb, m_page0_addr_lsb);
}
READ16_MEMBER(gcm394_base_video_device::tmap0_tilebase_msb_r)
{
return m_page0_addr_msb;
}
WRITE16_MEMBER(gcm394_base_video_device::tmap0_tilebase_msb_w)
{
LOGMASKED(LOG_GCM394_TMAP, "%s:gcm394_base_video_device::tmap0_tilebase_msb_w %04x\n", machine().describe_context(), data);
@ -718,6 +734,12 @@ WRITE16_MEMBER(gcm394_base_video_device::tmap1_regs_w)
write_tmap_regs(1, m_tmap1_regs, offset, data);
}
READ16_MEMBER(gcm394_base_video_device::tmap1_tilebase_lsb_r)
{
return m_page1_addr_lsb;
}
WRITE16_MEMBER(gcm394_base_video_device::tmap1_tilebase_lsb_w)
{
LOGMASKED(LOG_GCM394_TMAP, "%s:gcm394_base_video_device::tmap1_tilebase_lsb_w %04x\n", machine().describe_context(), data);
@ -725,6 +747,11 @@ WRITE16_MEMBER(gcm394_base_video_device::tmap1_tilebase_lsb_w)
LOGMASKED(LOG_GCM394_TMAP, "\t(tmap1 tilegfxbase is now %04x%04x)\n", m_page1_addr_msb, m_page1_addr_lsb);
}
READ16_MEMBER(gcm394_base_video_device::tmap1_tilebase_msb_r)
{
return m_page1_addr_msb;
}
WRITE16_MEMBER(gcm394_base_video_device::tmap1_tilebase_msb_w)
{
LOGMASKED(LOG_GCM394_TMAP, "%s:gcm394_base_video_device::tmap1_tilebase_msb_w %04x\n", machine().describe_context(), data);
@ -811,6 +838,11 @@ WRITE16_MEMBER(gcm394_base_video_device::unk_vid2_gfxbase_msb_w)
// set to 001264c0 in wrlshunt, which point at the menu selectors (game names, arrows etc.)
READ16_MEMBER(gcm394_base_video_device::sprite_7022_gfxbase_lsb_r)
{
return m_sprite_7022_gfxbase_lsb;
}
WRITE16_MEMBER(gcm394_base_video_device::sprite_7022_gfxbase_lsb_w)
{
LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::sprite_7022_gfxbase_lsb_w %04x\n", machine().describe_context(), data);
@ -818,6 +850,11 @@ WRITE16_MEMBER(gcm394_base_video_device::sprite_7022_gfxbase_lsb_w)
LOGMASKED(LOG_GCM394_TMAP, "\t(sprite tilebase is now %04x%04x)\n", m_sprite_702d_gfxbase_msb, m_sprite_7022_gfxbase_lsb);
}
READ16_MEMBER(gcm394_base_video_device::sprite_702d_gfxbase_msb_r)
{
return m_sprite_702d_gfxbase_msb;
}
WRITE16_MEMBER(gcm394_base_video_device::sprite_702d_gfxbase_msb_w)
{
LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::sprite_702d_gfxbase_msb_w %04x\n", machine().describe_context(), data);

View File

@ -29,11 +29,15 @@ public:
DECLARE_READ16_MEMBER(tmap0_regs_r);
DECLARE_WRITE16_MEMBER(tmap0_regs_w);
DECLARE_READ16_MEMBER(tmap0_tilebase_lsb_r);
DECLARE_READ16_MEMBER(tmap0_tilebase_msb_r);
DECLARE_WRITE16_MEMBER(tmap0_tilebase_lsb_w);
DECLARE_WRITE16_MEMBER(tmap0_tilebase_msb_w);
DECLARE_READ16_MEMBER(tmap1_regs_r);
DECLARE_WRITE16_MEMBER(tmap1_regs_w);
DECLARE_READ16_MEMBER(tmap1_tilebase_lsb_r);
DECLARE_READ16_MEMBER(tmap1_tilebase_msb_r);
DECLARE_WRITE16_MEMBER(tmap1_tilebase_lsb_w);
DECLARE_WRITE16_MEMBER(tmap1_tilebase_msb_w);
@ -44,6 +48,9 @@ public:
DECLARE_WRITE16_MEMBER(unk_vid2_regs_w);
DECLARE_WRITE16_MEMBER(unk_vid2_gfxbase_lsb_w);
DECLARE_WRITE16_MEMBER(unk_vid2_gfxbase_msb_w);
DECLARE_READ16_MEMBER(sprite_7022_gfxbase_lsb_r);
DECLARE_READ16_MEMBER(sprite_702d_gfxbase_msb_r);
DECLARE_WRITE16_MEMBER(sprite_7022_gfxbase_lsb_w);
DECLARE_WRITE16_MEMBER(sprite_702d_gfxbase_msb_w);
@ -220,6 +227,7 @@ protected:
int m_maxgfxelement;
void decodegfx(const char* tag);
int m_global_y_mask;
};
class gcm394_video_device : public gcm394_base_video_device

View File

@ -7,6 +7,12 @@
unlike earlier SunPlus / GeneralPlus based SoCs this one seems to be
ARM based
NAND types
Star Wars Blaster MX30LF1G08AA (2048+64) x 64 x 512
TMNT Hero Portal MX30LF1G08AA (2048+64) x 64 x 512
*****************************************************************************/

View File

@ -15,6 +15,10 @@
TODO: everything!
NAND types
Storio Spanish old BIOS TC58NVG0S3ETA00 (2048+64) x 64 x 1024
*******************************************************************************/
#include "emu.h"

View File

@ -5,6 +5,7 @@
Compared to vii.cpp this is clearly newer, has extra opcodes, different internal map etc. also scaling and higher resolutions based on Spongebob
note, these SoC types always have a 128Kwords internal ROM, which the JAKKS games appear to use for basic bootstrap purposes.
GPL600
Smart Fit Park
@ -28,6 +29,17 @@
smartfp: hold button Circle, Star and Home on startup for Test Menu
these are both unsp 2.0 type, as they use the extended ocpodes
NAND types:
Toy Story Mania H27U518S2C dumped as HY27US08121A (512+16) x 32 x 4096
Beam Box GPR27P512A dumped as HY27US08121A (512+16) x 32 x 4096
Golden Tee GPR27P512A dumped as HY27US08121A (512+16) x 32 x 4096
Cars 2 GPR27P512A dumped as HY27US08121A (512+16) x 32 x 4096
V.Baby HY27UF081G2A (2048+64) x 64 x 1024
*/
#include "emu.h"
@ -86,7 +98,6 @@ private:
uint32_t m_current_bank;
int m_numbanks;
};
class wrlshunt_game_state : public gcm394_game_state
@ -127,7 +138,9 @@ class generalplus_gpac800_game_state : public gcm394_game_state
public:
generalplus_gpac800_game_state(const machine_config& mconfig, device_type type, const char* tag) :
gcm394_game_state(mconfig, type, tag),
m_mainram(*this, "mainram")
m_mainram(*this, "mainram"),
m_initial_copy_words(0x2000),
m_nandreadbase(0)
{
}
@ -135,20 +148,42 @@ public:
void nand_init210();
void nand_init840();
void nand_wlsair60();
void nand_vbaby();
void nand_tsm();
protected:
virtual void machine_reset() override;
void generalplus_gpac800_map(address_map &map);
DECLARE_READ8_MEMBER(read_nand);
private:
void nand_init(int blocksize, int blocksize_stripped);
required_shared_ptr<u16> m_mainram;
std::vector<uint8_t> m_strippedrom;
int m_strippedsize;
int m_initial_copy_words;
int m_nandreadbase;
virtual DECLARE_WRITE16_MEMBER(write_external_space) override;
};
READ8_MEMBER(generalplus_gpac800_game_state::read_nand)
{
return m_strippedrom[(offset + m_nandreadbase) & (m_strippedsize - 1)];
}
WRITE16_MEMBER(generalplus_gpac800_game_state::write_external_space)
{
if (offset < 0x0400000)
{
m_mainram[offset] = data;
// logerror("DMA writing to external space (RAM?) %08x %04x\n", offset, data);
}
}
READ16_MEMBER(gcm394_game_state::read_external_space)
@ -310,6 +345,11 @@ void generalplus_gpac800_game_state::generalplus_gpac800(machine_config &config)
m_maincpu->add_route(ALL_OUTPUTS, "lspeaker", 0.5);
m_maincpu->add_route(ALL_OUTPUTS, "rspeaker", 0.5);
m_maincpu->nand_read_callback().set(FUNC(generalplus_gpac800_game_state::read_nand));
m_screen->set_size(320*2, 262*2);
m_screen->set_visarea(0, (320*2)-1, 0, (240*2)-1);
}
@ -353,6 +393,21 @@ void gcm394_game_state::machine_reset()
m_current_bank = 0;
}
/*
map info
map(0x000000, 0x006fff) internal RAM
map(0x007000, 0x007fff) internal peripherals
map(0x008000, 0x00ffff) internal ROM (lower 32kwords) - can also be configured to mirror CS0 308000 area with external pin for boot from external ROM
map(0x010000, 0x027fff) internal ROM (upper 96kwords) - can't be switched
map(0x028000, 0x02ffff) reserved
map(0x030000, 0x0.....) view into external spaces (CS0 area starts here. followed by CS1 area, CS2 area etc.)
map(0x200000, 0x3fffff) continued view into external spaces, but this area is banked with m_membankswitch_7810 (valid bank values 0x00-0x3f)
*/
void gcm394_game_state::mem_map_4m(address_map &map)
{
map(0x000000, 0x00ffff).rom().region("maincpu", 0); // non-banked area on this SoC?
@ -797,22 +852,13 @@ void generalplus_gpac800_game_state::machine_reset()
int dest = m_strippedrom[0x15] << 8;
// copy a block of code from the NAND to RAM
for (int i = 0; i < 0x7000-dest; i++)
for (int i = 0; i < m_initial_copy_words; i++)
{
uint16_t word = m_strippedrom[(i * 2) + 0] | (m_strippedrom[(i * 2) + 1] << 8);
mem.write_word(dest+i, word);
}
int rambase = 0x30000;
for (int i = 0x4000/2; i < 0x37c000/2; i++)
{
uint16_t word = m_strippedrom[(i * 2) + 0] | (m_strippedrom[(i * 2) + 1] << 8);
m_mainram[rambase] = word;
rambase++;
}
mem.write_word(0xfff5, 0x6fea);
mem.write_word(0xfff6, 0x6fec);
mem.write_word(0xfff7, dest+0x20); // point boot vector at code in RAM
@ -825,20 +871,6 @@ void generalplus_gpac800_game_state::machine_reset()
mem.write_word(0xfffe, 0x6ffc);
mem.write_word(0xffff, 0x6ffe);
// note, these patch the code copied to SRAM so the 'PROGRAM ROM' check fails (it passes otherwise)
if (mem.read_word(0x3f368) == 0x4840)
mem.write_word(0x3f368, 0x4841); // cars 2 IRQ? wait hack
if (mem.read_word(0x4368c) == 0x4846)
mem.write_word(0x4368c, 0x4840); // cars 2 force service mode
if (mem.read_word(0x4d8d4) == 0x4840)
mem.write_word(0x4d8d4, 0x4841); // golden tee IRQ? wait hack
if (mem.read_word(0x34410) == 0x4846)
mem.write_word(0x34410, 0x4840); // golden tee force service mode
m_maincpu->reset(); // reset CPU so vector gets read etc.
}
@ -849,8 +881,8 @@ void generalplus_gpac800_game_state::nand_init(int blocksize, int blocksize_stri
int size = memregion("maincpu")->bytes();
int numblocks = size / blocksize;
m_strippedrom.resize(numblocks * blocksize_stripped);
m_strippedsize = numblocks * blocksize_stripped;
m_strippedrom.resize(m_strippedsize);
for (int i = 0; i < numblocks; i++)
{
@ -888,11 +920,39 @@ void generalplus_gpac800_game_state::nand_init840()
nand_init(0x840, 0x800);
}
void generalplus_gpac800_game_state::nand_wlsair60()
{
nand_init840();
m_initial_copy_words = 0x2800;
}
void generalplus_gpac800_game_state::nand_vbaby()
{
nand_init840();
m_initial_copy_words = 0x1000;
}
void generalplus_gpac800_game_state::nand_tsm()
{
nand_init210();
// something odd must be going on with the bootloader?
// structure has the first 0x4000 block repeated 3 times (must appear in RAM on startup?)
// then it has a 0x10000 block repeated 4 times (must get copied to 0x30000 by code)
// then it has the larger, main payload, just the once.
// the addresses written to the NAND device don't compensate for these data repeats, however dump seems ok as no other data is being repeated?
// reads after startup still need checking
m_nandreadbase = (0x2000 + 0x2000 + 0x8000 + 0x8000 + 0x8000) * 2;
}
// NAND dumps w/ internal bootstrap (and u'nSP 2.0 extended opcodes) (have gpnandnand strings)
// the JAKKS ones seem to be known as 'Generalplus GPAC800' hardware
CONS(2010, wlsair60, 0, 0, generalplus_gpac800, jak_car2, generalplus_gpac800_game_state, nand_init840, "Jungle Soft / Kids Station Toys Inc", "Wireless Air 60", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)
CONS(200?, jak_gtg, 0, 0, generalplus_gpac800, jak_gtg, generalplus_gpac800_game_state, nand_init210, "JAKKS Pacific Inc", "Golden Tee Golf (JAKKS Pacific TV Game)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)
CONS(200?, jak_car2, 0, 0, generalplus_gpac800, jak_car2, generalplus_gpac800_game_state, nand_init210, "JAKKS Pacific Inc", "Cars 2 (JAKKS Pacific TV Game)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)
CONS(200?, jak_tsm , 0, 0, generalplus_gpac800, jak_car2, generalplus_gpac800_game_state, nand_init210, "JAKKS Pacific Inc", "Toy Story Mania (JAKKS Pacific TV Game)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)
CONS(200?, vbaby, 0, 0, generalplus_gpac800, jak_car2, generalplus_gpac800_game_state, nand_init840, "VTech", "V.Baby", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)
CONS(200?, beambox, 0, 0, generalplus_gpac800, jak_car2, generalplus_gpac800_game_state, nand_init210, "Hasbro", "Playskool Heroes Transformers Rescue Bots Beam Box (Spain)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)
CONS(2010, wlsair60, 0, 0, generalplus_gpac800, jak_car2, generalplus_gpac800_game_state, nand_wlsair60, "Jungle Soft / Kids Station Toys Inc", "Wireless Air 60", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)
CONS(200?, jak_gtg, 0, 0, generalplus_gpac800, jak_gtg, generalplus_gpac800_game_state, nand_init210, "JAKKS Pacific Inc", "Golden Tee Golf (JAKKS Pacific TV Game)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)
CONS(200?, jak_car2, 0, 0, generalplus_gpac800, jak_car2, generalplus_gpac800_game_state, nand_init210, "JAKKS Pacific Inc", "Cars 2 (JAKKS Pacific TV Game)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)
CONS(200?, jak_tsm , 0, 0, generalplus_gpac800, jak_car2, generalplus_gpac800_game_state, nand_tsm, "JAKKS Pacific Inc", "Toy Story Mania (JAKKS Pacific TV Game)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)
CONS(200?, vbaby, 0, 0, generalplus_gpac800, jak_car2, generalplus_gpac800_game_state, nand_vbaby, "VTech", "V.Baby", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)
CONS(200?, beambox, 0, 0, generalplus_gpac800, jak_car2, generalplus_gpac800_game_state, nand_init210, "Hasbro", "Playskool Heroes Transformers Rescue Bots Beam Box (Spain)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)