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
This commit is contained in:
Aaron Giles 2007-12-28 06:11:52 +00:00
parent 8d6c62b976
commit 2f8231e10a
15 changed files with 1028 additions and 207 deletions

View File

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

View File

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

View File

@ -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);
UINT16 oldstate = tms32031.irq_state;
UINT16 intmask = 1 << irqline;
/* ignore anything out of range */
if (irqline >= 12)
return;
/* check for IRQs */
if (state != CLEAR_LINE)
check_irqs();
/* 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 --- */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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,20 +89,14 @@ static MACHINE_RESET( midzeus )
/*************************************
*
* CMOS access
* CMOS access (Zeus only)
*
*************************************/
static WRITE32_HANDLER( cmos_protect_w )
{
cmos_protected = FALSE;
}
static WRITE32_HANDLER( cmos_w )
{
if (!cmos_protected)
COMBINE_DATA(generic_nvram32 + offset);
COMBINE_DATA(&generic_nvram32[offset]);
cmos_protected = TRUE;
}
@ -97,6 +107,45 @@ static READ32_HANDLER( cmos_r )
}
static WRITE32_HANDLER( cmos_protect_w )
{
cmos_protected = FALSE;
}
/*************************************
*
* Timekeeper access (Zeus 2 only)
*
*************************************/
static READ32_HANDLER( timekeeper_r )
{
UINT8 result = timekeeper_0_r(offset);
// logerror("%06X:cmos_time_r(%X) = %02X\n", activecpu_get_pc(), offset, result);
return result;
}
static WRITE32_HANDLER( timekeeper_w )
{
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);
}
}
@ -179,6 +228,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)

View File

@ -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"
@ -98,43 +99,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]);

View File

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

View File

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

View File

@ -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)
{
@ -605,6 +639,33 @@ static void zeus_register_update(offs_t offset, UINT32 oldval, int logit)
/*************************************
*
* Process the FIFO
*
*************************************/
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
@ -613,17 +674,141 @@ static void zeus_register_update(offs_t offset, UINT32 oldval, int logit)
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:
@ -640,6 +825,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));
}