From 5ad522f0c1c39d9982400adbd1440e8ccd07055d Mon Sep 17 00:00:00 2001 From: Angelo Salese Date: Fri, 15 May 2020 22:16:46 +0200 Subject: [PATCH] jaguar.cpp updates [Angelo Salese] * move i/o handlers to specific maps, untangle register array usage, to be completed * Nuke duplicate I/O accesses, rename to iobus_r/w, make go_w to be an actual line * Fix addqmod & subqmod modulo mask for DSP * Refactor TOM to host CPU function, and fix GPU irq lv 3 when a GPU object is encountered. Fixes mutntpng and atarikrt booting * Fix Jaguar irq line to 2, trusted * Start reworking the blitter * Relicensed to BSD --- hash/jaguar.xml | 11 +- scripts/target/mame/arcade.lua | 2 + src/devices/cpu/jaguar/jaguar.cpp | 607 ++++++++++++++++-------------- src/devices/cpu/jaguar/jaguar.h | 127 ++++--- src/mame/audio/jaguar.cpp | 2 +- src/mame/drivers/jaguar.cpp | 56 +-- src/mame/includes/jaguar.h | 8 +- src/mame/video/jag_blitter.cpp | 240 ++++++++++++ src/mame/video/jag_blitter.h | 100 +++++ src/mame/video/jagobj.hxx | 16 +- src/mame/video/jaguar.cpp | 69 ++-- 11 files changed, 846 insertions(+), 392 deletions(-) create mode 100644 src/mame/video/jag_blitter.cpp create mode 100644 src/mame/video/jag_blitter.h diff --git a/hash/jaguar.xml b/hash/jaguar.xml index da65900767f..6d5a11e2b06 100644 --- a/hash/jaguar.xml +++ b/hash/jaguar.xml @@ -168,7 +168,7 @@ Unreleased (possibly no prototypes exist): - + Atari Karts 1995 @@ -181,8 +181,8 @@ Unreleased (possibly no prototypes exist): - - + + Attack of the Mutant Penguins 1996 Atari @@ -592,7 +592,8 @@ Unreleased (possibly no prototypes exist): - + + NBA Jam T.E. - Tournament Edition 1996 @@ -966,7 +967,7 @@ Unreleased (possibly no prototypes exist): - + Troy Aikman NFL Football 1995 Williams Entertainment diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index fd0a950e205..6051f733403 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -1219,6 +1219,8 @@ files { MAME_DIR .. "src/mame/drivers/jaguar.cpp", MAME_DIR .. "src/mame/includes/jaguar.h", MAME_DIR .. "src/mame/audio/jaguar.cpp", + MAME_DIR .. "src/mame/video/jag_blitter.cpp", + MAME_DIR .. "src/mame/video/jag_blitter.h", MAME_DIR .. "src/mame/video/jaguar.cpp", MAME_DIR .. "src/mame/video/jagblit.h", MAME_DIR .. "src/mame/video/jagblit.hxx", diff --git a/src/devices/cpu/jaguar/jaguar.cpp b/src/devices/cpu/jaguar/jaguar.cpp index de7421181f9..eebf2a0fc2a 100644 --- a/src/devices/cpu/jaguar/jaguar.cpp +++ b/src/devices/cpu/jaguar/jaguar.cpp @@ -10,7 +10,9 @@ - Implement pipeline, actually instruction cycles; Currently implementation is similar to single stepping with single cycle - - Implement and acknowlodge remain registers + - Implement and acknowlodge remain registers; + - Improve delay slot display in debugger (highlight current instruction + doesn't work but instruction hook does); ***************************************************************************/ @@ -53,13 +55,13 @@ enum : u32 CINT5FLAG = 0x20000 // DSP only }; -inline void jaguar_cpu_device::CLR_Z() { m_ctrl[G_FLAGS] &= ~ZFLAG; } -inline void jaguar_cpu_device::CLR_ZN() { m_ctrl[G_FLAGS] &= ~(ZFLAG | NFLAG); } -inline void jaguar_cpu_device::CLR_ZNC() { m_ctrl[G_FLAGS] &= ~(CFLAG | ZFLAG | NFLAG); } -inline void jaguar_cpu_device::SET_Z(u32 r) { m_ctrl[G_FLAGS] |= (r == 0); } -inline void jaguar_cpu_device::SET_C_ADD(u32 a, u32 b) { m_ctrl[G_FLAGS] |= (b > (~a)) << 1; } -inline void jaguar_cpu_device::SET_C_SUB(u32 a, u32 b) { m_ctrl[G_FLAGS] |= (b > a) << 1; } -inline void jaguar_cpu_device::SET_N(u32 r) { m_ctrl[G_FLAGS] |= ((r >> 29) & 4); } +inline void jaguar_cpu_device::CLR_Z() { m_flags &= ~ZFLAG; } +inline void jaguar_cpu_device::CLR_ZN() { m_flags &= ~(ZFLAG | NFLAG); } +inline void jaguar_cpu_device::CLR_ZNC() { m_flags &= ~(CFLAG | ZFLAG | NFLAG); } +inline void jaguar_cpu_device::SET_Z(u32 r) { m_flags |= (r == 0); } +inline void jaguar_cpu_device::SET_C_ADD(u32 a, u32 b) { m_flags |= (b > (~a)) << 1; } +inline void jaguar_cpu_device::SET_C_SUB(u32 a, u32 b) { m_flags |= (b > a) << 1; } +inline void jaguar_cpu_device::SET_N(u32 r) { m_flags |= ((r >> 29) & 4); } inline void jaguar_cpu_device::SET_ZN(u32 r) { SET_N(r); SET_Z(r); } inline void jaguar_cpu_device::SET_ZNC_ADD(u32 a, u32 b, u32 r) { SET_N(r); SET_Z(r); SET_C_ADD(a, b); } inline void jaguar_cpu_device::SET_ZNC_SUB(u32 a, u32 b, u32 r) { SET_N(r); SET_Z(r); SET_C_SUB(a, b); } @@ -69,12 +71,9 @@ inline void jaguar_cpu_device::SET_ZNC_SUB(u32 a, u32 b, u32 r) { SET_N(r); SET_ MACROS ***************************************************************************/ -#define PC m_ctrl[G_PC] -#define FLAGS m_ctrl[G_FLAGS] - inline u8 jaguar_cpu_device::CONDITION(u8 x) { - return condition_table[x + ((m_ctrl[G_FLAGS] & 7) << 5)]; + return condition_table[x + ((m_flags & 7) << 5)]; } inline u8 jaguar_cpu_device::READBYTE(offs_t a) { return m_program->read_byte(a); } @@ -151,15 +150,33 @@ DEFINE_DEVICE_TYPE(JAGUARGPU, jaguargpu_cpu_device, "jaguargpu", "Motorola Atari DEFINE_DEVICE_TYPE(JAGUARDSP, jaguardsp_cpu_device, "jaguardsp", "Motorola Atari Jaguar DSP \"Jerry\"") -jaguar_cpu_device::jaguar_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 version, bool isdsp) +jaguar_cpu_device::jaguar_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 version, bool isdsp, address_map_constructor io_map) : cpu_device(mconfig, type, tag, owner, clock) , m_program_config("program", ENDIANNESS_BIG, 32, 24, 0) + , m_io_config("io", ENDIANNESS_BIG, 32, 8, 0, io_map) , m_version(version) // 1 : Jaguar prototype, 2 : Jaguar first release, 3 : Midsummer prototype, Other : unknown/reserved , m_isdsp(isdsp) , m_cpu_interrupt(*this) , m_tables_referenced(false) , table_refcount(0) , m_table(isdsp ? dsp_op_table : gpu_op_table) + , m_io_end(0x00070007) + , m_io_pc(0) + , m_io_status(0) + , m_pc(0) + , m_flags(0) + , m_imask(false) + , m_maddw(0) + , m_mwidth(0) + , m_mtxaddr(0) + , m_go(false) + , m_int_latch(0) + , m_int_mask(0) + , m_bus_hog(false) + , m_div_remainder(0) + , m_div_offset(false) + , m_hidata(0) + , m_modulo(0xffffffff) { if (isdsp) { @@ -175,20 +192,21 @@ jaguar_cpu_device::jaguar_cpu_device(const machine_config &mconfig, device_type jaguargpu_cpu_device::jaguargpu_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : jaguar_cpu_device(mconfig, JAGUARGPU, tag, owner, clock, 2, false) + : jaguar_cpu_device(mconfig, JAGUARGPU, tag, owner, clock, 2, false, address_map_constructor(FUNC(jaguargpu_cpu_device::io_map), this)) { } jaguardsp_cpu_device::jaguardsp_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : jaguar_cpu_device(mconfig, JAGUARDSP, tag, owner, clock, 2, true) + : jaguar_cpu_device(mconfig, JAGUARDSP, tag, owner, clock, 2, true, address_map_constructor(FUNC(jaguardsp_cpu_device::io_map), this)) { } device_memory_interface::space_config_vector jaguar_cpu_device::memory_space_config() const { return space_config_vector { - std::make_pair(AS_PROGRAM, &m_program_config) + std::make_pair(AS_PROGRAM, &m_program_config), + std::make_pair(AS_IO, &m_io_config) }; } @@ -196,8 +214,8 @@ device_memory_interface::space_config_vector jaguar_cpu_device::memory_space_con void jaguar_cpu_device::update_register_banks() { /* pick the bank */ - u32 bank = FLAGS & RPAGEFLAG; - if (FLAGS & IFLAG) bank = 0; + u32 bank = m_flags & RPAGEFLAG; + if (m_imask == true) bank = 0; /* do we need to swap? */ if ((bank == 0 && m_b0 != m_r) || (bank != 0 && m_b1 != m_r)) @@ -237,51 +255,43 @@ void jaguar_cpu_device::check_irqs() int which = 0; /* if the IMASK is set, bail */ - if (FLAGS & IFLAG) + if (m_imask == true) return; - /* get the active interrupt bits */ - u8 bits = (m_ctrl[G_CTRL] >> 6) & 0x1f; - bits |= (m_ctrl[G_CTRL] >> 10) & 0x20; - - /* get the interrupt mask */ - u8 mask = (FLAGS >> 4) & 0x1f; - mask |= (FLAGS >> 11) & 0x20; + u8 latch = m_int_latch; + u8 mask = m_int_mask; /* bail if nothing is available */ - bits &= mask; - if (bits == 0) + latch &= mask; + if (latch == 0) return; - + /* determine which interrupt */ - if (bits & 0x01) which = 0; - if (bits & 0x02) which = 1; - if (bits & 0x04) which = 2; - if (bits & 0x08) which = 3; - if (bits & 0x10) which = 4; - if (bits & 0x20) which = 5; + for (int i = 0; i < 6; i++) + if (latch & (1 << i)) + which = i; /* set the interrupt flag */ - FLAGS |= IFLAG; + m_imask = true; update_register_banks(); - /* push the PC-2 on the stack */ + /* push the m_pc-2 on the stack */ m_r[31] -= 4; - WRITELONG(m_r[31], PC - 2); + WRITELONG(m_r[31], m_pc - 2); /* dispatch */ - PC = (m_isdsp) ? 0xf1b000 : 0xf03000; - PC += which * 0x10; + m_pc = m_internal_ram_start; + m_pc += which * 0x10; } void jaguar_cpu_device::execute_set_input(int irqline, int state) { - const u32 mask = (irqline < 5) ? (0x40 << irqline) : 0x10000; - m_ctrl[G_CTRL] &= ~mask; + const u32 mask = (1 << irqline); + m_int_latch &= ~mask; if (state != CLEAR_LINE) { - m_ctrl[G_CTRL] |= mask; + m_int_latch |= mask; check_irqs(); } } @@ -346,14 +356,29 @@ void jaguar_cpu_device::device_start() init_tables(); m_program = &space(AS_PROGRAM); + m_io = &space(AS_IO); m_cache = m_program->cache<2, 0, ENDIANNESS_BIG>(); m_cpu_interrupt.resolve_safe(); save_item(NAME(m_r)); save_item(NAME(m_a)); - save_item(NAME(m_ctrl)); save_item(NAME(m_ppc)); + save_item(NAME(m_go)); + save_item(NAME(m_int_latch)); + save_item(NAME(m_int_mask)); + save_item(NAME(m_bus_hog)); + save_item(NAME(m_flags)); + save_item(NAME(m_imask)); + save_item(NAME(m_div_remainder)); + save_item(NAME(m_div_offset)); + + save_item(NAME(m_io_end)); + save_item(NAME(m_io_pc)); + save_item(NAME(m_io_status)); + save_item(NAME(m_io_mtxc)); + save_item(NAME(m_io_mtxa)); + // TODO: data map if (m_isdsp) { m_internal_ram_start = 0xf1b000; @@ -367,13 +392,12 @@ void jaguar_cpu_device::device_start() std::fill(std::begin(m_r), std::end(m_r), 0); std::fill(std::begin(m_a), std::end(m_a), 0); - std::fill(std::begin(m_ctrl), std::end(m_ctrl), 0); m_ppc = 0; m_accum = 0; m_bankswitch_icount = 0; - state_add( JAGUAR_PC, "PC", PC).formatstr("%08X"); - state_add( JAGUAR_FLAGS, "FLAGS", FLAGS).formatstr("%08X"); + state_add( JAGUAR_PC, "PC", m_pc).formatstr("%08X"); + state_add( JAGUAR_FLAGS, "FLAGS", m_flags).formatstr("%08X"); state_add( JAGUAR_R0, "R0", m_r[0]).formatstr("%08X"); state_add( JAGUAR_R1, "R1", m_r[1]).formatstr("%08X"); state_add( JAGUAR_R2, "R2", m_r[2]).formatstr("%08X"); @@ -407,9 +431,9 @@ void jaguar_cpu_device::device_start() state_add( JAGUAR_R30, "R30", m_r[30]).formatstr("%08X"); state_add( JAGUAR_R31, "R31", m_r[31]).formatstr("%08X"); - state_add( STATE_GENPC, "GENPC", PC).noshow(); + state_add( STATE_GENPC, "GENPC", m_pc).noshow(); state_add( STATE_GENPCBASE, "CURPC", m_ppc).noshow(); - state_add( STATE_GENFLAGS, "GENFLAGS", FLAGS).formatstr("%11s").noshow(); + state_add( STATE_GENFLAGS, "GENFLAGS", m_flags).formatstr("%11s").noshow(); set_icountptr(m_icount); } @@ -421,17 +445,17 @@ void jaguar_cpu_device::state_string_export(const device_state_entry &entry, std { case STATE_GENFLAGS: str = string_format("%c%c%c%c%c%c%c%c%c%c%c", - FLAGS & 0x8000 ? 'D':'.', - FLAGS & 0x4000 ? 'A':'.', - FLAGS & 0x0100 ? '4':'.', - FLAGS & 0x0080 ? '3':'.', - FLAGS & 0x0040 ? '2':'.', - FLAGS & 0x0020 ? '1':'.', - FLAGS & 0x0010 ? '0':'.', - FLAGS & 0x0008 ? 'I':'.', - FLAGS & 0x0004 ? 'N':'.', - FLAGS & 0x0002 ? 'C':'.', - FLAGS & 0x0001 ? 'Z':'.'); + m_flags & 0x8000 ? 'D':'.', + m_flags & 0x4000 ? 'A':'.', + m_flags & 0x0100 ? '4':'.', + m_flags & 0x0080 ? '3':'.', + m_flags & 0x0040 ? '2':'.', + m_flags & 0x0020 ? '1':'.', + m_flags & 0x0010 ? '0':'.', + m_imask == true ? 'I':'.', + m_flags & 0x0004 ? 'N':'.', + m_flags & 0x0002 ? 'C':'.', + m_flags & 0x0001 ? 'Z':'.'); break; } } @@ -441,6 +465,7 @@ void jaguar_cpu_device::device_reset() { m_b0 = m_r; m_b1 = m_a; + m_modulo = 0xffffffff; } @@ -464,7 +489,7 @@ jaguar_cpu_device::~jaguar_cpu_device() void jaguargpu_cpu_device::execute_run() { /* if we're halted, we shouldn't be here */ - if (!(m_ctrl[G_CTRL] & 1)) + if (m_go == false) { //device->execute().set_input_line(INPUT_LINE_HALT, ASSERT_LINE); m_icount = 0; @@ -481,13 +506,13 @@ void jaguargpu_cpu_device::execute_run() do { /* debugging */ - //if (PC < 0xf03000 || PC > 0xf04000) { fatalerror("GPU: PC = %06X (ppc = %06X)\n", PC, m_ppc); } - m_ppc = PC; - debugger_instruction_hook(PC); + //if (m_pc < 0xf03000 || m_pc > 0xf04000) { fatalerror("GPU: m_pc = %06X (ppc = %06X)\n", m_pc, m_ppc); } + m_ppc = m_pc; + debugger_instruction_hook(m_pc); /* instruction fetch */ - const u16 op = ROPCODE(PC); - PC += 2; + const u16 op = ROPCODE(m_pc); + m_pc += 2; /* parse the instruction */ (this->*gpu_op_table[op >> 10])(op); @@ -499,7 +524,7 @@ void jaguargpu_cpu_device::execute_run() void jaguardsp_cpu_device::execute_run() { /* if we're halted, we shouldn't be here */ - if (!(m_ctrl[G_CTRL] & 1)) + if (m_go == false) { //device->execute().set_input_line(INPUT_LINE_HALT, ASSERT_LINE); m_icount = 0; @@ -516,13 +541,13 @@ void jaguardsp_cpu_device::execute_run() do { /* debugging */ - //if (PC < 0xf1b000 || PC > 0xf1d000) { fatalerror(stderr, "DSP: PC = %06X\n", PC); } - m_ppc = PC; - debugger_instruction_hook(PC); + //if (m_pc < 0xf1b000 || m_pc > 0xf1d000) { fatalerror(stderr, "DSP: m_pc = %06X\n", m_pc); } + m_ppc = m_pc; + debugger_instruction_hook(m_pc); /* instruction fetch */ - const u16 op = ROPCODE(PC); - PC += 2; + const u16 op = ROPCODE(m_pc); + m_pc += 2; /* parse the instruction */ (this->*dsp_op_table[op >> 10])(op); @@ -544,7 +569,7 @@ void jaguar_cpu_device::abs_rn(u16 op) if (res & 0x80000000) { m_r[dreg] = res = -res; - FLAGS |= CFLAG; + m_flags |= CFLAG; } SET_Z(res); } @@ -564,7 +589,7 @@ void jaguar_cpu_device::addc_rn_rn(u16 op) const u8 dreg = op & 31; const u32 r1 = m_r[(op >> 5) & 31]; const u32 r2 = m_r[dreg]; - u32 c = ((FLAGS >> 1) & 1); + u32 c = ((m_flags >> 1) & 1); const u32 res = r2 + r1 + c; m_r[dreg] = res; CLR_ZNC(); SET_ZNC_ADD(r2, r1 + c, res); @@ -586,7 +611,7 @@ void jaguar_cpu_device::addqmod_n_rn(u16 op) /* DSP only */ const u32 r1 = convert_zero[(op >> 5) & 31]; const u32 r2 = m_r[dreg]; u32 res = r2 + r1; - res = (res & ~m_ctrl[D_MOD]) | (r2 & ~m_ctrl[D_MOD]); + res = (res & ~m_modulo) | (r2 & m_modulo); m_r[dreg] = res; CLR_ZNC(); SET_ZNC_ADD(r2, r1, res); } @@ -634,7 +659,7 @@ void jaguar_cpu_device::btst_n_rn(u16 op) { const u32 r1 = (op >> 5) & 31; const u32 r2 = m_r[op & 31]; - CLR_Z(); FLAGS |= (~r2 >> r1) & 1; + CLR_Z(); m_flags |= (~r2 >> r1) & 1; } void jaguar_cpu_device::cmp_rn_rn(u16 op) @@ -660,19 +685,23 @@ void jaguar_cpu_device::div_rn_rn(u16 op) const u32 r2 = m_r[dreg]; if (r1) { - if (m_ctrl[D_DIVCTRL] & 1) + if (m_div_offset & 1) { m_r[dreg] = ((u64)r2 << 16) / r1; - m_ctrl[D_REMAINDER] = ((u64)r2 << 16) % r1; + m_div_remainder = ((u64)r2 << 16) % r1; } else { m_r[dreg] = r2 / r1; - m_ctrl[D_REMAINDER] = r2 % r1; + m_div_remainder = r2 % r1; } } else + { + // TODO: exact values for divide by zero m_r[dreg] = 0xffffffff; + m_div_remainder = 0xffffffff; + } } void jaguar_cpu_device::illegal(u16 op) @@ -684,6 +713,7 @@ void jaguar_cpu_device::imacn_rn_rn(u16 op) const u32 r1 = m_r[(op >> 5) & 31]; const u32 r2 = m_r[op & 31]; m_accum += (s64)((int16_t)r1 * (int16_t)r2); + // TODO: what's really "unexpected"? logerror("Unexpected IMACN instruction!\n"); } @@ -706,18 +736,18 @@ void jaguar_cpu_device::imultn_rn_rn(u16 op) m_accum = (s32)res; CLR_ZN(); SET_ZN(res); - op = ROPCODE(PC); + op = ROPCODE(m_pc); while ((op >> 10) == 20) { r1 = m_r[(op >> 5) & 31]; r2 = m_r[op & 31]; m_accum += (s64)((int16_t)r1 * (int16_t)r2); - PC += 2; - op = ROPCODE(PC); + m_pc += 2; + op = ROPCODE(m_pc); } if ((op >> 10) == 19) { - PC += 2; + m_pc += 2; m_r[op & 31] = (u32)m_accum; } } @@ -727,10 +757,10 @@ void jaguar_cpu_device::jr_cc_n(u16 op) if (CONDITION(op & 31)) { const s32 r1 = (s8)((op >> 2) & 0xf8) >> 2; - const u32 newpc = PC + r1; - debugger_instruction_hook(PC); - op = ROPCODE(PC); - PC = newpc; + const u32 newpc = m_pc + r1; + debugger_instruction_hook(m_pc); + op = ROPCODE(m_pc); + m_pc = newpc; (this->*m_table[op >> 10])(op); m_icount -= 3; /* 3 wait states guaranteed */ @@ -745,9 +775,9 @@ void jaguar_cpu_device::jump_cc_rn(u16 op) /* special kludge for risky code in the cojag DSP interrupt handlers */ const u32 newpc = (m_icount == m_bankswitch_icount) ? m_a[reg] : m_r[reg]; - debugger_instruction_hook(PC); - op = ROPCODE(PC); - PC = newpc; + debugger_instruction_hook(m_pc); + op = ROPCODE(m_pc); + m_pc = newpc; (this->*m_table[op >> 10])(op); m_icount -= 3; /* 3 wait states guaranteed */ @@ -819,7 +849,7 @@ void jaguar_cpu_device::loadp_rn_rn(u16 op) /* GPU only */ } else { - m_ctrl[G_HIDATA] = READLONG(r1); + m_hidata = READLONG(r1); m_r[op & 31] = READLONG(r1+4); } } @@ -835,13 +865,13 @@ void jaguar_cpu_device::mirror_rn(u16 op) /* DSP only */ void jaguar_cpu_device::mmult_rn_rn(u16 op) { - const u8 count = m_ctrl[G_MTXC] & 15; + const u8 count = m_mwidth; const u8 sreg = (op >> 5) & 31; const u8 dreg = op & 31; - u32 addr = m_ctrl[G_MTXA]; + u32 addr = m_mtxaddr; s64 accum = 0; - if (!(m_ctrl[G_MTXC] & 0x10)) + if (m_maddw == false) { for (int i = 0; i < count; i++) { @@ -879,8 +909,8 @@ void jaguar_cpu_device::movefa_rn_rn(u16 op) void jaguar_cpu_device::movei_n_rn(u16 op) { - const u32 res = ROPCODE(PC) | (ROPCODE(PC + 2) << 16); - PC += 4; + const u32 res = ROPCODE(m_pc) | (ROPCODE(m_pc + 2) << 16); + m_pc += 4; m_r[op & 31] = res; } @@ -987,7 +1017,7 @@ void jaguar_cpu_device::ror_rn_rn(u16 op) const u32 r2 = m_r[dreg]; const u32 res = (r2 >> r1) | (r2 << (32 - r1)); m_r[dreg] = res; - CLR_ZNC(); SET_ZN(res); FLAGS |= (r2 >> 30) & 2; + CLR_ZNC(); SET_ZN(res); m_flags |= (r2 >> 30) & 2; } void jaguar_cpu_device::rorq_n_rn(u16 op) @@ -997,7 +1027,7 @@ void jaguar_cpu_device::rorq_n_rn(u16 op) const u32 r2 = m_r[dreg]; const u32 res = (r2 >> r1) | (r2 << (32 - r1)); m_r[dreg] = res; - CLR_ZNC(); SET_ZN(res); FLAGS |= (r2 >> 30) & 2; + CLR_ZNC(); SET_ZN(res); m_flags |= (r2 >> 30) & 2; } void jaguar_cpu_device::sat8_rn(u16 op) /* GPU only */ @@ -1057,12 +1087,12 @@ void jaguar_cpu_device::sh_rn_rn(u16 op) if (r1 < 0) { res = (r1 <= -32) ? 0 : (r2 << -r1); - FLAGS |= (r2 >> 30) & 2; + m_flags |= (r2 >> 30) & 2; } else { res = (r1 >= 32) ? 0 : (r2 >> r1); - FLAGS |= (r2 << 1) & 2; + m_flags |= (r2 << 1) & 2; } m_r[dreg] = res; SET_ZN(res); @@ -1079,12 +1109,12 @@ void jaguar_cpu_device::sha_rn_rn(u16 op) if (r1 < 0) { res = (r1 <= -32) ? 0 : (r2 << -r1); - FLAGS |= (r2 >> 30) & 2; + m_flags |= (r2 >> 30) & 2; } else { res = (r1 >= 32) ? ((s32)r2 >> 31) : ((s32)r2 >> r1); - FLAGS |= (r2 << 1) & 2; + m_flags |= (r2 << 1) & 2; } m_r[dreg] = res; SET_ZN(res); @@ -1097,7 +1127,7 @@ void jaguar_cpu_device::sharq_n_rn(u16 op) const u32 r2 = m_r[dreg]; const u32 res = (s32)r2 >> r1; m_r[dreg] = res; - CLR_ZNC(); SET_ZN(res); FLAGS |= (r2 << 1) & 2; + CLR_ZNC(); SET_ZN(res); m_flags |= (r2 << 1) & 2; } void jaguar_cpu_device::shlq_n_rn(u16 op) @@ -1107,7 +1137,7 @@ void jaguar_cpu_device::shlq_n_rn(u16 op) const u32 r2 = m_r[dreg]; const u32 res = r2 << (32 - r1); m_r[dreg] = res; - CLR_ZNC(); SET_ZN(res); FLAGS |= (r2 >> 30) & 2; + CLR_ZNC(); SET_ZN(res); m_flags |= (r2 >> 30) & 2; } void jaguar_cpu_device::shrq_n_rn(u16 op) @@ -1117,7 +1147,7 @@ void jaguar_cpu_device::shrq_n_rn(u16 op) const u32 r2 = m_r[dreg]; const u32 res = r2 >> r1; m_r[dreg] = res; - CLR_ZNC(); SET_ZN(res); FLAGS |= (r2 << 1) & 2; + CLR_ZNC(); SET_ZN(res); m_flags |= (r2 << 1) & 2; } void jaguar_cpu_device::store_rn_rn(u16 op) @@ -1185,7 +1215,7 @@ void jaguar_cpu_device::storep_rn_rn(u16 op) /* GPU only */ } else { - WRITELONG(r1, m_ctrl[G_HIDATA]); + WRITELONG(r1, m_hidata); WRITELONG(r1+4, m_r[op & 31]); } } @@ -1205,7 +1235,7 @@ void jaguar_cpu_device::subc_rn_rn(u16 op) const u8 dreg = op & 31; const u32 r1 = m_r[(op >> 5) & 31]; const u32 r2 = m_r[dreg]; - u32 c = ((FLAGS >> 1) & 1); + u32 c = ((m_flags >> 1) & 1); const u32 res = r2 - r1 - c; m_r[dreg] = res; CLR_ZNC(); SET_ZNC_SUB(r2, r1 + c, res); @@ -1227,7 +1257,7 @@ void jaguar_cpu_device::subqmod_n_rn(u16 op) /* DSP only */ const u32 r1 = convert_zero[(op >> 5) & 31]; const u32 r2 = m_r[dreg]; u32 res = r2 - r1; - res = (res & ~m_ctrl[D_MOD]) | (r2 & ~m_ctrl[D_MOD]); + res = (res & ~m_modulo) | (r2 & m_modulo); m_r[dreg] = res; CLR_ZNC(); SET_ZNC_SUB(r2, r1, res); } @@ -1257,191 +1287,212 @@ void jaguar_cpu_device::xor_rn_rn(u16 op) I/O HANDLING ***************************************************************************/ -u32 jaguargpu_cpu_device::ctrl_r(offs_t offset) +void jaguar_cpu_device::io_common_map(address_map &map) { - if (LOG_GPU_IO) logerror("GPU read register @ F021%02X\n", offset * 4); - - u32 res = m_ctrl[offset]; - if (offset == G_CTRL) - res |= (m_version & 0xf) << 12; - - return res; + map(0x00, 0x03).rw(FUNC(jaguar_cpu_device::flags_r), FUNC(jaguar_cpu_device::flags_w)); + map(0x04, 0x07).w(FUNC(jaguar_cpu_device::matrix_control_w)); + map(0x08, 0x0b).w(FUNC(jaguar_cpu_device::matrix_address_w)); +// map(0x0c, 0x0f) endian + map(0x10, 0x13).w(FUNC(jaguar_cpu_device::pc_w)); + map(0x14, 0x17).rw(FUNC(jaguar_cpu_device::status_r), FUNC(jaguar_cpu_device::control_w)); +// map(0x18, 0x1b) implementation specific + map(0x1c, 0x1f).rw(FUNC(jaguar_cpu_device::div_remainder_r), FUNC(jaguar_cpu_device::div_control_w)); } - -void jaguargpu_cpu_device::ctrl_w(offs_t offset, u32 data, u32 mem_mask) +// $f02100 +void jaguargpu_cpu_device::io_map(address_map &map) { - if (LOG_GPU_IO && offset != G_HIDATA) - logerror("GPU write register @ F021%02X = %08X\n", offset * 4, data); + jaguar_cpu_device::io_common_map(map); + map(0x0c, 0x0f).w(FUNC(jaguargpu_cpu_device::end_w)); + map(0x18, 0x1b).rw(FUNC(jaguargpu_cpu_device::hidata_r), FUNC(jaguargpu_cpu_device::hidata_w)); +} - /* remember the old and set the new */ - const u32 oldval = m_ctrl[offset]; - u32 newval = oldval; - COMBINE_DATA(&newval); +// $f0a100 +void jaguardsp_cpu_device::io_map(address_map &map) +{ + jaguar_cpu_device::io_common_map(map); + map(0x0c, 0x0f).w(FUNC(jaguardsp_cpu_device::dsp_end_w)); + map(0x18, 0x1b).w(FUNC(jaguardsp_cpu_device::modulo_w)); + map(0x20, 0x23).r(FUNC(jaguardsp_cpu_device::high_accum_r)); +} - /* handle the various registers */ - switch (offset) +READ32_MEMBER(jaguar_cpu_device::flags_r) +{ + return (m_flags & 0x1c1f7) | (m_imask << 3); +} + +WRITE32_MEMBER(jaguar_cpu_device::flags_w) +{ + COMBINE_DATA(&m_flags); + // clear imask only on bit 3 clear (1 has no effect) + if ((m_flags & 0x08) == 0) + m_imask = false; + + // update int latch & mask + m_int_mask = (m_flags >> 4) & 0x1f; + m_int_latch &= ~((m_flags >> 9) & 0x1f); + + // TODO: move to specific handler + if (m_isdsp) { - case G_FLAGS: - - /* combine the data properly */ - m_ctrl[offset] = newval & (ZFLAG | CFLAG | NFLAG | EINT04FLAGS | RPAGEFLAG); - if (newval & IFLAG) - m_ctrl[offset] |= oldval & IFLAG; - - /* clear interrupts */ - m_ctrl[G_CTRL] &= ~((newval & CINT04FLAGS) >> 3); - - /* determine which register bank should be active */ - update_register_banks(); - - /* update IRQs */ - check_irqs(); - break; - - case G_MTXC: - case G_MTXA: - m_ctrl[offset] = newval; - break; - - case G_END: - m_ctrl[offset] = newval; - if ((newval & 7) != 7) - logerror("GPU to set to little-endian!\n"); - break; - - case G_PC: - PC = newval & 0xffffff; - break; - - case G_CTRL: - m_ctrl[offset] = newval; - if ((oldval ^ newval) & 0x01) - { - set_input_line(INPUT_LINE_HALT, (newval & 1) ? CLEAR_LINE : ASSERT_LINE); - yield(); - } - if (newval & 0x02) - { - m_cpu_interrupt(ASSERT_LINE); - m_ctrl[offset] &= ~0x02; - } - if (newval & 0x04) - { - m_ctrl[G_CTRL] |= 1 << 6; - m_ctrl[offset] &= ~0x04; - check_irqs(); - } - if (newval & 0x18) - { - logerror("GPU single stepping was enabled!\n"); - } - break; - - case G_HIDATA: - case G_DIVCTRL: - m_ctrl[offset] = newval; - break; + m_int_mask |= (BIT(m_flags, 16) << 5); + m_int_latch &= ~(BIT(m_flags, 17) << 5); } + + // TODO: DMAEN (bit 15) + + update_register_banks(); + check_irqs(); } +WRITE32_MEMBER(jaguar_cpu_device::matrix_control_w) +{ + COMBINE_DATA(&m_io_mtxc); + m_mwidth = m_io_mtxc & 0xf; + m_maddw = BIT(m_io_mtxc, 4); +} +WRITE32_MEMBER(jaguar_cpu_device::matrix_address_w) +{ + COMBINE_DATA(&m_io_mtxa); + // matrix can be long word address only, and only read from internal RAM + m_mtxaddr = m_internal_ram_start | (m_io_mtxa & 0xffc); +} + +WRITE32_MEMBER(jaguar_cpu_device::pc_w) +{ + COMBINE_DATA(&m_io_pc); + if (m_go == false) + m_pc = m_io_pc & 0xffffff; + else + throw emu_fatalerror("%s: inflight PC write %08x", this->tag(), m_pc); +} + +/* + * Data Organization Register + * Note: The canonical way to set this up from 68k is $00070007, + * so that Power-On endianness doesn't matter. 1=Big Endian + * ---- -x-- Instruction endianness + * ---- --x- Pixel endianness (GPU only) + * ---- ---x I/O endianness + */ +// TODO: just log if anything farts for now, change to bit struct once we have something to test out +WRITE32_MEMBER(jaguar_cpu_device::end_w) +{ + COMBINE_DATA(&m_io_end); + // sburnout sets bit 1 == 0 + if ((m_io_end & 0x7) != 0x7) + throw emu_fatalerror("%s: fatal endian setup %08x", this->tag(), m_io_end); +} + +WRITE32_MEMBER(jaguardsp_cpu_device::dsp_end_w) +{ + COMBINE_DATA(&m_io_end); + // wolfn3d writes a '0' to bit 1 (which is a NOP for DSP) + if ((m_io_end & 0x5) != 0x5) + throw emu_fatalerror("%s: fatal endian setup %08x", this->tag(), m_io_end); +} + +/* + * Control/Status Register + * - xxxx ---- ---- ---- chip version number + * - ---- x--- ---- ---- bus hog (increase self chip priority on bus) + * y ---- -xxx xx-- ---- interrupt latch (y is DSP specific) (r/o) + * - ---- ---- --0- ---- + * - ---- ---- ---x x--- single step regs + * - ---- ---- ---- -x-- GPUINT0 or DSPINT0 + * - ---- ---- ---- --x- Host interrupt (w/o) + * - ---- ---- ---- ---x GPUGO or DSPGO flag + * + */ +READ32_MEMBER(jaguar_cpu_device::status_r) +{ + u32 result = ((m_version & 0xf)<<12) | (m_bus_hog<<11) | m_go; + result|= (m_int_latch & 0x1f) << 6; + // TODO: make it DSP specific + if (m_isdsp == true) + result|= (m_int_latch & 0x20) << 11; + return result; +} + +WRITE_LINE_MEMBER(jaguar_cpu_device::go_w) +{ + m_go = state; + set_input_line(INPUT_LINE_HALT, (m_go == true) ? CLEAR_LINE : ASSERT_LINE); + yield(); +} + +WRITE32_MEMBER(jaguar_cpu_device::control_w) +{ + COMBINE_DATA(&m_io_status); + bool new_go = BIT(m_io_status, 0); + if (new_go != m_go) + go_w(new_go); + + if (BIT(m_io_status, 1)) + m_cpu_interrupt(ASSERT_LINE); + + // TODO: following does nothing if set by itself, or acts as a trap? + if (BIT(m_io_status, 2)) + { + m_int_latch |= 1; + check_irqs(); + } + + // TODO: single step handling + + m_bus_hog = BIT(m_io_status, 11); + // TODO: protect/protectse uses this, why? + if (m_bus_hog == true) + logerror("%s: bus hog enabled\n", this->tag()); +} + +READ32_MEMBER(jaguargpu_cpu_device::hidata_r) +{ + return m_hidata; +} + +WRITE32_MEMBER(jaguargpu_cpu_device::hidata_w) +{ + COMBINE_DATA(&m_hidata); +} + +READ32_MEMBER(jaguar_cpu_device::div_remainder_r) +{ + // TODO: truly 32-bit? + return m_div_remainder; +} + +WRITE32_MEMBER(jaguar_cpu_device::div_control_w) +{ + m_div_offset = BIT(data, 0); +} + +WRITE32_MEMBER(jaguardsp_cpu_device::modulo_w) +{ + COMBINE_DATA(&m_modulo); +} + +READ32_MEMBER(jaguardsp_cpu_device::high_accum_r) +{ + printf("%s: high 16-bit accumulator read\n", this->tag()); + return (m_accum >> 32) & 0xff; +} + +u32 jaguar_cpu_device::iobus_r(offs_t offset, u32 mem_mask) +{ + return m_io->read_dword(offset*4, mem_mask); +} + +void jaguar_cpu_device::iobus_w(offs_t offset, u32 data, u32 mem_mask) +{ + m_io->write_dword(offset*4, data, mem_mask); +} /*************************************************************************** - I/O HANDLING + DASM ***************************************************************************/ -u32 jaguardsp_cpu_device::ctrl_r(offs_t offset) -{ - if (LOG_DSP_IO && offset != D_FLAGS) - logerror("DSP read register @ F1A1%02X\n", offset * 4); - - /* switch to the target context */ - u32 res = m_ctrl[offset]; - if (offset == D_CTRL) - res |= (m_version & 0xf) << 12; - - return res; -} - - -void jaguardsp_cpu_device::ctrl_w(offs_t offset, u32 data, u32 mem_mask) -{ - if (LOG_DSP_IO && offset != D_FLAGS) - logerror("DSP write register @ F1A1%02X = %08X\n", offset * 4, data); - - /* remember the old and set the new */ - const u32 oldval = m_ctrl[offset]; - u32 newval = oldval; - COMBINE_DATA(&newval); - - /* handle the various registers */ - switch (offset) - { - case D_FLAGS: - - /* combine the data properly */ - m_ctrl[offset] = newval & (ZFLAG | CFLAG | NFLAG | EINT04FLAGS | EINT5FLAG | RPAGEFLAG); - if (newval & IFLAG) - m_ctrl[offset] |= oldval & IFLAG; - - /* clear interrupts */ - m_ctrl[D_CTRL] &= ~((newval & CINT04FLAGS) >> 3); - m_ctrl[D_CTRL] &= ~((newval & CINT5FLAG) >> 1); - - /* determine which register bank should be active */ - update_register_banks(); - - /* update IRQs */ - check_irqs(); - break; - - case D_MTXC: - case D_MTXA: - m_ctrl[offset] = newval; - break; - - case D_END: - m_ctrl[offset] = newval; - if ((newval & 7) != 7) - logerror("DSP to set to little-endian!\n"); - break; - - case D_PC: - PC = newval & 0xffffff; - break; - - case D_CTRL: - m_ctrl[offset] = newval; - if ((oldval ^ newval) & 0x01) - { - set_input_line(INPUT_LINE_HALT, (newval & 1) ? CLEAR_LINE : ASSERT_LINE); - yield(); - } - if (newval & 0x02) - { - m_cpu_interrupt(ASSERT_LINE); - m_ctrl[offset] &= ~0x02; - } - if (newval & 0x04) - { - m_ctrl[D_CTRL] |= 1 << 6; - m_ctrl[offset] &= ~0x04; - check_irqs(); - } - if (newval & 0x18) - { - logerror("DSP single stepping was enabled!\n"); - } - break; - - case D_MOD: - case D_DIVCTRL: - m_ctrl[offset] = newval; - break; - } -} - std::unique_ptr jaguargpu_cpu_device::create_disassembler() { return std::make_unique(jaguar_disassembler::variant::GPU); diff --git a/src/devices/cpu/jaguar/jaguar.h b/src/devices/cpu/jaguar/jaguar.h index 3324ca3facd..499a3233f7e 100644 --- a/src/devices/cpu/jaguar/jaguar.h +++ b/src/devices/cpu/jaguar/jaguar.h @@ -28,38 +28,6 @@ enum JAGUAR_R24,JAGUAR_R25,JAGUAR_R26,JAGUAR_R27,JAGUAR_R28,JAGUAR_R29,JAGUAR_R30,JAGUAR_R31 }; -enum -{ - G_FLAGS = 0, - G_MTXC, - G_MTXA, - G_END, - G_PC, - G_CTRL, - G_HIDATA, - G_DIVCTRL, - G_DUMMY, - G_REMAINDER, - G_CTRLMAX -}; - -enum -{ - D_FLAGS = 0, - D_MTXC, - D_MTXA, - D_END, - D_PC, - D_CTRL, - D_MOD, - D_DIVCTRL, - D_MACHI, - D_REMAINDER, - D_CTRLMAX -}; - - - /*************************************************************************** INTERRUPT CONSTANTS ***************************************************************************/ @@ -81,7 +49,7 @@ DECLARE_DEVICE_TYPE(JAGUARGPU, jaguargpu_cpu_device) DECLARE_DEVICE_TYPE(JAGUARDSP, jaguardsp_cpu_device) -class jaguar_cpu_device : public cpu_device +class jaguar_cpu_device : public cpu_device { public: // construction/destruction @@ -90,11 +58,13 @@ public: // configuration helpers auto irq() { return m_cpu_interrupt.bind(); } - virtual void ctrl_w(offs_t offset, u32 data, u32 mem_mask = ~0) = 0; - virtual u32 ctrl_r(offs_t offset) = 0; + // TODO: add which device triggered the I/O + void iobus_w(offs_t offset, u32 data, u32 mem_mask = ~0); + u32 iobus_r(offs_t offset, u32 mem_mask = ~0); + DECLARE_WRITE_LINE_MEMBER(go_w); protected: - jaguar_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 version, bool isdsp); + jaguar_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 version, bool isdsp, address_map_constructor io_map); // device-level overrides virtual void device_start() override; @@ -112,6 +82,18 @@ protected: // device_state_interface overrides virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; + + // I/Os (common) + DECLARE_READ32_MEMBER(flags_r); + DECLARE_WRITE32_MEMBER(flags_w); + DECLARE_WRITE32_MEMBER(matrix_control_w); + DECLARE_WRITE32_MEMBER(matrix_address_w); + DECLARE_WRITE32_MEMBER(end_w); + DECLARE_WRITE32_MEMBER(pc_w); + DECLARE_READ32_MEMBER(status_r); + DECLARE_WRITE32_MEMBER(control_w); + DECLARE_READ32_MEMBER(div_remainder_r); + DECLARE_WRITE32_MEMBER(div_control_w); // defines inline void CLR_Z(); @@ -138,6 +120,7 @@ protected: inline u16 ROPCODE(offs_t pc); address_space_config m_program_config; + address_space_config m_io_config; /* core registers */ u32 m_r[32]; @@ -146,7 +129,6 @@ protected: u32 * m_b1; /* control registers */ - u32 m_ctrl[G_CTRLMAX]; u32 m_ppc; u64 m_accum; @@ -157,6 +139,7 @@ protected: int m_bankswitch_icount; devcb_write_line m_cpu_interrupt; address_space *m_program; + address_space *m_io; memory_access_cache<2, 0, ENDIANNESS_BIG> *m_cache; u32 m_internal_ram_start; @@ -164,8 +147,6 @@ protected: typedef void (jaguar_cpu_device::*op_func)(u16 op); - static const op_func gpu_op_table[64]; - static const op_func dsp_op_table[64]; static const u32 convert_zero[32]; bool m_tables_referenced; @@ -179,7 +160,6 @@ protected: void add_rn_rn(u16 op); void addc_rn_rn(u16 op); void addq_n_rn(u16 op); - void addqmod_n_rn(u16 op); /* DSP only */ void addqt_n_rn(u16 op); void and_rn_rn(u16 op); void bclr_n_rn(u16 op); @@ -201,8 +181,6 @@ protected: void load_r15rn_rn(u16 op); void loadb_rn_rn(u16 op); void loadw_rn_rn(u16 op); - void loadp_rn_rn(u16 op); /* GPU only */ - void mirror_rn(u16 op); /* DSP only */ void mmult_rn_rn(u16 op); void move_rn_rn(u16 op); void move_pc_rn(u16 op); @@ -217,15 +195,10 @@ protected: void normi_rn_rn(u16 op); void not_rn(u16 op); void or_rn_rn(u16 op); - void pack_rn(u16 op); /* GPU only */ void resmac_rn(u16 op); void ror_rn_rn(u16 op); void rorq_n_rn(u16 op); - void sat8_rn(u16 op); /* GPU only */ - void sat16_rn(u16 op); /* GPU only */ - void sat16s_rn(u16 op); /* DSP only */ - void sat24_rn(u16 op); /* GPU only */ - void sat32s_rn(u16 op); /* DSP only */ + void sh_rn_rn(u16 op); void sha_rn_rn(u16 op); void sharq_n_rn(u16 op); @@ -238,16 +211,58 @@ protected: void store_rn_r15rn(u16 op); void storeb_rn_rn(u16 op); void storew_rn_rn(u16 op); - void storep_rn_rn(u16 op); /* GPU only */ void sub_rn_rn(u16 op); void subc_rn_rn(u16 op); void subq_n_rn(u16 op); - void subqmod_n_rn(u16 op); /* DSP only */ void subqt_n_rn(u16 op); void xor_rn_rn(u16 op); + // GPU only opcodes + void loadp_rn_rn(u16 op); + void pack_rn(u16 op); + void sat8_rn(u16 op); + void sat16_rn(u16 op); + void sat24_rn(u16 op); + void storep_rn_rn(u16 op); + // DSP only opcodes + void addqmod_n_rn(u16 op); + void mirror_rn(u16 op); + void sat16s_rn(u16 op); + void sat32s_rn(u16 op); + void subqmod_n_rn(u16 op); + void update_register_banks(); void check_irqs(); void init_tables(); + + // I/O internal regs + void io_common_map(address_map &map); + // TODO: the m_io* stubs are conventionally given for allowing a correct register setup from vanilla 68k. + // This is yet another reason about needing a bus device dispatcher for this system. + u32 m_io_end; + u32 m_io_pc; + u32 m_io_status; + u32 m_io_mtxc; + u32 m_io_mtxa; + + u32 m_pc; + u32 m_flags; + bool m_imask; + bool m_maddw; + u8 m_mwidth; + u32 m_mtxaddr; + bool m_go; + u8 m_int_latch; + u8 m_int_mask; + bool m_bus_hog; + u32 m_div_remainder; + bool m_div_offset; + + // GPU specific + u32 m_hidata; + static const op_func gpu_op_table[64]; + // DSP specific + u32 m_modulo; + static const op_func dsp_op_table[64]; }; @@ -257,12 +272,14 @@ public: // construction/destruction jaguargpu_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); - void ctrl_w(offs_t offset, u32 data, u32 mem_mask = ~0) override; - u32 ctrl_r(offs_t offset) override; + void io_map(address_map &map); protected: virtual void execute_run() override; virtual std::unique_ptr create_disassembler() override; + + DECLARE_WRITE32_MEMBER(hidata_w); + DECLARE_READ32_MEMBER(hidata_r); }; @@ -272,14 +289,16 @@ public: // construction/destruction jaguardsp_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); - void ctrl_w(offs_t offset, u32 data, u32 mem_mask = ~0) override; - u32 ctrl_r(offs_t offset) override; + void io_map(address_map &map); protected: virtual u32 execute_input_lines() const noexcept override { return 6; } virtual void execute_run() override; virtual std::unique_ptr create_disassembler() override; + DECLARE_WRITE32_MEMBER(modulo_w); + DECLARE_WRITE32_MEMBER(dsp_end_w); + DECLARE_READ32_MEMBER(high_accum_r); }; diff --git a/src/mame/audio/jaguar.cpp b/src/mame/audio/jaguar.cpp index c3c044e95a0..a7cabde84fe 100644 --- a/src/mame/audio/jaguar.cpp +++ b/src/mame/audio/jaguar.cpp @@ -261,7 +261,7 @@ WRITE16_MEMBER( jaguar_state::jerry_regs_w ) WRITE32_MEMBER( jaguar_state::dsp_flags_w ) { /* write the data through */ - m_dsp->ctrl_w(offset, data, mem_mask); + m_dsp->iobus_w(offset, data, mem_mask); /* if they were clearing the A2S interrupt, see if we are headed for the spin */ /* loop with R22 != 0; if we are, just start spinning again */ diff --git a/src/mame/drivers/jaguar.cpp b/src/mame/drivers/jaguar.cpp index cd8108a394b..447c2b5fafb 100644 --- a/src/mame/drivers/jaguar.cpp +++ b/src/mame/drivers/jaguar.cpp @@ -459,8 +459,8 @@ void jaguar_state::machine_reset() dsp_resume(); /* halt the CPUs */ - m_gpu->ctrl_w(G_CTRL, 0); - m_dsp->ctrl_w(D_CTRL, 0); + m_gpu->go_w(false); + m_dsp->go_w(false); /* set blitter idle flag */ m_blitter_status = 1; @@ -640,8 +640,8 @@ WRITE32_MEMBER(jaguar_state::misc_control_w) dsp_resume(); /* halt the CPUs */ - m_gpu->ctrl_w(G_CTRL, 0); - m_dsp->ctrl_w(D_CTRL, 0); + m_gpu->go_w(false); + m_dsp->go_w(false); } /* adjust banking */ @@ -663,17 +663,14 @@ WRITE32_MEMBER(jaguar_state::misc_control_w) READ32_MEMBER(jaguar_state::gpuctrl_r) { - return m_gpu->ctrl_r(offset); + return m_gpu->iobus_r(offset, mem_mask); } - WRITE32_MEMBER(jaguar_state::gpuctrl_w) { - m_gpu->ctrl_w(offset, data, mem_mask); + m_gpu->iobus_w(offset, data, mem_mask); } - - /************************************* * * 32-bit access to the DSP @@ -682,16 +679,14 @@ WRITE32_MEMBER(jaguar_state::gpuctrl_w) READ32_MEMBER(jaguar_state::dspctrl_r) { - return m_dsp->ctrl_r(offset); + return m_dsp->iobus_r(offset, mem_mask); } - WRITE32_MEMBER(jaguar_state::dspctrl_w) { - m_dsp->ctrl_w(offset, data, mem_mask); + m_dsp->iobus_w(offset, data, mem_mask); } - /************************************* * * Input ports @@ -1119,7 +1114,7 @@ void jaguar_state::console_base_map(address_map &map) map(0xe00000, 0xe1ffff).rom().region("mainrom", 0); map(0xf00000, 0xf003ff).rw(FUNC(jaguar_state::tom_regs_r), FUNC(jaguar_state::tom_regs_w)); // might be reversed endian of the others.. map(0xf00400, 0xf005ff).mirror(0x000200).rw(FUNC(jaguar_state::gpu_clut_r16), FUNC(jaguar_state::gpu_clut_w16)); - map(0xf02100, 0xf021ff).mirror(0x008000).rw(FUNC(jaguar_state::gpuctrl_r16), FUNC(jaguar_state::gpuctrl_w16)); + map(0xf02100, 0xf021ff).rw(FUNC(jaguar_state::gpuctrl_r16), FUNC(jaguar_state::gpuctrl_w16)); map(0xf02200, 0xf022ff).mirror(0x008000).rw(FUNC(jaguar_state::blitter_r16), FUNC(jaguar_state::blitter_w16)); map(0xf03000, 0xf03fff).mirror(0x008000).rw(FUNC(jaguar_state::gpu_ram_r16), FUNC(jaguar_state::gpu_ram_w16)); map(0xf10000, 0xf103ff).rw(FUNC(jaguar_state::jerry_regs_r), FUNC(jaguar_state::jerry_regs_w)); // might be reversed endian of the others.. @@ -1141,7 +1136,7 @@ void jaguar_state::jaguar_map(address_map &map) void jaguar_state::cpu_space_map(address_map &map) { map(0xfffff0, 0xffffff).m(m_maincpu, FUNC(m68000_base_device::autovectors_map)); - map(0xfffffd, 0xfffffd).lr8([] () -> u8 { return 0x40; }, "level6"); + map(0xfffff5, 0xfffff5).lr8([] () -> u8 { return 0x40; }, "level2"); } /* @@ -1451,7 +1446,7 @@ void jaguar_state::console_base_gpu_map(address_map &map) map(0xe00000, 0xe1ffff).r(FUNC(jaguar_state::rom_base_r)); map(0xf00000, 0xf003ff).rw(FUNC(jaguar_state::tom_regs_r), FUNC(jaguar_state::tom_regs_w)); map(0xf00400, 0xf005ff).mirror(0x000200).ram().share("gpuclut"); - map(0xf02100, 0xf021ff).mirror(0x008000).rw(FUNC(jaguar_state::gpuctrl_r), FUNC(jaguar_state::gpuctrl_w)); + map(0xf02100, 0xf021ff).rw(FUNC(jaguar_state::gpuctrl_r), FUNC(jaguar_state::gpuctrl_w)); map(0xf02200, 0xf022ff).mirror(0x008000).rw(FUNC(jaguar_state::blitter_r), FUNC(jaguar_state::blitter_w)); map(0xf03000, 0xf03fff).mirror(0x008000).ram().share("gpuram"); map(0xf10000, 0xf103ff).rw(FUNC(jaguar_state::jerry_regs_r), FUNC(jaguar_state::jerry_regs_w)); @@ -1764,18 +1759,28 @@ INPUT_PORTS_END * *************************************/ +void jaguar_state::video_config(machine_config &config, const XTAL clock) +{ + JAGUARGPU(config, m_gpu, clock); + m_gpu->irq().set(FUNC(jaguar_state::gpu_cpu_int)); + + JAGUARDSP(config, m_dsp, clock); + m_dsp->irq().set(FUNC(jaguar_state::dsp_cpu_int)); + + // TODO: Tom + // TODO: Object Processor + + JAG_BLITTER(config, m_blitter, clock); +} + void jaguar_state::cojagr3k(machine_config &config) { /* basic machine hardware */ R3041(config, m_maincpu, R3000_CLOCK).set_endianness(ENDIANNESS_BIG); m_maincpu->set_addrmap(AS_PROGRAM, &jaguar_state::r3000_map); - JAGUARGPU(config, m_gpu, COJAG_CLOCK/2); - m_gpu->irq().set(FUNC(jaguar_state::gpu_cpu_int)); + video_config(config, COJAG_CLOCK/2); m_gpu->set_addrmap(AS_PROGRAM, &jaguar_state::gpu_map); - - JAGUARDSP(config, m_dsp, COJAG_CLOCK/2); - m_dsp->irq().set(FUNC(jaguar_state::dsp_cpu_int)); m_dsp->set_addrmap(AS_PROGRAM, &jaguar_state::dsp_map); NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_1); @@ -1803,6 +1808,8 @@ void jaguar_state::cojagr3k(machine_config &config) vref.add_route(0, "ldac", -1.0, DAC_VREF_NEG_INPUT); vref.add_route(0, "rdac", 1.0, DAC_VREF_POS_INPUT); vref.add_route(0, "rdac", -1.0, DAC_VREF_NEG_INPUT); + + // TODO: subwoofer speaker } void jaguar_state::cojagr3k_rom(machine_config &config) @@ -1832,12 +1839,8 @@ void jaguar_state::jaguar(machine_config &config) m_maincpu->set_addrmap(AS_PROGRAM, &jaguar_state::jaguar_map); m_maincpu->set_addrmap(m68000_device::AS_CPU_SPACE, &jaguar_state::cpu_space_map); - JAGUARGPU(config, m_gpu, JAGUAR_CLOCK); - m_gpu->irq().set(FUNC(jaguar_state::gpu_cpu_int)); + video_config(config, JAGUAR_CLOCK); m_gpu->set_addrmap(AS_PROGRAM, &jaguar_state::jag_gpu_dsp_map); - - JAGUARDSP(config, m_dsp, JAGUAR_CLOCK); - m_dsp->irq().set(FUNC(jaguar_state::dsp_cpu_int)); m_dsp->set_addrmap(AS_PROGRAM, &jaguar_state::jag_gpu_dsp_map); // MCFG_NVRAM_HANDLER(jaguar) @@ -1902,6 +1905,7 @@ void jaguar_state::fix_endian( void *base, uint32_t size ) void jaguar_state::init_jaguar() { + m_is_cojag = false; m_hacks_enabled = false; save_item(NAME(m_joystick_data)); diff --git a/src/mame/includes/jaguar.h b/src/mame/includes/jaguar.h index 50165c04360..87a77371ddb 100644 --- a/src/mame/includes/jaguar.h +++ b/src/mame/includes/jaguar.h @@ -12,6 +12,7 @@ #include "machine/eepromser.h" #include "machine/vt83c461.h" #include "imagedev/snapquik.h" +#include "video/jag_blitter.h" #include "cdrom.h" #include "imagedev/chd_cd.h" #include "screen.h" @@ -33,6 +34,7 @@ public: : driver_device(mconfig, type, tag) , m_maincpu(*this, "maincpu") , m_gpu(*this, "gpu") + , m_blitter(*this, "blitter") , m_dsp(*this, "dsp") , m_ldac(*this, "ldac") , m_rdac(*this, "rdac") @@ -111,9 +113,12 @@ protected: virtual void device_postload(); virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + void video_config(machine_config &config, const XTAL clock); + // devices required_device m_maincpu; required_device m_gpu; + required_device m_blitter; required_device m_dsp; required_device m_ldac; required_device m_rdac; @@ -301,7 +306,8 @@ private: void get_crosshair_xy(int player, int &x, int &y); int effective_hvalue(int value); bool adjust_object_timer(int vc); - void update_cpu_irq(); + inline void trigger_host_cpu_irq(int level); + inline void verify_host_cpu_irq(); uint8_t *memory_base(uint32_t offset) { return reinterpret_cast(m_gpu->space(AS_PROGRAM).get_read_ptr(offset)); } void blitter_run(); void scanline_update(int param); diff --git a/src/mame/video/jag_blitter.cpp b/src/mame/video/jag_blitter.cpp new file mode 100644 index 00000000000..d2f33aacfeb --- /dev/null +++ b/src/mame/video/jag_blitter.cpp @@ -0,0 +1,240 @@ +// license:BSD-3-Clause +// copyright-holders:Angelo Salese +/*************************************************************************** + + Atari Jaguar "Blitter" device + + TODO: + - Stub device, port/rewrite from jagblit; + - actual codename/chip part number; + - has different revs, encapsulate; + +***************************************************************************/ + +#include "emu.h" +#include "jag_blitter.h" + + + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +// device type definition +DEFINE_DEVICE_TYPE(JAG_BLITTER, jag_blitter_device, "jag_blitter", "Atari Jaguar Blitter") + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// jag_blitter_device - constructor +//------------------------------------------------- + +jag_blitter_device::jag_blitter_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, JAG_BLITTER, tag, owner, clock) + , device_memory_interface(mconfig, *this) + , m_space_config("regs", ENDIANNESS_BIG, 32, 8, 0, address_map_constructor(FUNC(jag_blitter_device::regs_map), this)) + , m_command_latch(0) + , m_status_idle(true) + , m_count_lines(0) + , m_count_pixels(0) +{ + m_a1.base = 0; + m_a1.xstep = 0; + m_a1.ystep = 0; +} + +device_memory_interface::space_config_vector jag_blitter_device::memory_space_config() const +{ + return space_config_vector { + std::make_pair(0, &m_space_config) + }; +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void jag_blitter_device::device_start() +{ + save_item(NAME(m_status_idle)); + save_item(NAME(m_command_latch)); + save_item(NAME(m_count_lines)); + save_item(NAME(m_count_pixels)); + save_item(NAME(m_a1.base)); + save_item(NAME(m_a1.xstep)); + save_item(NAME(m_a1.ystep)); + + m_command_timer = timer_alloc(0); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void jag_blitter_device::device_reset() +{ + m_command_latch = 0; + m_status_idle = true; + + m_command_timer->adjust(attotime::never); +} + +//-------------------------------------------------- +// core workings +//-------------------------------------------------- + +/*************************************************************************** + FUNCTION TABLES +***************************************************************************/ + +const jag_blitter_device::op_func jag_blitter_device::upda_ops[8] = +{ + &jag_blitter_device::op_nop, + &jag_blitter_device::op_unemulated, // upda1f + &jag_blitter_device::op_upda1, + &jag_blitter_device::op_unemulated, // upda1 + upda1f + + &jag_blitter_device::op_unemulated, // upda2 + &jag_blitter_device::op_unemulated, // upda1f + upda2 + &jag_blitter_device::op_unemulated, // upda1 + upda2 + &jag_blitter_device::op_unemulated // upda1 + upda1f + upda2 +}; + +void jag_blitter_device::op_nop() +{ + // do nothing for this step +} + +// common cases for unhandled, will be removed once everything is set +void jag_blitter_device::op_unemulated() +{ + throw emu_fatalerror("%s: unhandled step with command latch %08x",m_command_latch); +} + +void jag_blitter_device::op_upda1() +{ + // ... + +} + +inline void jag_blitter_device::command_start() +{ + if (m_status_idle == false) + throw emu_fatalerror("%s: inflight blitter trigger %08x", this->tag(), m_command_latch); + m_status_idle = false; + // TODO: to be removed, see below + m_command_timer->adjust(attotime::from_ticks(m_count_lines * m_count_pixels, this->clock())); +} + +inline void jag_blitter_device::command_run() +{ + // TODO: need to single step, have different timings between pixel and phrase modes, + // calculate collision detection, delay a bit the kickoff due of bus chain requests, + // take more time by virtue of using additional steps, be a civilian or not depending + // of BUSHI setting + + printf("%08x\n",m_command_latch); + // init + m_a1.ptr = m_a1.base; + + // ... + + command_done(); +} + +inline void jag_blitter_device::command_done() +{ + // m_status_idle = true; + // ... +} + +void jag_blitter_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + command_run(); +} + +//************************************************************************** +// READ/WRITE HANDLERS +//************************************************************************** + +void jag_blitter_device::regs_map(address_map &map) +{ + // $f02200 + map(0x00, 0x03).w(FUNC(jag_blitter_device::a1_base_w)); + map(0x10, 0x13).w(FUNC(jag_blitter_device::a1_ystep_w)).umask32(0xffff0000); + map(0x10, 0x13).w(FUNC(jag_blitter_device::a1_xstep_w)).umask32(0x0000ffff); + map(0x38, 0x3b).rw(FUNC(jag_blitter_device::status_r), FUNC(jag_blitter_device::command_w)); + map(0x3c, 0x3f).w(FUNC(jag_blitter_device::count_outer_w)).umask32(0xffff0000); + map(0x3c, 0x3f).w(FUNC(jag_blitter_device::count_inner_w)).umask32(0x0000ffff); +} + +WRITE32_MEMBER(jag_blitter_device::a1_base_w) +{ + COMBINE_DATA(&m_a1.base); + // align to phrase + m_a1.base &= ~7; +} + +WRITE16_MEMBER(jag_blitter_device::a1_xstep_w) +{ + COMBINE_DATA(&m_a1.xstep); +} + +WRITE16_MEMBER(jag_blitter_device::a1_ystep_w) +{ + COMBINE_DATA(&m_a1.ystep); +} + +READ32_MEMBER(jag_blitter_device::status_r) +{ + // TODO: stopped bit + // TODO: diag bits 2-31 + return m_status_idle; +} + +WRITE32_MEMBER(jag_blitter_device::command_w) +{ + COMBINE_DATA(&m_command_latch); + // TODO: is it possible from 68k to write on this in byte units? + // We may just do so in order to take endianness into account, or just delegate to the overlying bus framework, + // may be a common problem with ALL video regs for that matter. + if (ACCESSING_BITS_0_15) + command_start(); +} + +WRITE16_MEMBER(jag_blitter_device::count_outer_w) +{ + COMBINE_DATA(&m_count_lines); + if (m_count_lines == 0) + { + // according to documentation, log it out + m_count_lines = 0x10000; + popmessage("Blitter: line count set to max, contact MAMEdev"); + } +} + +WRITE16_MEMBER(jag_blitter_device::count_inner_w) +{ + COMBINE_DATA(&m_count_pixels); + if (m_count_pixels == 0) + { + // according to documentation, log it out + m_count_pixels = 0x10000; + popmessage("Blitter: pixel count set to max, contact MAMEdev"); + } +} + +u32 jag_blitter_device::iobus_r(offs_t offset, u32 mem_mask) +{ + return space().read_dword(offset*4, mem_mask); +} + +void jag_blitter_device::iobus_w(offs_t offset, u32 data, u32 mem_mask) +{ + space().write_dword(offset*4, data, mem_mask); +} diff --git a/src/mame/video/jag_blitter.h b/src/mame/video/jag_blitter.h new file mode 100644 index 00000000000..6812871d647 --- /dev/null +++ b/src/mame/video/jag_blitter.h @@ -0,0 +1,100 @@ +// license:BSD-3-Clause +// copyright-holders:Angelo Salese +/*************************************************************************** + + Atari Jaguar "Blitter" device + +***************************************************************************/ + +#ifndef MAME_MACHINE_JAG_BLITTER_H +#define MAME_MACHINE_JAG_BLITTER_H + +#pragma once + + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> jag_blitter_device + +class jag_blitter_device : public device_t, + public device_memory_interface +{ +public: + // construction/destruction + jag_blitter_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // TODO: add which device triggered the I/O + void iobus_w(offs_t offset, u32 data, u32 mem_mask = ~0); + u32 iobus_r(offs_t offset, u32 mem_mask = ~0); + +protected: + // device-level overrides + //virtual void device_validity_check(validity_checker &valid) const override; + virtual void device_start() override; + virtual void device_reset() override; + void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + virtual space_config_vector memory_space_config() const override; + + const address_space_config m_space_config; + +// address_space *m_host_space; + +private: + void regs_map(address_map &map); + + DECLARE_WRITE32_MEMBER(a1_base_w); + DECLARE_WRITE16_MEMBER(a1_xstep_w); + DECLARE_WRITE16_MEMBER(a1_ystep_w); + DECLARE_READ32_MEMBER(status_r); + DECLARE_WRITE32_MEMBER(command_w); + DECLARE_WRITE16_MEMBER(count_outer_w); + DECLARE_WRITE16_MEMBER(count_inner_w); + + // timer setups + emu_timer *m_command_timer; + inline void command_start(); + inline void command_run(); + inline void command_done(); + + // functional switches + + typedef void (jag_blitter_device::*op_func)(void); + + static const op_func upda_ops[8]; + void op_nop(); + void op_unemulated(); + void op_upda1(); + + u32 m_command_latch; + bool m_status_idle; + u32 m_count_lines, m_count_pixels; + + struct { + u32 base; + s16 xstep, ystep; + + u32 ptr; /**< Current pixel address */ + } m_a1; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(JAG_BLITTER, jag_blitter_device) + + + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + + +#endif // MAME_MACHINE_JAG_BLITTER_H diff --git a/src/mame/video/jagobj.hxx b/src/mame/video/jagobj.hxx index c11ff0f73f0..ffa8e7cdd8c 100644 --- a/src/mame/video/jagobj.hxx +++ b/src/mame/video/jagobj.hxx @@ -1056,9 +1056,11 @@ void jaguar_state::process_object_list(int vc, uint16_t *scanline) m_gpu_regs[OB_HL]=objdata[1]&0xffff; m_gpu_regs[OB_LH]=(objdata[0]&0xffff0000)>>16; m_gpu_regs[OB_LL]=objdata[0]&0xffff; - m_cpu_irq_state |= 2; - update_cpu_irq(); + m_gpu->set_input_line(3, ASSERT_LINE); done=1; + // mutntpng, atarikrt VPOS = 0 + // TODO: what the VPOS is actually for? + //printf("GPU irq VPOS = %04x\n",(objdata[1] >> 3) & 0x7ff); break; /* branch */ @@ -1078,16 +1080,20 @@ void jaguar_state::process_object_list(int vc, uint16_t *scanline) logerror("stop = %08X-%08X\n", objdata[0], objdata[1]); if (interrupt) { + // TODO: fball95 doesn't have a real handling for stop irq, causing the line to be always asserted, how to prevent? // fprintf(stderr, "stop int=%d\n", interrupt); - m_cpu_irq_state |= 4; - update_cpu_irq(); + trigger_host_cpu_irq(2); } break; } + case 6: + // kasumi: F7000000 00F0311E (nop? bad align?) + break; + default: fprintf(stderr, "%08X %08X\n", objdata[0], objdata[1]); - done = 1; + //done = 1; break; } } diff --git a/src/mame/video/jaguar.cpp b/src/mame/video/jaguar.cpp index cd28bd255c6..06e0995577b 100644 --- a/src/mame/video/jaguar.cpp +++ b/src/mame/video/jaguar.cpp @@ -4,6 +4,12 @@ Atari Jaguar hardware + TODO (list of exceptions): + jaguar_state::generic_blitter() + - atarikrt, bretth, brutalsp, nbajamte, spacewar, spacewarp, tempst2k + jaguar_state::blitter_09800009_000020_000020() + - ruinerp + **************************************************************************** ------------------------------------------------------------ @@ -150,7 +156,8 @@ #define LOG_BLITTER_STATS 0 #define LOG_BLITTER_WRITE 0 #define LOG_UNHANDLED_BLITS 0 - +// use the new version in jag_blitter.cpp/.h if 0 +#define USE_LEGACY_BLITTER 1 @@ -266,25 +273,38 @@ inline bool jaguar_state::adjust_object_timer(int vc) * *************************************/ -void jaguar_state::update_cpu_irq() +// TODO: new TOM install irq handler +inline void jaguar_state::verify_host_cpu_irq() { - if ((m_cpu_irq_state & m_gpu_regs[INT1] & 0x1f) != 0) - m_maincpu->set_input_line(m_is_r3000 ? INPUT_LINE_IRQ4 : M68K_IRQ_6, ASSERT_LINE); + // jaguar uses irq 2 + if (m_is_cojag == false) + m_maincpu->set_input_line(M68K_IRQ_2, ((m_cpu_irq_state & m_gpu_regs[INT1] & 0x1f) != 0) ? ASSERT_LINE : CLEAR_LINE); else - m_maincpu->set_input_line(m_is_r3000 ? INPUT_LINE_IRQ4 : M68K_IRQ_6, CLEAR_LINE); + { + // cojag r3000 uses irq 4 + // cojag 68020 uses irq 6 + if ((m_cpu_irq_state & m_gpu_regs[INT1] & 0x1f) != 0) + m_maincpu->set_input_line(m_is_r3000 ? INPUT_LINE_IRQ4 : M68K_IRQ_6, ASSERT_LINE); + else + m_maincpu->set_input_line(m_is_r3000 ? INPUT_LINE_IRQ4 : M68K_IRQ_6, CLEAR_LINE); + } +} + +inline void jaguar_state::trigger_host_cpu_irq(int level) +{ + m_cpu_irq_state |= 1 << level; + verify_host_cpu_irq(); } WRITE_LINE_MEMBER( jaguar_state::gpu_cpu_int ) { - m_cpu_irq_state |= 2; - update_cpu_irq(); + trigger_host_cpu_irq(1); } WRITE_LINE_MEMBER( jaguar_state::dsp_cpu_int ) { - m_cpu_irq_state |= 16; - update_cpu_irq(); + trigger_host_cpu_irq(4); } @@ -524,6 +544,7 @@ if (++reps % 100 == 99) READ32_MEMBER( jaguar_state::blitter_r ) { +#if USE_LEGACY_BLITTER switch (offset) { case B_CMD: /* B_CMD */ @@ -533,11 +554,15 @@ READ32_MEMBER( jaguar_state::blitter_r ) logerror("%s:Blitter read register @ F022%02X\n", machine().describe_context(), offset * 4); return 0; } + #else + return m_blitter->iobus_r(offset, mem_mask); + #endif } WRITE32_MEMBER( jaguar_state::blitter_w ) { +#if USE_LEGACY_BLITTER COMBINE_DATA(&m_blitter_regs[offset]); if ((offset == B_CMD) && ACCESSING_BITS_0_15) { @@ -549,7 +574,10 @@ WRITE32_MEMBER( jaguar_state::blitter_w ) } if (LOG_BLITTER_WRITE) - logerror("%s:Blitter write register @ F022%02X = %08X\n", machine().describe_context(), offset * 4, data); + logerror("%s:Blitter write register @ F022%02X = %08X\n", machine().describe_context(), offset * 4, data); +#else + m_blitter->iobus_w(offset, data, mem_mask); +#endif } @@ -568,7 +596,9 @@ READ16_MEMBER( jaguar_state::tom_regs_r ) switch (offset) { case INT1: + { return m_cpu_irq_state; + } case HC: return m_screen->hpos() % (m_screen->width() / 2); @@ -615,8 +645,10 @@ WRITE16_MEMBER( jaguar_state::tom_regs_w ) case INT1: m_cpu_irq_state &= ~(m_gpu_regs[INT1] >> 8); - update_cpu_irq(); + verify_host_cpu_irq(); break; + + // TODO: INT2 bus mechanism case VMODE: if (reg_store != m_gpu_regs[offset]) @@ -624,8 +656,7 @@ WRITE16_MEMBER( jaguar_state::tom_regs_w ) break; case OBF: /* clear GPU interrupt */ - m_cpu_irq_state &= 0xfd; - update_cpu_irq(); + m_gpu->set_input_line(3, CLEAR_LINE); break; case HP: @@ -715,10 +746,7 @@ void jaguar_state::device_timer(emu_timer &timer, device_timer_id id, int param, case TID_PIT: if (m_gpu_regs[INT1] & 0x8) - { - m_cpu_irq_state |= 8; - update_cpu_irq(); - } + trigger_host_cpu_irq(3); if (m_gpu_regs[PIT0] != 0) { attotime sample_period = attotime::from_ticks((1+m_gpu_regs[PIT0]) * (1+m_gpu_regs[PIT1]), m_gpu->clock()/2); @@ -789,10 +817,7 @@ void jaguar_state::scanline_update(int param) { /* handle vertical interrupts */ if (vc == m_gpu_regs[VI]) - { - m_cpu_irq_state |= 1; - update_cpu_irq(); - } + trigger_host_cpu_irq(0); /* point to the next counter value */ if (++vc / 2 >= m_screen->height()) @@ -824,7 +849,7 @@ void jaguar_state::video_start() void jaguar_state::device_postload() { - update_cpu_irq(); + verify_host_cpu_irq(); }