Misc SunPlus (wrlshunt research) (#6015)

* misc logging fixes etc. (nw)

* (nw)

* bank spriteram even when not through dma (nw)

* notes (nw)

* logging changes (nw)

* stability fixes for smartfp (nw)

* note (nw)

* note (nw)

* still making notes (nw)

* impove logging (nw)

* yeah this is spritebase (nw)

* yep sprite base (nw)

* read through space (nw)

* wrlshunt - show something that at least looks like sprites (nw)

* wrlshunt note (nw)

* notes (nw)

* regs note (nw)
This commit is contained in:
David Haywood 2019-12-09 12:49:07 +00:00 committed by R. Belmont
parent 51daaf2f93
commit 10ebda40e2
7 changed files with 356 additions and 168 deletions

View File

@ -164,7 +164,7 @@ protected:
struct internal_unsp_state
{
uint32_t m_r[8];
uint32_t m_r[8]; // why are these 32-bit? they're 16-bit regs? (changing to uint16_t causes crashes tho, so something is depending on this)
uint32_t m_enable_irq;
uint32_t m_enable_fiq;
uint32_t m_irq;

View File

@ -181,7 +181,7 @@ void unsp_12_device::execute_exxx_group(uint16_t op)
case 0x02:
logerror("pc:%06x: %s = %s lsl %s (%04x %04x) : ", UNSP_LPC, regs[rd], regs[rd], regs[rs], m_core->m_r[rd], m_core->m_r[rs]);
m_core->m_r[rd] = (uint16_t)(m_core->m_r[rd] << (m_core->m_r[rs] & 0x0f));
m_core->m_r[rd] = (uint16_t)((m_core->m_r[rd]&0xffff) << (m_core->m_r[rs] & 0x0f));
logerror("result %04x\n", m_core->m_r[rd]);
return;
@ -190,7 +190,7 @@ void unsp_12_device::execute_exxx_group(uint16_t op)
// wrlshunt uses this
logerror("pc:%06x: %s = %s lslor %s (%04x %04x) : ", UNSP_LPC, regs[rd], regs[rd], regs[rs], m_core->m_r[rd], m_core->m_r[rs]);
uint16_t tmp = m_core->m_r[rd];
m_core->m_r[rd] = (uint16_t)(m_core->m_r[rd] << (m_core->m_r[rs] & 0x0f));
m_core->m_r[rd] = (uint16_t)((m_core->m_r[rd]&0xffff) << (m_core->m_r[rs] & 0x0f));
m_core->m_r[rd] |= tmp; // guess
logerror("result %04x\n", m_core->m_r[rd]);
return;
@ -199,7 +199,7 @@ void unsp_12_device::execute_exxx_group(uint16_t op)
case 0x04:
// smartfp loops increasing shift by 4 up to values of 28? (but regs are 16-bit?)
logerror("pc:%06x: %s = %s lsr %s (%04x %04x) : ", UNSP_LPC, regs[rd], regs[rd], regs[rs], m_core->m_r[rd], m_core->m_r[rs]);
m_core->m_r[rd] = (uint16_t)(m_core->m_r[rd] >> (m_core->m_r[rs] & 0xf));
m_core->m_r[rd] = (uint16_t)((m_core->m_r[rd]&0xffff) >> (m_core->m_r[rs] & 0xf));
logerror("result %04x\n", m_core->m_r[rd]);
return;
@ -207,7 +207,7 @@ void unsp_12_device::execute_exxx_group(uint16_t op)
{
logerror("pc:%06x: %s = %s lsror %s (%04x %04x) : ", UNSP_LPC, regs[rd], regs[rd], regs[rs], m_core->m_r[rd], m_core->m_r[rs]);
uint16_t tmp = m_core->m_r[rd];
m_core->m_r[rd] = (uint16_t)(m_core->m_r[rd] >> (m_core->m_r[rs] & 0x0f));
m_core->m_r[rd] = (uint16_t)((m_core->m_r[rd]&0xffff) >> (m_core->m_r[rs] & 0x0f));
m_core->m_r[rd] |= tmp; // guess
logerror("result %04x\n", m_core->m_r[rd]);
return;

View File

@ -16,6 +16,10 @@ inline void unsp_device::execute_fxxx_000_group(uint16_t op)
// DS Reg 1 1 1 1 - - - 0 0 0 1 0 w r r r
// FR Reg 1 1 1 1 - - - 0 0 0 1 1 w r r r
// FR = 'inner flag register' on ISA1.2+
// does this mean 1.2+ do not store the registers in the upper bits of SR, or is this something else?
// smartfp IRQ4 reads this and puts in on the stack
if (((op & 0xffc0) == 0xfe00) && m_iso >= 12)
{
// ds = imm6

View File

@ -136,8 +136,19 @@ 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; }
READ16_MEMBER(sunplus_gcm394_base_device::unkarea_7810_r) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7810_r\n", machine().describe_context()); return m_7810; }
WRITE16_MEMBER(sunplus_gcm394_base_device::unkarea_7810_w) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7810_w %04x\n", machine().describe_context(), data); m_7810 = 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)
{
LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7810_r\n", machine().describe_context());
return m_7810;
}
WRITE16_MEMBER(sunplus_gcm394_base_device::unkarea_7810_w)
{
printf( "%s:sunplus_gcm394_base_device::unkarea_7810_w %04x\n", machine().describe_context().c_str(), data);
m_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; }
@ -154,24 +165,25 @@ 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; }
// IO here?
READ16_MEMBER(sunplus_gcm394_base_device::ioport_a_r)
READ16_MEMBER(sunplus_gcm394_base_device::ioarea_7860_porta_r)
{
LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::ioport_a_r\n", machine().describe_context());
LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::ioarea_7860_porta_r\n", machine().describe_context());
return m_porta_in();
}
WRITE16_MEMBER(sunplus_gcm394_base_device::ioport_a_w)
WRITE16_MEMBER(sunplus_gcm394_base_device::ioarea_7860_porta_w)
{
LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::ioport_a_w %04x\n", machine().describe_context(), data);
LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::ioarea_7860_porta_w %04x\n", machine().describe_context(), data);
m_porta_out(data);
}
@ -207,8 +219,17 @@ WRITE16_MEMBER(sunplus_gcm394_base_device::unkarea_7863_w)
// similar read/write pattern to above, 2nd group?
READ16_MEMBER(sunplus_gcm394_base_device::unkarea_7870_r) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7870_r\n", machine().describe_context()); return m_portb_in(); }
WRITE16_MEMBER(sunplus_gcm394_base_device::unkarea_7870_w) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7870_w %04x\n", machine().describe_context(), data); m_7870 = data; }
READ16_MEMBER(sunplus_gcm394_base_device::ioarea_7870_portb_r)
{
LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::ioarea_7870_portb_r\n", machine().describe_context());
return m_portb_in();
}
WRITE16_MEMBER(sunplus_gcm394_base_device::ioarea_7870_portb_w)
{
LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::ioarea_7870_portb_w %04x\n", machine().describe_context(), data);
m_7870 = data;
}
READ16_MEMBER(sunplus_gcm394_base_device::unkarea_7871_r) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7871_r\n", machine().describe_context()); return 0xffff;// m_7871;
}
@ -317,44 +338,48 @@ void sunplus_gcm394_base_device::internal_map(address_map &map)
// note, tilemaps are at the same address offsets in video device as spg2xx (but unknown devices are extra)
map(0x007000, 0x007007).w(m_spg_video, FUNC(gcm394_base_video_device::unk_vid1_regs_w));
map(0x007008, 0x00700f).w(m_spg_video, FUNC(gcm394_base_video_device::unk_vid2_regs_w));
map(0x007000, 0x007007).w(m_spg_video, FUNC(gcm394_base_video_device::unk_vid1_regs_w)); // written with other unknown_video_device1 LSB/MSB regs below (roz layer or line layer?)
map(0x007008, 0x00700f).w(m_spg_video, FUNC(gcm394_base_video_device::unk_vid2_regs_w)); // written with other unknown_video_device2 LSB/MSB regs below (roz layer or line layer?)
map(0x007010, 0x007015).rw(m_spg_video, FUNC(gcm394_base_video_device::tmap0_regs_r), FUNC(gcm394_base_video_device::tmap0_regs_w));
map(0x007016, 0x00701b).rw(m_spg_video, FUNC(gcm394_base_video_device::tmap1_regs_r), FUNC(gcm394_base_video_device::tmap1_regs_w));
map(0x007020, 0x007020).w(m_spg_video, FUNC(gcm394_base_video_device::tmap0_tilebase_lsb_w)); // probably tilebase, written with other tmap0 regs
map(0x007021, 0x007021).w(m_spg_video, FUNC(gcm394_base_video_device::tmap1_tilebase_lsb_w)); // probably tilebase, written with other tmap1 regs
map(0x007022, 0x007022).w(m_spg_video, FUNC(gcm394_base_video_device::unk_vid0_gfxbase_lsb_w)); // another tilebase? maybe sprites? 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_device0 regs
map(0x007024, 0x007024).w(m_spg_video, FUNC(gcm394_base_video_device::unk_vid2_gfxbase_lsb_w)); // written with other unknown_video_device1 regs
// 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(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));
map(0x00702a, 0x00702a).w(m_spg_video, FUNC(gcm394_base_video_device::video_702a_w)); // blend level control
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::unk_vid0_gfxbase_msb_w)); // maybe 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_device0 regs
map(0x00702f, 0x00702f).w(m_spg_video, FUNC(gcm394_base_video_device::unk_vid2_gfxbase_msb_w)); // written with other unknown_video_device1 regs
// 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(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?)
map(0x007030, 0x007030).rw(m_spg_video, FUNC(gcm394_base_video_device::video_7030_brightness_r), FUNC(gcm394_base_video_device::video_7030_brightness_w));
map(0x00703a, 0x00703a).rw(m_spg_video, FUNC(gcm394_base_video_device::video_703a_r), FUNC(gcm394_base_video_device::video_703a_w));
map(0x00703c, 0x00703c).w(m_spg_video, FUNC(gcm394_base_video_device::video_703c_w));
map(0x00703a, 0x00703a).rw(m_spg_video, FUNC(gcm394_base_video_device::video_703a_palettebank_r), FUNC(gcm394_base_video_device::video_703a_palettebank_w));
map(0x00703c, 0x00703c).w(m_spg_video, FUNC(gcm394_base_video_device::video_703c_w)); // TV Control 1
map(0x007042, 0x007042).w(m_spg_video, FUNC(gcm394_base_video_device::unk_vid0_extra_w)); // maybe sprites? written as 7022, 702d and 7042 group
map(0x007042, 0x007042).rw(m_spg_video, FUNC(gcm394_base_video_device::sprite_7042_extra_r), FUNC(gcm394_base_video_device::sprite_7042_extra_w)); // maybe sprites, written as 7022, 702d and 7042 group
map(0x007051, 0x007051).r(m_spg_video, FUNC(gcm394_base_video_device::video_7051_r)); // wrlshunt checks this
map(0x007051, 0x007051).r(m_spg_video, FUNC(gcm394_base_video_device::video_7051_r)); // wrlshunt checks this (doesn't exist on older SPG?)
map(0x007062, 0x007062).rw(m_spg_video, FUNC(gcm394_base_video_device::video_7062_r), FUNC(gcm394_base_video_device::video_7062_w));
map(0x007063, 0x007063).rw(m_spg_video, FUNC(gcm394_base_video_device::video_7063_r), FUNC(gcm394_base_video_device::video_7063_w));
map(0x007063, 0x007063).rw(m_spg_video, FUNC(gcm394_base_video_device::video_7063_videoirq_source_r), FUNC(gcm394_base_video_device::video_7063_videoirq_source_ack_w));
// note, 70 / 71 / 72 are the same offsets used for DMA as in spg2xx video device
map(0x007070, 0x007070).w(m_spg_video, FUNC(gcm394_base_video_device::video_dma_source_w)); // video dma, not system dma? (sets pointers to ram buffers)
map(0x007071, 0x007071).w(m_spg_video, FUNC(gcm394_base_video_device::video_dma_dest_w)); // sets pointers to 7300, 7400 ram areas below
map(0x007072, 0x007072).rw(m_spg_video, FUNC(gcm394_base_video_device::video_dma_size_r), FUNC(gcm394_base_video_device::video_dma_size_w)); //
map(0x00707e, 0x00707e).w(m_spg_video, FUNC(gcm394_base_video_device::video_dma_unk_w)); // written around same time as DMA, seems to select alt sprite bank
map(0x007072, 0x007072).rw(m_spg_video, FUNC(gcm394_base_video_device::video_dma_size_busy_r), FUNC(gcm394_base_video_device::video_dma_size_trigger_w)); //
// these don't exist on older SPG
map(0x00707c, 0x00707c).r(m_spg_video, FUNC(gcm394_base_video_device::video_707c_r)); // wrlshunt polls this waiting for 0x8000, is this some kind of manual port based data upload?
map(0x00707e, 0x00707e).w(m_spg_video, FUNC(gcm394_base_video_device::video_dma_unk_w)); // written around same time as DMA, seems to select alt sprite bank
map(0x00707f, 0x00707f).rw(m_spg_video, FUNC(gcm394_base_video_device::video_707f_r), FUNC(gcm394_base_video_device::video_707f_w));
// another set of registers for something?
@ -377,7 +402,7 @@ void sunplus_gcm394_base_device::internal_map(address_map &map)
map(0x007300, 0x0073ff).rw(m_spg_video, FUNC(gcm394_base_video_device::palette_r), FUNC(gcm394_base_video_device::palette_w));
map(0x007400, 0x0077ff).ram().share("spriteram");
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?
@ -407,7 +432,7 @@ void sunplus_gcm394_base_device::internal_map(address_map &map)
map(0x007835, 0x007835).w(FUNC(sunplus_gcm394_base_device::unkarea_7835_w));
map(0x007860, 0x007860).rw(FUNC(sunplus_gcm394_base_device::ioport_a_r), FUNC(sunplus_gcm394_base_device::ioport_a_w));
map(0x007860, 0x007860).rw(FUNC(sunplus_gcm394_base_device::ioarea_7860_porta_r), FUNC(sunplus_gcm394_base_device::ioarea_7860_porta_w));
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));
@ -415,7 +440,7 @@ void sunplus_gcm394_base_device::internal_map(address_map &map)
map(0x007868, 0x007868).r(FUNC(sunplus_gcm394_base_device::unkarea_7868_r)); // on startup
map(0x007870, 0x007870).rw(FUNC(sunplus_gcm394_base_device::unkarea_7870_r) ,FUNC(sunplus_gcm394_base_device::unkarea_7870_w));
map(0x007870, 0x007870).rw(FUNC(sunplus_gcm394_base_device::ioarea_7870_portb_r) ,FUNC(sunplus_gcm394_base_device::ioarea_7870_portb_w));
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));
@ -579,6 +604,9 @@ IRQ_CALLBACK_MEMBER(sunplus_gcm394_base_device::irq_vector_cb)
if (irqline == UNSP_IRQ6_LINE)
set_state_unsynced(UNSP_IRQ6_LINE, CLEAR_LINE);
if (irqline == UNSP_IRQ4_LINE)
set_state_unsynced(UNSP_IRQ4_LINE, CLEAR_LINE);
return 0;
}
@ -593,6 +621,31 @@ void sunplus_gcm394_base_device::checkirq6()
*/
}
/* the IRQ6 interrupt on Wrlshunt
reads 78a1, checks bit 0400
if it IS set, just increases value in RAM at 1a2e (no ack)
if it ISN'T set, then read/write 78b2 (ack something?) then increase value in RAM at 1a2e
(smartfp doesn't touch these addresses? but instead reads/writes 7935, alt ack?)
wrlshunt also has an IRQ4
it always reads/writes 78c0 before executing payload (ack?)
payload is a lot of manipulation of values in RAM, no registers touched
wrlshunt also has FIQ
no ack mechanism, for sound timer maybe (as it appears to be on spg110)
----
IRQ5 is video IRQ
in both games writing 0x0001 to 7063 seems to be an ack mechanism
wrlshunt also checks bit 0x0040 of 7863 and will ack that too with alt code paths
7863 is therefore some kind of 'video irq source' ?
*/
void sunplus_gcm394_base_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
switch (id)
@ -601,6 +654,8 @@ void sunplus_gcm394_base_device::device_timer(emu_timer &timer, device_timer_id
{
m_7935 |= 0x0100;
set_state_unsynced(UNSP_IRQ6_LINE, ASSERT_LINE);
//set_state_unsynced(UNSP_IRQ4_LINE, ASSERT_LINE);
// checkirq6();
break;
}
@ -620,8 +675,11 @@ WRITE_LINE_MEMBER(sunplus_gcm394_base_device::videoirq_w)
uint16_t sunplus_gcm394_base_device::read_space(uint32_t offset)
{
uint16_t b = m_gfxregion[(offset * 2) & (m_gfxregionsize - 1)] | (m_gfxregion[(offset * 2 + 1) & (m_gfxregionsize - 1)] << 8);
return b;
// uint16_t b = m_gfxregion[(offset * 2) & (m_gfxregionsize - 1)] | (m_gfxregion[(offset * 2 + 1) & (m_gfxregionsize - 1)] << 8);
// return b;
address_space& mem = this->space(AS_PROGRAM);
uint16_t retdata = mem.read_word(offset);
return retdata;
}

View File

@ -181,8 +181,8 @@ private:
DECLARE_READ16_MEMBER(unkarea_782d_r);
DECLARE_WRITE16_MEMBER(unkarea_782d_w);
DECLARE_READ16_MEMBER(ioport_a_r);
DECLARE_WRITE16_MEMBER(ioport_a_w);
DECLARE_READ16_MEMBER(ioarea_7860_porta_r);
DECLARE_WRITE16_MEMBER(ioarea_7860_porta_w);
DECLARE_READ16_MEMBER(unkarea_7861_r);
@ -191,8 +191,8 @@ private:
DECLARE_READ16_MEMBER(unkarea_7863_r);
DECLARE_WRITE16_MEMBER(unkarea_7863_w);
DECLARE_READ16_MEMBER(unkarea_7870_r);
DECLARE_WRITE16_MEMBER(unkarea_7870_w);
DECLARE_READ16_MEMBER(ioarea_7870_portb_r);
DECLARE_WRITE16_MEMBER(ioarea_7870_portb_w);
DECLARE_READ16_MEMBER(unkarea_7871_r);

View File

@ -27,7 +27,6 @@ gcm394_base_video_device::gcm394_base_video_device(const machine_config &mconfig
, m_cpu(*this, finder_base::DUMMY_TAG)
, m_screen(*this, finder_base::DUMMY_TAG)
// , m_scrollram(*this, "scrollram")
, m_spriteram(*this, "^spriteram")
, m_video_irq_cb(*this)
, m_palette(*this, "palette")
, m_gfxdecode(*this, "gfxdecode")
@ -42,9 +41,12 @@ gcm394_video_device::gcm394_video_device(const machine_config &mconfig, const ch
void gcm394_base_video_device::decodegfx(const char* tag)
{
if (!memregion(tag))
return;
uint8_t* gfxregion = memregion(tag)->base();
int gfxregionsize = memregion(tag)->bytes();
if (1)
{
gfx_layout obj_layout =
@ -151,7 +153,7 @@ void gcm394_base_video_device::decodegfx(const char* tag)
m_gfxdecode->set_gfx(m_maxgfxelement, std::make_unique<gfx_element>(m_palette, obj_layout, gfxregion, 0, 0x40 * 0x10, 0));
m_maxgfxelement++;
}
if (1)
{
gfx_layout obj_layout =
@ -207,6 +209,8 @@ void gcm394_base_video_device::device_start()
decodegfx(":maincpu");
save_item(NAME(m_spriteextra));
save_item(NAME(m_spriteram));
m_space_read_cb.resolve_safe(0);
}
@ -218,22 +222,26 @@ void gcm394_base_video_device::device_reset()
m_tmap1_regs[i] = 0x0000;
}
for (int i=0;i<0x100;i++)
for (int i = 0; i < 0x400; i++)
{
m_spriteextra[i] = 0x0000;
m_spriteram[i] = 0x0000;
}
for (int i=0;i<0x100;i++)
m_paletteram[i] = machine().rand()&0x7fff;
m_707f = 0x0000;
m_703a = 0x0000;
m_703a_palettebank = 0x0000;
m_7062 = 0x0000;
m_7063 = 0x0000;
m_702a = 0x0000;
m_7030_brightness = 0x0000;
m_703c = 0x0000;
m_7042_sprite = 0x0000;
m_7080 = 0x0000;
m_7081 = 0x0000;
@ -245,15 +253,15 @@ void gcm394_base_video_device::device_reset()
m_7087 = 0x0000;
m_7088 = 0x0000;
m_videodma_bank = 0x0000;
m_707e_videodma_bank = 0x0000;
m_videodma_size = 0x0000;
m_videodma_dest = 0x0000;
m_videodma_source = 0x0000;
m_video_irq_status = 0x0000;
m_unk_vid0_gfxbase_lsb = 0;
m_unk_vid0_gfxbase_msb = 0;
m_sprite_7022_gfxbase_lsb = 0;
m_sprite_702d_gfxbase_msb = 0;
m_unk_vid1_gfxbase_lsb = 0;
m_unk_vid1_gfxbase_msb = 0;
m_unk_vid2_gfxbase_lsb = 0;
@ -266,7 +274,7 @@ void gcm394_base_video_device::device_reset()
*************************/
template<gcm394_base_video_device::blend_enable_t Blend, gcm394_base_video_device::rowscroll_enable_t RowScroll, gcm394_base_video_device::flipx_t FlipX>
void gcm394_base_video_device::draw(const rectangle &cliprect, uint32_t line, uint32_t xoff, uint32_t yoff, uint32_t bitmap_addr, uint32_t tile, int32_t h, int32_t w, uint8_t bpp, uint32_t yflipmask, uint32_t palette_offset)
void gcm394_base_video_device::draw(const rectangle &cliprect, uint32_t line, uint32_t xoff, uint32_t yoff, uint32_t bitmap_addr, uint32_t tile, int32_t h, int32_t w, uint8_t bpp, uint32_t yflipmask, uint32_t palette_offset, int addressing_mode)
{
uint32_t nc_bpp = ((bpp) + 1) << 1;
@ -275,11 +283,18 @@ void gcm394_base_video_device::draw(const rectangle &cliprect, uint32_t line, ui
//palette_offset <<= nc_bpp;
uint32_t bits_per_row = nc_bpp * w / 16;
//uint32_t words_per_tile = bits_per_row * h;
uint32_t words_per_tile;
if (addressing_mode == 1)
{
words_per_tile = bits_per_row * h;
}
else
{
words_per_tile = 8; // seems to be correct for sprites regardless of size / bpp on smartfp
}
uint32_t words_per_tile = 8; // seems to be correct for sprites regardless of size / bpp
uint32_t m = (bitmap_addr - 0x20000) + (words_per_tile * tile + bits_per_row * (line ^ yflipmask));
uint32_t m = (bitmap_addr) + (words_per_tile * tile + bits_per_row * (line ^ yflipmask));
uint32_t bits = 0;
@ -448,16 +463,16 @@ void gcm394_base_video_device::draw_page(const rectangle &cliprect, uint32_t sca
if (row_scroll)
{
if (flip_x)
draw<BlendOn, RowScrollOn, FlipXOn>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset);
draw<BlendOn, RowScrollOn, FlipXOn>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, 0);
else
draw<BlendOn, RowScrollOn, FlipXOff>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset);
draw<BlendOn, RowScrollOn, FlipXOff>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, 0);
}
else
{
if (flip_x)
draw<BlendOn, RowScrollOff, FlipXOn>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset);
draw<BlendOn, RowScrollOff, FlipXOn>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, 0);
else
draw<BlendOn, RowScrollOff, FlipXOff>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset);
draw<BlendOn, RowScrollOff, FlipXOff>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, 0);
}
}
else
@ -465,16 +480,16 @@ void gcm394_base_video_device::draw_page(const rectangle &cliprect, uint32_t sca
if (row_scroll)
{
if (flip_x)
draw<BlendOff, RowScrollOn, FlipXOn>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset);
draw<BlendOff, RowScrollOn, FlipXOn>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, 0);
else
draw<BlendOff, RowScrollOn, FlipXOff>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset);
draw<BlendOff, RowScrollOn, FlipXOff>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, 0);
}
else
{
if (flip_x)
draw<BlendOff, RowScrollOff, FlipXOn>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset);
draw<BlendOff, RowScrollOff, FlipXOn>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, 0);
else
draw<BlendOff, RowScrollOff, FlipXOff>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset);
draw<BlendOff, RowScrollOff, FlipXOff>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, 0);
}
}
}
@ -483,7 +498,7 @@ void gcm394_base_video_device::draw_page(const rectangle &cliprect, uint32_t sca
void gcm394_base_video_device::draw_sprite(const rectangle &cliprect, uint32_t scanline, int priority, uint32_t base_addr)
{
uint32_t bitmap_addr = (m_unk_vid1_gfxbase_msb << 16) | m_unk_vid1_gfxbase_lsb; // or unk_vid2 / 0
uint32_t bitmap_addr = (m_sprite_702d_gfxbase_msb << 16) | m_sprite_7022_gfxbase_lsb;
uint32_t tile = m_spriteram[base_addr + 0];
int16_t x = m_spriteram[base_addr + 1];
int16_t y = m_spriteram[base_addr + 2];
@ -495,6 +510,15 @@ void gcm394_base_video_device::draw_sprite(const rectangle &cliprect, uint32_t s
return;
}
int addressing_mode = 0;
// m_7042_sprite is f7 on smartfp
// 01 on wrlshunt
// this is not enough to conclude anything
if (m_7042_sprite == 0x01)
addressing_mode = 1;
tile |= m_spriteextra[base_addr / 4] << 16;
if (((attr & PAGE_PRIORITY_FLAG_MASK) >> PAGE_PRIORITY_FLAG_SHIFT) != priority)
@ -527,7 +551,15 @@ void gcm394_base_video_device::draw_sprite(const rectangle &cliprect, uint32_t s
}
bool blend = (attr & 0x4000);
bool flip_x = (attr & TILE_X_FLIP);
bool flip_x = false;
// different attribute use?
if (addressing_mode == 0)
{
flip_x = (attr & TILE_X_FLIP);
}
const uint8_t bpp = attr & 0x0003;
const uint32_t yflipmask = attr & TILE_Y_FLIP ? h - 1 : 0;
uint32_t palette_offset = (attr & 0x0f00) >> 4;
@ -538,16 +570,16 @@ void gcm394_base_video_device::draw_sprite(const rectangle &cliprect, uint32_t s
if (blend)
{
if (flip_x)
draw<BlendOn, RowScrollOff, FlipXOn>(cliprect, tile_line, x, y, bitmap_addr, tile, h, w, bpp, yflipmask, palette_offset);
draw<BlendOn, RowScrollOff, FlipXOn>(cliprect, tile_line, x, y, bitmap_addr, tile, h, w, bpp, yflipmask, palette_offset, addressing_mode);
else
draw<BlendOn, RowScrollOff, FlipXOff>(cliprect, tile_line, x, y, bitmap_addr, tile, h, w, bpp, yflipmask, palette_offset);
draw<BlendOn, RowScrollOff, FlipXOff>(cliprect, tile_line, x, y, bitmap_addr, tile, h, w, bpp, yflipmask, palette_offset, addressing_mode);
}
else
{
if (flip_x)
draw<BlendOff, RowScrollOff, FlipXOn>(cliprect, tile_line, x, y, bitmap_addr, tile, h, w, bpp, yflipmask, palette_offset);
draw<BlendOff, RowScrollOff, FlipXOn>(cliprect, tile_line, x, y, bitmap_addr, tile, h, w, bpp, yflipmask, palette_offset, addressing_mode);
else
draw<BlendOff, RowScrollOff, FlipXOff>(cliprect, tile_line, x, y, bitmap_addr, tile, h, w, bpp, yflipmask, palette_offset);
draw<BlendOff, RowScrollOff, FlipXOff>(cliprect, tile_line, x, y, bitmap_addr, tile, h, w, bpp, yflipmask, palette_offset, addressing_mode);
}
}
@ -607,24 +639,24 @@ void gcm394_base_video_device::write_tmap_regs(int tmap, uint16_t* regs, int off
break;
case 0x2: // Page Attributes
LOGMASKED(LOG_GCM394_TMAP, "%s: write_tmap_regs: Page %d Attributes = %04x (Depth:%d, Palette:%d, VSize:%d, HSize:%d, FlipY:%d, FlipX:%d, BPP:%d)\n", machine().describe_context(), tmap, 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));
LOGMASKED(LOG_GCM394_TMAP, "%s: write_tmap_regs: Page %d Attributes = %04x (unk %01x: Depth:%d, Palette:%d, VSize:%d, HSize:%d, FlipY:%d, FlipX:%d, BPP:%d)\n", machine().describe_context(), tmap, data,
(data & 0xc000) >> 14, (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[offset] = data;
break;
case 0x3: // Page Control
LOGMASKED(LOG_GCM394_TMAP, "%s: write_tmap_regs: Page %d Control = %04x (Blend:%d, HiColor:%d, RowScroll:%d, Enable:%d, Wallpaper:%d, RegSet:%d, Bitmap:%d)\n", machine().describe_context(), tmap, data
, BIT(data, 8), BIT(data, 7), BIT(data, 4), BIT(data, 3), BIT(data, 2), BIT(data, 1), BIT(data, 0));
LOGMASKED(LOG_GCM394_TMAP, "%s: write_tmap_regs: Page %d Control = %04x (unk:%02x Blend:%d, HiColor:%d, unk:%d, unk%d, RowScroll:%d, Enable:%d, Wallpaper:%d, RegSet:%d, Bitmap:%d)\n", machine().describe_context(), tmap, data,
(data & 0xfe00) >> 9, BIT(data, 8), BIT(data, 7), BIT(data, 6), BIT(data, 5), BIT(data, 4), BIT(data, 3), BIT(data, 2), BIT(data, 1), BIT(data, 0));
regs[offset] = data;
break;
case 0x4: // Page Tile Address
LOGMASKED(LOG_GCM394_TMAP, "%s: write_tmap_regs: Page %d Tile Address = %04x\n", machine().describe_context(), tmap, data & 0x1fff);
LOGMASKED(LOG_GCM394_TMAP, "%s: write_tmap_regs: Page %d Tile Address = %04x\n", machine().describe_context(), tmap, data);
regs[offset] = data;
break;
case 0x5: // Page Attribute write_tmap_regs
LOGMASKED(LOG_GCM394_TMAP, "%s: write_tmap_regs: Page %d Attribute Address = %04x\n", machine().describe_context(), tmap, data & 0x1fff);
LOGMASKED(LOG_GCM394_TMAP, "%s: write_tmap_regs: Page %d Attribute Address = %04x\n", machine().describe_context(), tmap, data);
regs[offset] = data;
break;
}
@ -682,32 +714,36 @@ WRITE16_MEMBER(gcm394_base_video_device::tmap1_tilebase_msb_w)
// offsets 0,1,4,5,6,7 used in main IRQ code
// offsets 2,3 only cleared on startup
// Based on code analysis this seems to be the same as the regular tilemap regs, except for the addition of regs 2,3 which shift the remaining ones along.
// As the hardware appears to support ROZ these are probably 2 extra tile layers, with the 2 additional words being the ROZ parameters?
void gcm394_base_video_device::unk_vid_regs_w(int which, int offset, uint16_t data)
{
switch (offset)
{
case 0x0:
LOGMASKED(LOG_GCM394_VIDEO, "unk_vid_regs_w (unk chip %d) %01x %04x (X scroll?)\n", machine().describe_context(), which, offset, data); // masked with 0x3ff in code like x-scroll for tilemaps
LOGMASKED(LOG_GCM394_VIDEO, "%s: unk_vid_regs_w (unk chip %d) (offset %01x) (data %04x) (X scroll?)\n", machine().describe_context(), which, offset, data); // masked with 0x3ff in code like x-scroll for tilemaps
break;
case 0x1:
LOGMASKED(LOG_GCM394_VIDEO, "unk_vid_regs_w (unk chip %d) %01x %04x (y scroll?)\n", machine().describe_context(), which, offset, data); // masked with 0x3ff in code like x-scroll for tilemaps
LOGMASKED(LOG_GCM394_VIDEO, "%s: unk_vid_regs_w (unk chip %d) (offset %01x) (data %04x) (y scroll?)\n", machine().describe_context(), which, offset, data); // masked with 0x3ff in code like x-scroll for tilemaps
break;
case 0x05: // seems to be similar / the same as Page Control for tilemaps (written with same basic code, but for these layers)
LOGMASKED(LOG_GCM394_VIDEO, "%s: unk_vid_regs_w (unk chip %d) (offset %01x) (data %04x) (Page Control?)\n", machine().describe_context(), which, offset, data);
break;
case 0x02: // startup?
case 0x03: // startup?
case 0x04:
case 0x05:
case 0x06:
case 0x07:
LOGMASKED(LOG_GCM394_VIDEO, "unk_vid_regs_w (unk chip %d) %01x %04x\n", machine().describe_context(), which, offset, data);
LOGMASKED(LOG_GCM394_VIDEO, "%s: unk_vid_regs_w (unk chip %d) (offset %01x) (data %04x)\n", machine().describe_context(), which, offset, data);
break;
}
}
// **************************************** unknown video device 1 (another tilemap? sprite layer?) *************************************************
// **************************************** unknown video device 1 (another tilemap? roz? line? zooming sprite layer?) *************************************************
WRITE16_MEMBER(gcm394_base_video_device::unk_vid1_regs_w)
{
@ -728,7 +764,7 @@ WRITE16_MEMBER(gcm394_base_video_device::unk_vid1_gfxbase_msb_w)
LOGMASKED(LOG_GCM394_TMAP, " (unk_vid1 tilegfxbase is now %04x%04x)\n", m_unk_vid1_gfxbase_msb, m_unk_vid1_gfxbase_lsb);
}
// **************************************** unknown video device 2 (another tilemap? sprite layer?) *************************************************
// **************************************** unknown video device 2 (another tilemap? roz? lines? zooming sprite layer?) *************************************************
WRITE16_MEMBER(gcm394_base_video_device::unk_vid2_regs_w)
{
@ -749,25 +785,35 @@ WRITE16_MEMBER(gcm394_base_video_device::unk_vid2_gfxbase_msb_w)
LOGMASKED(LOG_GCM394_TMAP, " (unk_vid2 tilegfxbase is now %04x%04x)\n", m_unk_vid2_gfxbase_msb, m_unk_vid2_gfxbase_lsb);
}
// **************************************** unknown video device 0 (sprite control?) *************************************************
// **************************************** sprite control registers *************************************************
WRITE16_MEMBER(gcm394_base_video_device::unk_vid0_gfxbase_lsb_w)
// set to 001264c0 in wrlshunt, which point at the menu selectors (game names, arrows etc.)
WRITE16_MEMBER(gcm394_base_video_device::sprite_7022_gfxbase_lsb_w)
{
LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::unk_vid0_gfxbase_lsb_w %04x\n", machine().describe_context(), data);
m_unk_vid0_gfxbase_lsb = data;
LOGMASKED(LOG_GCM394_TMAP, " (unk_vid0 tilegfxbase is now %04x%04x)\n", m_unk_vid0_gfxbase_msb, m_unk_vid0_gfxbase_lsb);
LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::sprite_7022_gfxbase_lsb_w %04x\n", machine().describe_context(), data);
m_sprite_7022_gfxbase_lsb = data;
LOGMASKED(LOG_GCM394_TMAP, " (sprite tilebase is now %04x%04x)\n", m_sprite_702d_gfxbase_msb, m_sprite_7022_gfxbase_lsb);
}
WRITE16_MEMBER(gcm394_base_video_device::unk_vid0_gfxbase_msb_w)
WRITE16_MEMBER(gcm394_base_video_device::sprite_702d_gfxbase_msb_w)
{
LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::unk_vid0_gfxbase_msb_w %04x\n", machine().describe_context(), data);
m_unk_vid0_gfxbase_msb = data;
LOGMASKED(LOG_GCM394_TMAP, " (unk_vid0 tilegfxbase is now %04x%04x)\n", m_unk_vid0_gfxbase_msb, m_unk_vid0_gfxbase_lsb);
LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::sprite_702d_gfxbase_msb_w %04x\n", machine().describe_context(), data);
m_sprite_702d_gfxbase_msb = data;
LOGMASKED(LOG_GCM394_TMAP, " (sprite tilebase tilegfxbase is now %04x%04x)\n", m_sprite_702d_gfxbase_msb, m_sprite_7022_gfxbase_lsb);
}
WRITE16_MEMBER(gcm394_base_video_device::unk_vid0_extra_w)
READ16_MEMBER(gcm394_base_video_device::sprite_7042_extra_r)
{
LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::unk_vid0_extra_w %04x\n", machine().describe_context(), data);
uint16_t retdata = m_7042_sprite;
LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::sprite_7042_extra_r (returning: %04x)\n", machine().describe_context(), retdata);
return retdata;
}
WRITE16_MEMBER(gcm394_base_video_device::sprite_7042_extra_w)
{
LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::sprite_7042_extra_w %04x\n", machine().describe_context(), data);
m_7042_sprite = data;
}
@ -785,91 +831,126 @@ WRITE16_MEMBER(gcm394_base_video_device::video_dma_dest_w)
m_videodma_dest = data;
}
READ16_MEMBER(gcm394_base_video_device::video_dma_size_r)
READ16_MEMBER(gcm394_base_video_device::video_dma_size_busy_r)
{
LOGMASKED(LOG_GCM394_VIDEO_DMA, "%s:gcm394_base_video_device::video_dma_size_r\n", machine().describe_context());
LOGMASKED(LOG_GCM394_VIDEO_DMA, "%s:gcm394_base_video_device::video_dma_size_busy_r\n", machine().describe_context());
return 0x0000;
}
WRITE16_MEMBER(gcm394_base_video_device::video_dma_size_w)
WRITE16_MEMBER(gcm394_base_video_device::video_dma_size_trigger_w)
{
LOGMASKED(LOG_GCM394_VIDEO_DMA, "%s:gcm394_base_video_device::video_dma_size_w %04x\n", machine().describe_context(), data);
LOGMASKED(LOG_GCM394_VIDEO_DMA, "%s:gcm394_base_video_device::video_dma_size_trigger_w %04x\n", machine().describe_context(), data);
m_videodma_size = data;
LOGMASKED(LOG_GCM394_VIDEO_DMA, "%s: doing sprite / video DMA source %04x dest %04x size %04x bank %04x\n", machine().describe_context(), m_videodma_source, m_videodma_dest, m_videodma_size, m_videodma_bank );
LOGMASKED(LOG_GCM394_VIDEO_DMA, "%s: doing sprite / video DMA source %04x dest %04x size %04x value of 707e (bank) %04x value of 707f %04x\n", machine().describe_context(), m_videodma_source, m_videodma_dest, m_videodma_size, m_707e_videodma_bank, m_707f );
if (m_videodma_dest == 0x7400)
for (int i = 0; i <= m_videodma_size; i++)
{
if (m_videodma_bank == 0x0001) // transfers an additional word for each sprite with this bit set
{
m_videodma_size &= 0xff;
for (int i = 0; i <= m_videodma_size; i++)
{
uint16_t dat = space.read_word(m_videodma_source+i);
m_spriteextra[i] = dat;
}
}
else if (m_videodma_bank == 0x0000)
{
m_videodma_size &= 0x3ff;
for (int i = 0; i <= m_videodma_size; i++)
{
uint16_t dat = space.read_word(m_videodma_source+i);
m_spriteram[i] = dat;
}
}
else
{
logerror("unhandled: m_videodma_bank is %04x\n", m_videodma_bank);
}
}
else
{
logerror("unhandled: m_videodma_dest is %04x\n", m_videodma_dest);
uint16_t dat = space.read_word(m_videodma_source+i);
space.write_word(m_videodma_dest + i, dat);
}
m_videodma_size = 0x0000;
}
WRITE16_MEMBER(gcm394_base_video_device::video_dma_unk_w)
{
LOGMASKED(LOG_GCM394_VIDEO_DMA, "%s:gcm394_base_video_device::video_dma_unk_w %04x\n", machine().describe_context(), data);
m_videodma_bank = data;
m_707e_videodma_bank = data;
}
READ16_MEMBER(gcm394_base_video_device::video_707c_r)
{
LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_707c_r\n", machine().describe_context());
return 0x8000;
}
/* 707f is VERY important, lots of rendering codepaths in the code depend on the value it returns.
READ16_MEMBER(gcm394_base_video_device::video_707f_r) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_707f_r\n", machine().describe_context()); return m_707f; }
WRITE16_MEMBER(gcm394_base_video_device::video_707f_w) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_707f_w %04x\n", machine().describe_context(), data); m_707f = data; }
all operations in the code based on 707f are bit based, usually read register, set / clear a bit
and then write register, or read register and test an individual bit.
READ16_MEMBER(gcm394_base_video_device::video_703a_r) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_703a_r\n", machine().describe_context()); return m_703a; } // something to do with palette access, maybe bank?
WRITE16_MEMBER(gcm394_base_video_device::video_703a_w) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_703a_w %04x\n", machine().describe_context(), data); m_703a = data; }
our current codeflow means that bits are only ever set, not cleared.
are the bits triggers? acks? enables? status flags?
in wrlshunt this ends up being set to 02f9 ---- --x- xxxx x--x
and in smartfp it ends up being set to 0065 ---- ---- -xx- -x-x
is this because wrlshunt uses more layers?
*/
/* wrlshunt BG Tilemap location note
background tilemap appears to be at 24ad30 - 24af87 (byte address) in RAM == 125698 - 1257c3 (word address)
there are pointers to this
(2879-287a) = 98 56 12 00 (00125698) (main background tilemap data is at this address)
(287b-287c) = 30 5e 12 00 (00125e30) (address for other layer tilemap)
where do we get these copied to registers or used as a source to copy from?
does it depend on 707f behavior?
if you return rand() on 707f reads sometimes you see
[:maincpu] pc:053775: r4 = r4 lsr r3 (5698 0009) : [:maincpu] result 002b
(bg tile addressing is also done by tile #, like the sprites, not fixed step like smartfp)
*/
READ16_MEMBER(gcm394_base_video_device::video_707f_r)
{
uint16_t retdata = m_707f;
LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_707f_r (returning %04x)\n", machine().describe_context(), retdata);
return retdata;
}
WRITE16_MEMBER(gcm394_base_video_device::video_707f_w)
{
LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_707f_w %04x\n", machine().describe_context(), data);
for (int i = 0; i < 16; i++)
{
uint16_t mask = 1 << i;
if ((m_707f & mask) != (data & mask))
{
if (data & mask)
{
LOGMASKED(LOG_GCM394_VIDEO, " bit %04x Low -> High\n", mask);
}
else
{
LOGMASKED(LOG_GCM394_VIDEO, " bit %04x High -> Low\n", mask);
}
}
}
m_707f = data;
}
READ16_MEMBER(gcm394_base_video_device::video_703a_palettebank_r)
{
LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_703a_palettebank_r\n", machine().describe_context());
return m_703a_palettebank;
}
WRITE16_MEMBER(gcm394_base_video_device::video_703a_palettebank_w)
{
LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_703a_palettebank_w %04x\n", machine().describe_context(), data);
m_703a_palettebank = data;
}
READ16_MEMBER(gcm394_base_video_device::video_7062_r) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_7062_r\n", machine().describe_context()); return m_7062; }
WRITE16_MEMBER(gcm394_base_video_device::video_7062_w) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_7062_w %04x\n", machine().describe_context(), data); m_7062 = data; }
READ16_MEMBER(gcm394_base_video_device::video_7063_r)
READ16_MEMBER(gcm394_base_video_device::video_7063_videoirq_source_r)
{
LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_7063_r\n", machine().describe_context());
LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_7063_videoirq_source_r\n", machine().describe_context());
return machine().rand();
}
WRITE16_MEMBER(gcm394_base_video_device::video_7063_w)
WRITE16_MEMBER(gcm394_base_video_device::video_7063_videoirq_source_ack_w)
{
LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_7063_w %04x\n", machine().describe_context(), data);
LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_7063_videoirq_source_ack_w %04x\n", machine().describe_context(), data);
m_7063 = data;
// ack or enable? happens near start of the IRQ
@ -910,6 +991,7 @@ READ16_MEMBER(gcm394_base_video_device::video_7051_r)
return retdat;
}
// this block get set once, in a single function, could be important
WRITE16_MEMBER(gcm394_base_video_device::video_7080_w) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_7080_w %04x\n", machine().describe_context(), data); m_7080 = data; }
WRITE16_MEMBER(gcm394_base_video_device::video_7081_w) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_7081_w %04x\n", machine().describe_context(), data); m_7081 = data; }
WRITE16_MEMBER(gcm394_base_video_device::video_7082_w) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_7082_w %04x\n", machine().describe_context(), data); m_7082 = data; }
@ -922,17 +1004,56 @@ WRITE16_MEMBER(gcm394_base_video_device::video_7088_w) { LOGMASKED(LOG_GCM394_VI
READ16_MEMBER(gcm394_base_video_device::video_7083_r) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_7083_r\n", machine().describe_context()); return m_7083; }
WRITE16_MEMBER(gcm394_base_video_device::palette_w)
WRITE16_MEMBER(gcm394_base_video_device::spriteram_w)
{
LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::palette_w %04x : %04x (value of 0x703a is %04x)\n", machine().describe_context(), offset, data, m_703a);
// transfers an additional word for each sprite with this bit set (smartfp) or an entire extra bank (wrlshunt)
// wrlshunt instead seems to base if it writes the extra data based on 707f so maybe this is more complex than banking
// however for 707e only 0/1 is written, and it also gets written before system DMA, so despite being in the video DMA
// region seems to operate separate from that.
if (m_703a & 0xfff0)
if (m_707e_videodma_bank == 0x0000)
{
fatalerror("palette writes with m_703a %04x\n", m_703a);
m_spriteram[offset] = data;
}
else if (m_707e_videodma_bank == 0x0001)
{
m_spriteextra[offset] = data;
}
else
{
offset |= (m_703a & 0x000f) << 8;
LOGMASKED(LOG_GCM394_VIDEO, "%s: spriteram_w %04x %04x unknown bank %04x\n", machine().describe_context(), offset, data, m_707e_videodma_bank);
}
}
READ16_MEMBER(gcm394_base_video_device::spriteram_r)
{
if (m_707e_videodma_bank == 0x0000)
{
return m_spriteram[offset];
}
else if (m_707e_videodma_bank == 0x0001)
{
return m_spriteextra[offset];
}
else
{
LOGMASKED(LOG_GCM394_VIDEO, "%s: spriteram_r %04x unknown bank %04x\n", machine().describe_context(), offset, m_707e_videodma_bank);
return 0x0000;
}
}
WRITE16_MEMBER(gcm394_base_video_device::palette_w)
{
LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::palette_w %04x : %04x (value of 0x703a is %04x)\n", machine().describe_context(), offset, data, m_703a_palettebank);
if (m_703a_palettebank & 0xfff0)
{
fatalerror("palette writes with m_703a_palettebank %04x\n", m_703a_palettebank);
}
else
{
offset |= (m_703a_palettebank & 0x000f) << 8;
m_paletteram[offset] = data;
@ -947,13 +1068,13 @@ WRITE16_MEMBER(gcm394_base_video_device::palette_w)
READ16_MEMBER(gcm394_base_video_device::palette_r)
{
if (m_703a & 0xfff0)
if (m_703a_palettebank & 0xfff0)
{
fatalerror("palette read with m_703a %04x\n", m_703a);
fatalerror("palette read with m_703a_palettebank %04x\n", m_703a_palettebank);
}
else
{
offset |= (m_703a & 0x000f) << 8;
offset |= (m_703a_palettebank & 0x000f) << 8;
return m_paletteram[offset];
}
}

View File

@ -45,24 +45,25 @@ public:
DECLARE_WRITE16_MEMBER(unk_vid2_gfxbase_lsb_w);
DECLARE_WRITE16_MEMBER(unk_vid2_gfxbase_msb_w);
DECLARE_WRITE16_MEMBER(unk_vid0_gfxbase_lsb_w);
DECLARE_WRITE16_MEMBER(unk_vid0_gfxbase_msb_w);
DECLARE_WRITE16_MEMBER(unk_vid0_extra_w);
DECLARE_WRITE16_MEMBER(sprite_7022_gfxbase_lsb_w);
DECLARE_WRITE16_MEMBER(sprite_702d_gfxbase_msb_w);
DECLARE_READ16_MEMBER(sprite_7042_extra_r);
DECLARE_WRITE16_MEMBER(sprite_7042_extra_w);
DECLARE_WRITE16_MEMBER(video_dma_source_w);
DECLARE_WRITE16_MEMBER(video_dma_dest_w);
DECLARE_READ16_MEMBER(video_dma_size_r);
DECLARE_WRITE16_MEMBER(video_dma_size_w);
DECLARE_READ16_MEMBER(video_dma_size_busy_r);
DECLARE_WRITE16_MEMBER(video_dma_size_trigger_w);
DECLARE_WRITE16_MEMBER(video_dma_unk_w);
DECLARE_READ16_MEMBER(video_703a_r);
DECLARE_WRITE16_MEMBER(video_703a_w);
DECLARE_READ16_MEMBER(video_703a_palettebank_r);
DECLARE_WRITE16_MEMBER(video_703a_palettebank_w);
DECLARE_READ16_MEMBER(video_7062_r);
DECLARE_WRITE16_MEMBER(video_7062_w);
DECLARE_READ16_MEMBER(video_7063_r);
DECLARE_WRITE16_MEMBER(video_7063_w);
DECLARE_READ16_MEMBER(video_7063_videoirq_source_r);
DECLARE_WRITE16_MEMBER(video_7063_videoirq_source_ack_w);
DECLARE_WRITE16_MEMBER(video_702a_w);
DECLARE_READ16_MEMBER(video_7030_brightness_r);
@ -89,6 +90,9 @@ public:
DECLARE_READ16_MEMBER(palette_r);
DECLARE_WRITE16_MEMBER(palette_w);
DECLARE_WRITE16_MEMBER(spriteram_w);
DECLARE_READ16_MEMBER(spriteram_r);
DECLARE_READ16_MEMBER(video_7051_r);
auto write_video_irq_callback() { return m_video_irq_cb.bind(); };
@ -141,7 +145,7 @@ protected:
};
template<blend_enable_t Blend, rowscroll_enable_t RowScroll, flipx_t FlipX>
void draw(const rectangle &cliprect, uint32_t line, uint32_t xoff, uint32_t yoff, uint32_t bitmap_addr, uint32_t tile, int32_t h, int32_t w, uint8_t bpp, uint32_t yflipmask, uint32_t palette_offset);
void draw(const rectangle &cliprect, uint32_t line, uint32_t xoff, uint32_t yoff, uint32_t bitmap_addr, uint32_t tile, int32_t h, int32_t w, uint8_t bpp, uint32_t yflipmask, uint32_t palette_offset, int addressing_mode);
void draw_page(const rectangle &cliprect, uint32_t scanline, int priority, uint32_t bitmap_addr, uint16_t *regs);
void draw_sprites(const rectangle& cliprect, uint32_t scanline, int priority);
void draw_sprite(const rectangle& cliprect, uint32_t scanline, int priority, uint32_t base_addr);
@ -153,7 +157,6 @@ protected:
required_device<unsp_device> m_cpu;
required_device<screen_device> m_screen;
// required_shared_ptr<uint16_t> m_scrollram;
required_shared_ptr<uint16_t> m_spriteram;
uint16_t m_page0_addr_lsb;
uint16_t m_page0_addr_msb;
@ -161,7 +164,7 @@ protected:
uint16_t m_page1_addr_lsb;
uint16_t m_page1_addr_msb;
uint16_t m_videodma_bank;
uint16_t m_707e_videodma_bank;
uint16_t m_videodma_size;
uint16_t m_videodma_dest;
uint16_t m_videodma_source;
@ -174,7 +177,7 @@ protected:
uint16_t m_tmap1_regs[0x6];
uint16_t m_707f;
uint16_t m_703a;
uint16_t m_703a_palettebank;
uint16_t m_7062;
uint16_t m_7063;
@ -182,6 +185,7 @@ protected:
uint16_t m_7030_brightness;
uint16_t m_703c;
uint16_t m_7042_sprite;
uint16_t m_7080;
uint16_t m_7081;
@ -193,8 +197,8 @@ protected:
uint16_t m_7087;
uint16_t m_7088;
uint16_t m_unk_vid0_gfxbase_lsb;
uint16_t m_unk_vid0_gfxbase_msb;
uint16_t m_sprite_7022_gfxbase_lsb;
uint16_t m_sprite_702d_gfxbase_msb;
uint16_t m_unk_vid1_gfxbase_lsb;
uint16_t m_unk_vid1_gfxbase_msb;
uint16_t m_unk_vid2_gfxbase_lsb;
@ -204,7 +208,8 @@ protected:
uint16_t m_video_irq_status;
uint16_t m_spriteextra[0x100];
uint16_t m_spriteram[0x400];
uint16_t m_spriteextra[0x400];
uint16_t m_paletteram[0x100*0x10];
required_device<palette_device> m_palette;