mirror of
https://github.com/holub/mame
synced 2025-05-23 06:08:48 +03:00
accurate irq timers (more like ymf262.c now)
This commit is contained in:
parent
2e021824b5
commit
69e6ade6f9
@ -108,8 +108,7 @@ typedef struct
|
|||||||
INT8 memmode;
|
INT8 memmode;
|
||||||
INT32 memadr;
|
INT32 memadr;
|
||||||
|
|
||||||
UINT8 busy;
|
UINT8 status_busy, status_ld;
|
||||||
UINT8 ld;
|
|
||||||
emu_timer *timer_busy;
|
emu_timer *timer_busy;
|
||||||
emu_timer *timer_ld;
|
emu_timer *timer_ld;
|
||||||
UINT8 exp;
|
UINT8 exp;
|
||||||
@ -117,7 +116,9 @@ typedef struct
|
|||||||
INT32 fm_l, fm_r;
|
INT32 fm_l, fm_r;
|
||||||
INT32 pcm_l, pcm_r;
|
INT32 pcm_l, pcm_r;
|
||||||
|
|
||||||
UINT8 timer_a_count, timer_b_count, enable, current_irq;
|
attotime timer_base;
|
||||||
|
UINT8 timer_a_count, timer_b_count;
|
||||||
|
UINT8 enable, current_irq;
|
||||||
emu_timer *timer_a, *timer_b;
|
emu_timer *timer_a, *timer_b;
|
||||||
int irq_line;
|
int irq_line;
|
||||||
|
|
||||||
@ -382,38 +383,9 @@ static TIMER_CALLBACK( ymf278b_timer_b_tick )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ymf278b_timer_a_reset(YMF278BChip *chip)
|
|
||||||
{
|
|
||||||
if(chip->enable & 1)
|
|
||||||
{
|
|
||||||
attotime period = attotime::from_nsec((256-chip->timer_a_count) * 80800);
|
|
||||||
|
|
||||||
if (chip->clock != YMF278B_STD_CLOCK)
|
|
||||||
period = (period * chip->clock) / YMF278B_STD_CLOCK;
|
|
||||||
|
|
||||||
chip->timer_a->adjust(period, 0, period);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
chip->timer_a->adjust(attotime::never);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ymf278b_timer_b_reset(YMF278BChip *chip)
|
|
||||||
{
|
|
||||||
if(chip->enable & 2)
|
|
||||||
{
|
|
||||||
attotime period = attotime::from_nsec((256-chip->timer_b_count) * 323100);
|
|
||||||
|
|
||||||
if (chip->clock != YMF278B_STD_CLOCK)
|
|
||||||
period = (period * chip->clock) / YMF278B_STD_CLOCK;
|
|
||||||
|
|
||||||
chip->timer_b->adjust(period, 0, period);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
chip->timer_b->adjust(attotime::never);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ymf278b_A_w(running_machine &machine, YMF278BChip *chip, UINT8 reg, UINT8 data)
|
static void ymf278b_A_w(running_machine &machine, YMF278BChip *chip, UINT8 reg, UINT8 data)
|
||||||
{
|
{
|
||||||
|
// FM register array 0 (compatible with YMF262)
|
||||||
switch(reg)
|
switch(reg)
|
||||||
{
|
{
|
||||||
// LSI TEST
|
// LSI TEST
|
||||||
@ -421,28 +393,50 @@ static void ymf278b_A_w(running_machine &machine, YMF278BChip *chip, UINT8 reg,
|
|||||||
case 0x01:
|
case 0x01:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// timer a count
|
||||||
case 0x02:
|
case 0x02:
|
||||||
chip->timer_a_count = data;
|
if (data != chip->timer_a_count)
|
||||||
ymf278b_timer_a_reset(chip);
|
{
|
||||||
|
chip->timer_a_count = data;
|
||||||
|
|
||||||
|
// change period, ~80.8us * t
|
||||||
|
if (chip->enable & 1)
|
||||||
|
chip->timer_a->adjust(chip->timer_a->remaining(), 0, chip->timer_base * (256-data) * 4);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// timer b count
|
||||||
case 0x03:
|
case 0x03:
|
||||||
chip->timer_b_count = data;
|
if (data != chip->timer_b_count)
|
||||||
ymf278b_timer_b_reset(chip);
|
{
|
||||||
|
chip->timer_b_count = data;
|
||||||
|
|
||||||
|
// change period, ~323.1us * t
|
||||||
|
if (chip->enable & 2)
|
||||||
|
chip->timer_b->adjust(chip->timer_b->remaining(), 0, chip->timer_base * (256-data) * 16);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// timer control
|
||||||
case 0x04:
|
case 0x04:
|
||||||
if(data & 0x80)
|
if(data & 0x80)
|
||||||
chip->current_irq = 0;
|
chip->current_irq = 0;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UINT8 old_enable = chip->enable;
|
// reset timers
|
||||||
|
if((chip->enable ^ data) & 1)
|
||||||
|
{
|
||||||
|
attotime period = (data & 1) ? chip->timer_base * (256-chip->timer_a_count) * 4 : attotime::never;
|
||||||
|
chip->timer_a->adjust(period, 0, period);
|
||||||
|
}
|
||||||
|
if((chip->enable ^ data) & 2)
|
||||||
|
{
|
||||||
|
attotime period = (data & 2) ? chip->timer_base * (256-chip->timer_b_count) * 16 : attotime::never;
|
||||||
|
chip->timer_b->adjust(period, 0, period);
|
||||||
|
}
|
||||||
|
|
||||||
chip->enable = data;
|
chip->enable = data;
|
||||||
chip->current_irq &= ~data;
|
chip->current_irq &= ~data;
|
||||||
if((old_enable ^ data) & 1)
|
|
||||||
ymf278b_timer_a_reset(chip);
|
|
||||||
if((old_enable ^ data) & 2)
|
|
||||||
ymf278b_timer_b_reset(chip);
|
|
||||||
}
|
}
|
||||||
ymf278b_irq_check(machine, chip);
|
ymf278b_irq_check(machine, chip);
|
||||||
break;
|
break;
|
||||||
@ -455,6 +449,7 @@ static void ymf278b_A_w(running_machine &machine, YMF278BChip *chip, UINT8 reg,
|
|||||||
|
|
||||||
static void ymf278b_B_w(YMF278BChip *chip, UINT8 reg, UINT8 data)
|
static void ymf278b_B_w(YMF278BChip *chip, UINT8 reg, UINT8 data)
|
||||||
{
|
{
|
||||||
|
// FM register array 1 (compatible with YMF262)
|
||||||
switch(reg)
|
switch(reg)
|
||||||
{
|
{
|
||||||
// LSI TEST
|
// LSI TEST
|
||||||
@ -476,7 +471,7 @@ static void ymf278b_B_w(YMF278BChip *chip, UINT8 reg, UINT8 data)
|
|||||||
static TIMER_CALLBACK( ymf278b_timer_ld_clear )
|
static TIMER_CALLBACK( ymf278b_timer_ld_clear )
|
||||||
{
|
{
|
||||||
YMF278BChip *chip = (YMF278BChip *)ptr;
|
YMF278BChip *chip = (YMF278BChip *)ptr;
|
||||||
chip->ld = 0;
|
chip->status_ld = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ymf278b_C_w(YMF278BChip *chip, UINT8 reg, UINT8 data)
|
static void ymf278b_C_w(YMF278BChip *chip, UINT8 reg, UINT8 data)
|
||||||
@ -507,7 +502,7 @@ static void ymf278b_C_w(YMF278BChip *chip, UINT8 reg, UINT8 data)
|
|||||||
|
|
||||||
// load wavetable header
|
// load wavetable header
|
||||||
// status register LD bit is on for approx 300us
|
// status register LD bit is on for approx 300us
|
||||||
chip->ld = 1;
|
chip->status_ld = 1;
|
||||||
period = attotime::from_usec(300);
|
period = attotime::from_usec(300);
|
||||||
if (chip->clock != YMF278B_STD_CLOCK)
|
if (chip->clock != YMF278B_STD_CLOCK)
|
||||||
period = (period * chip->clock) / YMF278B_STD_CLOCK;
|
period = (period * chip->clock) / YMF278B_STD_CLOCK;
|
||||||
@ -668,13 +663,13 @@ static void ymf278b_C_w(YMF278BChip *chip, UINT8 reg, UINT8 data)
|
|||||||
static TIMER_CALLBACK( ymf278b_timer_busy_clear )
|
static TIMER_CALLBACK( ymf278b_timer_busy_clear )
|
||||||
{
|
{
|
||||||
YMF278BChip *chip = (YMF278BChip *)ptr;
|
YMF278BChip *chip = (YMF278BChip *)ptr;
|
||||||
chip->busy = 0;
|
chip->status_busy = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ymf278b_timer_busy_reset(YMF278BChip *chip, int is_pcm)
|
static void ymf278b_timer_busy_reset(YMF278BChip *chip, int is_pcm)
|
||||||
{
|
{
|
||||||
// status register BUSY bit is on for 56(FM) or 88(PCM) cycles
|
// status register BUSY bit is on for 56(FM) or 88(PCM) cycles
|
||||||
chip->busy = 1;
|
chip->status_busy = 1;
|
||||||
chip->timer_busy->adjust(attotime::from_hz(chip->clock / (is_pcm ? 88 : 56)));
|
chip->timer_busy->adjust(attotime::from_hz(chip->clock / (is_pcm ? 88 : 56)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -733,7 +728,7 @@ READ8_DEVICE_HANDLER( ymf278b_r )
|
|||||||
// bits 0 and 1 are only valid if NEW2 is set
|
// bits 0 and 1 are only valid if NEW2 is set
|
||||||
UINT8 newbits = 0;
|
UINT8 newbits = 0;
|
||||||
if (chip->exp & 2)
|
if (chip->exp & 2)
|
||||||
newbits = (chip->ld << 1) | chip->busy;
|
newbits = (chip->status_ld << 1) | chip->status_busy;
|
||||||
|
|
||||||
return newbits | chip->current_irq | (chip->irq_line == ASSERT_LINE ? 0x80 : 0x00);
|
return newbits | chip->current_irq | (chip->irq_line == ASSERT_LINE ? 0x80 : 0x00);
|
||||||
}
|
}
|
||||||
@ -759,7 +754,8 @@ READ8_DEVICE_HANDLER( ymf278b_r )
|
|||||||
logerror("%s: unexpected read at offset %X from ymf278b\n", device->machine().describe_context(), offset);
|
logerror("%s: unexpected read at offset %X from ymf278b\n", device->machine().describe_context(), offset);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return 0xff;
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -767,13 +763,14 @@ static void ymf278b_init(device_t *device, YMF278BChip *chip, void (*cb)(device_
|
|||||||
{
|
{
|
||||||
chip->rom = *device->region();
|
chip->rom = *device->region();
|
||||||
chip->romsize = device->region()->bytes();
|
chip->romsize = device->region()->bytes();
|
||||||
|
chip->clock = device->clock();
|
||||||
chip->irq_callback = cb;
|
chip->irq_callback = cb;
|
||||||
|
chip->timer_base = attotime::from_hz(chip->clock) * (19*36);
|
||||||
chip->timer_a = device->machine().scheduler().timer_alloc(FUNC(ymf278b_timer_a_tick), chip);
|
chip->timer_a = device->machine().scheduler().timer_alloc(FUNC(ymf278b_timer_a_tick), chip);
|
||||||
chip->timer_b = device->machine().scheduler().timer_alloc(FUNC(ymf278b_timer_b_tick), chip);
|
chip->timer_b = device->machine().scheduler().timer_alloc(FUNC(ymf278b_timer_b_tick), chip);
|
||||||
chip->timer_busy = device->machine().scheduler().timer_alloc(FUNC(ymf278b_timer_busy_clear), chip);
|
chip->timer_busy = device->machine().scheduler().timer_alloc(FUNC(ymf278b_timer_busy_clear), chip);
|
||||||
chip->timer_ld = device->machine().scheduler().timer_alloc(FUNC(ymf278b_timer_ld_clear), chip);
|
chip->timer_ld = device->machine().scheduler().timer_alloc(FUNC(ymf278b_timer_ld_clear), chip);
|
||||||
chip->irq_line = CLEAR_LINE;
|
chip->irq_line = CLEAR_LINE;
|
||||||
chip->clock = device->clock();
|
|
||||||
|
|
||||||
chip->timer_a->reset();
|
chip->timer_a->reset();
|
||||||
chip->timer_b->reset();
|
chip->timer_b->reset();
|
||||||
@ -791,8 +788,8 @@ static void ymf278b_register_save_state(device_t *device, YMF278BChip *chip)
|
|||||||
device->save_item(NAME(chip->wavetblhdr));
|
device->save_item(NAME(chip->wavetblhdr));
|
||||||
device->save_item(NAME(chip->memmode));
|
device->save_item(NAME(chip->memmode));
|
||||||
device->save_item(NAME(chip->memadr));
|
device->save_item(NAME(chip->memadr));
|
||||||
device->save_item(NAME(chip->busy));
|
device->save_item(NAME(chip->status_busy));
|
||||||
device->save_item(NAME(chip->ld));
|
device->save_item(NAME(chip->status_ld));
|
||||||
device->save_item(NAME(chip->exp));
|
device->save_item(NAME(chip->exp));
|
||||||
device->save_item(NAME(chip->fm_l));
|
device->save_item(NAME(chip->fm_l));
|
||||||
device->save_item(NAME(chip->fm_r));
|
device->save_item(NAME(chip->fm_r));
|
||||||
|
Loading…
Reference in New Issue
Block a user