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
This commit is contained in:
Angelo Salese 2020-05-15 22:16:46 +02:00 committed by GitHub
parent 12ec6362bb
commit 5ad522f0c1
11 changed files with 846 additions and 392 deletions

View File

@ -168,7 +168,7 @@ Unreleased (possibly no prototypes exist):
</part>
</software>
<!-- black screen -->
<!-- boot OK, gameplay graphics have clipping/alignment issues, eventually throws an exception, no sound -->
<software name="atarikrt" supported="no">
<description>Atari Karts</description>
<year>1995</year>
@ -181,8 +181,8 @@ Unreleased (possibly no prototypes exist):
</part>
</software>
<!-- black screen -->
<software name="mutntpng" supported="no">
<!-- boot OK, title screen foreground layer not drawn properly, no sound -->
<software name="mutntpng" supported="partial">
<description>Attack of the Mutant Penguins</description>
<year>1996</year>
<publisher>Atari</publisher>
@ -592,7 +592,8 @@ Unreleased (possibly no prototypes exist):
</part>
</software>
<!-- hangs at the NBA Jam TE logo -->
<!-- exception on non-debug, on debug gameplay sports no sprite GFXs -->
<!-- minor glitch on team box when selecting one (blitter not filling properly) -->
<software name="nbajamte" supported="no">
<description>NBA Jam T.E. - Tournament Edition</description>
<year>1996</year>
@ -966,7 +967,7 @@ Unreleased (possibly no prototypes exist):
</software>
<!-- boot OK, no BGMs, has minor GFX pitch issue when action summary message pops up after a play -->
<software name="troyaik" supported="no">
<software name="troyaik" supported="partial">
<description>Troy Aikman NFL Football</description>
<year>1995</year>
<publisher>Williams Entertainment</publisher>

View File

@ -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",

View File

@ -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- ---- <unused>
* - ---- ---- ---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<util::disasm_interface> jaguargpu_cpu_device::create_disassembler()
{
return std::make_unique<jaguar_disassembler>(jaguar_disassembler::variant::GPU);

View File

@ -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<util::disasm_interface> 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<util::disasm_interface> create_disassembler() override;
DECLARE_WRITE32_MEMBER(modulo_w);
DECLARE_WRITE32_MEMBER(dsp_end_w);
DECLARE_READ32_MEMBER(high_accum_r);
};

View File

@ -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 */

View File

@ -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));

View File

@ -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<cpu_device> m_maincpu;
required_device<jaguargpu_cpu_device> m_gpu;
required_device<jag_blitter_device> m_blitter;
required_device<jaguardsp_cpu_device> m_dsp;
required_device<dac_word_interface> m_ldac;
required_device<dac_word_interface> 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<uint8_t *>(m_gpu->space(AS_PROGRAM).get_read_ptr(offset)); }
void blitter_run();
void scanline_update(int param);

View File

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

View File

@ -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

View File

@ -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;
}
}

View File

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