From 25b70ce773f13bc771f7663c461b130ff4561dda Mon Sep 17 00:00:00 2001 From: David Haywood Date: Tue, 23 Oct 2018 02:35:02 +0100 Subject: XaviX - support per-line rendering and raster interrupts (#4180) * checkpoint (nw) * improve rasters (nw) * improve again (nw) * raster effect improvements (nw) * tidy (nw) * keep happy (nw) * also keep things happy (nw) * rad_rh notes (nw) * kill unneeded code (nw) * (nw) * oops (nw) * extra rad_bass inputs (nw) * misc refactors (nw) * 2nd palette on superxavix (nw) * improvements to line renderer (nw) * optimize slightly (nw) * bitmap layer related (nw) * this bitmap in xavtennis is very big (nw) --- src/devices/cpu/m6502/dxavix.lst | 2 +- src/devices/cpu/m6502/dxavix2000.lst | 2 +- src/devices/cpu/m6502/oxavix.lst | 2 +- src/devices/cpu/m6502/xavix.cpp | 234 +++++++++-- src/devices/cpu/m6502/xavix.h | 18 +- src/mame/drivers/xavix.cpp | 130 +++--- src/mame/includes/xavix.h | 43 +- src/mame/machine/xavix.cpp | 193 +++++---- src/mame/video/xavix.cpp | 743 +++++++++++++++++++---------------- 9 files changed, 825 insertions(+), 542 deletions(-) diff --git a/src/devices/cpu/m6502/dxavix.lst b/src/devices/cpu/m6502/dxavix.lst index 127cf45ff30..34664f772d6 100644 --- a/src/devices/cpu/m6502/dxavix.lst +++ b/src/devices/cpu/m6502/dxavix.lst @@ -12,7 +12,7 @@ bvs_rel adc_idy kil_non rra_idy nop_zpx adc_zpx ror_zpx retf_imp sta_idx nop_imm sax_idx sty_zpg sta_zpg stx_zpg sax_zpg dey_imp nop_imm txa_imp ane_imm sty_aba sta_aba stx_aba sax_aba bcc_rel sta_idy kil_non sha_idy sty_zpx sta_zpx stx_zpy sax_zpy tya_imp sta_aby txs_imp shs_aby shy_abx sta_abx shx_aby sha_aby ldy_imm lda_idx ldx_imm lax_idx ldy_zpg lda_zpg ldx_zpg lax_zpg tay_imp lda_imm tax_imp lxa_imm ldy_aba lda_aba ldx_aba lax_aba -bcs_rel xa_lda_idy kil_non lax_idy ldy_zpx lda_zpx ldx_zpy lax_zpy clv_imp lda_aby tsx_imp las_aby ldy_abx lda_abx ldx_aby lax_aby +bcs_rel xavlda_idy kil_non lax_idy ldy_zpx lda_zpx ldx_zpy lax_zpy clv_imp lda_aby tsx_imp las_aby ldy_abx lda_abx ldx_aby lax_aby cpy_imm cmp_idx nop_imm dcp_idx cpy_zpg cmp_zpg dec_zpg dcp_zpg iny_imp cmp_imm dex_imp sbx_imm cpy_aba cmp_aba dec_aba dcp_aba bne_rel cmp_idy kil_non dcp_idy nop_zpx cmp_zpx dec_zpx dcp_zpx cld_imp cmp_aby nop_imp dcp_aby nop_abx cmp_abx dec_abx dcp_abx cpx_imm sbc_idx nop_imm isb_idx cpx_zpg sbc_zpg inc_zpg isb_zpg inx_imp sbc_imm nop_imp sbc_imm cpx_aba sbc_aba inc_aba isb_aba diff --git a/src/devices/cpu/m6502/dxavix2000.lst b/src/devices/cpu/m6502/dxavix2000.lst index 82cb12d312a..01308c9842d 100644 --- a/src/devices/cpu/m6502/dxavix2000.lst +++ b/src/devices/cpu/m6502/dxavix2000.lst @@ -12,7 +12,7 @@ bvs_rel adc_idy ply_imp adcpa_imp nop_imp adc_zpx ror_zpx retf_imp sta_idx stz_zpg stal0_acc sty_zpg sta_zpg stx_zpg stal1_acc dey_imp sev_imp txa_imp stal2_acc sty_aba sta_aba stx_aba stal3_acc bcc_rel sta_idy stz_aba stapa_imp sty_zpx sta_zpx stx_zpy stapb_imp tya_imp sta_aby txs_imp spa2_acc sty_abx sta_abx stx_aby spb2_acc ldy_imm lda_idx ldx_imm ldal0_acc ldy_zpg lda_zpg ldx_zpg ldal1_acc tay_imp lda_imm tax_imp ldal2_acc ldy_aba lda_aba ldx_aba ldal3_acc -bcs_rel xa_lda_idy clr_acc ldapa_imp ldy_zpx lda_zpx ldx_zpy ldapb_imp clv_imp lda_aby tsx_imp lpa2_acc ldy_abx lda_abx ldx_aby lpb2_acc +bcs_rel xavlda_idy clr_acc ldapa_imp ldy_zpx lda_zpx ldx_zpy ldapb_imp clv_imp lda_aby tsx_imp lpa2_acc ldy_abx lda_abx ldx_aby lpb2_acc cpy_imm cmp_idx dec_acc cmpl0_acc cpy_zpg cmp_zpg dec_zpg cmpl1_acc iny_imp cmp_imm dex_imp cmpl2_acc cpy_aba cmp_aba dec_aba cmpl3_acc bne_rel cmp_idy not_acc cmppa_imp nop_imp cmp_zpx dec_zpx cmppb_imp cld_imp cmp_aby nop_imp decpa_imp nop_imp cmp_abx dec_abx decpb_imp cpx_imm sbc_idx inc_acc sbcl0_acc cpx_zpg sbc_zpg inc_zpg sbcl1_acc inx_imp sbc_imm nop_imp sbcl2_acc cpx_aba sbc_aba inc_aba sbcl3_acc diff --git a/src/devices/cpu/m6502/oxavix.lst b/src/devices/cpu/m6502/oxavix.lst index 6e7d8290aac..5cb5fd62349 100644 --- a/src/devices/cpu/m6502/oxavix.lst +++ b/src/devices/cpu/m6502/oxavix.lst @@ -113,7 +113,7 @@ rti_xav_imp prefetch(); -xa_lda_idy +xavlda_idy TMP2 = read_pc(); // we need to fetch the zero page part from zero page, but the rest as if zero page wasn't there, similar to the 6509 TMP = read(TMP2); TMP = set_h(TMP, read((TMP2+1) & 0xff)); diff --git a/src/devices/cpu/m6502/xavix.cpp b/src/devices/cpu/m6502/xavix.cpp index 8ae59f2e0d4..206c07bece5 100644 --- a/src/devices/cpu/m6502/xavix.cpp +++ b/src/devices/cpu/m6502/xavix.cpp @@ -33,28 +33,28 @@ DEFINE_DEVICE_TYPE(XAVIX, xavix_device, "xavix", "XaviX (SSD 97 / SSD 98)") xavix_device::xavix_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : m6502_device(mconfig, XAVIX, tag, owner, clock), XPC(0), - m_special_data_config("specialdata", ENDIANNESS_LITTLE, 8, 24) + m_lowbus_config("lowbus", ENDIANNESS_LITTLE, 8, 15) { program_config.m_addr_width = 24; program_config.m_logaddr_width = 24; sprogram_config.m_addr_width = 24; sprogram_config.m_logaddr_width = 24; - m_special_data_config.m_addr_width = 24; - m_special_data_config.m_logaddr_width = 24; + m_lowbus_config.m_addr_width = 15; + m_lowbus_config.m_logaddr_width = 15; } xavix_device::xavix_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : m6502_device(mconfig, type, tag, owner, clock), XPC(0), - m_special_data_config("specialdata", ENDIANNESS_LITTLE, 8, 24) + m_lowbus_config("lowbus", ENDIANNESS_LITTLE, 8, 15) { program_config.m_addr_width = 24; program_config.m_logaddr_width = 24; sprogram_config.m_addr_width = 24; sprogram_config.m_logaddr_width = 24; - m_special_data_config.m_addr_width = 24; - m_special_data_config.m_logaddr_width = 24; + m_lowbus_config.m_addr_width = 15; + m_lowbus_config.m_logaddr_width = 15; } @@ -82,7 +82,7 @@ void xavix_device::device_start() init(); - m_special_data_space = &space(4); + m_lowbus_space = &space(5); state_add(XAVIX_DATABANK, "DATBNK", m_databank).callimport().formatstr("%2s");; state_add(XAVIX_CODEBANK, "CODBNK", m_codebank).callimport().formatstr("%2s"); @@ -95,51 +95,229 @@ void xavix_device::device_reset() m6502_device::device_reset(); } +// used by the xalda_idy ( lda ($**), y )opcodes uint8_t xavix_device::read_special(uint16_t adr) { - return m_special_data_space->read_byte(adr | (m_databank<<16)); + return read_full_data_sp(m_databank, adr); } +uint8_t xavix_device::read_full_special(uint32_t adr) +{ + return read_full_data_sp((adr&0xff0000)>>16, adr&0xffff); +} + + xavix_device::mi_xavix_normal::mi_xavix_normal(xavix_device *_base) { base = _base; } +uint8_t xavix_device::read_full_data(uint32_t addr) +{ + return read_full_data((addr & 0xff0000)>>16, addr & 0xffff); +} + +inline uint8_t xavix_device::read_full_data(uint8_t databank, uint16_t adr) +{ + if (databank < 0x80) + { + if (adr < 0x8000) + { + if (adr == 0xfe) + return m_codebank; + else if (adr == 0xff) + return databank; + + return m_lowbus_space->read_byte(adr); + } + else + { + return mintf->program->read_byte((databank << 16) | adr); + } + } + else + { + if (adr < 0x8000) + { + if (adr == 0xfe) + return m_codebank; + else if (adr == 0xff) + return databank; + + if ((adr & 0x7fff) >= 0x200) + { + return mintf->program->read_byte((databank << 16) | adr); + } + else + { + return m_lowbus_space->read_byte(adr); + } + } + else + { + return mintf->program->read_byte((databank << 16) | adr); + } + } +} +uint8_t xavix_device::read_full_data_sp(uint8_t databank, uint16_t adr) +{ + if (databank < 0x80) + { + if (adr < 0x8000) + { + if (adr == 0xfe) + return m_codebank; + else if (adr == 0xff) + return databank; + + return m_lowbus_space->read_byte(adr); + } + else + { + return mintf->program->read_byte((databank << 16) | adr); + } + } + else + { + return mintf->program->read_byte((databank << 16) | adr); + } +} + + +// data reads uint8_t xavix_device::mi_xavix_normal::read(uint16_t adr) { - if (adr == 0xfe) - return base->m_codebank; - else if (adr == 0xff) - return base->m_databank; + uint8_t databank = base->get_databank(); + return base->read_full_data(databank, adr); +} - return program->read_byte((base->get_databank() << 16) | adr); +uint8_t xavix_device::read_full_code(uint32_t addr) +{ + return read_full_code(mintf->cache, (addr & 0xff0000)>>16, addr & 0xffff); } + +uint8_t xavix_device::read_full_code(memory_access_cache<0, 0, ENDIANNESS_LITTLE> * space, uint8_t codebank, uint16_t adr) +{ + if (codebank < 0x80) + { + if (adr < 0x8000) + { + return m_lowbus_space->read_byte(adr); + } + else + { + return space->read_byte(codebank << 16 | adr); + } + } + else + { + return space->read_byte(codebank << 16 | adr); + } +} + +uint8_t xavix_device::read_full_code(address_space* space, uint8_t codebank, uint16_t adr) +{ + if (codebank < 0x80) + { + if (adr < 0x8000) + { + return m_lowbus_space->read_byte(adr); + } + else + { + return space->read_byte(codebank << 16 | adr); + } + } + else + { + return space->read_byte(codebank << 16 | adr); + } +} + + +// opcode reads uint8_t xavix_device::mi_xavix_normal::read_sync(uint16_t adr) { - return scache->read_byte(base->adr_with_codebank(adr)); + uint8_t codebank = base->get_codebank(); + return base->read_full_code(scache, codebank, adr); } uint8_t xavix_device::mi_xavix_normal::read_arg(uint16_t adr) { - return cache->read_byte(base->adr_with_codebank(adr)); + uint8_t codebank = base->get_codebank(); + return base->read_full_code(cache, codebank, adr); } -void xavix_device::mi_xavix_normal::write(uint16_t adr, uint8_t val) +// data writes +void xavix_device::write_full_data(uint32_t addr, uint8_t val) { - if (adr == 0xfe) + write_full_data((addr & 0xff0000)>>16, addr & 0xffff, val); +} + + +// data writes +void xavix_device::write_full_data(uint8_t databank, uint16_t adr, uint8_t val) +{ + if (databank < 0x80) { - base->m_codebank = val; - return; + if (adr < 0x8000) + { + if (adr == 0xfe) + { + m_codebank = val; + return; + } + else if (adr == 0xff) + { + m_databank = val; + return; + } + + m_lowbus_space->write_byte(adr, val); + } + else + { + mintf->program->write_byte((databank << 16) | adr, val); + } } - else if (adr == 0xff) + else { - base->m_databank = val; - return; + if (adr < 0x8000) + { + if (adr == 0xfe) + { + m_codebank = val; + return; + } + else if (adr == 0xff) + { + m_databank = val; + return; + } + + if ((adr & 0x7fff) >= 0x200) + { + mintf->program->write_byte((databank << 16) | adr, val); + } + else + { + m_lowbus_space->write_byte(adr, val); + } + } + else + { + mintf->program->write_byte((databank << 16) | adr, val); + } } +} - program->write_byte((base->get_databank() << 16) | adr, val); + +void xavix_device::mi_xavix_normal::write(uint16_t adr, uint8_t val) +{ + uint8_t databank = base->get_databank(); + base->write_full_data(databank, adr, val); } xavix_device::mi_xavix_nd::mi_xavix_nd(xavix_device *_base) : mi_xavix_normal(_base) @@ -148,12 +326,14 @@ xavix_device::mi_xavix_nd::mi_xavix_nd(xavix_device *_base) : mi_xavix_normal(_b uint8_t xavix_device::mi_xavix_nd::read_sync(uint16_t adr) { - return sprogram->read_byte(base->adr_with_codebank(adr)); + uint8_t codebank = base->get_codebank(); + return base->read_full_code(sprogram, codebank, adr); } uint8_t xavix_device::mi_xavix_nd::read_arg(uint16_t adr) { - return program->read_byte(base->adr_with_codebank(adr)); + uint8_t codebank = base->get_codebank(); + return base->read_full_code(program, codebank, adr); } void xavix_device::set_codebank(uint8_t bank) @@ -186,12 +366,12 @@ device_memory_interface::space_config_vector xavix_device::memory_space_config() return space_config_vector { std::make_pair(AS_PROGRAM, &program_config), std::make_pair(AS_OPCODES, &sprogram_config), - std::make_pair(4, &m_special_data_config) + std::make_pair(5, &m_lowbus_config) }; else return space_config_vector { std::make_pair(AS_PROGRAM, &program_config), - std::make_pair(4, &m_special_data_config) + std::make_pair(5, &m_lowbus_config) }; } diff --git a/src/devices/cpu/m6502/xavix.h b/src/devices/cpu/m6502/xavix.h index a0fa5215605..190d216ba40 100644 --- a/src/devices/cpu/m6502/xavix.h +++ b/src/devices/cpu/m6502/xavix.h @@ -32,7 +32,7 @@ public: O(brk_xav_imp); O(rti_xav_imp); - O(xa_lda_idy); + O(xavlda_idy); typedef device_delegate xavix_interrupt_vector_delegate; @@ -41,6 +41,20 @@ public: #undef O + void write_full_data(uint8_t databank, uint16_t adr, uint8_t val); + uint8_t read_full_code(address_space* space, uint8_t codebank, uint16_t adr); + uint8_t read_full_code(memory_access_cache<0, 0, ENDIANNESS_LITTLE> * space, uint8_t codebank, uint16_t adr); + + uint8_t read_full_code(uint32_t addr); + + uint8_t read_full_data(uint8_t databank, uint16_t addr); + uint8_t read_full_data_sp(uint8_t databank, uint16_t adr); + uint8_t read_full_special(uint32_t adr); + + uint8_t read_full_data(uint32_t addr); + + void write_full_data(uint32_t addr, uint8_t val); + protected: class mi_xavix_normal : public memory_interface { public: @@ -81,6 +95,8 @@ protected: address_space_config m_special_data_config; address_space *m_special_data_space; + address_space_config m_lowbus_config; + address_space *m_lowbus_space; uint8_t read_special(uint16_t adr); diff --git a/src/mame/drivers/xavix.cpp b/src/mame/drivers/xavix.cpp index 1db34df5993..cb163f9d633 100644 --- a/src/mame/drivers/xavix.cpp +++ b/src/mame/drivers/xavix.cpp @@ -211,26 +211,12 @@ READ8_MEMBER(xavix_state::main_r) { - if (offset & 0x8000) - { - return m_rgn[(offset) & (m_rgnlen - 1)]; - } - else - { - return m_lowbus->read8(space, offset&0x7fff); - } + return m_rgn[(offset) & (m_rgnlen - 1)]; } WRITE8_MEMBER(xavix_state::main_w) { - if (offset & 0x8000) - { - logerror("write to ROM area?\n"); - } - else - { - m_lowbus->write8(space, offset & 0x7fff, data); - } + logerror("write to ROM area?\n"); } /* rad_madf has callf #$8f3f21 in various places, and expects to jump to code in ROM, it is unclear how things map in this case, as presumably @@ -259,63 +245,13 @@ WRITE8_MEMBER(xavix_state::main_w) */ -READ8_MEMBER(xavix_state::main2_r) -{ - if (offset & 0x8000) - { - return m_rgn[(offset) & (m_rgnlen - 1)]; - } - else - { - if ((offset & 0xffff) >= 0x200) - { - return m_rgn[(offset) & (m_rgnlen - 1)]; - } - else - return m_lowbus->read8(space, offset & 0x7fff); - } -} - -WRITE8_MEMBER(xavix_state::main2_w) -{ - - if (offset & 0x8000) - { - - } - else - { - if ((offset & 0xffff) >= 0x200) - logerror("write to ROM area?\n"); - else - m_lowbus->write8(space, offset & 0x7fff, data); - } -} // DATA reads from 0x8000-0xffff are banked by byte 0xff of 'ram' (this is handled in the CPU core) +// access to external bus / ROM void xavix_state::xavix_map(address_map &map) { - map(0x000000, 0x7fffff).rw(FUNC(xavix_state::main_r), FUNC(xavix_state::main_w)); - map(0x800000, 0xffffff).rw(FUNC(xavix_state::main2_r), FUNC(xavix_state::main2_w)); -} - -// used by the xa_lda_idy ( lda ($**), y )opcodes -READ8_MEMBER(xavix_state::main3_r) -{ - return m_rgn[(offset) & (m_rgnlen - 1)]; -} - -WRITE8_MEMBER(xavix_state::main3_w) -{ - // -} - - -void xavix_state::xavix_special_map(address_map &map) -{ - map(0x000000, 0x7fffff).rw(FUNC(xavix_state::main_r), FUNC(xavix_state::main_w)); - map(0x800000, 0xffffff).rw(FUNC(xavix_state::main3_r), FUNC(xavix_state::main3_w)); + map(0x000000, 0xffffff).rw(FUNC(xavix_state::main_r), FUNC(xavix_state::main_w)); } void xavix_state::xavix_lowbus_map(address_map &map) @@ -357,13 +293,13 @@ void xavix_state::xavix_lowbus_map(address_map &map) // Colour Mixing / Enabling Registers map(0x6ff0, 0x6ff0).ram().share("colmix_sh"); // a single colour (for effects?) not bgpen map(0x6ff1, 0x6ff1).ram().share("colmix_l"); - map(0x6ff2, 0x6ff2).w(FUNC(xavix_state::colmix_6ff2_w)); // set to 07 after clearing above things in interrupt 0 + map(0x6ff2, 0x6ff2).ram().w(FUNC(xavix_state::colmix_6ff2_w)).share("colmix_ctrl"); // set to 07 after clearing above things in interrupt 0 // Display Control Register / Status Flags map(0x6ff8, 0x6ff8).rw(FUNC(xavix_state::dispctrl_6ff8_r), FUNC(xavix_state::dispctrl_6ff8_w)); // always seems to be a read/store or read/modify/store map(0x6ff9, 0x6ff9).r(FUNC(xavix_state::pal_ntsc_r)); - map(0x6ffa, 0x6ffa).w(FUNC(xavix_state::dispctrl_posirq_x_w)); - map(0x6ffb, 0x6ffb).w(FUNC(xavix_state::dispctrl_posirq_y_w)); // increases / decreases when you jump in snowboard (snowboard, used to blank ground) + map(0x6ffa, 0x6ffa).ram().w(FUNC(xavix_state::dispctrl_posirq_x_w)).share("posirq_x"); + map(0x6ffb, 0x6ffb).ram().w(FUNC(xavix_state::dispctrl_posirq_y_w)).share("posirq_y"); // increases / decreases when you jump in snowboard (snowboard, used to blank ground) // Lightgun / pen 1 control // map(0x6ffc, 0x6fff) @@ -451,6 +387,17 @@ void xavix_state::xavix_lowbus_map(address_map &map) map(0x7fff, 0x7fff).w(FUNC(xavix_state::irq_vector_hi_w)); } +void xavix_state::superxavix_lowbus_map(address_map &map) +{ + xavix_lowbus_map(map); + + // bitmap layer palette + map(0x6c00, 0x6cff).ram().share("bmp_palram_sh"); + map(0x6d00, 0x6dff).ram().share("bmp_palram_l"); + + map(0x6fb0, 0x6fc7).ram().share("bmp_base"); +} + static INPUT_PORTS_START( xavix ) PORT_START("IN0") PORT_DIPNAME( 0x01, 0x00, "IN0" ) @@ -605,6 +552,12 @@ static INPUT_PORTS_START( rad_bass ) PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) + + PORT_MODIFY("IN1") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_POWER_OFF ) PORT_NAME("Power Switch") // pressing this will turn the game off. + INPUT_PORTS_END static INPUT_PORTS_START( rad_bassp ) @@ -666,7 +619,7 @@ static INPUT_PORTS_START( rad_bb2 ) PORT_MODIFY("IN1") PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("X") PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("O") - PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME(".") + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_POWER_OFF ) PORT_NAME("Power Switch") // pressing this will turn the game off. INPUT_PORTS_END static INPUT_PORTS_START( ttv_mx ) @@ -679,6 +632,21 @@ static INPUT_PORTS_START( ttv_mx ) PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) INPUT_PORTS_END + +CUSTOM_INPUT_MEMBER( xavix_state::rad_rh_in1_08_r ) +{ + // it's unclear what rad_rh wants here + // it sits in loops waiting for this to toggle, but changing it can simply crash the code + return 0; //machine().rand(); +} + +static INPUT_PORTS_START( rad_rh ) + PORT_INCLUDE(xavix) + + PORT_MODIFY("IN1") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(DEVICE_SELF, xavix_state,rad_rh_in1_08_r, (void *)0) +INPUT_PORTS_END + /* correct, 4bpp gfxs */ static const gfx_layout charlayout = { @@ -737,26 +705,23 @@ MACHINE_CONFIG_START(xavix_state::xavix) /* basic machine hardware */ MCFG_DEVICE_ADD("maincpu",XAVIX,MAIN_CLOCK) MCFG_DEVICE_PROGRAM_MAP(xavix_map) - MCFG_DEVICE_ADDRESS_MAP(4, xavix_special_map) + MCFG_DEVICE_ADDRESS_MAP(5, xavix_lowbus_map) + MCFG_M6502_DISABLE_CACHE() MCFG_DEVICE_VBLANK_INT_DRIVER("screen", xavix_state, interrupt) MCFG_XAVIX_VECTOR_CALLBACK(xavix_state, get_vectors) - - MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", xavix_state, scanline_cb, "screen", 0, 1) - ADDRESS_MAP_BANK(config, "lowbus").set_map(&xavix_state::xavix_lowbus_map).set_options(ENDIANNESS_LITTLE, 8, 24, 0x8000); - - /* video hardware */ MCFG_SCREEN_ADD("screen", RASTER) MCFG_SCREEN_REFRESH_RATE(60) MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) MCFG_SCREEN_UPDATE_DRIVER(xavix_state, screen_update) MCFG_SCREEN_SIZE(32*8, 32*8) - MCFG_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 0*8, 28*8-1) + MCFG_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 2*8, 30*8-1) MCFG_SCREEN_PALETTE("palette") + //MCFG_SCREEN_VIDEO_ATTRIBUTES(VIDEO_UPDATE_SCANLINE) MCFG_DEVICE_ADD("gfxdecode", GFXDECODE, "palette", gfx_xavix) @@ -787,11 +752,14 @@ MACHINE_CONFIG_START(xavix_state::xavix2000) MCFG_DEVICE_ADD("maincpu",XAVIX2000,MAIN_CLOCK) MCFG_DEVICE_PROGRAM_MAP(xavix_map) - MCFG_DEVICE_ADDRESS_MAP(4, xavix_special_map) + MCFG_DEVICE_ADDRESS_MAP(5, superxavix_lowbus_map) MCFG_M6502_DISABLE_CACHE() MCFG_DEVICE_VBLANK_INT_DRIVER("screen", xavix_state, interrupt) MCFG_XAVIX_VECTOR_CALLBACK(xavix_state, get_vectors) + MCFG_DEVICE_REMOVE("palette") + MCFG_PALETTE_ADD("palette", 512+1) + MACHINE_CONFIG_END MACHINE_CONFIG_START(xavix_state::xavix2000_i2c) @@ -986,7 +954,7 @@ CONS( 2003, rad_madf, 0, 0, xavix, xavix, xavix_state, init_xavix CONS( 200?, rad_fb, 0, 0, xavix, xavix, xavix_state, init_xavix, "Radica / SSD Company LTD", "Play TV Football (NTSC)", MACHINE_IS_SKELETON) // USA only release? doesn't change logo for PAL -CONS( 200?, rad_rh, 0, 0, xavix, xavix, xavix_state, init_xavix, "Radioa / Fisher-Price / SSD Company LTD", "Play TV Rescue Heroes", MACHINE_IS_SKELETON) +CONS( 200?, rad_rh, 0, 0, xavix, rad_rh, xavix_state, init_xavix, "Radioa / Fisher-Price / SSD Company LTD", "Play TV Rescue Heroes", MACHINE_IS_SKELETON) CONS( 200?, epo_efdx, 0, 0, xavix_i2c, xavix, xavix_state, init_xavix, "Epoch / SSD Company LTD", "Excite Fishing DX (Japan)", MACHINE_IS_SKELETON) diff --git a/src/mame/includes/xavix.h b/src/mame/includes/xavix.h index 5948203bf53..6749bc0f10b 100644 --- a/src/mame/includes/xavix.h +++ b/src/mame/includes/xavix.h @@ -27,15 +27,20 @@ public: m_rom_dma_len(*this,"rom_dma_len"), m_palram_sh(*this, "palram_sh"), m_palram_l(*this, "palram_l"), + m_bmp_palram_sh(*this, "bmp_palram_sh"), + m_bmp_palram_l(*this, "bmp_palram_l"), + m_bmp_base(*this, "bmp_base"), m_colmix_sh(*this, "colmix_sh"), m_colmix_l(*this, "colmix_l"), + m_colmix_ctrl(*this, "colmix_ctrl"), + m_posirq_x(*this, "posirq_x"), + m_posirq_y(*this, "posirq_y"), m_segment_regs(*this, "segment_regs"), m_palette(*this, "palette"), m_in0(*this, "IN0"), m_in1(*this, "IN1"), m_region(*this, "REGION"), m_gfxdecode(*this, "gfxdecode"), - m_lowbus(*this, "lowbus"), m_i2cmem(*this, "i2cmem") { } @@ -48,14 +53,16 @@ public: void init_xavix(); + DECLARE_CUSTOM_INPUT_MEMBER(rad_rh_in1_08_r); + private: // screen updates uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); void xavix_map(address_map &map); - void xavix_special_map(address_map &map); void xavix_lowbus_map(address_map &map); + void superxavix_lowbus_map(address_map &map); INTERRUPT_GEN_MEMBER(interrupt); TIMER_DEVICE_CALLBACK_MEMBER(scanline_cb); @@ -134,9 +141,6 @@ private: DECLARE_READ8_MEMBER(dispctrl_6ff8_r); DECLARE_WRITE8_MEMBER(dispctrl_6ff8_w); - DECLARE_WRITE8_MEMBER(dispctrl_posirq_x_w); - DECLARE_WRITE8_MEMBER(dispctrl_posirq_y_w); - DECLARE_READ8_MEMBER(sound_75f0_r); DECLARE_WRITE8_MEMBER(sound_75f0_w); @@ -191,7 +195,7 @@ private: DECLARE_READ8_MEMBER(mult_param_r); DECLARE_WRITE8_MEMBER(mult_param_w); - required_device m_maincpu; + required_device m_maincpu; required_device m_screen; uint8_t m_vectorenable; @@ -214,7 +218,7 @@ private: uint8_t m_arena_control; uint8_t m_6ff0; - uint8_t m_6ff8; + uint8_t m_video_ctrl; uint8_t m_io0_data; uint8_t m_io1_data; @@ -226,6 +230,12 @@ private: uint8_t m_timer_baseval; int16_t get_vectors(int which, int half); + + // raster IRQ + TIMER_CALLBACK_MEMBER(interrupt_gen); + emu_timer *m_interrupt_timer; + DECLARE_WRITE8_MEMBER(dispctrl_posirq_x_w); + DECLARE_WRITE8_MEMBER(dispctrl_posirq_y_w); required_shared_ptr m_mainram; required_shared_ptr m_fragment_sprite; @@ -235,9 +245,17 @@ private: required_shared_ptr m_palram_sh; required_shared_ptr m_palram_l; + + optional_shared_ptr m_bmp_palram_sh; + optional_shared_ptr m_bmp_palram_l; + optional_shared_ptr m_bmp_base; + required_shared_ptr m_colmix_sh; required_shared_ptr m_colmix_l; + required_shared_ptr m_colmix_ctrl; + required_shared_ptr m_posirq_x; + required_shared_ptr m_posirq_y; required_shared_ptr m_segment_regs; @@ -249,11 +267,14 @@ private: required_device m_gfxdecode; - void handle_palette(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + void handle_palette(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, uint8_t* ramsh, uint8_t* raml, int size, int basecol); double hue2rgb(double p, double q, double t); - void draw_tile(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int tile, int bpp, int xpos, int ypos, int drawheight, int drawwidth, int flipx, int flipy, int pal, int zval); + void draw_tile_line(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int tile, int bpp, int xpos, int ypos, int drawheight, int drawwidth, int flipx, int flipy, int pal, int zval, int line); void draw_tilemap(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int which); + void draw_tilemap_line(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int which, int line); void draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + void draw_sprites_line(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int line); + bitmap_ind16 m_zbuffer; uint8_t m_spritereg; @@ -264,13 +285,13 @@ private: // variables used by rendering int m_tmp_dataaddress; int m_tmp_databit; + uint8_t m_bit; + void set_data_address(int address, int bit); uint8_t get_next_bit(); uint8_t get_next_byte(); int get_current_address_byte(); - - required_device m_lowbus; optional_device m_i2cmem; }; diff --git a/src/mame/machine/xavix.cpp b/src/mame/machine/xavix.cpp index 5ad392d7c2c..698ae5c7e62 100644 --- a/src/mame/machine/xavix.cpp +++ b/src/mame/machine/xavix.cpp @@ -4,46 +4,36 @@ #include "emu.h" #include "includes/xavix.h" +// #define VERBOSE 1 +#include "logmacro.h" + // general DMA to/from entire main map (not dedicated sprite DMA) WRITE8_MEMBER(xavix_state::rom_dmatrg_w) { if (data & 0x01) // namcons2 writes 0x81, most of the time things write 0x01 { - logerror("%s: rom_dmatrg_w (do DMA?) %02x\n", machine().describe_context(), data); + LOG("%s: rom_dmatrg_w (do DMA?) %02x\n", machine().describe_context(), data); uint32_t source = (m_rom_dma_src[2] << 16) | (m_rom_dma_src[1] << 8) | m_rom_dma_src[0]; uint16_t dest = (m_rom_dma_dst[1] << 8) | m_rom_dma_dst[0]; uint16_t len = (m_rom_dma_len[1] << 8) | m_rom_dma_len[0]; - logerror(" (possible DMA op SRC %08x DST %04x LEN %04x)\n", source, dest, len); - - address_space& destspace = m_maincpu->space(AS_PROGRAM); + LOG(" (possible DMA op SRC %08x DST %04x LEN %04x)\n", source, dest, len); for (int i = 0; i < len; i++) { - uint32_t m_tmpaddress = source+i; + uint32_t m_tmpaddress = source + i; // many games explicitly want to access with the high bank bit set, so probably the same logic as when grabbing tile data // we have to be careful here or we get the zero page memory read, hence not just using read8 on the whole space // this again probably indicates there is 'data space' where those don't appear - uint8_t dat = 0; - // if bank is > 0x80, or address is >0x8000 it's a plain ROM read - if ((m_tmpaddress >= 0x80000) || (m_tmpaddress & 0x8000)) - { - dat= m_rgn[m_tmpaddress & (m_rgnlen - 1)]; - } - else - { - address_space& mainspace = m_maincpu->space(AS_PROGRAM); - dat = m_lowbus->read8(mainspace, m_tmpaddress & 0x7fff); - } - - destspace.write_byte(dest + i, dat); + uint8_t dat = m_maincpu->read_full_special(m_tmpaddress); + m_maincpu->write_full_data(dest+i, dat); } } else // the interrupt routine writes 0x80 to the trigger, maybe 'clear IRQ?' { - logerror("%s: rom_dmatrg_w (unknown) %02x\n", machine().describe_context(), data); + LOG("%s: rom_dmatrg_w (unknown) %02x\n", machine().describe_context(), data); } } @@ -51,26 +41,26 @@ WRITE8_MEMBER(xavix_state::rom_dmatrg_w) WRITE8_MEMBER(xavix_state::rom_dmasrc_w) { // has_wamg expects to be able to read back the source to modify it (need to check if it expects it to change after an operation) - logerror("%s: rom_dmasrc_w (%02x) %02x\n", machine().describe_context(), offset, data); + LOG("%s: rom_dmasrc_w (%02x) %02x\n", machine().describe_context(), offset, data); m_rom_dma_src[offset] = data; } WRITE8_MEMBER(xavix_state::rom_dmadst_w) { - logerror("%s: rom_dmadst_w (%02x) %02x\n", machine().describe_context(), offset, data); + LOG("%s: rom_dmadst_w (%02x) %02x\n", machine().describe_context(), offset, data); m_rom_dma_dst[offset] = data; } WRITE8_MEMBER(xavix_state::rom_dmalen_w) { - logerror("%s: rom_dmalen_w (%02x) %02x\n", machine().describe_context(), offset, data); + LOG("%s: rom_dmalen_w (%02x) %02x\n", machine().describe_context(), offset, data); m_rom_dma_len[offset] = data; } READ8_MEMBER(xavix_state::rom_dmastat_r) { - logerror("%s: rom_dmastat_r (operation status?)\n", machine().describe_context()); + LOG("%s: rom_dmastat_r (operation status?)\n", machine().describe_context()); return 0x00; } @@ -78,87 +68,87 @@ READ8_MEMBER(xavix_state::rom_dmastat_r) WRITE8_MEMBER(xavix_state::vector_enable_w) { - logerror("%s: vector_enable_w %02x\n", machine().describe_context(), data); + LOG("%s: vector_enable_w %02x\n", machine().describe_context(), data); m_vectorenable = data; } WRITE8_MEMBER(xavix_state::nmi_vector_lo_w) { - logerror("%s: nmi_vector_lo_w %02x\n", machine().describe_context(), data); + LOG("%s: nmi_vector_lo_w %02x\n", machine().describe_context(), data); m_nmi_vector_lo_data = data; } WRITE8_MEMBER(xavix_state::nmi_vector_hi_w) { - logerror("%s: nmi_vector_hi_w %02x\n", machine().describe_context(), data); + LOG("%s: nmi_vector_hi_w %02x\n", machine().describe_context(), data); m_nmi_vector_hi_data = data; } WRITE8_MEMBER(xavix_state::irq_vector_lo_w) { - logerror("%s: irq_vector_lo_w %02x\n", machine().describe_context(), data); + LOG("%s: irq_vector_lo_w %02x\n", machine().describe_context(), data); m_irq_vector_lo_data = data; } WRITE8_MEMBER(xavix_state::irq_vector_hi_w) { - logerror("%s: irq_vector_hi_w %02x\n", machine().describe_context(), data); + LOG("%s: irq_vector_hi_w %02x\n", machine().describe_context(), data); m_irq_vector_hi_data = data; } WRITE8_MEMBER(xavix_state::extintrf_7900_w) { - logerror("%s: extintrf_7900_w %02x (---FIRST WRITE ON STARTUP---)\n", machine().describe_context(), data); + LOG("%s: extintrf_7900_w %02x (---FIRST WRITE ON STARTUP---)\n", machine().describe_context(), data); } WRITE8_MEMBER(xavix_state::extintrf_7901_w) { - logerror("%s: extintrf_7901_w %02x\n", machine().describe_context(), data); + LOG("%s: extintrf_7901_w %02x\n", machine().describe_context(), data); } WRITE8_MEMBER(xavix_state::extintrf_7902_w) { - logerror("%s: extintrf_7902_w %02x\n", machine().describe_context(), data); + LOG("%s: extintrf_7902_w %02x\n", machine().describe_context(), data); } WRITE8_MEMBER(xavix_state::xavix_7a80_w) { - logerror("%s: xavix_7a80_w %02x\n", machine().describe_context(), data); + LOG("%s: xavix_7a80_w %02x\n", machine().describe_context(), data); } WRITE8_MEMBER(xavix_state::adc_7b00_w) { - logerror("%s: adc_7b00_w %02x\n", machine().describe_context(), data); + LOG("%s: adc_7b00_w %02x\n", machine().describe_context(), data); } READ8_MEMBER(xavix_state::adc_7b80_r) { - logerror("%s: adc_7b80_r\n", machine().describe_context()); + LOG("%s: adc_7b80_r\n", machine().describe_context()); return 0x00;//0xff; } WRITE8_MEMBER(xavix_state::adc_7b80_w) { - logerror("%s: adc_7b80_w %02x\n", machine().describe_context(), data); + LOG("%s: adc_7b80_w %02x\n", machine().describe_context(), data); } WRITE8_MEMBER(xavix_state::adc_7b81_w) { - logerror("%s: adc_7b81_w %02x\n", machine().describe_context(), data); + LOG("%s: adc_7b81_w %02x\n", machine().describe_context(), data); } READ8_MEMBER(xavix_state::adc_7b81_r) { - return 0x00; -// return machine().rand(); +// has_wamg polls this if interrupt is enabled + return machine().rand(); } WRITE8_MEMBER(xavix_state::slotreg_7810_w) { - logerror("%s: slotreg_7810_w %02x\n", machine().describe_context(), data); + LOG("%s: slotreg_7810_w %02x\n", machine().describe_context(), data); } @@ -169,8 +159,11 @@ TIMER_DEVICE_CALLBACK_MEMBER(xavix_state::scanline_cb) INTERRUPT_GEN_MEMBER(xavix_state::interrupt) { - if (m_6ff8 & 0x20) - m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero); + if (m_video_ctrl & 0x20) + { + m_maincpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE); + m_video_ctrl |= 0x80; + } } @@ -178,31 +171,71 @@ INTERRUPT_GEN_MEMBER(xavix_state::interrupt) WRITE8_MEMBER(xavix_state::colmix_6ff2_w) { - logerror("%s: colmix_6ff2_w %02x\n", machine().describe_context(), data); + LOG("%s: colmix_6ff2_w %02x\n", machine().describe_context(), data); + m_colmix_ctrl[0] = data; } READ8_MEMBER(xavix_state::dispctrl_6ff8_r) { - //logerror("%s: dispctrl_6ff8_r\n", machine().describe_context()); - return m_6ff8; + // 0x80 = main IRQ asserted flag + // 0x40 = raster IRQ asserted flag + // 0x20 = main IRQ enable + // 0x10 = raster IRQ enable? + + //LOG("%s: dispctrl_6ff8_r\n", machine().describe_context()); + return m_video_ctrl; } WRITE8_MEMBER(xavix_state::dispctrl_6ff8_w) { // I think this is something to do with IRQ ack / enable - m_6ff8 = data; - logerror("%s: dispctrl_6ff8_w %02x\n", machine().describe_context(), data); + + // 0x80 = main IRQ ack? + // 0x40 = raster IRQ ack? + // 0x20 = main IRQ enable + // 0x10 = raster IRQ enable? + + if (data & 0x40) + { + m_maincpu->set_input_line(0, CLEAR_LINE); + } + + if (data & 0x80) + { + m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE); + } + + m_video_ctrl = data & 0x3f; + // printf("%s: dispctrl_6ff8_w %02x\n", machine().describe_context(), data); +} + + +TIMER_CALLBACK_MEMBER(xavix_state::interrupt_gen) +{ + if (m_video_ctrl & 0x10) + { + //printf("callback on scanline %d %d with IRQ enabled\n", m_screen->vpos(), m_screen->hpos()); + m_maincpu->set_input_line(0, ASSERT_LINE); + m_video_ctrl |= 0x40; + m_screen->update_partial(m_screen->vpos()); + } + m_interrupt_timer->adjust(attotime::never, 0); } + WRITE8_MEMBER(xavix_state::dispctrl_posirq_x_w) { - logerror("%s: dispctrl_posirq_x_w %02x\n", machine().describe_context(), data); + LOG("%s: dispctrl_posirq_x_w %02x\n", machine().describe_context(), data); + m_posirq_x[0] = data; } WRITE8_MEMBER(xavix_state::dispctrl_posirq_y_w) { - logerror("%s: dispctrl_posirq_y_w %02x\n", machine().describe_context(), data); + LOG("%s: dispctrl_posirq_y_w %02x\n", machine().describe_context(), data); + m_posirq_y[0] = data; + + m_interrupt_timer->adjust(m_screen->time_until_pos(m_posirq_y[0], m_posirq_x[0]), 0); } READ8_MEMBER(xavix_state::io0_data_r) @@ -245,13 +278,13 @@ READ8_MEMBER(xavix_state::io1_direction_r) WRITE8_MEMBER(xavix_state::io0_data_w) { m_io0_data = data; - logerror("%s: io0_data_w %02x\n", machine().describe_context(), data); + LOG("%s: io0_data_w %02x\n", machine().describe_context(), data); } WRITE8_MEMBER(xavix_state::io1_data_w) { m_io1_data = data; - logerror("%s: io1_data_w %02x\n", machine().describe_context(), data); + LOG("%s: io1_data_w %02x\n", machine().describe_context(), data); if (m_i2cmem) { @@ -270,76 +303,81 @@ WRITE8_MEMBER(xavix_state::io1_data_w) WRITE8_MEMBER(xavix_state::io0_direction_w) { m_io0_direction = data; - logerror("%s: io0_direction_w %02x\n", machine().describe_context(), data); - io0_data_w(space,0,m_io0_data); + LOG("%s: io0_direction_w %02x\n", machine().describe_context(), data); + io0_data_w(space, 0, m_io0_data); } WRITE8_MEMBER(xavix_state::io1_direction_w) { m_io1_direction = data; - logerror("%s: io1_direction_w %02x\n", machine().describe_context(), data); - io1_data_w(space,0,m_io1_data); // requires this for i2cmem to work, is it correct tho? + LOG("%s: io1_direction_w %02x\n", machine().describe_context(), data); + io1_data_w(space, 0, m_io1_data); // requires this for i2cmem to work, is it correct tho? } READ8_MEMBER(xavix_state::arena_start_r) { - //logerror("%s: arena_start_r\n", machine().describe_context()); + //LOG("%s: arena_start_r\n", machine().describe_context()); return m_arena_start; } WRITE8_MEMBER(xavix_state::arena_start_w) { - logerror("%s: arena_start_w %02x\n", machine().describe_context(), data); + LOG("%s: arena_start_w %02x\n", machine().describe_context(), data); m_arena_start = data; // expected to return data written } READ8_MEMBER(xavix_state::arena_end_r) { - logerror("%s: arena_end_r\n", machine().describe_context()); + LOG("%s: arena_end_r\n", machine().describe_context()); return m_arena_end; } WRITE8_MEMBER(xavix_state::arena_end_w) { - logerror("%s: arena_end_w %02x\n", machine().describe_context(), data); + LOG("%s: arena_end_w %02x\n", machine().describe_context(), data); m_arena_end = data; // expected to return data written } READ8_MEMBER(xavix_state::arena_control_r) { - m_arena_control ^= 0x40; // unknown, xavtenni expects this to become high, also seems to be running in some kind of interlace mode, so could be a field flag? + // xavtenni expects 0x40 to go high (interlace related?) + m_arena_control ^= 0x40; return m_arena_control; } WRITE8_MEMBER(xavix_state::arena_control_w) { - logerror("%s: arena_control_w %02x\n", machine().describe_context(), data); + LOG("%s: arena_control_w %02x\n", machine().describe_context(), data); m_arena_control = data; + + // rad_bb2 waits on this in the IRQ (what does it want?) is this hblank related? + if (data & 0x80) + m_arena_control &= ~0x80; } READ8_MEMBER(xavix_state::timer_baseval_r) { - logerror("%s: timer_baseval_r\n", machine().describe_context()); + LOG("%s: timer_baseval_r\n", machine().describe_context()); return m_timer_baseval; } WRITE8_MEMBER(xavix_state::timer_control_w) { - logerror("%s: timer_control_w %02x\n", machine().describe_context(), data); + LOG("%s: timer_control_w %02x\n", machine().describe_context(), data); } WRITE8_MEMBER(xavix_state::timer_baseval_w) { // expected to return data written m_timer_baseval = data; - logerror("%s: timer_baseval_w %02x\n", machine().describe_context(), data); + LOG("%s: timer_baseval_w %02x\n", machine().describe_context(), data); } WRITE8_MEMBER(xavix_state::timer_freq_w) { // 4-bit prescale - logerror("%s: timer_freq_w %02x\n", machine().describe_context(), data); + LOG("%s: timer_freq_w %02x\n", machine().describe_context(), data); } @@ -378,8 +416,8 @@ WRITE8_MEMBER(xavix_state::mult_param_w) int param2 = m_multparams[2]; #if 0 - int signparam1 = (m_multparams[0] & 0x02)>>1; - int signparam2 = (m_multparams[0] & 0x01)>>0; + int signparam1 = (m_multparams[0] & 0x02) >> 1; + int signparam2 = (m_multparams[0] & 0x01) >> 0; if (signparam1) param1 = -param1; if (signparam2) param2 = -param2; @@ -403,8 +441,8 @@ WRITE8_MEMBER(xavix_state::mult_param_w) popmessage("unknown multiplier mode %02n", m_multparams[0] & 0xc0); } - m_multresults[1] = (result>>8)&0xff; - m_multresults[0] = result&0xff; + m_multresults[1] = (result >> 8) & 0xff; + m_multresults[0] = result & 0xff; } } @@ -414,22 +452,23 @@ READ8_MEMBER(xavix_state::irq_source_r) /* the 2nd IRQ routine (regular IRQ) reads here before deciding what to do the following bits have been seen to be checked (active low?) + monster truck does most extensive checking 0x80 - Sound Irq 0x40 - Picture / Arena Irq? - 0x20 - DMA Irq + 0x20 - DMA Irq (most routines check this as first priority, and ignore other requests if it is set?) 0x10 - Timer / Counter IRQ 0x08 - IO Irq (ADC? - used for analog control on Monster Truck) (uses 7a80 top bit to determine direction, and 7a81 0x08 as an output, presumably to clock) 0x04 - ADC IRQ - loads/stores 7b81 */ - logerror("%s: irq_source_r\n", machine().describe_context()); - return 0xff; + LOG("%s: irq_source_r\n", machine().describe_context()); + return 0x40; } WRITE8_MEMBER(xavix_state::irq_source_w) { - logerror("%s: irq_source_w %02x\n", machine().describe_context(), data); + LOG("%s: irq_source_w %02x\n", machine().describe_context(), data); // cleared on startup in monster truck, no purpose? } @@ -439,6 +478,8 @@ void xavix_state::machine_start() // card night expects RAM to be initialized to 0xff or it will show the pause menu over the startup graphics?! // don't do this every reset or it breaks the baseball 2 secret mode toggle which flips a bit in RAM std::fill_n(&m_mainram[0], 0x4000, 0xff); + + m_interrupt_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(xavix_state::interrupt_gen), this)); } void xavix_state::machine_reset() @@ -459,7 +500,7 @@ void xavix_state::machine_reset() m_irq_vector_lo_data = 0; m_irq_vector_hi_data = 0; - m_6ff8 = 0; + m_video_ctrl = 0; m_arena_control = 0; m_arena_start = 0; @@ -485,7 +526,7 @@ void xavix_state::machine_reset() std::fill(std::begin(m_txarray), std::end(m_txarray), 0x00); std::fill_n(&m_fragment_sprite[0], 0x800, 0x00); // taito nostalgia 1 never initializes the ram at 0x6400 but there's no condition on using it at present? - m_lowbus->set_bank(0); + //m_lowbus->set_bank(0); m_io0_data = 0x00; m_io1_data = 0x00; @@ -495,11 +536,11 @@ void xavix_state::machine_reset() } -typedef device_delegate xavix_interrupt_vector_delegate; +typedef device_delegate xavix_interrupt_vector_delegate; int16_t xavix_state::get_vectors(int which, int half) { -// logerror("get_vectors %d %d\n", which, half); + // LOG("get_vectors %d %d\n", which, half); if (m_vectorenable == 0) return -1; diff --git a/src/mame/video/xavix.cpp b/src/mame/video/xavix.cpp index f00f5ec701f..dd66a532eca 100644 --- a/src/mame/video/xavix.cpp +++ b/src/mame/video/xavix.cpp @@ -4,6 +4,9 @@ #include "emu.h" #include "includes/xavix.h" +// #define VERBOSE 1 +#include "logmacro.h" + inline void xavix_state::set_data_address(int address, int bit) { m_tmp_dataaddress = address; @@ -12,21 +15,14 @@ inline void xavix_state::set_data_address(int address, int bit) inline uint8_t xavix_state::get_next_bit() { - uint8_t bit; - - // if bank is > 0x80, or address is >0x8000 it's a plain ROM read - if ((m_tmp_dataaddress >= 0x80000) || (m_tmp_dataaddress & 0x8000)) - { - bit= m_rgn[m_tmp_dataaddress & (m_rgnlen - 1)]; - } - else // otherwise we read from RAM etc.? (baseball 2 secret test mode relies on this as it puts 1bpp characters in RAM) + // going through memory is slow, try not to do it too often! + if (m_tmp_databit == 0) { - address_space& mainspace = m_maincpu->space(AS_PROGRAM); - bit = m_lowbus->read8(mainspace, m_tmp_dataaddress & 0x7fff); + m_bit = m_maincpu->read_full_special(m_tmp_dataaddress); } - bit = bit >> m_tmp_databit; - bit &= 1; + uint8_t ret = m_bit >> m_tmp_databit; + ret &= 1; m_tmp_databit++; @@ -36,7 +32,7 @@ inline uint8_t xavix_state::get_next_bit() m_tmp_dataaddress++; } - return bit; + return ret; } inline uint8_t xavix_state::get_next_byte() @@ -71,44 +67,34 @@ double xavix_state::hue2rgb(double p, double q, double t) return p; } - -void xavix_state::handle_palette(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +void xavix_state::handle_palette(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, uint8_t* ramsh, uint8_t* raml, int size, int basecol) { // not verified int offs = 0; - for (int index = 0; index < 257; index++) + for (int index = 0; index < size; index++) { uint16_t dat; - - if (index < 256) - { - dat = m_palram_sh[offs]; - dat |= m_palram_l[offs] << 8; - } - else - { - dat = m_colmix_sh[0]; - dat |= m_colmix_l[0] << 8; - } - + dat = ramsh[offs]; + dat |= raml[offs] << 8; + offs++; int l_raw = (dat & 0x1f00) >> 8; - int sl_raw =(dat & 0x00e0) >> 5; + int s_raw = (dat & 0x00e0) >> 5; int h_raw = (dat & 0x001f) >> 0; //if (h_raw > 24) - // logerror("hraw >24 (%02x)\n", h_raw); + // LOG("hraw >24 (%02x)\n", h_raw); //if (l_raw > 17) - // logerror("lraw >17 (%02x)\n", l_raw); + // LOG("lraw >17 (%02x)\n", l_raw); - //if (sl_raw > 7) - // logerror("sl_raw >5 (%02x)\n", sl_raw); + //if (s_raw > 7) + // LOG("s_raw >5 (%02x)\n", s_raw); double l = (double)l_raw / 17.0f; - double s = (double)sl_raw / 7.0f; - double h = (double)h_raw / 24.0f; + double s = (double)s_raw / 7.0f; + double h = (double)h_raw / 24.0f; // hue values 24-31 render as transparent double r, g, b; @@ -127,12 +113,21 @@ void xavix_state::handle_palette(screen_device &screen, bitmap_ind16 &bitmap, co int g_real = g * 255.0f; int b_real = b * 255.0f; - m_palette->set_pen_color(index, r_real, g_real, b_real); + m_palette->set_pen_color(basecol+index, r_real, g_real, b_real); } } void xavix_state::draw_tilemap(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int which) +{ + for (int y = cliprect.min_y; y <= cliprect.max_y; y++) + { + draw_tilemap_line(screen, bitmap, cliprect, which, y); + } +} + + +void xavix_state::draw_tilemap_line(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int which, int line) { uint8_t* tileregs; if (which == 0) @@ -145,7 +140,7 @@ void xavix_state::draw_tilemap(screen_device &screen, bitmap_ind16 &bitmap, cons } // bail if tilemap is disabled - if (!(tileregs[0x7] & 0x80)) + if (!(tileregs[0x7] & 0x80)) return; int alt_tileaddressing = 0; @@ -155,6 +150,7 @@ void xavix_state::draw_tilemap(screen_device &screen, bitmap_ind16 &bitmap, cons int xdimension = 0; int ytilesize = 0; int xtilesize = 0; + int yshift = 0; switch (tileregs[0x3] & 0x30) { @@ -163,6 +159,7 @@ void xavix_state::draw_tilemap(screen_device &screen, bitmap_ind16 &bitmap, cons xdimension = 32; ytilesize = 8; xtilesize = 8; + yshift = 3; break; case 0x10: @@ -170,6 +167,7 @@ void xavix_state::draw_tilemap(screen_device &screen, bitmap_ind16 &bitmap, cons xdimension = 16; ytilesize = 8; xtilesize = 16; + yshift = 3; break; case 0x20: // guess @@ -177,6 +175,7 @@ void xavix_state::draw_tilemap(screen_device &screen, bitmap_ind16 &bitmap, cons xdimension = 32; ytilesize = 16; xtilesize = 8; + yshift = 4; break; case 0x30: @@ -184,6 +183,7 @@ void xavix_state::draw_tilemap(screen_device &screen, bitmap_ind16 &bitmap, cons xdimension = 16; ytilesize = 16; xtilesize = 16; + yshift = 4; break; } @@ -198,219 +198,211 @@ void xavix_state::draw_tilemap(screen_device &screen, bitmap_ind16 &bitmap, cons if ((tileregs[0x7] & 0x7f) == 0x04) alt_tileaddressing2 = 2; - /* - static int hackx = 1; + //LOG("draw tilemap %d, regs base0 %02x base1 %02x base2 %02x tilesize,bpp %02x scrollx %02x scrolly %02x pal %02x mode %02x\n", which, tileregs[0x0], tileregs[0x1], tileregs[0x2], tileregs[0x3], tileregs[0x4], tileregs[0x5], tileregs[0x6], tileregs[0x7]); - if (machine().input().code_pressed_once(KEYCODE_Q)) - { - hackx--; - logerror("%02x\n", hackx); - } + // there's a tilemap register to specify base in main ram, although in the monster truck test mode it points to an unmapped region + // and expected a fixed layout, we handle that in the memory map at the moment - if (machine().input().code_pressed_once(KEYCODE_W)) - { - hackx++; - logerror("%02x\n", hackx); - } - */ + int drawline = line; + int scrolly = tileregs[0x5]; - //logerror("draw tilemap %d, regs base0 %02x base1 %02x base2 %02x tilesize,bpp %02x scrollx %02x scrolly %02x pal %02x mode %02x\n", which, tileregs[0x0], tileregs[0x1], tileregs[0x2], tileregs[0x3], tileregs[0x4], tileregs[0x5], tileregs[0x6], tileregs[0x7]); + drawline += scrolly; - // there's a tilemap register to specify base in main ram, although in the monster truck test mode it points to an unmapped region - // and expected a fixed layout, we handle that in the memory map at the moment - int count = 0; - for (int y = 0; y < ydimension; y++) + drawline &= ((ydimension * ytilesize) - 1); + + int y = drawline >> yshift; + int yyline = drawline & (ytilesize - 1); + + for (int x = 0; x < xdimension; x++) { - for (int x = 0; x < xdimension; x++) + int count = (y * xdimension) + x; + + int tile = 0; + + // the register being 0 probably isn't the condition here + if (tileregs[0x0] != 0x00) tile |= m_maincpu->read_full_special((tileregs[0x0] << 8) + count); + + // only read the next byte if we're not in an 8-bit mode + if (((tileregs[0x7] & 0x7f) != 0x00) && ((tileregs[0x7] & 0x7f) != 0x08)) + tile |= m_maincpu->read_full_special((tileregs[0x1] << 8) + count) << 8; + + // 24 bit modes can use reg 0x2, otherwise it gets used as extra attribute in other modes + if (alt_tileaddressing2 == 2) + tile |= m_maincpu->read_full_special((tileregs[0x2] << 8) + count) << 16; + + + int bpp = (tileregs[0x3] & 0x0e) >> 1; + bpp++; + int pal = (tileregs[0x6] & 0xf0) >> 4; + int zval = (tileregs[0x6] & 0x0f) >> 0; + int scrollx = tileregs[0x4]; + + int basereg; + int flipx = 0; + int flipy = 0; + int gfxbase; + + // tile 0 is always skipped, doesn't even point to valid data packets in alt mode + // this is consistent with the top layer too + // should we draw as solid in solid layer? + if (tile == 0) { - address_space& mainspace = m_maincpu->space(AS_PROGRAM); - - int tile = 0; - - // the register being 0 probably isn't the condition here - if (tileregs[0x0] != 0x00) tile |= mainspace.read_byte((tileregs[0x0] << 8) + count); - - // only read the next byte if we're not in an 8-bit mode - if (((tileregs[0x7] & 0x7f) != 0x00) && ((tileregs[0x7] & 0x7f) != 0x08)) - tile |= mainspace.read_byte((tileregs[0x1] << 8) + count) << 8; - - // 24 bit modes can use reg 0x2, otherwise it gets used as extra attribute in other modes - if (alt_tileaddressing2 == 2) - tile |= mainspace.read_byte((tileregs[0x2] << 8) + count) << 16; - - - int bpp = (tileregs[0x3] & 0x0e) >> 1; - bpp++; - int pal = (tileregs[0x6] & 0xf0) >> 4; - int zval = (tileregs[0x6] & 0x0f) >> 0; - int scrolly = tileregs[0x5]; - int scrollx = tileregs[0x4]; - - int basereg; - int flipx = 0; - int flipy = 0; - int gfxbase; - - // tile 0 is always skipped, doesn't even point to valid data packets in alt mode - // this is consistent with the top layer too - // should we draw as solid in solid layer? - if (tile == 0) - { - count++; - continue; - } + continue; + } - const int debug_packets = 0; - int test = 0; + const int debug_packets = 0; + int test = 0; - if (!alt_tileaddressing) + if (!alt_tileaddressing) + { + if (alt_tileaddressing2 == 0) { - if (alt_tileaddressing2 == 0) - { - // Tile Based Addressing takes into account Tile Sizes and bpp - const int offset_multiplier = (ytilesize * xtilesize)/8; - - basereg = 0; - gfxbase = (m_segment_regs[(basereg * 2) + 1] << 16) | (m_segment_regs[(basereg * 2)] << 8); - - tile = tile * (offset_multiplier * bpp); - tile += gfxbase; - } - else if (alt_tileaddressing2 == 1) - { - // 8-byte alignment Addressing Mode uses a fixed offset? (like sprites) - tile = tile * 8; - basereg = (tile & 0x70000) >> 16; - tile &= 0xffff; - gfxbase = (m_segment_regs[(basereg * 2) + 1] << 16) | (m_segment_regs[(basereg * 2)] << 8); - tile += gfxbase; - } - else if (alt_tileaddressing2 == 2) - { - // 24-bit addressing - tile |= 0x800000; - } + // Tile Based Addressing takes into account Tile Sizes and bpp + const int offset_multiplier = (ytilesize * xtilesize) / 8; - // Tilemap specific mode extension with an 8-bit per tile attribute, works in all modes except 24-bit (no room for attribute) and header (not needed?) - if (tileregs[0x7] & 0x08) - { - uint8_t extraattr = mainspace.read_byte((tileregs[0x2] << 8) + count); - // make use of the extraattr stuff? - pal = (extraattr & 0xf0)>>4; - zval = (extraattr & 0x0f) >> 0; - } + basereg = 0; + gfxbase = (m_segment_regs[(basereg * 2) + 1] << 16) | (m_segment_regs[(basereg * 2)] << 8); + + tile = tile * (offset_multiplier * bpp); + tile += gfxbase; } - else + else if (alt_tileaddressing2 == 1) + { + // 8-byte alignment Addressing Mode uses a fixed offset? (like sprites) + tile = tile * 8; + basereg = (tile & 0x70000) >> 16; + tile &= 0xffff; + gfxbase = (m_segment_regs[(basereg * 2) + 1] << 16) | (m_segment_regs[(basereg * 2)] << 8); + tile += gfxbase; + } + else if (alt_tileaddressing2 == 2) { - // Addressing Mode 2 (plus Inline Header) + // 24-bit addressing (check if this is still needed) + //tile |= 0x800000; + } - if (debug_packets) logerror("for tile %04x (at %d %d): ", tile, (((x * 16) + scrollx) & 0xff), (((y * 16) + scrolly) & 0xff)); + // Tilemap specific mode extension with an 8-bit per tile attribute, works in all modes except 24-bit (no room for attribute) and header (not needed?) + if (tileregs[0x7] & 0x08) + { + uint8_t extraattr = m_maincpu->read_full_special((tileregs[0x2] << 8) + count); + // make use of the extraattr stuff? + pal = (extraattr & 0xf0) >> 4; + zval = (extraattr & 0x0f) >> 0; + } + } + else + { + // Addressing Mode 2 (plus Inline Header) + if (debug_packets) LOG("for tile %04x (at %d %d): ", tile, (((x * 16) + scrollx) & 0xff), (((y * 16) + scrolly) & 0xff)); - basereg = (tile & 0xf000) >> 12; - tile &= 0x0fff; - gfxbase = (m_segment_regs[(basereg * 2) + 1] << 16) | (m_segment_regs[(basereg * 2)] << 8); - tile += gfxbase; - set_data_address(tile, 0); + basereg = (tile & 0xf000) >> 12; + tile &= 0x0fff; + gfxbase = (m_segment_regs[(basereg * 2) + 1] << 16) | (m_segment_regs[(basereg * 2)] << 8); - // there seems to be a packet stored before the tile?! - // the offset used for flipped sprites seems to specifically be changed so that it picks up an extra byte which presumably triggers the flipping - uint8_t byte1 = 0; - int done = 0; - int skip = 0; + tile += gfxbase; + set_data_address(tile, 0); - do - { - byte1 = get_next_byte(); + // there seems to be a packet stored before the tile?! + // the offset used for flipped sprites seems to specifically be changed so that it picks up an extra byte which presumably triggers the flipping + uint8_t byte1 = 0; + int done = 0; + int skip = 0; - if (debug_packets) logerror(" %02x, ", byte1); + do + { + byte1 = get_next_byte(); - if (skip == 1) - { - skip = 0; - //test = 1; - } - else if ((byte1 & 0x0f) == 0x01) - { - // used - } - else if ((byte1 & 0x0f) == 0x03) - { - // causes next byte to be skipped?? - skip = 1; - } - else if ((byte1 & 0x0f) == 0x05) - { - // the upper bits are often 0x00, 0x10, 0x20, 0x30, why? - flipx = 1; - } - else if ((byte1 & 0x0f) == 0x06) // there must be other finish conditions too because sometimes this fails.. - { - // tile data will follow after this, always? - pal = (byte1 & 0xf0) >> 4; - done = 1; - } - else if ((byte1 & 0x0f) == 0x07) - { - // causes next byte to be skipped?? - skip = 1; - } - else if ((byte1 & 0x0f) == 0x09) - { - // used - } - else if ((byte1 & 0x0f) == 0x0a) - { - // not seen - } - else if ((byte1 & 0x0f) == 0x0b) - { - // used - } - else if ((byte1 & 0x0f) == 0x0c) - { - // not seen - } - else if ((byte1 & 0x0f) == 0x0d) - { - // used - } - else if ((byte1 & 0x0f) == 0x0e) - { - // not seen - } - else if ((byte1 & 0x0f) == 0x0f) - { - // used - } + if (debug_packets) LOG(" %02x, ", byte1); - } while (done == 0); - if (debug_packets) logerror("\n"); - tile = get_current_address_byte(); - } + if (skip == 1) + { + skip = 0; + //test = 1; + } + else if ((byte1 & 0x0f) == 0x01) + { + // used + } + else if ((byte1 & 0x0f) == 0x03) + { + // causes next byte to be skipped?? + skip = 1; + } + else if ((byte1 & 0x0f) == 0x05) + { + // the upper bits are often 0x00, 0x10, 0x20, 0x30, why? + flipx = 1; + } + else if ((byte1 & 0x0f) == 0x06) // there must be other finish conditions too because sometimes this fails.. + { + // tile data will follow after this, always? + pal = (byte1 & 0xf0) >> 4; + done = 1; + } + else if ((byte1 & 0x0f) == 0x07) + { + // causes next byte to be skipped?? + skip = 1; + } + else if ((byte1 & 0x0f) == 0x09) + { + // used + } + else if ((byte1 & 0x0f) == 0x0a) + { + // not seen + } + else if ((byte1 & 0x0f) == 0x0b) + { + // used + } + else if ((byte1 & 0x0f) == 0x0c) + { + // not seen + } + else if ((byte1 & 0x0f) == 0x0d) + { + // used + } + else if ((byte1 & 0x0f) == 0x0e) + { + // not seen + } + else if ((byte1 & 0x0f) == 0x0f) + { + // used + } - if (test == 1) pal = machine().rand() & 0xf; + } while (done == 0); + if (debug_packets) LOG("\n"); + tile = get_current_address_byte(); + } + if (test == 1) pal = machine().rand() & 0xf; - draw_tile(screen, bitmap, cliprect, tile, bpp, (x * xtilesize) + scrollx, ((y * ytilesize) - 16) - scrolly, ytilesize, xtilesize, flipx, flipy, pal, zval); - draw_tile(screen, bitmap, cliprect, tile, bpp, (x * xtilesize) + scrollx, (((y * ytilesize) - 16) - scrolly) + 256, ytilesize, xtilesize, flipx, flipy, pal, zval); // wrap-y - draw_tile(screen, bitmap, cliprect, tile, bpp, ((x * xtilesize) + scrollx) - 256, ((y * ytilesize) - 16) - scrolly, ytilesize, xtilesize, flipx, flipy, pal, zval); // wrap-x - draw_tile(screen, bitmap, cliprect, tile, bpp, ((x * xtilesize) + scrollx) - 256, (((y * ytilesize) - 16) - scrolly) + 256, ytilesize, xtilesize, flipx, flipy, pal, zval); // wrap-y and x - - count++; - } + draw_tile_line(screen, bitmap, cliprect, tile, bpp, (x * xtilesize) + scrollx, line, ytilesize, xtilesize, flipx, flipy, pal, zval, yyline); + draw_tile_line(screen, bitmap, cliprect, tile, bpp, ((x * xtilesize) + scrollx) - 256, line, ytilesize, xtilesize, flipx, flipy, pal, zval, yyline); // wrap-x } - } void xavix_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + for (int y = cliprect.min_y; y <= cliprect.max_y; y++) + { + draw_sprites_line(screen, bitmap, cliprect, y); + } +} + +void xavix_state::draw_sprites_line(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int line) { int alt_addressing = 0; - if (m_spritereg == 0x00) + if ((m_spritereg == 0x00) || (m_spritereg == 0x01)) { // 8-bit addressing (Tile Number) + // 16-bit addressing (Tile Number) (rad_rh) alt_addressing = 1; } else if (m_spritereg == 0x02) @@ -428,7 +420,8 @@ void xavix_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, cons popmessage("unknown sprite reg %02x", m_spritereg); } - //logerror("frame\n"); + + //LOG("frame\n"); // priority doesn't seem to be based on list order, there are bad sprite-sprite priorities with either forward or reverse for (int i = 0xff; i >= 0; i--) @@ -454,23 +447,23 @@ void xavix_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, cons int ypos = spr_ypos[i]; int xpos = spr_xpos[i]; int tile = 0; - + // high 8-bits only used in 24-bit mode if (((m_spritereg & 0x7f) == 0x04) || ((m_spritereg & 0x7f) == 0x15)) tile |= (spr_addr_hi[i] << 16); - + // mid 8-bits used in everything except 8-bit mode if ((m_spritereg & 0x7f) != 0x00) tile |= (spr_addr_md[i] << 8); - + // low 8-bits always read tile |= spr_addr_lo[i]; - + int attr0 = spr_attr0[i]; int attr1 = spr_attr1[i]; int pal = (attr0 & 0xf0) >> 4; - + int zval = (attr1 & 0xf0) >> 4; int flipx = (attr1 & 0x01); int flipy = (attr1 & 0x02); @@ -479,9 +472,7 @@ void xavix_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, cons int drawwidth = 16; int xpos_adjust = 0; - int ypos_adjust = 0; - - tile &= (m_rgnlen - 1); + int ypos_adjust = -16; // taito nost attr1 is 84 / 80 / 88 / 8c for the various elements of the xavix logo. monster truck uses ec / fc / dc / 4c / 5c / 6c (final 6 sprites ingame are 00 00 f0 f0 f0 f0, radar?) @@ -494,135 +485,149 @@ void xavix_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, cons { drawheight = 16; drawwidth = 8; - xpos_adjust = 4; + xpos_adjust += 4; } else if ((attr1 & 0x0c) == 0x04) { drawheight = 8; drawwidth = 16; - ypos_adjust = -4; + ypos_adjust -= 4; } else if ((attr1 & 0x0c) == 0x00) { drawheight = 8; drawwidth = 8; - xpos_adjust = 4; - ypos_adjust = -4; + xpos_adjust += 4; + ypos_adjust -= 4; } - // Everything except direct addressing (Addressing Mode 2) goes through the segment registers? - if (alt_addressing != 0) - { - // tile based addressing takes into account tile size (and bpp?) - if (alt_addressing == 1) - tile = (tile * drawheight * drawwidth) / 2; - - // 8-byte alignment Addressing Mode uses a fixed offset? - if (alt_addressing == 2) - tile = tile * 8; + ypos ^= 0xff; - int basereg = (tile & 0xf0000) >> 16; - tile &= 0xffff; - int gfxbase = (m_segment_regs[(basereg * 2) + 1] << 16) | (m_segment_regs[(basereg * 2)] << 8); - tile += gfxbase; + if (ypos & 0x80) + { + ypos = -0x80 + (ypos & 0x7f); } else { - // ?? in 24-bit mode the upper bit isn't being set, which causes some things to be drawn from RAM instead - // which is not what we want at all. are the segment registers still involved even in this mode? - tile |= 0x800000; + ypos &= 0x7f; } - /* coordinates are signed, based on screen position 0,0 being at the center of the screen - tile addressing likewise, point 0,0 is center of tile? - this makes the calculation a bit more annoying in terms of knowing when to apply offsets, when to wrap etc. - this is likely still incorrect - - Use of additional x-bit is very confusing rad_snow, taitons1 (ingame) etc. clearly need to use it - but the taitons1 xavix logo doesn't even initialize the RAM for it and behavior conflicts with ingame? - maybe only works with certain tile sizes? + ypos += 128 - 15 - 8; - some code even suggests this should be bit 0 of attr0, but it never gets set there + ypos -= ypos_adjust; - there must be a register somewhere (or a side-effect of another mode) that enables / disables this - behavior, as we need to make use of xposh for the left side in cases that need it, but that - completely breaks the games that never set it at all (monster truck, xavix logo on taitons1) + int spritelowy = ypos; + int spritehighy = ypos + drawheight; - */ + if ((line >= spritelowy) && (line < spritehighy)) + { + int drawline = line - spritelowy; - int xposh = spr_xposh[i]&1; - if (xpos & 0x80) // left side of center - { - xpos &=0x7f; - xpos = -0x80+xpos; - } - else // right side of center - { - xpos &= 0x7f; + /* coordinates are signed, based on screen position 0,0 being at the center of the screen + tile addressing likewise, point 0,0 is center of tile? + this makes the calculation a bit more annoying in terms of knowing when to apply offsets, when to wrap etc. + this is likely still incorrect - if (xposh) - xpos += 0x80; - } + Use of additional x-bit is very confusing rad_snow, taitons1 (ingame) etc. clearly need to use it + but the taitons1 xavix logo doesn't even initialize the RAM for it and behavior conflicts with ingame? + maybe only works with certain tile sizes? - xpos += 128 - 8; + some code even suggests this should be bit 0 of attr0, but it never gets set there - ypos ^= 0xff; + there must be a register somewhere (or a side-effect of another mode) that enables / disables this + behavior, as we need to make use of xposh for the left side in cases that need it, but that + completely breaks the games that never set it at all (monster truck, xavix logo on taitons1) - if (ypos & 0x80) - { - ypos = -0x80+(ypos&0x7f); - } - else - { - ypos &= 0x7f; - } + */ - ypos += 128 - 15 - 8; + int xposh = spr_xposh[i] & 1; + + if (xpos & 0x80) // left side of center + { + xpos &= 0x7f; + xpos = -0x80 + xpos; + } + else // right side of center + { + xpos &= 0x7f; + if (xposh) + xpos += 0x80; + } - int bpp = 1; + xpos += 128 - 8; - bpp = (attr0 & 0x0e) >> 1; - bpp += 1; - draw_tile(screen, bitmap, cliprect, tile, bpp, xpos + xpos_adjust, ypos - ypos_adjust, drawheight, drawwidth, flipx, flipy, pal, zval); - draw_tile(screen, bitmap, cliprect, tile, bpp, xpos + xpos_adjust, ypos - 256 - ypos_adjust, drawheight, drawwidth, flipx, flipy, pal, zval); // wrap-y - /* - if ((spr_ypos[i] != 0x81) && (spr_ypos[i] != 0x80) && (spr_ypos[i] != 0x00)) - { - logerror("sprite with enable? %02x attr0 %02x attr1 %02x attr3 %02x attr5 %02x attr6 %02x attr7 %02x\n", spr_ypos[i], spr_attr0[i], spr_attr1[i], spr_xpos[i], spr_addr_lo[i], spr_addr_md[i], spr_addr_hi[i] ); + + // Everything except directdirect addressing (Addressing Mode 2) goes through the segment registers? + if (alt_addressing != 0) + { + // tile based addressing takes into account tile size (and bpp?) + if (alt_addressing == 1) + tile = (tile * drawheight * drawwidth) / 2; + + // 8-byte alignment Addressing Mode uses a fixed offset? + if (alt_addressing == 2) + tile = tile * 8; + + int basereg = (tile & 0xf0000) >> 16; + tile &= 0xffff; + int gfxbase = (m_segment_regs[(basereg * 2) + 1] << 16) | (m_segment_regs[(basereg * 2)] << 8); + tile += gfxbase; + } + + + + + int bpp = 1; + + bpp = (attr0 & 0x0e) >> 1; + bpp += 1; + + draw_tile_line(screen, bitmap, cliprect, tile, bpp, xpos, line, drawheight, drawwidth, flipx, flipy, pal, zval, drawline); + + /* + if ((spr_ypos[i] != 0x81) && (spr_ypos[i] != 0x80) && (spr_ypos[i] != 0x00)) + { + LOG("sprite with enable? %02x attr0 %02x attr1 %02x attr3 %02x attr5 %02x attr6 %02x attr7 %02x\n", spr_ypos[i], spr_attr0[i], spr_attr1[i], spr_xpos[i], spr_addr_lo[i], spr_addr_md[i], spr_addr_hi[i] ); + } + */ } - */ } } -void xavix_state::draw_tile(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int tile, int bpp, int xpos, int ypos, int drawheight, int drawwidth, int flipx, int flipy, int pal, int zval) +void xavix_state::draw_tile_line(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int tile, int bpp, int xpos, int ypos, int drawheight, int drawwidth, int flipx, int flipy, int pal, int zval, int line) { - // set the address here so we can increment in bits in the draw function - set_data_address(tile, 0); + //const pen_t *paldata = m_palette->pens(); + + if (flipy) + line = drawheight - line; + + if (ypos > cliprect.max_y || ypos < cliprect.min_y) + return; - for (int y = 0; y < drawheight; y++) + if ((xpos > cliprect.max_x) || ((xpos + drawwidth) < cliprect.min_x)) + return; + + + if ((ypos >= cliprect.min_y && ypos <= cliprect.max_y)) { - int row; - if (flipy) - { - row = ypos + (drawheight-1) - y; - } - else - { - row = ypos + y; - } + int bits_per_tileline = drawwidth * bpp; + + // set the address here so we can increment in bits in the draw function + set_data_address(tile, 0); + m_tmp_dataaddress = m_tmp_dataaddress + ((line * bits_per_tileline) / 8); + m_tmp_databit = (line * bits_per_tileline) % 8; for (int x = 0; x < drawwidth; x++) { - int col; if (flipx) { - col = xpos + (drawwidth-1) - x; + col = xpos + (drawwidth - 1) - x; } else { @@ -636,22 +641,25 @@ void xavix_state::draw_tile(screen_device &screen, bitmap_ind16 &bitmap, const r dat |= (get_next_bit() << i); } - if ((row >= cliprect.min_y && row <= cliprect.max_y) && (col >= cliprect.min_x && col <= cliprect.max_x)) + if ((col >= cliprect.min_x && col <= cliprect.max_x)) { - uint16_t* rowptr = &bitmap.pix16(row); - uint16_t* zrowptr = &m_zbuffer.pix16(row); - + uint16_t* zyposptr = &m_zbuffer.pix16(ypos); - if (zval >= zrowptr[col]) + if (zval >= zyposptr[col]) { int pen = (dat + (pal << 4)) & 0xff; if ((m_palram_sh[pen] & 0x1f) < 24) // hue values 24-31 are transparent { - rowptr[col] = pen; - zrowptr[col] = zval; + uint16_t* yposptr = &bitmap.pix16(ypos); + yposptr[col] = pen; + + //uint32_t* yposptr = &bitmap.pix32(ypos); + //yposptr[col] = paldata[pen]; + + zyposptr[col] = zval; } - } + } } } } @@ -659,11 +667,24 @@ void xavix_state::draw_tile(screen_device &screen, bitmap_ind16 &bitmap, const r uint32_t xavix_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { - handle_palette(screen, bitmap, cliprect); + handle_palette(screen, bitmap, cliprect, m_palram_sh, m_palram_l, 256, 0); + + if (m_bmp_palram_sh) + { + handle_palette(screen, bitmap, cliprect, m_bmp_palram_sh, m_bmp_palram_l, 256, 256); + handle_palette(screen, bitmap, cliprect, m_colmix_sh, m_colmix_l, 1, 512); + } + else + { + handle_palette(screen, bitmap, cliprect, m_colmix_sh, m_colmix_l, 1, 256); + } // not sure what you end up with if you fall through all layers as transparent, so far no issues noticed bitmap.fill(m_palette->black_pen(), cliprect); - m_zbuffer.fill(0,cliprect); + m_zbuffer.fill(0, cliprect); + + + rectangle clip = cliprect; @@ -685,8 +706,8 @@ uint32_t xavix_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, */ if (((m_arena_start != 0x00) && (m_arena_end != 0x00)) && ((m_arena_start != 0xff) && (m_arena_end != 0xff))) { - clip.max_x = m_arena_start - 3; - clip.min_x = m_arena_end - 1; + clip.max_x = m_arena_start - 3; // must be -3 to hide garbage on the right hand side of snowboarder + clip.min_x = m_arena_end - 2; // must be -2 to render a single pixel line of the left border on Mappy remix (verified to render), although this creates a single pixel gap on the left of snowboarder status bar (need to verify) if (clip.min_x < cliprect.min_x) clip.min_x = cliprect.min_x; @@ -697,12 +718,49 @@ uint32_t xavix_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, } bitmap.fill(0, clip); - draw_tilemap(screen,bitmap,clip,1); - draw_tilemap(screen,bitmap,clip,0); - draw_sprites(screen,bitmap,clip); + draw_tilemap(screen, bitmap, clip, 1); + draw_tilemap(screen, bitmap, clip, 0); + draw_sprites(screen, bitmap, clip); //popmessage("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", m_soundregs[0],m_soundregs[1],m_soundregs[2],m_soundregs[3],m_soundregs[4],m_soundregs[5],m_soundregs[6],m_soundregs[7],m_soundregs[8],m_soundregs[9],m_soundregs[10],m_soundregs[11],m_soundregs[12],m_soundregs[13],m_soundregs[14],m_soundregs[15]); + // temp, needs priority, transparency etc. also it's far bigger than the screen, I guess it must get scaled?! + if (m_bmp_base) + { + if (m_bmp_base[0x14] & 0x01) + { + popmessage("bitmap %02x %02x %02x %02x %02x %02x %02x %02x -- -- %02x %02x %02x %02x %02x %02x -- -- %02x %02x %02x %02x %02x %02x", + m_bmp_base[0x00], m_bmp_base[0x01], m_bmp_base[0x02], m_bmp_base[0x03], m_bmp_base[0x04], m_bmp_base[0x05], m_bmp_base[0x06], m_bmp_base[0x07], + /*m_bmp_base[0x08], m_bmp_base[0x09],*/ m_bmp_base[0x0a], m_bmp_base[0x0b], m_bmp_base[0x0c], m_bmp_base[0x0d], m_bmp_base[0x0e], m_bmp_base[0x0f], + /*m_bmp_base[0x10], m_bmp_base[0x11],*/ m_bmp_base[0x12], m_bmp_base[0x13], m_bmp_base[0x14], m_bmp_base[0x15], m_bmp_base[0x16], m_bmp_base[0x17]); + + int base = ((m_bmp_base[0x11] << 8) | m_bmp_base[0x10]) * 0x800; + int base2 = ((m_bmp_base[0x09] << 8) | m_bmp_base[0x08]) * 0x8; + + //int count = 0; + set_data_address(base + base2, 0); + + for (int y = 0; y < 256; y++) + { + for (int x = 0; x < 512; x++) + { + uint16_t* yposptr = &bitmap.pix16(y); + + int bpp = 6; + + uint8_t dat = 0; + for (int i = 0; i < bpp; i++) + { + dat |= (get_next_bit() << i); + } + + yposptr[x] = dat + 0x100; + } + } + + } + } + return 0; } @@ -720,12 +778,12 @@ WRITE8_MEMBER(xavix_state::spritefragment_dma_params_2_w) WRITE8_MEMBER(xavix_state::spritefragment_dma_trg_w) { uint16_t len = data & 0x07; - uint16_t src = (m_spritefragment_dmaparam1[1]<<8) | m_spritefragment_dmaparam1[0]; - uint16_t dst = (m_spritefragment_dmaparam2[0]<<8); + uint16_t src = (m_spritefragment_dmaparam1[1] << 8) | m_spritefragment_dmaparam1[0]; + uint16_t dst = (m_spritefragment_dmaparam2[0] << 8); uint8_t unk = m_spritefragment_dmaparam2[1]; - logerror("%s: spritefragment_dma_trg_w with trg %02x size %04x src %04x dest %04x unk (%02x)\n", machine().describe_context(), data & 0xf8, len,src,dst,unk); + LOG("%s: spritefragment_dma_trg_w with trg %02x size %04x src %04x dest %04x unk (%02x)\n", machine().describe_context(), data & 0xf8, len, src, dst, unk); if (unk) { @@ -735,7 +793,7 @@ WRITE8_MEMBER(xavix_state::spritefragment_dma_trg_w) if (len == 0x00) { len = 0x08; - logerror(" (length was 0x0, assuming 0x8)\n"); + LOG(" (length was 0x0, assuming 0x8)\n"); } len = len << 8; @@ -744,7 +802,7 @@ WRITE8_MEMBER(xavix_state::spritefragment_dma_trg_w) { for (int i = 0; i < len; i++) { - uint8_t dat = m_maincpu->space(AS_PROGRAM).read_byte(src + i); + uint8_t dat = m_maincpu->read_full_special(src + i); m_fragment_sprite[(dst + i) & 0x7ff] = dat; } } @@ -773,7 +831,7 @@ WRITE8_MEMBER(xavix_state::tmap1_regs_w) 0x2 pointer to upper tile bits 0x3 Fftt bbb- Ff = flip Y,X - tt = tile/tilemap size + tt = tile/tilemap size b = bpp - = unused @@ -781,16 +839,16 @@ WRITE8_MEMBER(xavix_state::tmap1_regs_w) 0x5 scroll 0x6 pppp zzzz p = palette - z = priority + z = priority 0x7 e--m mmmm e = enable - m = mode + m = mode modes are ---0 0000 (00) 8-bit addressing (Tile Number) ---0 0001 (01) 16-bit addressing (Tile Number) (monster truck, ekara) ---0 0010 (02) 16-bit addressing (8-byte alignment Addressing Mode) (boxing) - ---0 0011 (03) 16-bit addressing (Addressing Mode 2) + ---0 0011 (03) 16-bit addressing (Addressing Mode 2) ---0 0100 (04) 24-bit addressing (Addressing Mode 2) (epo_efdx) ---0 1000 (08) 8-bit+8 addressing (Tile Number + 8-bit Attribute) @@ -805,7 +863,7 @@ WRITE8_MEMBER(xavix_state::tmap1_regs_w) if ((offset != 0x4) && (offset != 0x5)) { - logerror("%s: tmap1_regs_w offset %02x data %02x\n", machine().describe_context(), offset, data); + LOG("%s: tmap1_regs_w offset %02x data %02x\n", machine().describe_context(), offset, data); } COMBINE_DATA(&m_tmap1_regs[offset]); @@ -816,7 +874,7 @@ WRITE8_MEMBER(xavix_state::tmap2_regs_w) // same as above but for 2nd tilemap if ((offset != 0x4) && (offset != 0x5)) { - logerror("%s: tmap2_regs_w offset %02x data %02x\n", machine().describe_context(), offset, data); + LOG("%s: tmap2_regs_w offset %02x data %02x\n", machine().describe_context(), offset, data); } COMBINE_DATA(&m_tmap2_regs[offset]); @@ -825,7 +883,7 @@ WRITE8_MEMBER(xavix_state::tmap2_regs_w) WRITE8_MEMBER(xavix_state::spriteregs_w) { - logerror("%s: spriteregs_w data %02x\n", machine().describe_context(), data); + LOG("%s: spriteregs_w data %02x\n", machine().describe_context(), data); /* This is similar to Tilemap reg 7 and is used to set the addressing mode for sprite data @@ -843,13 +901,13 @@ WRITE8_MEMBER(xavix_state::spriteregs_w) READ8_MEMBER(xavix_state::tmap1_regs_r) { - logerror("%s: tmap1_regs_r offset %02x\n", offset, machine().describe_context()); + LOG("%s: tmap1_regs_r offset %02x\n", offset, machine().describe_context()); return m_tmap1_regs[offset]; } READ8_MEMBER(xavix_state::tmap2_regs_r) { - logerror("%s: tmap2_regs_r offset %02x\n", offset, machine().describe_context()); + LOG("%s: tmap2_regs_r offset %02x\n", offset, machine().describe_context()); return m_tmap2_regs[offset]; } @@ -871,7 +929,7 @@ WRITE8_MEMBER(xavix_state::xavix_memoryemu_txarray_w) else if (offset < 0x1000) { m_txarray[2] = data; - } + } } READ8_MEMBER(xavix_state::xavix_memoryemu_txarray_r) @@ -879,22 +937,22 @@ READ8_MEMBER(xavix_state::xavix_memoryemu_txarray_r) if (offset < 0x100) { offset &= 0xff; - return ((offset>>4) | (offset<<4)); + return ((offset >> 4) | (offset << 4)); } else if (offset < 0x200) { offset &= 0xff; - return ((offset>>4) | (~offset<<4)); + return ((offset >> 4) | (~offset << 4)); } else if (offset < 0x300) { offset &= 0xff; - return ((~offset>>4) | (offset<<4)); + return ((~offset >> 4) | (offset << 4)); } else if (offset < 0x400) { offset &= 0xff; - return ((~offset>>4) | (~offset<<4)); + return ((~offset >> 4) | (~offset << 4)); } else if (offset < 0x800) { @@ -911,4 +969,3 @@ READ8_MEMBER(xavix_state::xavix_memoryemu_txarray_r) return 0xff; } - -- cgit v1.2.3