summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Aaron Giles <aaron@aarongiles.com>2007-12-28 06:11:52 +0000
committer Aaron Giles <aaron@aarongiles.com>2007-12-28 06:11:52 +0000
commit2f8231e10a29484f8af05ff396e3842e558a0c57 (patch)
tree1f55a4e382171bf0db48c71e4aa259db68dd560b
parent8d6c62b976d1f9190f5c776646f01cd76ede65e9 (diff)
TMS3203x core updates:
* fixed interrupt handling * added support for edge-triggered interrupts on '32 * expanded interrupt support for the '32 * updated drivers using TMS3203x core to deassert interrupts * added externally accessible functions for converting '3x floating point format * updated gaelco3d driver to use new functions Zeus2 (+related) updates: * fixed save states for DCS games * cleaned up Zeus2 waveram handling * added Zeus2 save state support * added preliminary model and quad rendering support for Zeus2 * added support to timekpr for the ZPRAM used on Zeus2 * hooked up ZPRAM in Zeus2 games * hooked up controls in Zeus2 games * updated poly.c to ensure it is idle before saving state
-rw-r--r--src/emu/cpu/adsp2100/adsp2100.c2
-rw-r--r--src/emu/cpu/tms32031/32031ops.c24
-rw-r--r--src/emu/cpu/tms32031/tms32031.c152
-rw-r--r--src/emu/cpu/tms32031/tms32031.h7
-rw-r--r--src/emu/machine/timekpr.c25
-rw-r--r--src/emu/machine/timekpr.h6
-rw-r--r--src/emu/video/poly.c17
-rw-r--r--src/mame/audio/cage.c1
-rw-r--r--src/mame/audio/dcs.c6
-rw-r--r--src/mame/drivers/midvunit.c3
-rw-r--r--src/mame/drivers/midzeus.c172
-rw-r--r--src/mame/video/gaelco3d.c78
-rw-r--r--src/mame/video/midvunit.c12
-rw-r--r--src/mame/video/midzeus.c2
-rw-r--r--src/mame/video/midzeus2.c728
15 files changed, 1028 insertions, 207 deletions
diff --git a/src/emu/cpu/adsp2100/adsp2100.c b/src/emu/cpu/adsp2100/adsp2100.c
index 2d2d9a4b0da..d5e2788e700 100644
--- a/src/emu/cpu/adsp2100/adsp2100.c
+++ b/src/emu/cpu/adsp2100/adsp2100.c
@@ -717,7 +717,6 @@ static void adsp2100_init(int index, int clock, const void *config, int (*irqcal
state_save_register_item("adsp2100", index, adsp2100.fl0);
state_save_register_item("adsp2100", index, adsp2100.fl1);
state_save_register_item("adsp2100", index, adsp2100.fl2);
-
state_save_register_item("adsp2100", index, adsp2100.idma_addr);
state_save_register_item("adsp2100", index, adsp2100.idma_cache);
state_save_register_item("adsp2100", index, adsp2100.idma_offs);
@@ -725,7 +724,6 @@ static void adsp2100_init(int index, int clock, const void *config, int (*irqcal
state_save_register_item("adsp2100", index, adsp2100.imask);
state_save_register_item("adsp2100", index, adsp2100.icntl);
state_save_register_item("adsp2100", index, adsp2100.ifc);
-
state_save_register_item_array("adsp2100", index, adsp2100.irq_state);
state_save_register_item_array("adsp2100", index, adsp2100.irq_latch);
state_save_register_item("adsp2100", index, adsp2100.interrupt_cycles);
diff --git a/src/emu/cpu/tms32031/32031ops.c b/src/emu/cpu/tms32031/32031ops.c
index bc8e1e96e8b..f4c9d1e74eb 100644
--- a/src/emu/cpu/tms32031/32031ops.c
+++ b/src/emu/cpu/tms32031/32031ops.c
@@ -1793,7 +1793,7 @@ static void float_imm(void)
static void idle(void)
{
- tms32031.is_idling = 1;
+ tms32031.is_idling = TRUE;
IREG(TMR_ST) |= GIEFLAG;
check_irqs();
if (tms32031.is_idling)
@@ -2541,7 +2541,7 @@ static void rtps_reg(void)
IREG(TMR_RE) = tms32031.pc;
IREG(TMR_ST) |= RMFLAG;
tms32031_icount -= 3*2;
- tms32031.delayed = 1;
+ tms32031.delayed = TRUE;
}
static void rtps_dir(void)
@@ -2551,7 +2551,7 @@ static void rtps_dir(void)
IREG(TMR_RE) = tms32031.pc;
IREG(TMR_ST) |= RMFLAG;
tms32031_icount -= 3*2;
- tms32031.delayed = 1;
+ tms32031.delayed = TRUE;
}
static void rtps_ind(void)
@@ -2561,7 +2561,7 @@ static void rtps_ind(void)
IREG(TMR_RE) = tms32031.pc;
IREG(TMR_ST) |= RMFLAG;
tms32031_icount -= 3*2;
- tms32031.delayed = 1;
+ tms32031.delayed = TRUE;
}
static void rtps_imm(void)
@@ -2571,7 +2571,7 @@ static void rtps_imm(void)
IREG(TMR_RE) = tms32031.pc;
IREG(TMR_ST) |= RMFLAG;
tms32031_icount -= 3*2;
- tms32031.delayed = 1;
+ tms32031.delayed = TRUE;
}
/*-----------------------------------------------------*/
@@ -5308,7 +5308,7 @@ static void ldizuf_imm(void)
INLINE void execute_delayed(UINT32 newpc)
{
- tms32031.delayed = 1;
+ tms32031.delayed = TRUE;
execute_one();
execute_one();
@@ -5317,10 +5317,10 @@ INLINE void execute_delayed(UINT32 newpc)
tms32031.pc = newpc;
UPDATEPC(tms32031.pc);
- tms32031.delayed = 0;
+ tms32031.delayed = FALSE;
if (tms32031.irq_pending)
{
- tms32031.irq_pending = 0;
+ tms32031.irq_pending = FALSE;
check_irqs();
}
}
@@ -5473,7 +5473,12 @@ static void trap(int trapnum)
{
WMEM(++IREG(TMR_SP), tms32031.pc);
IREG(TMR_ST) &= ~GIEFLAG;
- tms32031.pc = tms32031.mcu_mode ? (0x809fc0 + trapnum) : RMEM(trapnum);
+ if (tms32031.is_32032)
+ tms32031.pc = RMEM(((IREG(TMR_IF) >> 16) << 8) + trapnum);
+ else if (tms32031.mcu_mode)
+ tms32031.pc = 0x809fc0 + trapnum;
+ else
+ tms32031.pc = RMEM(trapnum);
UPDATEPC(tms32031.pc);
tms32031_icount -= 4*2;
}
@@ -5494,6 +5499,7 @@ static void retic_reg(void)
UPDATEPC(tms32031.pc);
IREG(TMR_ST) |= GIEFLAG;
tms32031_icount -= 3*2;
+ check_irqs();
}
}
diff --git a/src/emu/cpu/tms32031/tms32031.c b/src/emu/cpu/tms32031/tms32031.c
index 6907cd1cc2f..b6de2ca1312 100644
--- a/src/emu/cpu/tms32031/tms32031.c
+++ b/src/emu/cpu/tms32031/tms32031.c
@@ -95,11 +95,12 @@ typedef struct
UINT32 bkmask;
/* internal stuff */
- UINT32 ppc;
UINT32 op;
+ UINT16 irq_state;
UINT8 delayed;
UINT8 irq_pending;
UINT8 mcu_mode;
+ UINT8 is_32032;
UINT8 is_idling;
int interrupt_cycles;
@@ -167,7 +168,6 @@ typedef union int_double
} int_double;
-#if 0
static float dsp_to_float(union genreg *fp)
{
int_double id;
@@ -187,7 +187,6 @@ static float dsp_to_float(union genreg *fp)
}
return id.f[0];
}
-#endif
static double dsp_to_double(union genreg *fp)
@@ -252,6 +251,46 @@ static void double_to_dsp(double val, union genreg *result)
}
+float convert_tms3203x_fp_to_float(UINT32 floatdata)
+{
+ union genreg gen;
+
+ SET_MANTISSA(&gen, floatdata << 8);
+ SET_EXPONENT(&gen, (INT32)floatdata >> 24);
+
+ return dsp_to_float(&gen);
+}
+
+
+double convert_tms3203x_fp_to_double(UINT32 floatdata)
+{
+ union genreg gen;
+
+ SET_MANTISSA(&gen, floatdata << 8);
+ SET_EXPONENT(&gen, (INT32)floatdata >> 24);
+
+ return dsp_to_double(&gen);
+}
+
+
+UINT32 convert_float_to_tms3203x_fp(float fval)
+{
+ union genreg gen;
+
+ double_to_dsp(fval, &gen);
+ return (EXPONENT(&gen) << 24) | ((UINT32)MANTISSA(&gen) >> 8);
+}
+
+
+UINT32 convert_double_to_tms3203x_fp(double dval)
+{
+ union genreg gen;
+
+ double_to_dsp(dval, &gen);
+ return (EXPONENT(&gen) << 24) | ((UINT32)MANTISSA(&gen) >> 8);
+}
+
+
/***************************************************************************
EXECEPTION HANDLING
@@ -274,51 +313,64 @@ INLINE void invalid_instruction(UINT32 op)
static void check_irqs(void)
{
- int validints = IREG(TMR_IF) & IREG(TMR_IE) & 0x07ff;
- if (validints && (IREG(TMR_ST) & GIEFLAG))
- {
- int whichtrap = 0;
- int i;
+ int whichtrap = 0;
+ UINT16 validints;
+ int i;
- for (i = 0; i < 11; i++)
- if (validints & (1 << i))
- {
- whichtrap = i + 1;
- break;
- }
+ /* determine if we have any live interrupts */
+ validints = IREG(TMR_IF) & IREG(TMR_IE) & 0x0fff;
+ if (validints == 0 || (IREG(TMR_ST) & GIEFLAG) == 0)
+ return;
- if (whichtrap)
+ /* find the lowest signalled value */
+ for (i = 0; i < 12; i++)
+ if (validints & (1 << i))
{
- tms32031.is_idling = 0;
- if (!tms32031.delayed)
- {
- trap(whichtrap);
-
- /* for internal sources, clear the interrupt when taken */
- if (whichtrap > 4)
- IREG(TMR_IF) &= ~(1 << (whichtrap - 1));
- }
- else
- tms32031.irq_pending = 1;
+ whichtrap = i + 1;
+ break;
}
+
+ /* no longer idling if we get here */
+ tms32031.is_idling = FALSE;
+ if (!tms32031.delayed)
+ {
+ UINT16 intmask = 1 << (whichtrap - 1);
+
+ /* bit in IF is cleared when interrupt is taken */
+ IREG(TMR_IF) &= ~intmask;
+ trap(whichtrap);
+
+ /* external interrupts are level-sensitive on the '31 and can be
+ configured as such on the '32; in that case, if the external
+ signal is still high, we need to retrigger the interrupt */
+ if (whichtrap < 4 && (!tms32031.is_32032 || (IREG(TMR_ST) & 0x4000) == 0))
+ IREG(TMR_IF) |= tms32031.irq_state & intmask;
}
+ else
+ tms32031.irq_pending = TRUE;
}
static void set_irq_line(int irqline, int state)
{
- if (irqline < 11)
- {
- /* update the state */
- if (state == ASSERT_LINE)
- IREG(TMR_IF) |= 1 << irqline;
- else
- IREG(TMR_IF) &= ~(1 << irqline);
-
- /* check for IRQs */
- if (state != CLEAR_LINE)
- check_irqs();
+ UINT16 oldstate = tms32031.irq_state;
+ UINT16 intmask = 1 << irqline;
+
+ /* ignore anything out of range */
+ if (irqline >= 12)
+ return;
+
+ /* update the external state */
+ if (state == ASSERT_LINE)
+ {
+ tms32031.irq_state |= intmask;
+ IREG(TMR_IF) |= intmask;
}
+ else
+ tms32031.irq_state &= ~intmask;
+
+ /* check for IRQs */
+ check_irqs();
}
@@ -376,8 +428,8 @@ static void tms32031_init(int index, int clock, const void *_config, int (*irqca
state_save_register_generic("tms32031", index, namebuf, tms32031.r[i].i8, UINT8, 8);
}
state_save_register_item("tms32031", index, tms32031.bkmask);
- state_save_register_item("tms32031", index, tms32031.ppc);
state_save_register_item("tms32031", index, tms32031.op);
+ state_save_register_item("tms32031", index, tms32031.irq_state);
state_save_register_item("tms32031", index, tms32031.delayed);
state_save_register_item("tms32031", index, tms32031.irq_pending);
state_save_register_item("tms32031", index, tms32031.mcu_mode);
@@ -391,14 +443,15 @@ static void tms32031_reset(void)
/* if we have a config struct, get the boot ROM address */
if (tms32031.bootoffset)
{
- tms32031.mcu_mode = 1;
+ tms32031.mcu_mode = TRUE;
tms32031.pc = boot_loader(tms32031.bootoffset);
}
else
{
- tms32031.mcu_mode = 0;
+ tms32031.mcu_mode = FALSE;
tms32031.pc = RMEM(0);
}
+ tms32031.is_32032 = FALSE;
/* reset some registers */
IREG(TMR_IE) = 0;
@@ -407,8 +460,14 @@ static void tms32031_reset(void)
IREG(TMR_IOF) = 0;
/* reset internal stuff */
- tms32031.delayed = tms32031.irq_pending = 0;
- tms32031.is_idling = 0;
+ tms32031.delayed = tms32031.irq_pending = FALSE;
+ tms32031.is_idling = FALSE;
+}
+
+static void tms32032_reset(void)
+{
+ tms32031_reset();
+ tms32031.is_32032 = TRUE;
}
@@ -465,10 +524,10 @@ static int tms32031_execute(int cycles)
IREG(TMR_ST) &= ~RMFLAG;
if (tms32031.delayed)
{
- tms32031.delayed = 0;
+ tms32031.delayed = FALSE;
if (tms32031.irq_pending)
{
- tms32031.irq_pending = 0;
+ tms32031.irq_pending = FALSE;
check_irqs();
}
}
@@ -593,6 +652,7 @@ static void tms32031_set_info(UINT32 state, cpuinfo *info)
case CPUINFO_INT_INPUT_STATE + TMS32031_TINT0: set_irq_line(TMS32031_TINT0, info->i); break;
case CPUINFO_INT_INPUT_STATE + TMS32031_TINT1: set_irq_line(TMS32031_TINT1, info->i); break;
case CPUINFO_INT_INPUT_STATE + TMS32031_DINT: set_irq_line(TMS32031_DINT, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + TMS32031_DINT1: set_irq_line(TMS32031_DINT1, info->i); break;
case CPUINFO_INT_PC:
case CPUINFO_INT_REGISTER + TMS32031_PC: tms32031.pc = info->i; break;
@@ -692,8 +752,9 @@ void tms32031_get_info(UINT32 state, cpuinfo *info)
case CPUINFO_INT_INPUT_STATE + TMS32031_TINT0: info->i = (IREG(TMR_IF) & (1 << TMS32031_TINT0)) ? ASSERT_LINE : CLEAR_LINE; break;
case CPUINFO_INT_INPUT_STATE + TMS32031_TINT1: info->i = (IREG(TMR_IF) & (1 << TMS32031_TINT1)) ? ASSERT_LINE : CLEAR_LINE; break;
case CPUINFO_INT_INPUT_STATE + TMS32031_DINT: info->i = (IREG(TMR_IF) & (1 << TMS32031_DINT)) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + TMS32031_DINT1: info->i = (IREG(TMR_IF) & (1 << TMS32031_DINT1)) ? ASSERT_LINE : CLEAR_LINE; break;
- case CPUINFO_INT_PREVIOUSPC: info->i = tms32031.ppc; break;
+ case CPUINFO_INT_PREVIOUSPC: /* not implemented */ break;
case CPUINFO_INT_PC:
case CPUINFO_INT_REGISTER + TMS32031_PC: info->i = tms32031.pc; break;
@@ -819,6 +880,7 @@ void tms32032_get_info(UINT32 state, cpuinfo *info)
switch (state)
{
/* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_RESET: info->reset = tms32032_reset; break;
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map = construct_map_internal_32032; break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
diff --git a/src/emu/cpu/tms32031/tms32031.h b/src/emu/cpu/tms32031/tms32031.h
index 3a19a6e93a7..1ecc7ce5fdc 100644
--- a/src/emu/cpu/tms32031/tms32031.h
+++ b/src/emu/cpu/tms32031/tms32031.h
@@ -59,6 +59,8 @@ enum
#define TMS32031_TINT0 8 /* timer 0 interrupt */
#define TMS32031_TINT1 9 /* timer 1 interrupt */
#define TMS32031_DINT 10 /* DMA interrupt */
+#define TMS32031_DINT0 10 /* DMA 0 interrupt (32032 only) */
+#define TMS32031_DINT1 11 /* DMA 1 interrupt (32032 only) */
/***************************************************************************
@@ -68,4 +70,9 @@ enum
extern void tms32031_get_info(UINT32 state, cpuinfo *info);
extern void tms32032_get_info(UINT32 state, cpuinfo *info);
+extern float convert_tms3203x_fp_to_float(UINT32 floatdata);
+extern double convert_tms3203x_fp_to_double(UINT32 floatdata);
+extern UINT32 convert_float_to_tms3203x_fp(float fval);
+extern UINT32 convert_double_to_tms3203x_fp(double dval);
+
#endif /* _TMS32031_H */
diff --git a/src/emu/machine/timekpr.c b/src/emu/machine/timekpr.c
index b54b2d22441..a8c5fce4ea1 100644
--- a/src/emu/machine/timekpr.c
+++ b/src/emu/machine/timekpr.c
@@ -268,6 +268,19 @@ void timekeeper_init( int chip, int type, UINT8 *data )
c->offset_flags = 0x1ff0;
c->size = 0x2000;
break;
+ case TIMEKEEPER_MIDZEUS2:
+ c->offset_control = 0x7ff8;
+ c->offset_seconds = 0x7ff9;
+ c->offset_minutes = 0x7ffa;
+ c->offset_hours = 0x7ffb;
+ c->offset_day = 0x7ffc;
+ c->offset_date = 0x7ffd;
+ c->offset_month = 0x7ffe;
+ c->offset_year = 0x7fff;
+ c->offset_century = -1;
+ c->offset_flags = -1;
+ c->size = 0x8000;
+ break;
}
if( data == NULL )
@@ -383,6 +396,18 @@ static void timekeeper_write( UINT32 chip, offs_t offset, UINT8 data )
c->data[ offset ] = data;
}
+/* 8bit memory handlers */
+
+READ8_HANDLER( timekeeper_0_r )
+{
+ return timekeeper_read(0, offset);
+}
+
+WRITE8_HANDLER( timekeeper_0_w )
+{
+ timekeeper_write(0, offset, data);
+}
+
/* 16bit memory handlers */
static UINT16 timekeeper_msb16_read( UINT32 chip, offs_t offset, UINT16 mem_mask )
diff --git a/src/emu/machine/timekpr.h b/src/emu/machine/timekpr.h
index f651168fa80..b8d3bbd57ef 100644
--- a/src/emu/machine/timekpr.h
+++ b/src/emu/machine/timekpr.h
@@ -15,11 +15,17 @@ extern void timekeeper_init( int chip, int type, UINT8 *data );
#define TIMEKEEPER_M48T58 ( 1 )
#define TIMEKEEPER_M48T02 ( 2 )
#define TIMEKEEPER_MK48T08 ( 3 )
+#define TIMEKEEPER_MIDZEUS2 ( 4 )
/* nvram handlers */
extern NVRAM_HANDLER( timekeeper_0 );
+/* 8bit memory handlers */
+
+extern READ8_HANDLER( timekeeper_0_r );
+extern WRITE8_HANDLER( timekeeper_0_w );
+
/* 16bit memory handlers */
extern READ16_HANDLER( timekeeper_0_msb16_r );
diff --git a/src/emu/video/poly.c b/src/emu/video/poly.c
index adafbe6a47d..19604d900e3 100644
--- a/src/emu/video/poly.c
+++ b/src/emu/video/poly.c
@@ -9,6 +9,7 @@
#include "poly.h"
#include "eminline.h"
#include "mame.h"
+#include "state.h"
#include <math.h>
@@ -205,6 +206,7 @@ struct _poly_manager
static void **allocate_array(size_t *itemsize, UINT32 itemcount);
static void free_array(void **array);
static void *poly_item_callback(void *param, int threadid);
+static void poly_state_presave(void *param);
@@ -356,6 +358,9 @@ poly_manager *poly_alloc(int max_polys, size_t extra_data_size, UINT8 flags)
/* create the work queue */
if (!(flags & POLYFLAG_NO_WORK_QUEUE))
poly->queue = osd_work_queue_alloc(WORK_QUEUE_FLAG_MULTI | WORK_QUEUE_FLAG_HIGH_FREQ);
+
+ /* request a pre-save callback for synchronization */
+ state_save_register_func_presave_ptr(poly_state_presave, poly);
return poly;
}
@@ -1408,3 +1413,15 @@ static void *poly_item_callback(void *param, int threadid)
}
return NULL;
}
+
+
+/*-------------------------------------------------
+ poly_state_presave - pre-save callback to
+ ensure everything is synced before saving
+-------------------------------------------------*/
+
+static void poly_state_presave(void *param)
+{
+ poly_manager *poly = param;
+ poly_wait(poly, "pre-save");
+}
diff --git a/src/mame/audio/cage.c b/src/mame/audio/cage.c
index 7db002f4669..6e5c79624bf 100644
--- a/src/mame/audio/cage.c
+++ b/src/mame/audio/cage.c
@@ -466,6 +466,7 @@ static READ32_HANDLER( cage_from_main_r )
logerror("%06X:CAGE read command = %04X\n", activecpu_get_pc(), cage_from_main);
cpu_to_cage_ready = 0;
update_control_lines();
+ cpunum_set_input_line(cage_cpu, TMS32031_IRQ0, CLEAR_LINE);
return cage_from_main;
}
diff --git a/src/mame/audio/dcs.c b/src/mame/audio/dcs.c
index e3f61d00677..2ac84a2f825 100644
--- a/src/mame/audio/dcs.c
+++ b/src/mame/audio/dcs.c
@@ -891,6 +891,8 @@ static void dcs_register_state(void)
state_save_register_global(transfer.writes_left);
state_save_register_global(transfer.sum);
state_save_register_global(transfer.fifo_entries);
+
+ state_save_register_global_pointer(dcs_sram, 0x8000*4 / sizeof(dcs_sram[0]));
}
@@ -924,7 +926,6 @@ void dcs_init(void)
void dcs2_init(int dram_in_mb, offs_t polling_offset)
{
- dcs_register_state();
memset(&dcs, 0, sizeof(dcs));
/* find the DCS CPU and the sound ROMs */
@@ -978,6 +979,9 @@ void dcs2_init(int dram_in_mb, offs_t polling_offset)
if (transfer.hle_enabled)
transfer.watchdog = timer_alloc(transfer_watchdog_callback, NULL);
+ /* register for save states */
+ dcs_register_state();
+
/* reset the system */
dcs_reset(Machine, NULL, 0);
}
diff --git a/src/mame/drivers/midvunit.c b/src/mame/drivers/midvunit.c
index c60b5d3a83b..2e68cadb7c3 100644
--- a/src/mame/drivers/midvunit.c
+++ b/src/mame/drivers/midvunit.c
@@ -133,7 +133,10 @@ static READ32_HANDLER( port2_r )
static READ32_HANDLER( midvunit_adc_r )
{
if (!(control_data & 0x40))
+ {
+ cpunum_set_input_line(0, 3, CLEAR_LINE);
return adc_data << adc_shift;
+ }
else
logerror("adc_r without enabling reads!\n");
return 0xffffffff;
diff --git a/src/mame/drivers/midzeus.c b/src/mame/drivers/midzeus.c
index b239dd137c4..5a5ca058021 100644
--- a/src/mame/drivers/midzeus.c
+++ b/src/mame/drivers/midzeus.c
@@ -20,6 +20,7 @@
#include "cpu/adsp2100/adsp2100.h"
#include "includes/midzeus.h"
#include "machine/midwayic.h"
+#include "machine/timekpr.h"
#include "audio/dcs.h"
@@ -54,17 +55,32 @@ static TIMER_CALLBACK( invasn_gun_callback );
*
*************************************/
-static MACHINE_RESET( midzeus )
+static MACHINE_START( midzeus )
{
- memcpy(ram_base, memory_region(REGION_USER1), 0x40000*4);
-
- *(UINT32 *)ram_base *= 2;
-
timer[0] = timer_alloc(NULL, NULL);
timer[1] = timer_alloc(NULL, NULL);
gun_timer[0] = timer_alloc(invasn_gun_callback, NULL);
gun_timer[1] = timer_alloc(invasn_gun_callback, NULL);
+
+ state_save_register_global(gun_control);
+ state_save_register_global(gun_irq_state);
+ state_save_register_global_array(gun_x);
+ state_save_register_global_array(gun_y);
+}
+
+
+static MACHINE_START( midzeus2 )
+{
+ timekeeper_init(0, TIMEKEEPER_MIDZEUS2, NULL);
+ machine_start_midzeus(machine);
+}
+
+
+static MACHINE_RESET( midzeus )
+{
+ memcpy(ram_base, memory_region(REGION_USER1), 0x40000*4);
+ *ram_base <<= 1;
cmos_protected = TRUE;
}
@@ -73,30 +89,63 @@ static MACHINE_RESET( midzeus )
/*************************************
*
- * CMOS access
+ * CMOS access (Zeus only)
*
*************************************/
+static WRITE32_HANDLER( cmos_w )
+{
+ if (!cmos_protected)
+ COMBINE_DATA(&generic_nvram32[offset]);
+ cmos_protected = TRUE;
+}
+
+
+static READ32_HANDLER( cmos_r )
+{
+ return generic_nvram32[offset];
+}
+
+
static WRITE32_HANDLER( cmos_protect_w )
{
cmos_protected = FALSE;
}
-static WRITE32_HANDLER( cmos_w )
+
+/*************************************
+ *
+ * Timekeeper access (Zeus 2 only)
+ *
+ *************************************/
+
+static READ32_HANDLER( timekeeper_r )
{
- if (!cmos_protected)
- COMBINE_DATA(generic_nvram32 + offset);
- cmos_protected = TRUE;
+ UINT8 result = timekeeper_0_r(offset);
+// logerror("%06X:cmos_time_r(%X) = %02X\n", activecpu_get_pc(), offset, result);
+ return result;
}
-static READ32_HANDLER( cmos_r )
+static WRITE32_HANDLER( timekeeper_w )
{
- return generic_nvram32[offset];
+ if (!cmos_protected)
+ {
+// logerror("%06X:cmos_time_w(%X) = %02X\n", activecpu_get_pc(), offset, data);
+ timekeeper_0_w(offset, data);
+ }
+ cmos_protected = TRUE;
}
+
+/*************************************
+ *
+ * Zero-power RAM access (Zeus 2 only)
+ *
+ *************************************/
+
static WRITE32_HANDLER( zpram_w )
{
/* ZPRAM seems to use the same protection control as CMOS */
@@ -112,23 +161,23 @@ static READ32_HANDLER( zpram_r )
}
-static NVRAM_HANDLER( zeus2_nvram )
+
+/*************************************
+ *
+ * NVRAM handler (Zeus 2 only)
+ *
+ *************************************/
+
+static NVRAM_HANDLER( midzeus2 )
{
+ nvram_handler_timekeeper_0(machine, file, read_or_write);
+
if (read_or_write)
- {
- mame_fwrite(file, generic_nvram, generic_nvram_size);
mame_fwrite(file, zpram, zpram_size);
- }
else if (file)
- {
- mame_fread(file, generic_nvram, generic_nvram_size);
mame_fread(file, zpram, zpram_size);
- }
else
- {
- memset(generic_nvram, 0xff, generic_nvram_size);
memset(zpram, 0xff, zpram_size);
- }
}
@@ -181,6 +230,44 @@ static WRITE32_HANDLER( tms32031_control_w )
/*************************************
*
+ * 49-way joystick handling
+ *
+ *************************************/
+
+static UINT32 custom_49way_r(void *param)
+{
+ static const UINT8 translate49[7] = { 0x8, 0xc, 0xe, 0xf, 0x3, 0x1, 0x0 };
+ const char *namex = param;
+ const char *namey = namex + strlen(namex) + 1;
+ return (translate49[readinputportbytag(namey) >> 4] << 4) | translate49[readinputportbytag(namex) >> 4];
+}
+
+
+
+/*************************************
+ *
+ * Analog input handling
+ *
+ *************************************/
+
+static READ32_HANDLER( analog_r )
+{
+ static const char * const tags[] = { "ANALOG0", "ANALOG1", "ANALOG2", "ANALOG3" };
+ if (offset < 8 || offset > 11)
+ logerror("%06X:analog_r(%X)\n", activecpu_get_pc(), offset);
+ return readinputportbytag(tags[offset & 3]);
+}
+
+
+static WRITE32_HANDLER( analog_w )
+{
+ /* 16 writes to the location before a read */
+}
+
+
+
+/*************************************
+ *
* Lightgun handling
*
*************************************/
@@ -290,7 +377,8 @@ static WRITE32_HANDLER( unknown_9d0000_w )
static WRITE32_HANDLER( rombank_select_w )
{
- memory_set_bank(1, data);
+ if (data >= 0 && data <= 2)
+ memory_set_bank(1, data);
}
static READ32_HANDLER( unknown_8a0000_r )
@@ -335,8 +423,9 @@ static ADDRESS_MAP_START( zeus2_map, ADDRESS_SPACE_PROGRAM, 32 )
AM_RANGE(0x8d0005, 0x8d0005) AM_WRITE(rombank_select_w)
AM_RANGE(0x900000, 0x91ffff) AM_READWRITE(zpram_r, zpram_w) AM_BASE(&zpram) AM_SIZE(&zpram_size) AM_MIRROR(0x020000)
AM_RANGE(0x990000, 0x99000f) AM_READWRITE(midway_ioasic_r, midway_ioasic_w)
+ AM_RANGE(0x9c0000, 0x9c000f) AM_READWRITE(analog_r, analog_w)
AM_RANGE(0x9e0000, 0x9e0000) AM_WRITENOP // watchdog?
- AM_RANGE(0x9f0000, 0x9f7fff) AM_READWRITE(cmos_r, cmos_w) AM_BASE(&generic_nvram32) AM_SIZE(&generic_nvram_size)
+ AM_RANGE(0x9f0000, 0x9f7fff) AM_READWRITE(timekeeper_r, timekeeper_w)
AM_RANGE(0x9f8000, 0x9f8000) AM_WRITE(cmos_protect_w)
AM_RANGE(0xa00000, 0xbfffff) AM_ROM AM_REGION(REGION_USER1, 0)
AM_RANGE(0xc00000, 0xffffff) AM_ROMBANK(1) AM_REGION(REGION_USER2, 0)
@@ -652,6 +741,18 @@ static INPUT_PORTS_START( crusnexo )
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(3) /* keypad 2 */
PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_PLAYER(3) /* keypad 2 */
PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START_TAG("ANALOG3")
+ PORT_BIT( 0xff, 0x80, IPT_PADDLE ) PORT_MINMAX(0x10,0xf0) PORT_SENSITIVITY(25) PORT_KEYDELTA(20)
+
+ PORT_START_TAG("ANALOG2")
+ PORT_BIT( 0xff, 0x00, IPT_PEDAL ) PORT_SENSITIVITY(25) PORT_KEYDELTA(20)
+
+ PORT_START_TAG("ANALOG1")
+ PORT_BIT( 0xff, 0x00, IPT_PEDAL2 ) PORT_SENSITIVITY(25) PORT_KEYDELTA(20)
+
+ PORT_START_TAG("ANALOG0")
+ PORT_BIT( 0xff, 0x00, IPT_UNUSED )
INPUT_PORTS_END
@@ -740,7 +841,6 @@ static INPUT_PORTS_START( thegrid )
PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_VOLUME_UP )
PORT_BIT( 0x6000, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_BILL1 ) /* Bill */
- PORT_BIT (0xffff0000, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START /* Listed "names" are via the manual's "JAMMA" pinout sheet" */
PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_8WAY /* Not Used */
@@ -759,18 +859,16 @@ static INPUT_PORTS_START( thegrid )
PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) /* No Connection */
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) /* No Connection */
PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT (0xffff0000, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START
- PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(1)
- PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1)
- PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(1)
- PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(2)
- PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2)
- PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(2)
- PORT_BIT( 0xff80, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT (0xffff0000, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_CUSTOM(custom_49way_r, "49WAYX\0" "49WAYY")
+ PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START_TAG("49WAYX")
+ PORT_BIT( 0xff, 0x38, IPT_AD_STICK_X ) PORT_MINMAX(0x00,0x6f) PORT_SENSITIVITY(100) PORT_KEYDELTA(10)
+
+ PORT_START_TAG("49WAYY")
+ PORT_BIT( 0xff, 0x38, IPT_AD_STICK_Y ) PORT_MINMAX(0x00,0x6f) PORT_SENSITIVITY(100) PORT_KEYDELTA(10)
INPUT_PORTS_END
@@ -788,6 +886,7 @@ static MACHINE_DRIVER_START( midzeus )
MDRV_CPU_PROGRAM_MAP(zeus_map,0)
MDRV_CPU_VBLANK_INT(irq0_line_assert,1)
+ MDRV_MACHINE_START(midzeus)
MDRV_MACHINE_RESET(midzeus)
MDRV_NVRAM_HANDLER(generic_1fill)
@@ -814,8 +913,9 @@ static MACHINE_DRIVER_START( midzeus2 )
MDRV_CPU_PROGRAM_MAP(zeus2_map,0)
MDRV_CPU_VBLANK_INT(irq0_line_assert,1)
+ MDRV_MACHINE_START(midzeus2)
MDRV_MACHINE_RESET(midzeus)
- MDRV_NVRAM_HANDLER(zeus2_nvram)
+ MDRV_NVRAM_HANDLER(midzeus2)
/* video hardware */
MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER)
diff --git a/src/mame/video/gaelco3d.c b/src/mame/video/gaelco3d.c
index d346236242c..4bc4063d9f3 100644
--- a/src/mame/video/gaelco3d.c
+++ b/src/mame/video/gaelco3d.c
@@ -9,6 +9,7 @@
#include "driver.h"
#include "eminline.h"
#include "gaelco3d.h"
+#include "cpu/tms32031/tms32031.h"
#include "video/rgbutil.h"
#include "video/poly.h"
@@ -100,43 +101,6 @@ VIDEO_START( gaelco3d )
/*************************************
*
- * TMS32031 floating point conversion
- *
- *************************************/
-
-typedef union int_double
-{
- double d;
- float f[2];
- UINT32 i[2];
-} int_double;
-
-
-static float dsp_to_float(UINT32 val)
-{
- INT32 _mantissa = val << 8;
- INT8 _exponent = (INT32)val >> 24;
- int_double id;
-
- if (_mantissa == 0 && _exponent == -128)
- return 0;
- else if (_mantissa >= 0)
- {
- int exponent = (_exponent + 127) << 23;
- id.i[0] = exponent + (_mantissa >> 8);
- }
- else
- {
- int exponent = (_exponent + 127) << 23;
- INT32 man = -_mantissa;
- id.i[0] = 0x80000000 + exponent + ((man >> 8) & 0x00ffffff);
- }
- return id.f[0];
-}
-
-
-/*************************************
- *
* Polygon rendering
*
*************************************/
@@ -166,16 +130,16 @@ static void render_poly(UINT32 *polydata)
{
float midx = Machine->screen[0].width / 2;
float midy = Machine->screen[0].height / 2;
- float z0 = dsp_to_float(polydata[0]);
- float voz_dy = dsp_to_float(polydata[1]) * 256.0f;
- float voz_dx = dsp_to_float(polydata[2]) * 256.0f;
- float ooz_dy = dsp_to_float(polydata[3]);
- float ooz_dx = dsp_to_float(polydata[4]);
- float uoz_dy = dsp_to_float(polydata[5]) * 256.0f;
- float uoz_dx = dsp_to_float(polydata[6]) * 256.0f;
- float voz_base = dsp_to_float(polydata[7]) * 256.0f - midx * voz_dx - midy * voz_dy;
- float ooz_base = dsp_to_float(polydata[8]) - midx * ooz_dx - midy * ooz_dy;
- float uoz_base = dsp_to_float(polydata[9]) * 256.0f - midx * uoz_dx - midy * uoz_dy;
+ float z0 = convert_tms3203x_fp_to_float(polydata[0]);
+ float voz_dy = convert_tms3203x_fp_to_float(polydata[1]) * 256.0f;
+ float voz_dx = convert_tms3203x_fp_to_float(polydata[2]) * 256.0f;
+ float ooz_dy = convert_tms3203x_fp_to_float(polydata[3]);
+ float ooz_dx = convert_tms3203x_fp_to_float(polydata[4]);
+ float uoz_dy = convert_tms3203x_fp_to_float(polydata[5]) * 256.0f;
+ float uoz_dx = convert_tms3203x_fp_to_float(polydata[6]) * 256.0f;
+ float voz_base = convert_tms3203x_fp_to_float(polydata[7]) * 256.0f - midx * voz_dx - midy * voz_dy;
+ float ooz_base = convert_tms3203x_fp_to_float(polydata[8]) - midx * ooz_dx - midy * ooz_dy;
+ float uoz_base = convert_tms3203x_fp_to_float(polydata[9]) * 256.0f - midx * uoz_dx - midy * uoz_dy;
poly_extra_data *extra = poly_get_extra_data(poly);
int color = (polydata[10] & 0x7f) << 8;
poly_vertex vert[MAX_VERTICES];
@@ -186,16 +150,16 @@ static void render_poly(UINT32 *polydata)
{
int t;
logerror("poly: %12.2f %12.2f %12.2f %12.2f %12.2f %12.2f %12.2f %12.2f %12.2f %12.2f %08X %08X (%4d,%4d) %08X",
- (double)dsp_to_float(polydata[0]),
- (double)dsp_to_float(polydata[1]),
- (double)dsp_to_float(polydata[2]),
- (double)dsp_to_float(polydata[3]),
- (double)dsp_to_float(polydata[4]),
- (double)dsp_to_float(polydata[5]),
- (double)dsp_to_float(polydata[6]),
- (double)dsp_to_float(polydata[7]),
- (double)dsp_to_float(polydata[8]),
- (double)dsp_to_float(polydata[9]),
+ (double)convert_tms3203x_fp_to_float(polydata[0]),
+ (double)convert_tms3203x_fp_to_float(polydata[1]),
+ (double)convert_tms3203x_fp_to_float(polydata[2]),
+ (double)convert_tms3203x_fp_to_float(polydata[3]),
+ (double)convert_tms3203x_fp_to_float(polydata[4]),
+ (double)convert_tms3203x_fp_to_float(polydata[5]),
+ (double)convert_tms3203x_fp_to_float(polydata[6]),
+ (double)convert_tms3203x_fp_to_float(polydata[7]),
+ (double)convert_tms3203x_fp_to_float(polydata[8]),
+ (double)convert_tms3203x_fp_to_float(polydata[9]),
polydata[10],
polydata[11],
(INT16)(polydata[12] >> 16), (INT16)(polydata[12] << 2) >> 2, polydata[12]);
diff --git a/src/mame/video/midvunit.c b/src/mame/video/midvunit.c
index 5d7094106b9..5960ea2fdd3 100644
--- a/src/mame/video/midvunit.c
+++ b/src/mame/video/midvunit.c
@@ -56,9 +56,15 @@ struct _poly_extra_data
static TIMER_CALLBACK( scanline_timer_cb )
{
int scanline = param;
-
- cpunum_set_input_line(0, 0, ASSERT_LINE);
- timer_adjust(scanline_timer, video_screen_get_time_until_pos(0, scanline + 1, 0), scanline, attotime_zero);
+
+ if (scanline != -1)
+ {
+ cpunum_set_input_line(0, 0, ASSERT_LINE);
+ timer_adjust(scanline_timer, video_screen_get_time_until_pos(0, scanline + 1, 0), scanline, attotime_zero);
+ timer_set(video_screen_get_time_until_pos(0, video_screen_get_vpos(0) + 1, video_screen_get_hpos(0)), NULL, -1, scanline_timer_cb);
+ }
+ else
+ cpunum_set_input_line(0, 0, CLEAR_LINE);
}
diff --git a/src/mame/video/midzeus.c b/src/mame/video/midzeus.c
index 16decd6669d..3ca73400e6a 100644
--- a/src/mame/video/midzeus.c
+++ b/src/mame/video/midzeus.c
@@ -1392,7 +1392,7 @@ static void log_waveram(UINT32 length_and_base)
UINT32 numoctets = (length_and_base >> 24) + 1;
const UINT32 *ptr = waveram_ptr_from_block_addr(0, length_and_base);
- UINT64 checksum = length_and_base;
+ UINT32 checksum = length_and_base;
int foundit = FALSE;
int i;
diff --git a/src/mame/video/midzeus2.c b/src/mame/video/midzeus2.c
index 83ed6276f5b..e70706cf256 100644
--- a/src/mame/video/midzeus2.c
+++ b/src/mame/video/midzeus2.c
@@ -6,6 +6,7 @@
#include "driver.h"
#include "eminline.h"
+#include "cpu/tms32031/tms32031.h"
#include "includes/midzeus.h"
#include "video/poly.h"
#include "video/rgbutil.h"
@@ -18,10 +19,13 @@
*
*************************************/
-#define DUMP_WAVE_RAM 0
+#define DUMP_WAVE_RAM 1
-#define WAVERAM_WIDTH 1024
-#define WAVERAM_HEIGHT 2048
+#define WAVERAM0_WIDTH 1024
+#define WAVERAM0_HEIGHT 2048
+
+#define WAVERAM1_WIDTH 512
+#define WAVERAM1_HEIGHT 1024
@@ -62,9 +66,16 @@ static UINT8 zeus_fifo_words;
static void *zeus_renderbase;
static rectangle zeus_cliprect;
-static void *waveram[2];
+static float zeus_matrix[3][3];
+static float zeus_point[3];
+static float zeus_point2[3];
+static UINT32 zeus_texbase;
+static UINT32 zeus_unknown_40;
+static int zeus_quad_size;
+
+static UINT32 *waveram[2];
+static emu_timer *int_timer;
-static UINT32 max_waveram[2][2];
/*************************************
@@ -77,9 +88,14 @@ static void exit_handler(running_machine *machine);
static void zeus_register32_w(offs_t offset, UINT32 data, int logit);
static void zeus_register_update(offs_t offset, UINT32 oldval, int logit);
+static void zeus_pointer_write(UINT8 which, UINT32 value);
static int zeus_fifo_process(const UINT32 *data, int numwords);
+static void zeus_draw_model(UINT32 baseaddr, UINT16 count, int logit);
+static void zeus_draw_quad(const UINT32 *databuffer, UINT32 texoffs, int logit);
+static void render_poly_8bit(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid);
static void log_fifo_command(const UINT32 *data, int numwords, const char *suffix);
+static void log_waveram(UINT32 base, UINT16 length);
@@ -89,7 +105,8 @@ static void log_fifo_command(const UINT32 *data, int numwords, const char *suffi
*
*************************************/
-#define WAVERAM_BLOCK(bank, blocknum) ((void *)((UINT8 *)waveram[bank] + 16 * (blocknum)))
+#define WAVERAM_BLOCK0(blocknum) ((void *)((UINT8 *)waveram[0] + 8 * (blocknum)))
+#define WAVERAM_BLOCK1(blocknum) ((void *)((UINT8 *)waveram[1] + 12 * (blocknum)))
#define WAVERAM_PTR8(base, bytenum) ((UINT8 *)(base) + BYTE4_XOR_LE(bytenum))
#define WAVERAM_READ8(base, bytenum) (*WAVERAM_PTR8(base, bytenum))
@@ -103,14 +120,14 @@ static void log_fifo_command(const UINT32 *data, int numwords, const char *suffi
#define WAVERAM_READ32(base, dwordnum) (*WAVERAM_PTR32(base, dwordnum))
#define WAVERAM_WRITE32(base, dwordnum, data) do { *WAVERAM_PTR32(base, dwordnum) = (data); } while (0)
-#define PIXYX_TO_DWORDNUM(y, x) ((((y) & 0x1fe) << 11) | (((y) & 1) << 10) | (((x) & 0x1fe) << 1) | ((x) & 1))
-#define DEPTHYX_TO_DWORDNUM(y, x) (PIXYX_TO_DWORDNUM(y, x) | 2)
+#define PIXYX_TO_DWORDNUM(y, x) (((((y) & 0x1ff) << 8) | (((x) & 0x1fe) >> 1)) * 3 + ((x) & 1))
+#define DEPTHYX_TO_DWORDNUM(y, x) (PIXYX_TO_DWORDNUM(y, (x) & ~1) + 2)
#define WAVERAM_PTRPIX(base, y, x) WAVERAM_PTR32(base, PIXYX_TO_DWORDNUM(y, x))
#define WAVERAM_READPIX(base, y, x) (*WAVERAM_PTRPIX(base, y, x))
#define WAVERAM_WRITEPIX(base, y, x, color) do { *WAVERAM_PTRPIX(base, y, x) = (color); } while (0)
-#define WAVERAM_PTRDEPTH(base, y, x) WAVERAM_PTR16(base, DEPTHYX_TO_DWORDNUM(y, x & ~1) * 2 + (x & 1))
+#define WAVERAM_PTRDEPTH(base, y, x) WAVERAM_PTR16(base, DEPTHYX_TO_DWORDNUM(y, x) * 2 + (x & 1))
#define WAVERAM_READDEPTH(base, y, x) (*WAVERAM_PTRDEPTH(base, y, x))
#define WAVERAM_WRITEDEPTH(base, y, x, color) do { *WAVERAM_PTRDEPTH(base, y, x) = (color); } while (0)
@@ -122,22 +139,22 @@ static void log_fifo_command(const UINT32 *data, int numwords, const char *suffi
*
*************************************/
-INLINE void *waveram_ptr_from_block_addr(UINT8 bank, UINT32 addr)
+INLINE void *waveram0_ptr_from_expanded_addr(UINT32 addr)
{
- UINT32 blocknum = (addr % WAVERAM_WIDTH) + ((addr >> 12) % WAVERAM_HEIGHT) * WAVERAM_WIDTH;
- return WAVERAM_BLOCK(bank, blocknum);
+ UINT32 blocknum = (addr % WAVERAM0_WIDTH) + ((addr >> 16) % WAVERAM0_HEIGHT) * WAVERAM0_WIDTH;
+ return WAVERAM_BLOCK0(blocknum);
}
-INLINE void *waveram_ptr_from_expanded_addr(UINT8 bank, UINT32 addr)
+INLINE void *waveram1_ptr_from_expanded_addr(UINT32 addr)
{
- UINT32 blocknum = (addr % WAVERAM_WIDTH) + ((addr >> 16) % WAVERAM_HEIGHT) * WAVERAM_WIDTH;
- return WAVERAM_BLOCK(bank, blocknum);
+ UINT32 blocknum = (addr % WAVERAM1_WIDTH) + ((addr >> 16) % WAVERAM1_HEIGHT) * WAVERAM1_WIDTH;
+ return WAVERAM_BLOCK1(blocknum);
}
-INLINE void *waveram_ptr_from_texture_addr(UINT8 bank, UINT32 addr, int width)
+INLINE void *waveram0_ptr_from_texture_addr(UINT32 addr, int width)
{
UINT32 blocknum = ((addr & ~1) * width) / 8;
- return WAVERAM_BLOCK(bank, blocknum);
+ return WAVERAM_BLOCK0(blocknum);
}
@@ -214,14 +231,18 @@ INLINE UINT8 get_texel_4bit(const void *base, int y, int x, int width)
* Video startup
*
*************************************/
+
+static TIMER_CALLBACK( int_timer_callback )
+{
+ cpunum_set_input_line(0, 2, ASSERT_LINE);
+}
+
VIDEO_START( midzeus2 )
{
/* allocate memory for "wave" RAM */
- waveram[0] = auto_malloc(WAVERAM_WIDTH * WAVERAM_HEIGHT * 16);
- waveram[1] = auto_malloc(WAVERAM_WIDTH * WAVERAM_HEIGHT * 16);
- state_save_register_global_pointer(((UINT32 *)waveram[0]), WAVERAM_WIDTH * WAVERAM_HEIGHT * 16/4);
- state_save_register_global_pointer(((UINT32 *)waveram[1]), WAVERAM_WIDTH * WAVERAM_HEIGHT * 16/4);
+ waveram[0] = auto_malloc(WAVERAM0_WIDTH * WAVERAM0_HEIGHT * 8);
+ waveram[1] = auto_malloc(WAVERAM1_WIDTH * WAVERAM1_HEIGHT * 12);
/* initialize polygon engine */
poly = poly_alloc(10000, sizeof(poly_extra_data), POLYFLAG_ALLOW_QUADS);
@@ -230,6 +251,21 @@ VIDEO_START( midzeus2 )
add_exit_callback(machine, exit_handler);
zeus_renderbase = waveram[1];
+
+ int_timer = timer_alloc(int_timer_callback, NULL);
+
+ /* save states */
+ state_save_register_global_pointer(waveram[0], WAVERAM0_WIDTH * WAVERAM0_HEIGHT * 8 / sizeof(waveram[0][0]));
+ state_save_register_global_pointer(waveram[1], WAVERAM1_WIDTH * WAVERAM1_HEIGHT * 12 / sizeof(waveram[1][0]));
+ state_save_register_global_array(zeus_fifo);
+ state_save_register_global(zeus_fifo_words);
+ state_save_register_global(zeus_cliprect.min_x);
+ state_save_register_global(zeus_cliprect.max_x);
+ state_save_register_global(zeus_cliprect.min_y);
+ state_save_register_global(zeus_cliprect.max_y);
+ state_save_register_global_2d_array(zeus_matrix);
+ state_save_register_global_array(zeus_point);
+ state_save_register_global(zeus_texbase);
}
@@ -237,23 +273,20 @@ static void exit_handler(running_machine *machine)
{
#if DUMP_WAVE_RAM
FILE *f = fopen("waveram.dmp", "w");
- int bank;
int i;
- for (bank = 0; bank < 2; bank++)
- for (i = 0; i < WAVERAM_WIDTH * WAVERAM_HEIGHT; i++)
- {
- if (i % 4 == 0) fprintf(f, "%03X%03X: ", i / WAVERAM_WIDTH, i % WAVERAM_WIDTH);
- fprintf(f, " %08X %08X ", (UINT32)(waveram[bank][i] >> 32), (UINT32)waveram[bank][i]);
- if (i % 4 == 3) fprintf(f, "\n");
- }
+ for (i = 0; i < WAVERAM0_WIDTH * WAVERAM0_HEIGHT; i++)
+ {
+ if (i % 4 == 0) fprintf(f, "%03X%03X: ", i / WAVERAM0_WIDTH, i % WAVERAM0_WIDTH);
+ fprintf(f, " %08X %08X ",
+ WAVERAM_READ32(waveram[0], i*2+0),
+ WAVERAM_READ32(waveram[0], i*2+1));
+ if (i % 4 == 3) fprintf(f, "\n");
+ }
fclose(f);
#endif
poly_free(poly);
-
-printf("max[0] = %X, %X\n", max_waveram[0][0], max_waveram[0][1]);
-printf("max[1] = %X, %X\n", max_waveram[1][0], max_waveram[1][1]);
}
@@ -273,7 +306,7 @@ VIDEO_UPDATE( midzeus2 )
/* normal update case */
if (!input_code_pressed(KEYCODE_W))
{
- const void *base = waveram_ptr_from_expanded_addr(1, 0);//zeusbase[0xcc]);
+ const void *base = waveram1_ptr_from_expanded_addr(zeusbase[0x38]);
int xoffs = machine->screen[screen].visarea.min_x;
for (y = cliprect->min_y; y <= cliprect->max_y; y++)
{
@@ -296,15 +329,15 @@ VIDEO_UPDATE( midzeus2 )
if (input_code_pressed(KEYCODE_RIGHT) && width < 512) { width <<= 1; while (input_code_pressed(KEYCODE_RIGHT)) ; }
if (yoffs < 0) yoffs = 0;
- base = waveram_ptr_from_block_addr(0, yoffs << 12);
+ base = waveram0_ptr_from_expanded_addr(yoffs << 16);
for (y = cliprect->min_y; y <= cliprect->max_y; y++)
{
- UINT16 *dest = (UINT16 *)bitmap->base + y * bitmap->rowpixels;
+ UINT32 *dest = (UINT32 *)bitmap->base + y * bitmap->rowpixels;
for (x = cliprect->min_x; x <= cliprect->max_x; x++)
{
UINT8 tex = get_texel_8bit(base, y, x, width);
- dest[x] = (tex << 8) | tex;
+ dest[x] = (tex << 16) | (tex << 8) | tex;
}
}
popmessage("offs = %06X", yoffs << 12);
@@ -350,8 +383,8 @@ READ32_HANDLER( zeus2_r )
break;
case 0x54:
- /* lower 16 bits are masked when read -- is that the hpos? */
- result = video_screen_get_vpos(0) << 16;
+ /* both upper 16 bits and lower 16 bits seem to be used as vertical counters */
+ result = (video_screen_get_vpos(0) << 16) | video_screen_get_vpos(0);
break;
}
@@ -368,7 +401,9 @@ READ32_HANDLER( zeus2_r )
WRITE32_HANDLER( zeus2_w )
{
- int logit = (offset != 0x40 && offset != 0x41 && offset != 0x48 && offset != 0x49 && offset != 0x4e &&
+ int logit = (offset != 0x08 &&
+ (offset != 0x20 || data != 0) &&
+ offset != 0x40 && offset != 0x41 && offset != 0x48 && offset != 0x49 && offset != 0x4e &&
offset != 0x50 && offset != 0x51 && offset != 0x57 && offset != 0x58 && offset != 0x59 && offset != 0x5a && offset != 0x5e);
if (logit)
logerror("%06X:zeus2_w", activecpu_get_pc());
@@ -419,6 +454,9 @@ static void zeus_register_update(offs_t offset, UINT32 oldval, int logit)
zeus_fifo[zeus_fifo_words++] = zeusbase[0x08];
if (zeus_fifo_process(zeus_fifo, zeus_fifo_words))
zeus_fifo_words = 0;
+
+ /* set the interrupt signal to indicate we can handle more */
+ timer_adjust(int_timer, ATTOTIME_IN_NSEC(500), 0, attotime_zero);
break;
case 0x20:
@@ -429,6 +467,7 @@ static void zeus_register_update(offs_t offset, UINT32 oldval, int logit)
0 $04000190 $00000000
1 $04000000 $01900000
*/
+ zeus_pointer_write(zeusbase[0x20] >> 24, zeusbase[0x20]);
break;
case 0x33:
@@ -461,6 +500,7 @@ static void zeus_register_update(offs_t offset, UINT32 oldval, int logit)
UINT32 temp = zeusbase[0x38];
zeusbase[0x38] = oldval;
video_screen_update_partial(0, video_screen_get_vpos(0));
+ log_fifo = input_code_pressed(KEYCODE_L);
zeusbase[0x38] = temp;
}
break;
@@ -469,7 +509,7 @@ static void zeus_register_update(offs_t offset, UINT32 oldval, int logit)
/* this is the address, except in read mode, where it latches values */
if (zeusbase[0x4e] & 0x10)
{
- const void *src = waveram_ptr_from_expanded_addr(0, oldval);
+ const void *src = waveram0_ptr_from_expanded_addr(oldval);
zeusbase[0x41] = oldval;
zeusbase[0x48] = WAVERAM_READ32(src, 0);
zeusbase[0x49] = WAVERAM_READ32(src, 1);
@@ -497,11 +537,9 @@ static void zeus_register_update(offs_t offset, UINT32 oldval, int logit)
*/
if ((zeusbase[0x4e] & 0x08) && (offset & 3) == (zeusbase[0x4e] & 3))
{
- void *dest = waveram_ptr_from_expanded_addr(0, zeusbase[0x41]);
+ void *dest = waveram0_ptr_from_expanded_addr(zeusbase[0x41]);
WAVERAM_WRITE32(dest, 0, zeusbase[0x48]);
WAVERAM_WRITE32(dest, 1, zeusbase[0x49]);
- max_waveram[0][0] = MAX(max_waveram[0][0], zeusbase[0x41] & 0xffff);
- max_waveram[0][1] = MAX(max_waveram[0][1], zeusbase[0x41] >> 16);
if (zeusbase[0x4e] & 0x40)
{
@@ -516,7 +554,7 @@ static void zeus_register_update(offs_t offset, UINT32 oldval, int logit)
else if (logit)
logerror("\t[40]=%08X [4E]=%08X\n", zeusbase[0x40], zeusbase[0x4e]);
break;
-
+
case 0x51:
/* in this mode, crusnexo expects the reads to immediately latch */
@@ -526,7 +564,7 @@ static void zeus_register_update(offs_t offset, UINT32 oldval, int logit)
/* this is the address, except in read mode, where it latches values */
if ((zeusbase[0x5e] & 0x10) || (zeusbase[0x50] == 0x00a20000))
{
- const void *src = waveram_ptr_from_expanded_addr(1, oldval);
+ const void *src = waveram1_ptr_from_expanded_addr(oldval);
zeusbase[0x51] = oldval;
zeusbase[0x58] = WAVERAM_READ32(src, 0);
zeusbase[0x59] = WAVERAM_READ32(src, 1);
@@ -545,13 +583,11 @@ static void zeus_register_update(offs_t offset, UINT32 oldval, int logit)
/* thegrid uses this to write either left or right halves of pixels */
if (zeusbase[0x50] == 0x00e90000)
{
- void *dest = waveram_ptr_from_expanded_addr(1, zeusbase[0x51]);
+ void *dest = waveram1_ptr_from_expanded_addr(zeusbase[0x51]);
if (zeusbase[0x57] & 1)
WAVERAM_WRITE32(dest, 0, zeusbase[0x58]);
if (zeusbase[0x57] & 4)
WAVERAM_WRITE32(dest, 1, zeusbase[0x59]);
- max_waveram[1][0] = MAX(max_waveram[1][0], zeusbase[0x51] & 0xffff);
- max_waveram[1][1] = MAX(max_waveram[1][1], zeusbase[0x51] >> 16);
}
/* make sure we log anything else */
@@ -575,7 +611,7 @@ static void zeus_register_update(offs_t offset, UINT32 oldval, int logit)
*/
if ((zeusbase[0x5e] & 0x08) && (offset & 3) == (zeusbase[0x5e] & 3))
{
- void *dest = waveram_ptr_from_expanded_addr(1, zeusbase[0x51]);
+ void *dest = waveram1_ptr_from_expanded_addr(zeusbase[0x51]);
WAVERAM_WRITE32(dest, 0, zeusbase[0x58]);
if (zeusbase[0x5e] & 0x20)
WAVERAM_WRITE32(dest, 1, zeusbase[0x5a]);
@@ -584,8 +620,6 @@ static void zeus_register_update(offs_t offset, UINT32 oldval, int logit)
WAVERAM_WRITE32(dest, 1, zeusbase[0x59]);
WAVERAM_WRITE32(dest, 2, zeusbase[0x5a]);
}
- max_waveram[1][0] = MAX(max_waveram[1][0], zeusbase[0x51] & 0xffff);
- max_waveram[1][1] = MAX(max_waveram[1][1], zeusbase[0x51] >> 16);
if (zeusbase[0x5e] & 0x40)
{
@@ -611,19 +645,170 @@ static void zeus_register_update(offs_t offset, UINT32 oldval, int logit)
*
*************************************/
+static void zeus_pointer_write(UINT8 which, UINT32 value)
+{
+ switch (which)
+ {
+ case 0x04:
+ zeus_renderbase = waveram1_ptr_from_expanded_addr(value << 16);
+ break;
+
+ case 0x05:
+ zeus_texbase = value % (WAVERAM0_HEIGHT * WAVERAM0_WIDTH);
+ break;
+
+ case 0x40:
+ zeus_unknown_40 = value & 0xffffff;
+ zeus_quad_size = (zeus_unknown_40 == 0) ? 10 : 14;
+ break;
+ }
+}
+
+
+
+/*************************************
+ *
+ * Process the FIFO
+ *
+ *************************************/
+
static int zeus_fifo_process(const UINT32 *data, int numwords)
{
+ int dataoffs = 0;
+
/* handle logging */
switch (data[0] >> 24)
{
/* 0x05: write 32-bit value to low registers */
- /* in model data, this is 0x19 */
case 0x05:
if (numwords < 2)
return FALSE;
if (log_fifo)
log_fifo_command(data, numwords, " -- reg32");
- zeus_register32_w((data[0] >> 16) & 0x7f, data[1], log_fifo);
+ if (((data[0] >> 16) & 0x7f) != 0x08)
+ zeus_register32_w((data[0] >> 16) & 0x7f, data[1], log_fifo);
+ break;
+
+ /* 0x08: set matrix and point (thegrid) */
+ case 0x08:
+ if (numwords < 14)
+ return FALSE;
+ dataoffs = 1;
+
+ /* 0x07: set matrix and point (crusnexo) */
+ case 0x07:
+ if (numwords < 13)
+ return FALSE;
+
+ /* extract the matrix from the raw data */
+ zeus_matrix[0][0] = convert_tms3203x_fp_to_float(data[dataoffs + 1]);
+ zeus_matrix[0][1] = convert_tms3203x_fp_to_float(data[dataoffs + 2]);
+ zeus_matrix[0][2] = convert_tms3203x_fp_to_float(data[dataoffs + 3]);
+ zeus_matrix[1][0] = convert_tms3203x_fp_to_float(data[dataoffs + 4]);
+ zeus_matrix[1][1] = convert_tms3203x_fp_to_float(data[dataoffs + 5]);
+ zeus_matrix[1][2] = convert_tms3203x_fp_to_float(data[dataoffs + 6]);
+ zeus_matrix[2][0] = convert_tms3203x_fp_to_float(data[dataoffs + 7]);
+ zeus_matrix[2][1] = convert_tms3203x_fp_to_float(data[dataoffs + 8]);
+ zeus_matrix[2][2] = convert_tms3203x_fp_to_float(data[dataoffs + 9]);
+
+ /* extract the translation point from the raw data */
+ zeus_point[0] = convert_tms3203x_fp_to_float(data[dataoffs + 10]);
+ zeus_point[1] = convert_tms3203x_fp_to_float(data[dataoffs + 11]);
+ zeus_point[2] = convert_tms3203x_fp_to_float(data[dataoffs + 12]);
+
+ if (log_fifo)
+ {
+ log_fifo_command(data, numwords, "");
+ logerror("\n\t\tmatrix ( %8.2f %8.2f %8.2f ) ( %8.2f %8.2f %8.2f ) ( %8.2f %8.2f %8.2f )\n\t\tvector %8.2f %8.2f %8.5f\n",
+ zeus_matrix[0][0], zeus_matrix[0][1], zeus_matrix[0][2],
+ zeus_matrix[1][0], zeus_matrix[1][1], zeus_matrix[1][2],
+ zeus_matrix[2][0], zeus_matrix[2][1], zeus_matrix[2][2],
+ zeus_point[0],
+ zeus_point[1],
+ zeus_point[2]);
+ }
+ break;
+
+ /* 0x15: set point only (thegrid) */
+ /* 0x16: set point only (crusnexo) */
+ case 0x15:
+ case 0x16:
+ if (numwords < 4)
+ return FALSE;
+
+ /* extract the translation point from the raw data */
+ zeus_point[0] = convert_tms3203x_fp_to_float(data[1]);
+ zeus_point[1] = convert_tms3203x_fp_to_float(data[2]);
+ zeus_point[2] = convert_tms3203x_fp_to_float(data[3]);
+
+ if (log_fifo)
+ {
+ log_fifo_command(data, numwords, "");
+ logerror("\n\t\tvector %8.2f %8.2f %8.5f\n",
+ zeus_point[0],
+ zeus_point[1],
+ zeus_point[2]);
+ }
+ break;
+
+ /* 0x1c: */
+ case 0x1c:
+ if (numwords < 4)
+ return FALSE;
+ if (log_fifo)
+ {
+ log_fifo_command(data, numwords, " -- unknown control + hack clear screen\n");
+ logerror("\t\tvector %8.2f %8.2f %8.5f\n",
+ convert_tms3203x_fp_to_float(data[1]),
+ convert_tms3203x_fp_to_float(data[2]),
+ convert_tms3203x_fp_to_float(data[3]));
+
+ /* extract the translation point from the raw data */
+ zeus_point2[0] = convert_tms3203x_fp_to_float(data[1]);
+ zeus_point2[1] = convert_tms3203x_fp_to_float(data[2]);
+ zeus_point2[2] = convert_tms3203x_fp_to_float(data[3]);
+ }
+ {
+ /* not right -- just a hack */
+ int x, y;
+ for (y = zeus_cliprect.min_y; y <= zeus_cliprect.max_y; y++)
+ for (x = zeus_cliprect.min_x; x <= zeus_cliprect.max_x; x++)
+ waveram_plot_depth(y, x, 0, 0x7fff);
+ }
+ break;
+
+ /* 0x23: render model in waveram (thegrid) */
+ /* 0x24: render model in waveram (crusnexo) */
+ case 0x23:
+ case 0x24:
+ if (numwords < 2)
+ return FALSE;
+ if (log_fifo)
+ log_fifo_command(data, numwords, "");
+ zeus_draw_model(data[1], data[0] & 0xffff, log_fifo);
+ break;
+
+ /* 0x31: sync pipeline? (thegrid) */
+ /* 0x32: sync pipeline? (crusnexo) */
+ case 0x31:
+ case 0x32:
+ if (log_fifo)
+ log_fifo_command(data, numwords, "\n");
+ zeus_quad_size = 10;
+ break;
+
+ /* 0x38: direct render quad (crusnexo) */
+ case 0x38:
+ if (numwords < 12)
+ return FALSE;
+ if (log_fifo)
+ log_fifo_command(data, numwords, "");
+ break;
+
+ /* 0x40: ???? */
+ case 0x40:
+ if (log_fifo)
+ log_fifo_command(data, numwords, "\n");
break;
default:
@@ -642,6 +827,401 @@ static int zeus_fifo_process(const UINT32 *data, int numwords)
/*************************************
*
+ * Draw a model in waveram
+ *
+ *************************************/
+
+static void zeus_draw_model(UINT32 baseaddr, UINT16 count, int logit)
+{
+ UINT32 databuffer[32];
+ int databufcount = 0;
+ int model_done = FALSE;
+ UINT32 texoffs = 0;
+ int quadsize = zeus_quad_size;
+
+ if (logit)
+ logerror(" -- model @ %08X, len %04X\n", baseaddr, count);
+
+ while (baseaddr != 0 && !model_done)
+ {
+ const void *base = waveram0_ptr_from_expanded_addr(baseaddr);
+ int curoffs;
+
+ /* reset the objdata address */
+ baseaddr = 0;
+
+ /* loop until we run out of data */
+ for (curoffs = 0; curoffs <= count; curoffs++)
+ {
+ int countneeded = 2;
+ UINT8 cmd;
+
+ /* accumulate 2 words of data */
+ databuffer[databufcount++] = WAVERAM_READ32(base, curoffs * 2 + 0);
+ databuffer[databufcount++] = WAVERAM_READ32(base, curoffs * 2 + 1);
+
+ /* if this is enough, process the command */
+ cmd = databuffer[0] >> 24;
+ if (cmd == 0x38)
+ countneeded = quadsize;
+ if (databufcount == countneeded)
+ {
+ /* handle logging of the command */
+ if (logit)
+ {
+ int offs;
+ logerror("\t");
+ for (offs = 0; offs < databufcount; offs++)
+ logerror("%08X ", databuffer[offs]);
+ logerror("-- ");
+ }
+
+ /* handle the command */
+ switch (cmd)
+ {
+ case 0x21: /* thegrid */
+ case 0x22: /* crusnexo */
+ if (((databuffer[0] >> 16) & 0xff) == 0x9b)
+ {
+ texoffs = databuffer[1];
+ if (logit)
+ logerror("texture offset\n");
+ }
+ else if (logit)
+ logerror("unknown offset\n");
+ break;
+
+ case 0x31: /* thegrid */
+ if (logit)
+ logerror("sync?\n");
+ break;
+
+ case 0x35: /* thegrid */
+ case 0x36: /* crusnexo */
+ if (logit)
+ logerror("reg32");
+ zeus_register32_w((databuffer[0] >> 16) & 0x7f, databuffer[1], logit);
+ break;
+
+ case 0x38: /* crusnexo/thegrid */
+ zeus_draw_quad(databuffer, texoffs, logit);
+ break;
+
+ default:
+ if (quadsize == 10)
+ {
+ logerror("Correcting quad size\n");
+ quadsize = 14;
+ }
+ if (logit)
+ logerror("unknown model data\n");
+ break;
+ }
+
+ /* reset the count */
+ databufcount = 0;
+ }
+ }
+ }
+}
+
+
+
+/*************************************
+ *
+ * Draw a quad
+ *
+ *************************************/
+
+static void zeus_draw_quad(const UINT32 *databuffer, UINT32 texoffs, int logit)
+{
+ poly_draw_scanline callback;
+ poly_extra_data *extra;
+ poly_vertex clipvert[8];
+ poly_vertex vert[4];
+// float uscale, vscale;
+ float maxy, maxx;
+// int val1, val2, texwshift;
+ int numverts;
+ int i;
+// INT16 normal[3];
+// INT32 rotnormal[3];
+ int texmode = texoffs & 0xffff;
+
+ if (logit)
+ logerror("quad\n");
+
+if (input_code_pressed(KEYCODE_Q) && (texoffs & 0xffff) == 0x119) return;
+if (input_code_pressed(KEYCODE_E) && (texoffs & 0xffff) == 0x01d) return;
+if (input_code_pressed(KEYCODE_R) && (texoffs & 0xffff) == 0x11d) return;
+if (input_code_pressed(KEYCODE_T) && (texoffs & 0xffff) == 0x05d) return;
+if (input_code_pressed(KEYCODE_Y) && (texoffs & 0xffff) == 0x0dd) return;
+//if (input_code_pressed(KEYCODE_U) && (texoffs & 0xffff) == 0x119) return;
+//if (input_code_pressed(KEYCODE_I) && (texoffs & 0xffff) == 0x119) return;
+//if (input_code_pressed(KEYCODE_O) && (texoffs & 0xffff) == 0x119) return;
+//if (input_code_pressed(KEYCODE_L) && (texoffs & 0x100)) return;
+
+ callback = render_poly_8bit;
+
+/*
+0 38800000
+1 x2 | x1
+2 v1 | u1
+3 y2 | y1
+4 v2 | u2
+5 z2 | z1
+6 v3 | u3
+7 v4 | u4
+8 ???
+9 x4 | x3
+10 y4 | y3
+11 z4 | z3
+
+In memory:
+ +0 = ???
+ +1 = set via $05410000/value
+ +2 = x1
+ +3 = y1
+ +4 = z1
+ +5 = x2
+ +6 = y2
+ +7 = z2
+ +8 = x3
+ +9 = y3
+ +10= z3
+ +11= x4
+ +12= y4
+ +13= z4
+ +14= uv1
+ +15= uv2
+ +16= uv3
+ +17= uv4
+ +18= set via $05200000/$05000000 | (value << 10) (uvoffset?)
+ +19= ???
+
+
+ 38810000 00000000 00C7|FF38 FF5E|FF5E 15400154 11400114 00000000 00000000 FF38|00C7 00A3|00A3 -- quad
+ xxxx|xxxx yyyy|yyyy xxxx|xxxx yyyy|yyyy
+*/
+
+ /* extract raw x,y,z */
+ vert[0].x = (INT16)databuffer[2];
+ vert[0].y = (INT16)databuffer[3];
+ vert[0].p[0] = (INT16)databuffer[6];
+ vert[0].p[1] = (databuffer[1] >> 2) & 0xff;
+ vert[0].p[2] = (databuffer[1] >> 18) & 0xff;
+
+ vert[1].x = (INT16)(databuffer[2] >> 16);
+ vert[1].y = (INT16)(databuffer[3] >> 16);
+ vert[1].p[0] = (INT16)(databuffer[6] >> 16);
+ vert[1].p[1] = (databuffer[4] >> 2) & 0xff;
+ vert[1].p[2] = (databuffer[4] >> 12) & 0xff;
+
+ vert[2].x = (INT16)databuffer[8];
+ vert[2].y = (INT16)databuffer[9];
+ vert[2].p[0] = (INT16)databuffer[7];
+ vert[2].p[1] = (databuffer[4] >> 22) & 0xff;
+ vert[2].p[2] = (databuffer[5] >> 2) & 0xff;
+
+ vert[3].x = (INT16)(databuffer[8] >> 16);
+ vert[3].y = (INT16)(databuffer[9] >> 16);
+ vert[3].p[0] = (INT16)(databuffer[7] >> 16);
+ vert[3].p[1] = (databuffer[5] >> 12) & 0xff;
+ vert[3].p[2] = (databuffer[5] >> 22) & 0xff;
+
+/*
+ vert[0].x = (INT16)databuffer[1];
+ vert[0].y = (INT16)databuffer[3];
+ vert[0].p[0] = (INT16)databuffer[5];
+ vert[0].p[1] = (UINT16)databuffer[2];
+ vert[0].p[2] = (UINT16)(databuffer[2] >> 16);
+
+ vert[1].x = (INT16)(databuffer[1] >> 16);
+ vert[1].y = (INT16)(databuffer[3] >> 16);
+ vert[1].p[0] = (INT16)(databuffer[5] >> 16);
+ vert[1].p[1] = (UINT16)databuffer[4];
+ vert[1].p[2] = (UINT16)(databuffer[4] >> 16);
+
+ vert[2].x = (INT16)databuffer[9];
+ vert[2].y = (INT16)databuffer[10];
+ vert[2].p[0] = (INT16)databuffer[11];
+ vert[2].p[1] = (UINT16)databuffer[6];
+ vert[2].p[2] = (UINT16)(databuffer[6] >> 16);
+
+ vert[3].x = (INT16)(databuffer[9] >> 16);
+ vert[3].y = (INT16)(databuffer[10] >> 16);
+ vert[3].p[0] = (INT16)(databuffer[11] >> 16);
+ vert[3].p[1] = (UINT16)databuffer[7];
+ vert[3].p[2] = (UINT16)(databuffer[7] >> 16);
+*/
+ for (i = 0; i < 4; i++)
+ {
+ float x = vert[i].x;
+ float y = vert[i].y;
+ float z = vert[i].p[0];
+
+ vert[i].x = x * zeus_matrix[0][0] + y * zeus_matrix[0][1] + z * zeus_matrix[0][2] + zeus_point[0];
+ vert[i].y = x * zeus_matrix[1][0] + y * zeus_matrix[1][1] + z * zeus_matrix[1][2] + zeus_point[1];
+ vert[i].p[0] = x * zeus_matrix[2][0] + y * zeus_matrix[2][1] + z * zeus_matrix[2][2] + zeus_point[2];
+ vert[i].p[2] += texoffs >> 16;
+ vert[i].p[1] *= 256.0f;
+ vert[i].p[2] *= 256.0f;
+
+ if (logit)
+ {
+ logerror("\t\t(%f,%f,%f) (%02X,%02X)\n",
+ vert[i].x, vert[i].y, vert[i].p[0],
+ (int)(vert[i].p[1] / 256.0f), (int)(vert[i].p[2] / 256.0f));
+ }
+ }
+
+ numverts = poly_zclip_if_less(4, &vert[0], &clipvert[0], 4, 1.0f / 512.0f / 4.0f);
+ if (numverts < 3)
+ return;
+
+ maxx = maxy = -1000.0f;
+ for (i = 0; i < numverts; i++)
+ {
+ float ooz = 512.0f / clipvert[i].p[0];
+
+// ooz *= 1.0f / (512.0f * 512.0f);
+
+ clipvert[i].x *= ooz;
+ clipvert[i].y *= ooz;
+ clipvert[i].x += 256.5f;
+ clipvert[i].y += 200.5f;
+ clipvert[i].p[0] *= 65536.0f * 16.0f;
+
+ maxx = MAX(maxx, clipvert[i].x);
+ maxy = MAX(maxy, clipvert[i].y);
+ if (logit)
+ logerror("\t\t\tTranslated=(%f,%f)\n", clipvert[i].x, clipvert[i].y);
+ }
+ for (i = 0; i < numverts; i++)
+ {
+ if (clipvert[i].x == maxx)
+ clipvert[i].x += 0.0005f;
+ if (clipvert[i].y == maxy)
+ clipvert[i].y += 0.0005f;
+ }
+
+ extra = poly_get_extra_data(poly);
+ switch (texmode)
+ {
+ case 0x01d: /* crusnexo: RHS of score bar */
+ case 0x05d: /* crusnexo: background, road */
+ case 0x0dd: /* crusnexo: license plate letters */
+ case 0x11d: /* crusnexo: LHS of score bar */
+ case 0x15d: /* crusnexo */
+ case 0x85d: /* crusnexo */
+ case 0x95d: /* crusnexo */
+ case 0xc1d: /* crusnexo */
+ case 0xc5d: /* crusnexo */
+ extra->texwidth = 256;
+ break;
+
+ case 0x059: /* crusnexo */
+ case 0x0d9: /* crusnexo */
+ case 0x119: /* crusnexo: license plates */
+ case 0x159: /* crusnexo */
+ extra->texwidth = 128;
+ break;
+
+ case 0x055: /* crusnexo */
+ case 0x155: /* crusnexo */
+ extra->texwidth = 64;
+ break;
+
+ default:
+ {
+ static UINT8 hits[0x10000];
+ if (!hits[(texoffs & 0xffff)])
+ {
+ hits[(texoffs & 0xffff)] = 1;
+ printf("format = %04X\n", (texoffs & 0xffff));
+ }
+ break;
+ }
+ }
+
+ extra->solidcolor = 0;//zeusbase[0x00] & 0x7fff;
+ extra->zoffset = 0;//zeusbase[0x7e] >> 16;
+ extra->alpha = 0;//zeusbase[0x4e];
+ extra->transcolor = 0x100;//((databuffer[1] >> 16) & 1) ? 0 : 0x100;
+ extra->texbase = WAVERAM_BLOCK0(zeus_texbase);
+ extra->palbase = waveram0_ptr_from_expanded_addr(zeusbase[0x41]);
+
+ poly_render_quad_fan(poly, NULL, &zeus_cliprect, callback, 4, numverts, &clipvert[0]);
+}
+
+
+
+/*************************************
+ *
+ * Rasterizers
+ *
+ *************************************/
+
+static void render_poly_8bit(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid)
+{
+ const poly_extra_data *extra = extradata;
+ INT32 curz = extent->param[0].start;
+ INT32 curu = extent->param[1].start;
+ INT32 curv = extent->param[2].start;
+// INT32 curi = extent->param[3].start;
+ INT32 dzdx = extent->param[0].dpdx;
+ INT32 dudx = extent->param[1].dpdx;
+ INT32 dvdx = extent->param[2].dpdx;
+// INT32 didx = extent->param[3].dpdx;
+ const void *texbase = extra->texbase;
+ const void *palbase = extra->palbase;
+ UINT16 transcolor = extra->transcolor;
+ int texwidth = extra->texwidth;
+ int x;
+
+ for (x = extent->startx; x < extent->stopx; x++)
+ {
+ UINT16 *depthptr = WAVERAM_PTRDEPTH(zeus_renderbase, scanline, x);
+ INT32 depth = (curz >> 16) + extra->zoffset;
+ if (depth > 0x7fff) depth = 0x7fff;
+ if (depth >= 0 && depth <= *depthptr)
+ {
+ int u0 = (curu >> 8);// & (texwidth - 1);
+ int v0 = (curv >> 8);// & 255;
+ int u1 = (u0 + 1);
+ int v1 = (v0 + 1);
+ UINT8 texel0 = get_texel_8bit(texbase, v0, u0, texwidth);
+ UINT8 texel1 = get_texel_8bit(texbase, v0, u1, texwidth);
+ UINT8 texel2 = get_texel_8bit(texbase, v1, u0, texwidth);
+ UINT8 texel3 = get_texel_8bit(texbase, v1, u1, texwidth);
+ if (texel0 != transcolor)
+ {
+ rgb_t color0 = WAVERAM_READ16(palbase, texel0);
+ rgb_t color1 = WAVERAM_READ16(palbase, texel1);
+ rgb_t color2 = WAVERAM_READ16(palbase, texel2);
+ rgb_t color3 = WAVERAM_READ16(palbase, texel3);
+ rgb_t filtered;
+ color0 = ((color0 & 0x7c00) << 9) | ((color0 & 0x3e0) << 6) | ((color0 & 0x1f) << 3);
+ color1 = ((color1 & 0x7c00) << 9) | ((color1 & 0x3e0) << 6) | ((color1 & 0x1f) << 3);
+ color2 = ((color2 & 0x7c00) << 9) | ((color2 & 0x3e0) << 6) | ((color2 & 0x1f) << 3);
+ color3 = ((color3 & 0x7c00) << 9) | ((color3 & 0x3e0) << 6) | ((color3 & 0x1f) << 3);
+ filtered = rgb_bilinear_filter(color0, color1, color2, color3, curu, curv);
+ WAVERAM_WRITEPIX(zeus_renderbase, scanline, x, filtered);
+ *depthptr = depth;
+ }
+ }
+
+ curz += dzdx;
+ curu += dudx;
+ curv += dvdx;
+// curi += didx;
+ }
+}
+
+
+
+/*************************************
+ *
* Debugging tools
*
*************************************/
@@ -655,3 +1235,45 @@ static void log_fifo_command(const UINT32 *data, int numwords, const char *suffi
logerror(" %08X", data[wordnum]);
logerror("%s", suffix);
}
+
+
+static void log_waveram(UINT32 base, UINT16 length)
+{
+ static struct
+ {
+ UINT32 base;
+ UINT16 length;
+ UINT32 checksum;
+ } recent_entries[100];
+
+ UINT32 numoctets = length + 1;
+ const void *ptr = waveram0_ptr_from_expanded_addr(base);
+ UINT32 checksum = base | ((UINT64)length << 32);
+ int foundit = FALSE;
+ int i;
+
+ for (i = 0; i < numoctets; i++)
+ checksum += WAVERAM_READ32(ptr, i*2) + WAVERAM_READ32(ptr, i*2+1);
+
+ for (i = 0; i < ARRAY_LENGTH(recent_entries); i++)
+ if (recent_entries[i].base == base && recent_entries[i].length == length && recent_entries[i].checksum == checksum)
+ {
+ foundit = TRUE;
+ break;
+ }
+
+ if (i == ARRAY_LENGTH(recent_entries))
+ i--;
+ if (i != 0)
+ {
+ memmove(&recent_entries[1], &recent_entries[0], i * sizeof(recent_entries[0]));
+ recent_entries[0].base = base;
+ recent_entries[0].length = length;
+ recent_entries[0].checksum = checksum;
+ }
+ if (foundit)
+ return;
+
+ for (i = 0; i < numoctets; i++)
+ logerror("\t%02X: %08X %08X\n", i, WAVERAM_READ32(ptr, i*2), WAVERAM_READ32(ptr, i*2+1));
+}