mirror of
https://github.com/holub/mame
synced 2025-04-19 07:00:31 +03:00
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:
parent
12ec6362bb
commit
5ad522f0c1
@ -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>
|
||||
|
@ -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",
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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);
|
||||
|
240
src/mame/video/jag_blitter.cpp
Normal file
240
src/mame/video/jag_blitter.cpp
Normal 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);
|
||||
}
|
100
src/mame/video/jag_blitter.h
Normal file
100
src/mame/video/jag_blitter.h
Normal 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
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user