mirror of
https://github.com/holub/mame
synced 2025-05-23 14:19:01 +03:00
Hardware multiplication and division on the SNES takes 8 machine cycles to complete.
This commit is contained in:
parent
e277de3812
commit
2d26bc8efb
@ -36,6 +36,8 @@ static emu_timer *snes_scanline_timer;
|
|||||||
static emu_timer *snes_hblank_timer;
|
static emu_timer *snes_hblank_timer;
|
||||||
static emu_timer *snes_nmi_timer;
|
static emu_timer *snes_nmi_timer;
|
||||||
static emu_timer *snes_hirq_timer;
|
static emu_timer *snes_hirq_timer;
|
||||||
|
static emu_timer *snes_div_timer;
|
||||||
|
static emu_timer *snes_mult_timer;
|
||||||
static UINT16 hblank_offset;
|
static UINT16 hblank_offset;
|
||||||
UINT16 snes_htmult; /* in 512 wide, we run HTOTAL double and halve it on latching */
|
UINT16 snes_htmult; /* in 512 wide, we run HTOTAL double and halve it on latching */
|
||||||
UINT8 snes_has_addon_chip;
|
UINT8 snes_has_addon_chip;
|
||||||
@ -176,7 +178,7 @@ static TIMER_CALLBACK( snes_scanline_tick )
|
|||||||
timer_adjust_oneshot(snes_hirq_timer, video_screen_get_time_until_pos(machine->primary_screen, snes_ppu.beam.current_vert, pixel*snes_htmult), 0);
|
timer_adjust_oneshot(snes_hirq_timer, video_screen_get_time_until_pos(machine->primary_screen, snes_ppu.beam.current_vert, pixel*snes_htmult), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start of VBlank */
|
/* Start of VBlank */
|
||||||
if( snes_ppu.beam.current_vert == snes_ppu.beam.last_visible_line )
|
if( snes_ppu.beam.current_vert == snes_ppu.beam.last_visible_line )
|
||||||
@ -294,6 +296,36 @@ static TIMER_CALLBACK( snes_hblank_tick )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static TIMER_CALLBACK(snes_div_callback)
|
||||||
|
{
|
||||||
|
UINT16 value, dividend, remainder;
|
||||||
|
dividend = remainder = 0;
|
||||||
|
value = (snes_ram[WRDIVH] << 8) + snes_ram[WRDIVL];
|
||||||
|
if( snes_ram[WRDVDD] > 0 )
|
||||||
|
{
|
||||||
|
dividend = value / snes_ram[WRDVDD];
|
||||||
|
remainder = value % snes_ram[WRDVDD];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dividend = 0xffff;
|
||||||
|
remainder = value;
|
||||||
|
}
|
||||||
|
snes_ram[RDDIVL] = dividend & 0xff;
|
||||||
|
snes_ram[RDDIVH] = (dividend >> 8) & 0xff;
|
||||||
|
snes_ram[RDMPYL] = remainder & 0xff;
|
||||||
|
snes_ram[RDMPYH] = (remainder >> 8) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static TIMER_CALLBACK(snes_mult_callback)
|
||||||
|
{
|
||||||
|
UINT32 c = snes_ram[WRMPYA] * snes_ram[WRMPYB];
|
||||||
|
snes_ram[RDMPYL] = c & 0xff;
|
||||||
|
snes_ram[RDMPYH] = (c >> 8) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************
|
/*************************************
|
||||||
|
|
||||||
Input Handlers
|
Input Handlers
|
||||||
@ -1291,34 +1323,14 @@ WRITE8_HANDLER( snes_w_io )
|
|||||||
case WRMPYA: /* Multiplier A */
|
case WRMPYA: /* Multiplier A */
|
||||||
break;
|
break;
|
||||||
case WRMPYB: /* Multiplier B */
|
case WRMPYB: /* Multiplier B */
|
||||||
{
|
timer_adjust_oneshot(snes_mult_timer, cputag_clocks_to_attotime(space->machine, "maincpu", 8), 0);
|
||||||
UINT32 c = snes_ram[WRMPYA] * data;
|
break;
|
||||||
snes_ram[RDMPYL] = c & 0xff;
|
|
||||||
snes_ram[RDMPYH] = (c >> 8) & 0xff;
|
|
||||||
} break;
|
|
||||||
case WRDIVL: /* Dividend (low) */
|
case WRDIVL: /* Dividend (low) */
|
||||||
case WRDIVH: /* Dividend (high) */
|
case WRDIVH: /* Dividend (high) */
|
||||||
break;
|
break;
|
||||||
case WRDVDD: /* Divisor */
|
case WRDVDD: /* Divisor */
|
||||||
{
|
timer_adjust_oneshot(snes_div_timer, cputag_clocks_to_attotime(space->machine, "maincpu", 8), 0);
|
||||||
UINT16 value, dividend, remainder;
|
break;
|
||||||
dividend = remainder = 0;
|
|
||||||
value = (snes_ram[WRDIVH] << 8) + snes_ram[WRDIVL];
|
|
||||||
if( data > 0 )
|
|
||||||
{
|
|
||||||
dividend = value / data;
|
|
||||||
remainder = value % data;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dividend = 0xffff;
|
|
||||||
remainder = value;
|
|
||||||
}
|
|
||||||
snes_ram[RDDIVL] = dividend & 0xff;
|
|
||||||
snes_ram[RDDIVH] = (dividend >> 8) & 0xff;
|
|
||||||
snes_ram[RDMPYL] = remainder & 0xff;
|
|
||||||
snes_ram[RDMPYH] = (remainder >> 8) & 0xff;
|
|
||||||
} break;
|
|
||||||
case HTIMEL: /* H-Count timer settings (low) */
|
case HTIMEL: /* H-Count timer settings (low) */
|
||||||
case HTIMEH: /* H-Count timer settings (high) */
|
case HTIMEH: /* H-Count timer settings (high) */
|
||||||
case VTIMEL: /* V-Count timer settings (low) */
|
case VTIMEL: /* V-Count timer settings (low) */
|
||||||
@ -1983,6 +1995,10 @@ static void snes_init_timers(running_machine *machine)
|
|||||||
timer_adjust_oneshot(snes_nmi_timer, attotime_never, 0);
|
timer_adjust_oneshot(snes_nmi_timer, attotime_never, 0);
|
||||||
snes_hirq_timer = timer_alloc(machine, snes_hirq_tick_callback, NULL);
|
snes_hirq_timer = timer_alloc(machine, snes_hirq_tick_callback, NULL);
|
||||||
timer_adjust_oneshot(snes_hirq_timer, attotime_never, 0);
|
timer_adjust_oneshot(snes_hirq_timer, attotime_never, 0);
|
||||||
|
snes_div_timer = timer_alloc(machine, snes_div_callback, NULL);
|
||||||
|
timer_adjust_oneshot(snes_div_timer, attotime_never, 0);
|
||||||
|
snes_mult_timer = timer_alloc(machine, snes_mult_callback, NULL);
|
||||||
|
timer_adjust_oneshot(snes_mult_timer, attotime_never, 0);
|
||||||
|
|
||||||
// SNES hcounter has a 0-339 range. hblank starts at counter 260.
|
// SNES hcounter has a 0-339 range. hblank starts at counter 260.
|
||||||
// clayfighter sets an HIRQ at 260, apparently it wants it to be before hdma kicks off, so we'll delay 2 pixels.
|
// clayfighter sets an HIRQ at 260, apparently it wants it to be before hdma kicks off, so we'll delay 2 pixels.
|
||||||
|
Loading…
Reference in New Issue
Block a user