From 1363b36e3f4bd1766a51f01610f1506f597e821e Mon Sep 17 00:00:00 2001 From: David Haywood <28625134+DavidHaywood@users.noreply.github.com> Date: Mon, 30 Dec 2019 01:50:24 +0000 Subject: a few bits for jak_car2 (#6110) * other layer bits (nw) * work around some palette issues (nw) * this allows cars 2 to go 'ingame' (nw) * impove some visuals (nw) * investigate bitmap mode (nw) * these might turn out to be chip type differences (nw) * tweaks (nw) --- src/devices/cpu/unsp/unsp_exxx.cpp | 66 +++- src/devices/machine/sunplus_gcm394.cpp | 43 ++- src/devices/machine/sunplus_gcm394.h | 10 +- src/devices/machine/sunplus_gcm394_video.cpp | 504 ++++++++++++++++++--------- src/devices/machine/sunplus_gcm394_video.h | 40 ++- src/mame/drivers/sunplus_gcm394.cpp | 13 +- 6 files changed, 469 insertions(+), 207 deletions(-) diff --git a/src/devices/cpu/unsp/unsp_exxx.cpp b/src/devices/cpu/unsp/unsp_exxx.cpp index 202151ed2be..0107c1fd0c7 100644 --- a/src/devices/cpu/unsp/unsp_exxx.cpp +++ b/src/devices/cpu/unsp/unsp_exxx.cpp @@ -9,6 +9,14 @@ #include "unspdasm.h" +#define LOG_UNSP_SHIFTS (1U << 2) +#define LOG_UNSP_MULS (1U << 1) + +#define VERBOSE (0) + +#include "logmacro.h" + + void unsp_device::execute_exxx_group(uint16_t op) { // several exxx opcodes have already been decoded as jumps by the time we get here @@ -120,7 +128,7 @@ void unsp_12_device::execute_exxx_group(uint16_t op) const uint16_t opb = op & 7; m_core->m_icount -= 12; - logerror("%s: MUL su with %04x (signed) * %04x (unsigned) : ", machine().describe_context(), m_core->m_r[opa], m_core->m_r[opb]); + LOGMASKED(LOG_UNSP_MULS, "%s: MUL su with %04x (signed) * %04x (unsigned) : ", machine().describe_context(), m_core->m_r[opa], m_core->m_r[opb]); uint32_t lres = m_core->m_r[opa] * m_core->m_r[opb]; if (m_core->m_r[opa] & 0x8000) @@ -130,7 +138,7 @@ void unsp_12_device::execute_exxx_group(uint16_t op) m_core->m_r[REG_R4] = lres >> 16; m_core->m_r[REG_R3] = (uint16_t)lres; - logerror("result was : %08x\n", lres); + LOGMASKED(LOG_UNSP_MULS, "result was : %08x\n", lres); return; } @@ -156,7 +164,7 @@ void unsp_12_device::execute_exxx_group(uint16_t op) // MULS uu or MULS su (invalid?) print_muls(stream, op); */ - logerror("MULS uu or su\n"); + LOGMASKED(LOG_UNSP_MULS, "MULS uu or su\n"); unimplemented_opcode(op); return; } @@ -170,28 +178,52 @@ void unsp_12_device::execute_exxx_group(uint16_t op) switch (shift) { case 0x00: - logerror("%s = %s asr %s\n", regs[rd], regs[rd], regs[rs]); + LOGMASKED(LOG_UNSP_SHIFTS, "%s = %s asr %s\n", regs[rd], regs[rd], regs[rs]); unimplemented_opcode(op); return; - case 0x01: - logerror("%s = %s asror %s\n", regs[rd], regs[rd], regs[rs]); - unimplemented_opcode(op); + case 0x01: // jak_car2 on starting a game + { + LOGMASKED(LOG_UNSP_SHIFTS, "%s = %s asror %s\n", regs[rd], regs[rd], regs[rs]); + if (rd != 4) // 4 = R4 3 = R3 - the 'register bleeding' is only verified as needed between r3/r4, so bail for other regs until verified + unimplemented_opcode(op); + + uint32_t res = (uint16_t)(m_core->m_r[rd]); + int shift = (m_core->m_r[rs] & 0x01f); + res <<= 16; + + if (res & 0x80000000) + { + res = res >> shift; + res |= (0xffffffff << (32 - shift)); + + m_core->m_r[rd] = (res >> 16); + m_core->m_r[rd - 1] |= (res & 0xffff); // register bleeding? + } + else + { + res = res >> shift; + m_core->m_r[rd] = (res >> 16); + m_core->m_r[rd - 1] |= (res & 0xffff); // register bleeding? + } + + LOGMASKED(LOG_UNSP_SHIFTS, "result %04x\n", m_core->m_r[rd]); return; + } 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]); + LOGMASKED(LOG_UNSP_SHIFTS, "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]&0xffff) << (m_core->m_r[rs] & 0x01f)); - logerror("result %04x\n", m_core->m_r[rd]); + LOGMASKED(LOG_UNSP_SHIFTS, "result %04x\n", m_core->m_r[rd]); return; case 0x03: { // 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]); + LOGMASKED(LOG_UNSP_SHIFTS, "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]); if (rd != 3) // 4 = R4 3 = R3 - the 'register bleeding' is only verified as needed between r3/r4, so bail for other regs until verified unimplemented_opcode(op); @@ -203,20 +235,20 @@ void unsp_12_device::execute_exxx_group(uint16_t op) m_core->m_r[rd] = (res & 0xffff); m_core->m_r[rd + 1] |= (res >> 16); // register bleeding? - logerror("result %04x\n", m_core->m_r[rd]); + LOGMASKED(LOG_UNSP_SHIFTS, "result %04x\n", m_core->m_r[rd]); return; } 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]); + LOGMASKED(LOG_UNSP_SHIFTS, "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]&0xffff) >> (m_core->m_r[rs] & 0x1f)); - logerror("result %04x\n", m_core->m_r[rd]); + LOGMASKED(LOG_UNSP_SHIFTS, "result %04x\n", m_core->m_r[rd]); return; case 0x05: { - 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]); + LOGMASKED(LOG_UNSP_SHIFTS, "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]); if (rd != 4) // 4 = R4 3 = R3 - the 'register bleeding' is only verified as needed between r3/r4, so bail for other regs until verified unimplemented_opcode(op); @@ -239,17 +271,17 @@ void unsp_12_device::execute_exxx_group(uint16_t op) m_core->m_r[rd - 1] |= (res & 0xffff); // register bleeding? - logerror("result %04x\n", m_core->m_r[rd]); + LOGMASKED(LOG_UNSP_SHIFTS, "result %04x\n", m_core->m_r[rd]); return; } case 0x06: - logerror("%s = %s rol %s\n", regs[rd], regs[rd], regs[rs]); + LOGMASKED(LOG_UNSP_SHIFTS, "%s = %s rol %s\n", regs[rd], regs[rd], regs[rs]); unimplemented_opcode(op); return; case 0x07: - logerror("%s = %s ror %s\n", regs[rd], regs[rd], regs[rs]); + LOGMASKED(LOG_UNSP_SHIFTS, "%s = %s ror %s\n", regs[rd], regs[rd], regs[rs]); unimplemented_opcode(op); return; } diff --git a/src/devices/machine/sunplus_gcm394.cpp b/src/devices/machine/sunplus_gcm394.cpp index 3d5758d176d..5a94ae6ac60 100644 --- a/src/devices/machine/sunplus_gcm394.cpp +++ b/src/devices/machine/sunplus_gcm394.cpp @@ -169,6 +169,17 @@ WRITE16_MEMBER(sunplus_gcm394_base_device::system_dma_trigger_w) if (data & 0x02) trigger_systemm_dma(space, 1, data); } +READ16_MEMBER(sunplus_gcm394_base_device::system_dma_memtype_r) +{ + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_dma_memtype_r\n", machine().describe_context()); + return m_system_dma_memtype; +} + +WRITE16_MEMBER(sunplus_gcm394_base_device::system_dma_memtype_w) +{ + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_dma_memtype_w %04x\n", machine().describe_context(), data); + m_system_dma_memtype = data; +} // **************************************** 78xx region with some handling ************************************************* @@ -222,8 +233,8 @@ 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); - if (m_membankswitch_7810 != data) - popmessage("bankswitch %04x -> %04x", m_membankswitch_7810, data); +// if (m_membankswitch_7810 != data) +// popmessage("bankswitch %04x -> %04x", m_membankswitch_7810, data); m_membankswitch_7810 = data; } @@ -237,9 +248,6 @@ WRITE16_MEMBER(sunplus_gcm394_base_device::chipselect_csx_memory_device_control_ 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[] = { @@ -435,8 +443,8 @@ void sunplus_gcm394_base_device::base_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)); // 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(0x007000, 0x007007).rw(m_spg_video, FUNC(gcm394_base_video_device::tmap2_regs_r), FUNC(gcm394_base_video_device::tmap2_regs_w)); // written with other unknown_video_device1 LSB/MSB regs below (roz layer or line layer?) + map(0x007008, 0x00700f).rw(m_spg_video, FUNC(gcm394_base_video_device::tmap3_regs_r), FUNC(gcm394_base_video_device::tmap3_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)); @@ -445,8 +453,8 @@ void sunplus_gcm394_base_device::base_internal_map(address_map &map) 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(0x007023, 0x007023).rw(m_spg_video, FUNC(gcm394_base_video_device::unk_vid1_gfxbase_lsb_r), 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).rw(m_spg_video, FUNC(gcm394_base_video_device::unk_vid2_gfxbase_lsb_r), 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 @@ -454,8 +462,8 @@ void sunplus_gcm394_base_device::base_internal_map(address_map &map) 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?) + map(0x00702e, 0x00702e).rw(m_spg_video, FUNC(gcm394_base_video_device::unk_vid1_gfxbase_msb_r), 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).rw(m_spg_video, FUNC(gcm394_base_video_device::unk_vid2_gfxbase_msb_r), 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(0x007038, 0x007038).r(m_spg_video, FUNC(gcm394_base_video_device::video_curline_r)); @@ -466,7 +474,7 @@ void sunplus_gcm394_base_device::base_internal_map(address_map &map) 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(0x007062, 0x007062).rw(m_spg_video, FUNC(gcm394_base_video_device::videoirq_source_enable_r), FUNC(gcm394_base_video_device::videoirq_source_enable_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 @@ -495,8 +503,8 @@ void sunplus_gcm394_base_device::base_internal_map(address_map &map) // 73xx-77xx = video ram // ###################################################################################################################################################################################### - map(0x007100, 0x0071ef).ram().share("unkram1"); // maybe a line table? (assuming DMA isn't writing to wrong place) - map(0x007200, 0x0072ef).ram().share("unkram2"); // ^^ + map(0x007100, 0x0071ff).ram().share("unkram1"); // maybe a line table? (assuming DMA isn't writing to wrong place) + map(0x007200, 0x0072ff).ram().share("unkram2"); // ^^ map(0x007300, 0x0073ff).rw(m_spg_video, FUNC(gcm394_base_video_device::palette_r), FUNC(gcm394_base_video_device::palette_w)); @@ -636,12 +644,9 @@ void sunplus_gcm394_base_device::base_internal_map(address_map &map) // ###################################################################################################################################################################################### 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(0x007abe, 0x007abe).rw(FUNC(sunplus_gcm394_base_device::system_dma_memtype_r), FUNC(sunplus_gcm394_base_device::system_dma_memtype_w)); // 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)); // ###################################################################################################################################################################################### @@ -834,7 +839,6 @@ void sunplus_gcm394_base_device::device_start() m_space_read_cb.resolve_safe(0); m_space_write_cb.resolve(); - m_mapping_write_cb.resolve(); m_nand_read_cb.resolve_safe(0); @@ -917,6 +921,7 @@ void sunplus_gcm394_base_device::device_reset() m_7960 = 0x0000; m_7961 = 0x0000; + m_system_dma_memtype = 0x0000; m_unk_timer->adjust(attotime::from_hz(60), 0, attotime::from_hz(60)); } diff --git a/src/devices/machine/sunplus_gcm394.h b/src/devices/machine/sunplus_gcm394.h index 0f05342b9bd..72432980f85 100644 --- a/src/devices/machine/sunplus_gcm394.h +++ b/src/devices/machine/sunplus_gcm394.h @@ -41,7 +41,6 @@ public: m_csbase(0x20000), m_space_read_cb(*this), m_space_write_cb(*this), - m_mapping_write_cb(*this), m_boot_mode(0), m_cs_callback(*this, DEVICE_SELF, FUNC(sunplus_gcm394_base_device::default_cs_callback)) { @@ -56,7 +55,6 @@ public: auto space_read_callback() { return m_space_read_cb.bind(); } 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(); } @@ -71,6 +69,9 @@ public: void default_cs_callback(uint16_t cs0, uint16_t cs1, uint16_t cs2, uint16_t cs3, uint16_t cs4 ); void set_cs_space(address_space* csspace) { m_cs_space = csspace; } + + void set_paldisplaybank_high_hack(int pal_displaybank_high) { m_spg_video->set_paldisplaybank_high(pal_displaybank_high); } + void set_alt_tile_addressing_hack(int alt_tile_addressing) { m_spg_video->set_alt_tile_addressing(alt_tile_addressing); } protected: @@ -154,6 +155,8 @@ protected: uint16_t m_7960; uint16_t m_7961; + uint16_t m_system_dma_memtype; + devcb_read16 m_nand_read_cb; int m_csbase; @@ -169,7 +172,6 @@ protected: private: devcb_read16 m_space_read_cb; devcb_write16 m_space_write_cb; - devcb_write16 m_mapping_write_cb; DECLARE_READ16_MEMBER(unk_r); DECLARE_WRITE16_MEMBER(unk_w); @@ -184,6 +186,8 @@ private: 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(system_dma_memtype_r); + DECLARE_WRITE16_MEMBER(system_dma_memtype_w); DECLARE_READ16_MEMBER(unkarea_780f_status_r); DECLARE_READ16_MEMBER(unkarea_78fb_status_r); diff --git a/src/devices/machine/sunplus_gcm394_video.cpp b/src/devices/machine/sunplus_gcm394_video.cpp index 19391111da4..5fc11dffd26 100644 --- a/src/devices/machine/sunplus_gcm394_video.cpp +++ b/src/devices/machine/sunplus_gcm394_video.cpp @@ -11,7 +11,9 @@ DEFINE_DEVICE_TYPE(GCM394_VIDEO, gcm394_video_device, "gcm394_video", "SunPlus GCM394 System-on-a-Chip (Video)") -#define LOG_GCM394_VIDEO_DMA (1U << 3) +#define LOG_GCM394_VIDEO_PALETTE (1U << 5) +#define LOG_GCM394_VIDEO_DMA (1U << 4) +#define LOG_GCM394_TMAP_EXTRA (1U << 3) #define LOG_GCM394_TMAP (1U << 2) #define LOG_GCM394_VIDEO (1U << 1) @@ -20,18 +22,20 @@ DEFINE_DEVICE_TYPE(GCM394_VIDEO, gcm394_video_device, "gcm394_video", "SunPlus G #include "logmacro.h" -gcm394_base_video_device::gcm394_base_video_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, type, tag, owner, clock) - //, device_gfx_interface(mconfig, *this, nullptr) - , device_video_interface(mconfig, *this) - , m_cpu(*this, finder_base::DUMMY_TAG) - , m_screen(*this, finder_base::DUMMY_TAG) -// , m_scrollram(*this, "scrollram") - , m_video_irq_cb(*this) - , m_palette(*this, "palette") - , m_gfxdecode(*this, "gfxdecode") - , m_space_read_cb(*this) - , m_global_y_mask(0x1ff) +gcm394_base_video_device::gcm394_base_video_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, type, tag, owner, clock), + //device_gfx_interface(mconfig, *this, nullptr), + device_video_interface(mconfig, *this), + m_cpu(*this, finder_base::DUMMY_TAG), + m_screen(*this, finder_base::DUMMY_TAG), +// m_scrollram(*this, "scrollram"), + m_video_irq_cb(*this), + m_palette(*this, "palette"), + m_gfxdecode(*this, "gfxdecode"), + m_space_read_cb(*this), + m_global_y_mask(0x1ff), + m_pal_displaybank_high(0), + m_alt_tile_addressing(0) { } @@ -219,10 +223,20 @@ void gcm394_base_video_device::device_start() void gcm394_base_video_device::device_reset() { - for (int i = 0; i < 6; i++) + for (int i = 0; i < 4; i++) { m_tmap0_regs[i] = 0x0000; m_tmap1_regs[i] = 0x0000; + m_tmap2_regs[i] = 0x0000; + m_tmap3_regs[i] = 0x0000; + m_tmap2_scroll[i] = 0x0000; + m_tmap3_scroll[i] = 0x0000; + } + + for (int i = 0; i < 2; i++) + { + m_tmap0_scroll[i] = 0x0000; + m_tmap1_scroll[i] = 0x0000; } for (int i = 0; i < 0x400; i++) @@ -337,8 +351,8 @@ void gcm394_base_video_device::draw(const rectangle &cliprect, uint32_t line, ui { // 2bpp // 4bpp - - current_palette_offset |= 0x0800; + if (m_pal_displaybank_high) // how is this set? + current_palette_offset |= 0x0800; } else if (nc_bpp < 8) @@ -388,14 +402,14 @@ void gcm394_base_video_device::draw(const rectangle &cliprect, uint32_t line, ui } } -void gcm394_base_video_device::draw_page(const rectangle &cliprect, uint32_t scanline, int priority, uint32_t bitmap_addr, uint16_t *regs) +void gcm394_base_video_device::draw_page(const rectangle &cliprect, uint32_t scanline, int priority, uint32_t bitmap_addr, uint16_t *regs, uint16_t *scroll) { - uint32_t xscroll = regs[0]; - uint32_t yscroll = regs[1]; - uint32_t attr_reg = regs[2]; - uint32_t ctrl_reg = regs[3]; - uint32_t tilemap = regs[4]; - uint32_t palette_map = regs[5]; + uint32_t xscroll = scroll[0]; + uint32_t yscroll = scroll[1]; + uint32_t attr_reg = regs[0]; + uint32_t ctrl_reg = regs[1]; + uint32_t tilemap = regs[2]; + uint32_t palette_map = regs[3]; address_space &space = m_cpu->space(AS_PROGRAM); if (!(ctrl_reg & PAGE_ENABLE_MASK)) @@ -408,118 +422,186 @@ void gcm394_base_video_device::draw_page(const rectangle &cliprect, uint32_t sca return; } - 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); + if (ctrl_reg & 0x01) // bitmap mode jak_car2 uses this ingame + { + popmessage("bitmap mode %08x\n", bitmap_addr); - int total_width = 512; + uint32_t linebase = space.read_word(tilemap + scanline); // every other word is unused, but there are only enough entries for 240 lines then, sometimes to do with interlace mode? + uint16_t palette = space.read_word(palette_map + (scanline / 2)); - if ((attr_reg >> 14) & 0x2) - total_width = 1024; + if (scanline & 1) + palette >>= 8; - uint32_t tile_count_x = total_width / tile_w; + //if (linebase != 0) + // printf("scanline %d linebase %04x palette %04x\n", scanline, linebase, palette); - 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; + linebase |= ((palette >> 8) << 16); - for (uint32_t x0 = 0; x0 < tile_count_x; x0++, tile_address++) - { - 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); + int gfxbase = bitmap_addr + linebase; - uint16_t palette = (ctrl_reg & PAGE_WALLPAPER_MASK) ? space.read_word(palette_map) : space.read_word(palette_map + tile_address / 2); - if (x0 & 1) - palette >>= 8; + for (int i = 0; i < 160; i++) // will have to be 320 for jak_car2 ingame + { + uint16_t pix = m_space_read_cb((gfxbase++)&0xffffff); + int xx; + int y_index = scanline * m_screen->width(); + uint16_t pal; + + if ((scanline >= 0) && (scanline < 480)) + { + xx = (i * 2); + pal = (pix & 0xff) | 0x100; + if (xx >= 0 && xx <= cliprect.max_x) + { + int pix_index = xx + y_index; - if (!tile) - continue; + uint16_t rgb = m_paletteram[pal]; + if (!(rgb & 0x8000)) + { + m_screenbuf[pix_index] = m_rgb555_to_rgb888[rgb]; + } + } - uint32_t tileattr = attr_reg; - uint32_t tilectrl = ctrl_reg; + xx = (i * 2)+1; + pal = (pix >> 8) + 0x100; -#if 0 - if ((ctrl_reg & 2) == 0) - { // -(1) bld(1) flip(2) pal(4) - tileattr &= ~0x000c; - tileattr |= (palette >> 2) & 0x000c; // flip + if (xx >= 0 && xx <= cliprect.max_x) + { + int pix_index = xx + y_index; - tileattr &= ~0x0f00; - tileattr |= (palette << 8) & 0x0f00; // palette + uint16_t rgb = m_paletteram[pal]; - tilectrl &= ~0x0100; - tilectrl |= (palette << 2) & 0x0100; // blend + if (!(rgb & 0x8000)) + { + m_screenbuf[pix_index] = m_rgb555_to_rgb888[rgb]; + } + } + } } -#endif - bool blend; - bool row_scroll; - bool flip_x; - uint32_t yflipmask; - uint32_t palette_offset; - - blend = (tileattr & 0x4000 || tilectrl & 0x0100); - row_scroll = (tilectrl & 0x0010); + } + else + { + 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); - int use_alt_drawmode; + int total_width; + int use_alt_drawmode = m_alt_tile_addressing; - if ((ctrl_reg & 2) == 0) + // just a guess based on this being set on the higher resolution tilemaps we've seen, could be 100% incorrect register + if ((attr_reg >> 14) & 0x2) { - flip_x = 0; - yflipmask = 0; - palette_offset = (palette & 0x0f) << 4; - use_alt_drawmode = 1; + total_width = 1024; + // use_alt_drawmode = 1; // probably doesn't control this } else { - flip_x = (tileattr & TILE_X_FLIP); - yflipmask = tileattr & TILE_Y_FLIP ? tile_h - 1 : 0; - palette_offset = (tileattr & 0x0f00) >> 4; - tile |= (palette & 0x0007) << 16; - use_alt_drawmode = 0; + total_width = 512; + // use_alt_drawmode = 0; // probably doesn't control this } + uint32_t tile_count_x = total_width / tile_w; - //palette_offset |= 0x0900; - palette_offset |= 0x0100; + 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; - const uint8_t bpp = tileattr & 0x0003; + for (uint32_t x0 = 0; x0 < tile_count_x; x0++, tile_address++) + { + 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); + if (x0 & 1) + palette >>= 8; - if (blend) - { - if (row_scroll) + + if (!tile) + continue; + + + uint32_t tileattr = attr_reg; + uint32_t tilectrl = ctrl_reg; + +#if 0 + if ((ctrl_reg & 2) == 0) + { // -(1) bld(1) flip(2) pal(4) + tileattr &= ~0x000c; + tileattr |= (palette >> 2) & 0x000c; // flip + + tileattr &= ~0x0f00; + tileattr |= (palette << 8) & 0x0f00; // palette + + tilectrl &= ~0x0100; + tilectrl |= (palette << 2) & 0x0100; // blend + } +#endif + bool blend; + bool row_scroll; + bool flip_x; + uint32_t yflipmask; + uint32_t palette_offset; + + blend = (tileattr & 0x4000 || tilectrl & 0x0100); + row_scroll = (tilectrl & 0x0010); + + + if ((ctrl_reg & 2) == 0) { - if (flip_x) - draw(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode); - else - draw(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode); + flip_x = 0; + yflipmask = 0; + palette_offset = (palette & 0x0f) << 4; } - else + else // jak_car2 uses this mode for sky ingame { - if (flip_x) - draw(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode); - else - draw(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode); + flip_x = (tileattr & TILE_X_FLIP); + yflipmask = tileattr & TILE_Y_FLIP ? tile_h - 1 : 0; + palette_offset = (tileattr & 0x0f00) >> 4; + tile |= (palette & 0x0007) << 16; } - } - else - { - if (row_scroll) + + + //palette_offset |= 0x0900; + palette_offset |= 0x0100; + + const uint8_t bpp = tileattr & 0x0003; + + + if (blend) { - if (flip_x) - draw(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode); + if (row_scroll) + { + if (flip_x) + draw(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode); + else + draw(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode); + } else - draw(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode); + { + if (flip_x) + draw(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode); + else + draw(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode); + } } else { - if (flip_x) - draw(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode); + if (row_scroll) + { + if (flip_x) + draw(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode); + else + draw(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode); + } else - draw(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode); + { + if (flip_x) + draw(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode); + else + draw(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode); + } } } } @@ -625,19 +707,17 @@ uint32_t gcm394_base_video_device::screen_update(screen_device &screen, bitmap_r { memset(&m_screenbuf[m_screen->width() * cliprect.min_y], 0, 4 * m_screen->width() * ((cliprect.max_y - cliprect.min_y) + 1)); - const uint32_t page0_addr = (m_page0_addr_lsb | (m_page0_addr_msb<<16)); - const uint32_t page1_addr = (m_page1_addr_lsb | (m_page1_addr_msb<<16)); - uint16_t* page0_regs = m_tmap0_regs; - uint16_t* page1_regs = m_tmap1_regs; - for (uint32_t scanline = (uint32_t)cliprect.min_y; scanline <= (uint32_t)cliprect.max_y; scanline++) { for (int i = 0; i < 4; i++) { if (1) { - draw_page(cliprect, scanline, i, page0_addr, page0_regs); - draw_page(cliprect, scanline, i, page1_addr, page1_regs); + draw_page(cliprect, scanline, i, (m_page0_addr_lsb | (m_page0_addr_msb<<16)), m_tmap0_regs, m_tmap0_scroll); + draw_page(cliprect, scanline, i, (m_page1_addr_lsb | (m_page1_addr_msb<<16)), m_tmap1_regs, m_tmap1_scroll); + draw_page(cliprect, scanline, i, (m_unk_vid1_gfxbase_lsb | (m_unk_vid1_gfxbase_msb<<16)), m_tmap2_regs, m_tmap2_scroll); + draw_page(cliprect, scanline, i, (m_unk_vid2_gfxbase_lsb | (m_unk_vid2_gfxbase_msb<<16)), m_tmap3_regs, m_tmap3_scroll); + } draw_sprites(cliprect, scanline, i); } @@ -654,52 +734,106 @@ uint32_t gcm394_base_video_device::screen_update(screen_device &screen, bitmap_r } -void gcm394_base_video_device::write_tmap_regs(int tmap, uint16_t* regs, int offset, uint16_t data) +void gcm394_base_video_device::write_tmap_scroll(int tmap, uint16_t* regs, int offset, uint16_t data) { switch (offset) { case 0x0: // Page X scroll - LOGMASKED(LOG_GCM394_TMAP, "%s: write_tmap_regs: Page %d X Scroll = %04x\n", machine().describe_context(), tmap, data & 0x01ff); - regs[offset] = data & 0x01ff; + LOGMASKED(LOG_GCM394_TMAP, "%s: write_tmap_regs: Page %d X Scroll = %04x\n", machine().describe_context(), tmap, data); + regs[offset] = data; break; case 0x1: // Page Y scroll - LOGMASKED(LOG_GCM394_TMAP, "%s: write_tmap_regs: Page %d Y Scroll = %04x\n", machine().describe_context(), tmap, data & 0x00ff); - regs[offset] = data & 0x00ff; + LOGMASKED(LOG_GCM394_TMAP, "%s: write_tmap_regs: Page %d Y Scroll = %04x\n", machine().describe_context(), tmap, data); + regs[offset] = data; break; + } +} - case 0x2: // Page Attributes +void gcm394_base_video_device::write_tmap_regs(int tmap, uint16_t* regs, int offset, uint16_t data) +{ + switch (offset) + { + case 0x0: // Page Attributes 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 + case 0x1: // Page Control 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 + case 0x2: // Page Tile Address 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 + case 0x3: // Page Attribute Address LOGMASKED(LOG_GCM394_TMAP, "%s: write_tmap_regs: Page %d Attribute Address = %04x\n", machine().describe_context(), tmap, data); regs[offset] = data; break; } } + +// 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::write_tmap_extrascroll(int tmap, uint16_t* regs, int offset, uint16_t data) +{ + switch (offset) + { + case 0x0: // Page X scroll + case 0x1: // Page Y scroll + write_tmap_scroll(tmap, regs, offset, data); + break; + + case 0x2: // + LOGMASKED(LOG_GCM394_TMAP, "%s: write_tmap_regs: Page %d X Unk Rotation Zoom Attribute1 = %04x\n", machine().describe_context(), tmap, data); + regs[offset] = data; + break; + + case 0x3: + LOGMASKED(LOG_GCM394_TMAP, "%s: write_tmap_regs: Page %d X Unk Rotation Zoom Attribute = %04x\n", machine().describe_context(), tmap, data); + regs[offset] = data; + break; + + } +} + + // **************************************** TILEMAP 0 ************************************************* -READ16_MEMBER(gcm394_base_video_device::tmap0_regs_r) { return m_tmap0_regs[offset]; } +READ16_MEMBER(gcm394_base_video_device::tmap0_regs_r) +{ + if (offset < 2) + { + return m_tmap0_scroll[offset]; + } + else + { + return m_tmap0_regs[offset-2]; + } +} WRITE16_MEMBER(gcm394_base_video_device::tmap0_regs_w) { - LOGMASKED(LOG_GCM394_TMAP, "%s:gcm394_base_video_device::tmap0_regs_w %01x %04x\n", machine().describe_context(), offset, data); - write_tmap_regs(0, m_tmap0_regs, offset, data); + LOGMASKED(LOG_GCM394_TMAP_EXTRA, "%s:gcm394_base_video_device::tmap0_regs_w %01x %04x\n", machine().describe_context(), offset, data); + if (offset < 2) + { + write_tmap_scroll(0, m_tmap0_scroll, offset, data); + } + else + { + write_tmap_regs(0, m_tmap0_regs, offset-2, data); + } } READ16_MEMBER(gcm394_base_video_device::tmap0_tilebase_lsb_r) @@ -728,12 +862,30 @@ WRITE16_MEMBER(gcm394_base_video_device::tmap0_tilebase_msb_w) // **************************************** TILEMAP 1 ************************************************* -READ16_MEMBER(gcm394_base_video_device::tmap1_regs_r) { return m_tmap1_regs[offset]; } + +READ16_MEMBER(gcm394_base_video_device::tmap1_regs_r) +{ + if (offset < 2) + { + return m_tmap1_scroll[offset]; + } + else + { + return m_tmap1_regs[offset-2]; + } +} WRITE16_MEMBER(gcm394_base_video_device::tmap1_regs_w) { - LOGMASKED(LOG_GCM394_TMAP, "%s:gcm394_base_video_device::tmap1_regs_w %01x %04x\n", machine().describe_context(), offset, data); - write_tmap_regs(1, m_tmap1_regs, offset, data); + LOGMASKED(LOG_GCM394_TMAP_EXTRA, "%s:gcm394_base_video_device::tmap1_regs_w %01x %04x\n", machine().describe_context(), offset, data); + if (offset < 2) + { + write_tmap_scroll(1, m_tmap1_scroll, offset, data); + } + else + { + write_tmap_regs(1, m_tmap1_regs, offset-2, data); + } } READ16_MEMBER(gcm394_base_video_device::tmap1_tilebase_lsb_r) @@ -741,7 +893,6 @@ 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); @@ -761,46 +912,39 @@ WRITE16_MEMBER(gcm394_base_video_device::tmap1_tilebase_msb_w) LOGMASKED(LOG_GCM394_TMAP, "\t(tmap1 tilegfxbase is now %04x%04x)\n", m_page1_addr_msb, m_page1_addr_lsb); } -// **************************************** unknown video device handler for below ************************************************* - -// offsets 0,1,4,5,6,7 used in main IRQ code -// offsets 2,3 only cleared on startup +// **************************************** unknown video device 1 (another tilemap? roz? line? zooming sprite layer?) ************************************************* -// 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) +READ16_MEMBER(gcm394_base_video_device::tmap2_regs_r) { - switch (offset) + if (offset < 4) { - case 0x0: - 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, "%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 0x06: - case 0x07: - LOGMASKED(LOG_GCM394_VIDEO, "%s: unk_vid_regs_w (unk chip %d) (offset %01x) (data %04x)\n", machine().describe_context(), which, offset, data); - break; - + return m_tmap2_scroll[offset]; + } + else + { + return m_tmap2_regs[offset-4]; } } -// **************************************** unknown video device 1 (another tilemap? roz? line? zooming sprite layer?) ************************************************* +WRITE16_MEMBER(gcm394_base_video_device::tmap2_regs_w) +{ + LOGMASKED(LOG_GCM394_TMAP_EXTRA, "%s:gcm394_base_video_device::tmap2_regs_w %01x %04x\n", machine().describe_context(), offset, data); + if (offset < 4) + { + write_tmap_extrascroll(2, m_tmap2_scroll, offset, data); + } + else + { + write_tmap_regs(2, m_tmap2_regs, offset-4, data); + } +} -WRITE16_MEMBER(gcm394_base_video_device::unk_vid1_regs_w) +READ16_MEMBER(gcm394_base_video_device::unk_vid1_gfxbase_lsb_r) { - unk_vid_regs_w(0, offset, data); + return m_unk_vid1_gfxbase_lsb; } + WRITE16_MEMBER(gcm394_base_video_device::unk_vid1_gfxbase_lsb_w) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::unk_vid1_gfxbase_lsb_w %04x\n", machine().describe_context(), data); @@ -808,6 +952,11 @@ WRITE16_MEMBER(gcm394_base_video_device::unk_vid1_gfxbase_lsb_w) LOGMASKED(LOG_GCM394_TMAP, "\t(unk_vid1 tilegfxbase is now %04x%04x)\n", m_unk_vid1_gfxbase_msb, m_unk_vid1_gfxbase_lsb); } +READ16_MEMBER(gcm394_base_video_device::unk_vid1_gfxbase_msb_r) +{ + return m_unk_vid1_gfxbase_msb; +} + WRITE16_MEMBER(gcm394_base_video_device::unk_vid1_gfxbase_msb_w) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::unk_vid1_gfxbase_msb_w %04x\n", machine().describe_context(), data); @@ -817,11 +966,37 @@ WRITE16_MEMBER(gcm394_base_video_device::unk_vid1_gfxbase_msb_w) // **************************************** unknown video device 2 (another tilemap? roz? lines? zooming sprite layer?) ************************************************* -WRITE16_MEMBER(gcm394_base_video_device::unk_vid2_regs_w) +READ16_MEMBER(gcm394_base_video_device::tmap3_regs_r) { - unk_vid_regs_w(1, offset, data); + if (offset < 4) + { + return m_tmap3_scroll[offset]; + } + else + { + return m_tmap3_regs[offset-4]; + } } +WRITE16_MEMBER(gcm394_base_video_device::tmap3_regs_w) +{ + LOGMASKED(LOG_GCM394_TMAP_EXTRA, "%s:gcm394_base_video_device::tmap3_regs_w %01x %04x\n", machine().describe_context(), offset, data); + if (offset < 4) + { + write_tmap_extrascroll(3, m_tmap3_scroll, offset, data); + } + else + { + write_tmap_regs(3, m_tmap3_regs, offset-4, data); + } +} + +READ16_MEMBER(gcm394_base_video_device::unk_vid2_gfxbase_lsb_r) +{ + return m_unk_vid2_gfxbase_lsb; +} + + WRITE16_MEMBER(gcm394_base_video_device::unk_vid2_gfxbase_lsb_w) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::unk_vid2_gfxbase_lsb_w %04x\n", machine().describe_context(), data); @@ -829,6 +1004,12 @@ WRITE16_MEMBER(gcm394_base_video_device::unk_vid2_gfxbase_lsb_w) LOGMASKED(LOG_GCM394_TMAP, "\t(unk_vid2 tilegfxbase is now %04x%04x)\n", m_unk_vid2_gfxbase_msb, m_unk_vid2_gfxbase_lsb); } +READ16_MEMBER(gcm394_base_video_device::unk_vid2_gfxbase_msb_r) +{ + return m_unk_vid2_gfxbase_msb; +} + + WRITE16_MEMBER(gcm394_base_video_device::unk_vid2_gfxbase_msb_w) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::unk_vid2_gfxbase_msb_w %04x\n", machine().describe_context(), data); @@ -999,8 +1180,17 @@ WRITE16_MEMBER(gcm394_base_video_device::video_703a_palettebank_w) 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::videoirq_source_enable_r) +{ + LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::videoirq_source_enable_r\n", machine().describe_context()); + return m_7062; +} + +WRITE16_MEMBER(gcm394_base_video_device::videoirq_source_enable_w) +{ + LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::videoirq_source_enable_w %04x\n", machine().describe_context(), data); + m_7062 = data; +} READ16_MEMBER(gcm394_base_video_device::video_7063_videoirq_source_r) { @@ -1112,7 +1302,7 @@ READ16_MEMBER(gcm394_base_video_device::spriteram_r) 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); + LOGMASKED(LOG_GCM394_VIDEO_PALETTE, "%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) { diff --git a/src/devices/machine/sunplus_gcm394_video.h b/src/devices/machine/sunplus_gcm394_video.h index a2a54a1b388..72193ecc74f 100644 --- a/src/devices/machine/sunplus_gcm394_video.h +++ b/src/devices/machine/sunplus_gcm394_video.h @@ -25,8 +25,14 @@ public: auto space_read_callback() { return m_space_read_cb.bind(); } + void write_tmap_scroll(int tmap, uint16_t* regs, int offset, uint16_t data); + void write_tmap_extrascroll(int tmap, uint16_t* regs, int offset, uint16_t data); + void write_tmap_regs(int tmap, uint16_t* regs, int offset, uint16_t data); + void set_paldisplaybank_high(int pal_displaybank_high) { m_pal_displaybank_high = pal_displaybank_high; } + void set_alt_tile_addressing(int alt_tile_addressing) { m_alt_tile_addressing = alt_tile_addressing; } + DECLARE_READ16_MEMBER(tmap0_regs_r); DECLARE_WRITE16_MEMBER(tmap0_regs_w); DECLARE_READ16_MEMBER(tmap0_tilebase_lsb_r); @@ -41,11 +47,17 @@ public: DECLARE_WRITE16_MEMBER(tmap1_tilebase_lsb_w); DECLARE_WRITE16_MEMBER(tmap1_tilebase_msb_w); - DECLARE_WRITE16_MEMBER(unk_vid1_regs_w); + DECLARE_READ16_MEMBER(tmap2_regs_r); + DECLARE_WRITE16_MEMBER(tmap2_regs_w); + DECLARE_READ16_MEMBER(unk_vid1_gfxbase_lsb_r); + DECLARE_READ16_MEMBER(unk_vid1_gfxbase_msb_r); DECLARE_WRITE16_MEMBER(unk_vid1_gfxbase_lsb_w); DECLARE_WRITE16_MEMBER(unk_vid1_gfxbase_msb_w); - DECLARE_WRITE16_MEMBER(unk_vid2_regs_w); + DECLARE_READ16_MEMBER(tmap3_regs_r); + DECLARE_WRITE16_MEMBER(tmap3_regs_w); + DECLARE_READ16_MEMBER(unk_vid2_gfxbase_lsb_r); + DECLARE_READ16_MEMBER(unk_vid2_gfxbase_msb_r); DECLARE_WRITE16_MEMBER(unk_vid2_gfxbase_lsb_w); DECLARE_WRITE16_MEMBER(unk_vid2_gfxbase_msb_w); @@ -66,8 +78,8 @@ public: 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(videoirq_source_enable_r); + DECLARE_WRITE16_MEMBER(videoirq_source_enable_w); DECLARE_READ16_MEMBER(video_7063_videoirq_source_r); DECLARE_WRITE16_MEMBER(video_7063_videoirq_source_ack_w); @@ -154,7 +166,7 @@ protected: template 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_page(const rectangle &cliprect, uint32_t scanline, int priority, uint32_t bitmap_addr, uint16_t *regs, uint16_t *scroll); 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); @@ -181,8 +193,19 @@ protected: // video 70xx - uint16_t m_tmap0_regs[0x6]; - uint16_t m_tmap1_regs[0x6]; + uint16_t m_tmap0_regs[0x4]; + uint16_t m_tmap1_regs[0x4]; + + uint16_t m_tmap2_regs[0x4]; + uint16_t m_tmap3_regs[0x4]; + + + uint16_t m_tmap0_scroll[0x2]; + uint16_t m_tmap1_scroll[0x2]; + + uint16_t m_tmap2_scroll[0x4]; + uint16_t m_tmap3_scroll[0x4]; + uint16_t m_707f; uint16_t m_703a_palettebank; @@ -228,6 +251,9 @@ protected: void decodegfx(const char* tag); int m_global_y_mask; + + int m_pal_displaybank_high; + int m_alt_tile_addressing; }; class gcm394_video_device : public gcm394_base_video_device diff --git a/src/mame/drivers/sunplus_gcm394.cpp b/src/mame/drivers/sunplus_gcm394.cpp index 4bd2936ea56..3ff7bbf7b98 100644 --- a/src/mame/drivers/sunplus_gcm394.cpp +++ b/src/mame/drivers/sunplus_gcm394.cpp @@ -183,8 +183,6 @@ protected: DECLARE_READ16_MEMBER(portb_r); DECLARE_WRITE16_MEMBER(porta_w); - virtual DECLARE_WRITE16_MEMBER(mapping_w) {} - virtual DECLARE_READ16_MEMBER(read_external_space); virtual DECLARE_WRITE16_MEMBER(write_external_space); @@ -335,6 +333,9 @@ void wrlshunt_game_state::machine_reset() cs_callback(0x00, 0x00, 0x00, 0x00, 0x00); m_maincpu->set_cs_space(m_memory->get_program()); m_maincpu->reset(); // reset CPU so vector gets read etc. + + m_maincpu->set_paldisplaybank_high_hack(1); + m_maincpu->set_alt_tile_addressing_hack(1); } void wrlshunt_game_state::init_wrlshunt() @@ -409,7 +410,6 @@ void gcm394_game_state::base(machine_config &config) m_maincpu->space_read_callback().set(FUNC(gcm394_game_state::read_external_space)); m_maincpu->space_write_callback().set(FUNC(gcm394_game_state::write_external_space)); m_maincpu->set_irq_acknowledge_callback(m_maincpu, FUNC(sunplus_gcm394_base_device::irq_vector_cb)); - m_maincpu->mapping_write_callback().set(FUNC(gcm394_game_state::mapping_w)); m_maincpu->add_route(ALL_OUTPUTS, "lspeaker", 0.5); m_maincpu->add_route(ALL_OUTPUTS, "rspeaker", 0.5); m_maincpu->set_bootmode(1); // boot from external ROM / CS mirror @@ -469,7 +469,6 @@ void generalplus_gpac800_game_state::generalplus_gpac800(machine_config &config) m_maincpu->space_read_callback().set(FUNC(generalplus_gpac800_game_state::read_external_space)); m_maincpu->space_write_callback().set(FUNC(generalplus_gpac800_game_state::write_external_space)); m_maincpu->set_irq_acknowledge_callback(m_maincpu, FUNC(sunplus_gcm394_base_device::irq_vector_cb)); - m_maincpu->mapping_write_callback().set(FUNC(generalplus_gpac800_game_state::mapping_w)); m_maincpu->add_route(ALL_OUTPUTS, "lspeaker", 0.5); m_maincpu->add_route(ALL_OUTPUTS, "rspeaker", 0.5); m_maincpu->set_bootmode(0); // boot from internal ROM (NAND bootstrap) @@ -502,6 +501,9 @@ void gcm394_game_state::machine_reset() m_maincpu->set_cs_space(m_memory->get_program()); m_maincpu->reset(); // reset CPU so vector gets read etc. + + m_maincpu->set_paldisplaybank_high_hack(1); + m_maincpu->set_alt_tile_addressing_hack(0); } @@ -1043,6 +1045,9 @@ void generalplus_gpac800_game_state::machine_reset() } m_maincpu->reset(); // reset CPU so vector gets read etc. + + m_maincpu->set_paldisplaybank_high_hack(0); + m_maincpu->set_alt_tile_addressing_hack(1); } -- cgit v1.2.3