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();
}