forked from len0rd/rockbox
Remove unused sources from libgme.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30282 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
1b9f9fb465
commit
5f6d8bfcc0
3 changed files with 0 additions and 756 deletions
|
|
@ -4,7 +4,6 @@ kss_emu.c
|
|||
kss_scc_apu.c
|
||||
opl_apu.c
|
||||
sms_apu.c
|
||||
ymdeltat.c
|
||||
z80_cpu.c
|
||||
blip_buffer.c
|
||||
multi_buffer.c
|
||||
|
|
|
|||
|
|
@ -1,655 +0,0 @@
|
|||
/*
|
||||
**
|
||||
** File: ymdeltat.c
|
||||
**
|
||||
** YAMAHA DELTA-T adpcm sound emulation subroutine
|
||||
** used by fmopl.c (Y8950) and fm.c (YM2608 and YM2610/B)
|
||||
**
|
||||
** Base program is YM2610 emulator by Hiromitsu Shioya.
|
||||
** Written by Tatsuyuki Satoh
|
||||
** Improvements by Jarek Burczynski (bujar at mame dot net)
|
||||
**
|
||||
**
|
||||
** History:
|
||||
**
|
||||
** 03-08-2003 Jarek Burczynski:
|
||||
** - fixed BRDY flag implementation.
|
||||
**
|
||||
** 24-07-2003 Jarek Burczynski, Frits Hilderink:
|
||||
** - fixed delault value for control2 in YM_DELTAT_ADPCM_Reset
|
||||
**
|
||||
** 22-07-2003 Jarek Burczynski, Frits Hilderink:
|
||||
** - fixed external memory support
|
||||
**
|
||||
** 15-06-2003 Jarek Burczynski:
|
||||
** - implemented CPU -> AUDIO ADPCM synthesis (via writes to the ADPCM data reg $08)
|
||||
** - implemented support for the Limit address register
|
||||
** - supported two bits from the control register 2 ($01): RAM TYPE (x1 bit/x8 bit), ROM/RAM
|
||||
** - implemented external memory access (read/write) via the ADPCM data reg reads/writes
|
||||
** Thanks go to Frits Hilderink for the example code.
|
||||
**
|
||||
** 14-06-2003 Jarek Burczynski:
|
||||
** - various fixes to enable proper support for status register flags: BSRDY, PCM BSY, ZERO
|
||||
** - modified EOS handling
|
||||
**
|
||||
** 05-04-2003 Jarek Burczynski:
|
||||
** - implemented partial support for external/processor memory on sample replay
|
||||
**
|
||||
** 01-12-2002 Jarek Burczynski:
|
||||
** - fixed first missing sound in gigandes thanks to previous fix (interpolator) by ElSemi
|
||||
** - renamed/removed some YM_DELTAT struct fields
|
||||
**
|
||||
** 28-12-2001 Acho A. Tang
|
||||
** - added EOS status report on ADPCM playback.
|
||||
**
|
||||
** 05-08-2001 Jarek Burczynski:
|
||||
** - now_step is initialized with 0 at the start of play.
|
||||
**
|
||||
** 12-06-2001 Jarek Burczynski:
|
||||
** - corrected end of sample bug in YM_DELTAT_ADPCM_CALC.
|
||||
** Checked on real YM2610 chip - address register is 24 bits wide.
|
||||
** Thanks go to Stefan Jokisch (stefan.jokisch@gmx.de) for tracking down the problem.
|
||||
**
|
||||
** TO DO:
|
||||
** Check size of the address register on the other chips....
|
||||
**
|
||||
** Version 0.72
|
||||
**
|
||||
** sound chips that have this unit:
|
||||
** YM2608 OPNA
|
||||
** YM2610/B OPNB
|
||||
** Y8950 MSX AUDIO
|
||||
**
|
||||
*/
|
||||
|
||||
#include "ymdeltat.h"
|
||||
#define INLINE __inline
|
||||
#define logerror (void)
|
||||
|
||||
#define YM_DELTAT_DELTA_MAX (24576)
|
||||
#define YM_DELTAT_DELTA_MIN (127)
|
||||
#define YM_DELTAT_DELTA_DEF (127)
|
||||
|
||||
#define YM_DELTAT_DECODE_RANGE 32768
|
||||
#define YM_DELTAT_DECODE_MIN (-(YM_DELTAT_DECODE_RANGE))
|
||||
#define YM_DELTAT_DECODE_MAX ((YM_DELTAT_DECODE_RANGE)-1)
|
||||
|
||||
|
||||
/* Forecast to next Forecast (rate = *8) */
|
||||
/* 1/8 , 3/8 , 5/8 , 7/8 , 9/8 , 11/8 , 13/8 , 15/8 */
|
||||
static const INT32 ym_deltat_decode_tableB1[16] ICONST_ATTR = {
|
||||
1, 3, 5, 7, 9, 11, 13, 15,
|
||||
-1, -3, -5, -7, -9, -11, -13, -15,
|
||||
};
|
||||
/* delta to next delta (rate= *64) */
|
||||
/* 0.9 , 0.9 , 0.9 , 0.9 , 1.2 , 1.6 , 2.0 , 2.4 */
|
||||
static const INT32 ym_deltat_decode_tableB2[16] ICONST_ATTR = {
|
||||
57, 57, 57, 57, 77, 102, 128, 153,
|
||||
57, 57, 57, 57, 77, 102, 128, 153
|
||||
};
|
||||
|
||||
#if 0
|
||||
void YM_DELTAT_BRDY_callback(YM_DELTAT *DELTAT)
|
||||
{
|
||||
logerror("BRDY_callback reached (flag set) !\n");
|
||||
|
||||
/* set BRDY bit in status register */
|
||||
if(DELTAT->status_set_handler)
|
||||
if(DELTAT->status_change_BRDY_bit)
|
||||
(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
|
||||
}
|
||||
#endif
|
||||
|
||||
UINT8 YM_DELTAT_ADPCM_Read(YM_DELTAT *DELTAT)
|
||||
{
|
||||
UINT8 v = 0;
|
||||
|
||||
/* external memory read */
|
||||
if ( (DELTAT->portstate & 0xe0)==0x20 )
|
||||
{
|
||||
/* two dummy reads */
|
||||
if (DELTAT->memread)
|
||||
{
|
||||
DELTAT->now_addr = DELTAT->start << 1;
|
||||
DELTAT->memread--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if ( DELTAT->now_addr != (DELTAT->end<<1) )
|
||||
{
|
||||
v = DELTAT->memory[DELTAT->now_addr>>1];
|
||||
|
||||
/*logerror("YM Delta-T memory read $%08x, v=$%02x\n", DELTAT->now_addr >> 1, v);*/
|
||||
|
||||
DELTAT->now_addr+=2; /* two nibbles at a time */
|
||||
|
||||
/* reset BRDY bit in status register, which means we are reading the memory now */
|
||||
if(DELTAT->status_reset_handler)
|
||||
if(DELTAT->status_change_BRDY_bit)
|
||||
(DELTAT->status_reset_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
|
||||
|
||||
/* setup a timer that will callback us in 10 master clock cycles for Y8950
|
||||
* in the callback set the BRDY flag to 1 , which means we have another data ready.
|
||||
* For now, we don't really do this; we simply reset and set the flag in zero time, so that the IRQ will work.
|
||||
*/
|
||||
/* set BRDY bit in status register */
|
||||
if(DELTAT->status_set_handler)
|
||||
if(DELTAT->status_change_BRDY_bit)
|
||||
(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* set EOS bit in status register */
|
||||
if(DELTAT->status_set_handler)
|
||||
if(DELTAT->status_change_EOS_bit)
|
||||
(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_EOS_bit);
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
/* 0-DRAM x1, 1-ROM, 2-DRAM x8, 3-ROM (3 is bad setting - not allowed by the manual) */
|
||||
static const UINT8 dram_rightshift[4] ICONST_ATTR ={3,0,0,0};
|
||||
|
||||
/* DELTA-T ADPCM write register */
|
||||
void YM_DELTAT_ADPCM_Write(YM_DELTAT *DELTAT,int r,int v)
|
||||
{
|
||||
if(r>=0x10) return;
|
||||
DELTAT->reg[r] = v; /* stock data */
|
||||
|
||||
switch( r )
|
||||
{
|
||||
case 0x00:
|
||||
/*
|
||||
START:
|
||||
Accessing *external* memory is started when START bit (D7) is set to "1", so
|
||||
you must set all conditions needed for recording/playback before starting.
|
||||
If you access *CPU-managed* memory, recording/playback starts after
|
||||
read/write of ADPCM data register $08.
|
||||
|
||||
REC:
|
||||
0 = ADPCM synthesis (playback)
|
||||
1 = ADPCM analysis (record)
|
||||
|
||||
MEMDATA:
|
||||
0 = processor (*CPU-managed*) memory (means: using register $08)
|
||||
1 = external memory (using start/end/limit registers to access memory: RAM or ROM)
|
||||
|
||||
|
||||
SPOFF:
|
||||
controls output pin that should disable the speaker while ADPCM analysis
|
||||
|
||||
RESET and REPEAT only work with external memory.
|
||||
|
||||
|
||||
some examples:
|
||||
value: START, REC, MEMDAT, REPEAT, SPOFF, x,x,RESET meaning:
|
||||
C8 1 1 0 0 1 0 0 0 Analysis (recording) from AUDIO to CPU (to reg $08), sample rate in PRESCALER register
|
||||
E8 1 1 1 0 1 0 0 0 Analysis (recording) from AUDIO to EXT.MEMORY, sample rate in PRESCALER register
|
||||
80 1 0 0 0 0 0 0 0 Synthesis (playing) from CPU (from reg $08) to AUDIO,sample rate in DELTA-N register
|
||||
a0 1 0 1 0 0 0 0 0 Synthesis (playing) from EXT.MEMORY to AUDIO, sample rate in DELTA-N register
|
||||
|
||||
60 0 1 1 0 0 0 0 0 External memory write via ADPCM data register $08
|
||||
20 0 0 1 0 0 0 0 0 External memory read via ADPCM data register $08
|
||||
|
||||
*/
|
||||
/* handle emulation mode */
|
||||
if(DELTAT->emulation_mode == YM_DELTAT_EMULATION_MODE_YM2610)
|
||||
{
|
||||
v |= 0x20; /* YM2610 always uses external memory and doesn't even have memory flag bit. */
|
||||
}
|
||||
|
||||
DELTAT->portstate = v & (0x80|0x40|0x20|0x10|0x01); /* start, rec, memory mode, repeat flag copy, reset(bit0) */
|
||||
|
||||
if( DELTAT->portstate&0x80 )/* START,REC,MEMDATA,REPEAT,SPOFF,--,--,RESET */
|
||||
{
|
||||
/* set PCM BUSY bit */
|
||||
DELTAT->PCM_BSY = 1;
|
||||
|
||||
/* start ADPCM */
|
||||
DELTAT->now_step = 0;
|
||||
DELTAT->acc = 0;
|
||||
DELTAT->prev_acc = 0;
|
||||
DELTAT->adpcml = 0;
|
||||
DELTAT->adpcmd = YM_DELTAT_DELTA_DEF;
|
||||
DELTAT->now_data = 0;
|
||||
|
||||
}
|
||||
|
||||
if( DELTAT->portstate&0x20 ) /* do we access external memory? */
|
||||
{
|
||||
DELTAT->now_addr = DELTAT->start << 1;
|
||||
DELTAT->memread = 2; /* two dummy reads needed before accesing external memory via register $08*/
|
||||
|
||||
/* if yes, then let's check if ADPCM memory is mapped and big enough */
|
||||
if(DELTAT->memory == 0)
|
||||
{
|
||||
logerror("YM Delta-T ADPCM rom not mapped\n");
|
||||
DELTAT->portstate = 0x00;
|
||||
DELTAT->PCM_BSY = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( DELTAT->end >= DELTAT->memory_size ) /* Check End in Range */
|
||||
{
|
||||
/* logerror("YM Delta-T ADPCM end out of range: $%08x\n", DELTAT->end); */
|
||||
DELTAT->end = DELTAT->memory_size - 1;
|
||||
}
|
||||
if( DELTAT->start >= DELTAT->memory_size ) /* Check Start in Range */
|
||||
{
|
||||
/* logerror("YM Delta-T ADPCM start out of range: $%08x\n", DELTAT->start); */
|
||||
DELTAT->portstate = 0x00;
|
||||
DELTAT->PCM_BSY = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* we access CPU memory (ADPCM data register $08) so we only reset now_addr here */
|
||||
{
|
||||
DELTAT->now_addr = 0;
|
||||
}
|
||||
|
||||
if( DELTAT->portstate&0x01 )
|
||||
{
|
||||
DELTAT->portstate = 0x00;
|
||||
|
||||
/* clear PCM BUSY bit (in status register) */
|
||||
DELTAT->PCM_BSY = 0;
|
||||
|
||||
/* set BRDY flag */
|
||||
if(DELTAT->status_set_handler)
|
||||
if(DELTAT->status_change_BRDY_bit)
|
||||
(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
|
||||
}
|
||||
break;
|
||||
case 0x01: /* L,R,-,-,SAMPLE,DA/AD,RAMTYPE,ROM */
|
||||
/* handle emulation mode */
|
||||
if(DELTAT->emulation_mode == YM_DELTAT_EMULATION_MODE_YM2610)
|
||||
{
|
||||
v |= 0x01; /* YM2610 always uses ROM as an external memory and doesn't tave ROM/RAM memory flag bit. */
|
||||
}
|
||||
|
||||
DELTAT->pan = &DELTAT->output_pointer[(v>>6)&0x03];
|
||||
if ((DELTAT->control2 & 3) != (v & 3))
|
||||
{
|
||||
/*0-DRAM x1, 1-ROM, 2-DRAM x8, 3-ROM (3 is bad setting - not allowed by the manual) */
|
||||
if (DELTAT->DRAMportshift != dram_rightshift[v&3])
|
||||
{
|
||||
DELTAT->DRAMportshift = dram_rightshift[v&3];
|
||||
|
||||
/* final shift value depends on chip type and memory type selected:
|
||||
8 for YM2610 (ROM only),
|
||||
5 for ROM for Y8950 and YM2608,
|
||||
5 for x8bit DRAMs for Y8950 and YM2608,
|
||||
2 for x1bit DRAMs for Y8950 and YM2608.
|
||||
*/
|
||||
|
||||
/* refresh addresses */
|
||||
DELTAT->start = (DELTAT->reg[0x3]*0x0100 | DELTAT->reg[0x2]) << (DELTAT->portshift - DELTAT->DRAMportshift);
|
||||
DELTAT->end = (DELTAT->reg[0x5]*0x0100 | DELTAT->reg[0x4]) << (DELTAT->portshift - DELTAT->DRAMportshift);
|
||||
DELTAT->end += (1 << (DELTAT->portshift-DELTAT->DRAMportshift) ) - 1;
|
||||
DELTAT->limit = (DELTAT->reg[0xd]*0x0100 | DELTAT->reg[0xc]) << (DELTAT->portshift - DELTAT->DRAMportshift);
|
||||
}
|
||||
}
|
||||
DELTAT->control2 = v;
|
||||
break;
|
||||
case 0x02: /* Start Address L */
|
||||
case 0x03: /* Start Address H */
|
||||
DELTAT->start = (DELTAT->reg[0x3]*0x0100 | DELTAT->reg[0x2]) << (DELTAT->portshift - DELTAT->DRAMportshift);
|
||||
/*logerror("DELTAT start: 02=%2x 03=%2x addr=%8x\n",DELTAT->reg[0x2], DELTAT->reg[0x3],DELTAT->start );*/
|
||||
break;
|
||||
case 0x04: /* Stop Address L */
|
||||
case 0x05: /* Stop Address H */
|
||||
DELTAT->end = (DELTAT->reg[0x5]*0x0100 | DELTAT->reg[0x4]) << (DELTAT->portshift - DELTAT->DRAMportshift);
|
||||
DELTAT->end += (1 << (DELTAT->portshift-DELTAT->DRAMportshift) ) - 1;
|
||||
/*logerror("DELTAT end : 04=%2x 05=%2x addr=%8x\n",DELTAT->reg[0x4], DELTAT->reg[0x5],DELTAT->end );*/
|
||||
break;
|
||||
case 0x06: /* Prescale L (ADPCM and Record frq) */
|
||||
case 0x07: /* Prescale H */
|
||||
break;
|
||||
case 0x08: /* ADPCM data */
|
||||
|
||||
/*
|
||||
some examples:
|
||||
value: START, REC, MEMDAT, REPEAT, SPOFF, x,x,RESET meaning:
|
||||
C8 1 1 0 0 1 0 0 0 Analysis (recording) from AUDIO to CPU (to reg $08), sample rate in PRESCALER register
|
||||
E8 1 1 1 0 1 0 0 0 Analysis (recording) from AUDIO to EXT.MEMORY, sample rate in PRESCALER register
|
||||
80 1 0 0 0 0 0 0 0 Synthesis (playing) from CPU (from reg $08) to AUDIO,sample rate in DELTA-N register
|
||||
a0 1 0 1 0 0 0 0 0 Synthesis (playing) from EXT.MEMORY to AUDIO, sample rate in DELTA-N register
|
||||
|
||||
60 0 1 1 0 0 0 0 0 External memory write via ADPCM data register $08
|
||||
20 0 0 1 0 0 0 0 0 External memory read via ADPCM data register $08
|
||||
|
||||
*/
|
||||
|
||||
/* external memory write */
|
||||
if ( (DELTAT->portstate & 0xe0)==0x60 )
|
||||
{
|
||||
if (DELTAT->memread)
|
||||
{
|
||||
DELTAT->now_addr = DELTAT->start << 1;
|
||||
DELTAT->memread = 0;
|
||||
}
|
||||
|
||||
/*logerror("YM Delta-T memory write $%08x, v=$%02x\n", DELTAT->now_addr >> 1, v);*/
|
||||
|
||||
if ( DELTAT->now_addr != (DELTAT->end<<1) )
|
||||
{
|
||||
DELTAT->memory[DELTAT->now_addr>>1] = v;
|
||||
DELTAT->now_addr+=2; /* two nibbles at a time */
|
||||
|
||||
/* reset BRDY bit in status register, which means we are processing the write */
|
||||
if(DELTAT->status_reset_handler)
|
||||
if(DELTAT->status_change_BRDY_bit)
|
||||
(DELTAT->status_reset_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
|
||||
|
||||
/* setup a timer that will callback us in 10 master clock cycles for Y8950
|
||||
* in the callback set the BRDY flag to 1 , which means we have written the data.
|
||||
* For now, we don't really do this; we simply reset and set the flag in zero time, so that the IRQ will work.
|
||||
*/
|
||||
/* set BRDY bit in status register */
|
||||
if(DELTAT->status_set_handler)
|
||||
if(DELTAT->status_change_BRDY_bit)
|
||||
(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* set EOS bit in status register */
|
||||
if(DELTAT->status_set_handler)
|
||||
if(DELTAT->status_change_EOS_bit)
|
||||
(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_EOS_bit);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* ADPCM synthesis from CPU */
|
||||
if ( (DELTAT->portstate & 0xe0)==0x80 )
|
||||
{
|
||||
DELTAT->CPU_data = v;
|
||||
|
||||
/* Reset BRDY bit in status register, which means we are full of data */
|
||||
if(DELTAT->status_reset_handler)
|
||||
if(DELTAT->status_change_BRDY_bit)
|
||||
(DELTAT->status_reset_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
case 0x09: /* DELTA-N L (ADPCM Playback Prescaler) */
|
||||
case 0x0a: /* DELTA-N H */
|
||||
DELTAT->delta = (DELTAT->reg[0xa]*0x0100 | DELTAT->reg[0x9]);
|
||||
DELTAT->step = (UINT32)( (double)(DELTAT->delta /* *(1<<(YM_DELTAT_SHIFT-16)) */ ) * (DELTAT->freqbase) );
|
||||
/*logerror("DELTAT deltan:09=%2x 0a=%2x\n",DELTAT->reg[0x9], DELTAT->reg[0xa]);*/
|
||||
break;
|
||||
case 0x0b: /* Output level control (volume, linear) */
|
||||
{
|
||||
INT32 oldvol = DELTAT->volume;
|
||||
DELTAT->volume = (v&0xff) * (DELTAT->output_range/256) / YM_DELTAT_DECODE_RANGE;
|
||||
/* v * ((1<<16)>>8) >> 15;
|
||||
* thus: v * (1<<8) >> 15;
|
||||
* thus: output_range must be (1 << (15+8)) at least
|
||||
* v * ((1<<23)>>8) >> 15;
|
||||
* v * (1<<15) >> 15;
|
||||
*/
|
||||
/*logerror("DELTAT vol = %2x\n",v&0xff);*/
|
||||
if( oldvol != 0 )
|
||||
{
|
||||
DELTAT->adpcml = (int)((double)DELTAT->adpcml / (double)oldvol * (double)DELTAT->volume);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x0c: /* Limit Address L */
|
||||
case 0x0d: /* Limit Address H */
|
||||
DELTAT->limit = (DELTAT->reg[0xd]*0x0100 | DELTAT->reg[0xc]) << (DELTAT->portshift - DELTAT->DRAMportshift);
|
||||
/*logerror("DELTAT limit: 0c=%2x 0d=%2x addr=%8x\n",DELTAT->reg[0xc], DELTAT->reg[0xd],DELTAT->limit );*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void YM_DELTAT_ADPCM_Reset(YM_DELTAT *DELTAT,int pan,int emulation_mode)
|
||||
{
|
||||
DELTAT->now_addr = 0;
|
||||
DELTAT->now_step = 0;
|
||||
DELTAT->step = 0;
|
||||
DELTAT->start = 0;
|
||||
DELTAT->end = 0;
|
||||
DELTAT->limit = ~0; /* this way YM2610 and Y8950 (both of which don't have limit address reg) will still work */
|
||||
DELTAT->volume = 0;
|
||||
DELTAT->pan = &DELTAT->output_pointer[pan];
|
||||
DELTAT->acc = 0;
|
||||
DELTAT->prev_acc = 0;
|
||||
DELTAT->adpcmd = 127;
|
||||
DELTAT->adpcml = 0;
|
||||
DELTAT->emulation_mode = (UINT8)emulation_mode;
|
||||
DELTAT->portstate = (emulation_mode == YM_DELTAT_EMULATION_MODE_YM2610) ? 0x20 : 0;
|
||||
DELTAT->control2 = (emulation_mode == YM_DELTAT_EMULATION_MODE_YM2610) ? 0x01 : 0; /* default setting depends on the emulation mode. MSX demo called "facdemo_4" doesn't setup control2 register at all and still works */
|
||||
DELTAT->DRAMportshift = dram_rightshift[DELTAT->control2 & 3];
|
||||
|
||||
/* The flag mask register disables the BRDY after the reset, however
|
||||
** as soon as the mask is enabled the flag needs to be set. */
|
||||
|
||||
/* set BRDY bit in status register */
|
||||
if(DELTAT->status_set_handler)
|
||||
if(DELTAT->status_change_BRDY_bit)
|
||||
(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void YM_DELTAT_postload(YM_DELTAT *DELTAT,UINT8 *regs)
|
||||
{
|
||||
int r;
|
||||
|
||||
/* to keep adpcml */
|
||||
DELTAT->volume = 0;
|
||||
/* update */
|
||||
for(r=1;r<16;r++)
|
||||
YM_DELTAT_ADPCM_Write(DELTAT,r,regs[r]);
|
||||
DELTAT->reg[0] = regs[0];
|
||||
|
||||
/* current rom data */
|
||||
if (DELTAT->memory)
|
||||
DELTAT->now_data = *(DELTAT->memory + (DELTAT->now_addr>>1) );
|
||||
|
||||
}
|
||||
void YM_DELTAT_savestate(const device_config *device,YM_DELTAT *DELTAT)
|
||||
{
|
||||
#ifdef __STATE_H__
|
||||
state_save_register_device_item(device, 0, DELTAT->portstate);
|
||||
state_save_register_device_item(device, 0, DELTAT->now_addr);
|
||||
state_save_register_device_item(device, 0, DELTAT->now_step);
|
||||
state_save_register_device_item(device, 0, DELTAT->acc);
|
||||
state_save_register_device_item(device, 0, DELTAT->prev_acc);
|
||||
state_save_register_device_item(device, 0, DELTAT->adpcmd);
|
||||
state_save_register_device_item(device, 0, DELTAT->adpcml);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#define YM_DELTAT_Limit(val,max,min) \
|
||||
{ \
|
||||
if ( val > max ) val = max; \
|
||||
else if ( val < min ) val = min; \
|
||||
}
|
||||
|
||||
static INLINE void YM_DELTAT_synthesis_from_external_memory(YM_DELTAT *DELTAT)
|
||||
{
|
||||
UINT32 step;
|
||||
int data;
|
||||
|
||||
DELTAT->now_step += DELTAT->step;
|
||||
if ( DELTAT->now_step >= (1<<YM_DELTAT_SHIFT) )
|
||||
{
|
||||
step = DELTAT->now_step >> YM_DELTAT_SHIFT;
|
||||
DELTAT->now_step &= (1<<YM_DELTAT_SHIFT)-1;
|
||||
do{
|
||||
|
||||
if ( DELTAT->now_addr == (DELTAT->limit<<1) )
|
||||
DELTAT->now_addr = 0;
|
||||
|
||||
if ( DELTAT->now_addr == (DELTAT->end<<1) ) { /* 12-06-2001 JB: corrected comparison. Was > instead of == */
|
||||
if( DELTAT->portstate&0x10 ){
|
||||
/* repeat start */
|
||||
DELTAT->now_addr = DELTAT->start<<1;
|
||||
DELTAT->acc = 0;
|
||||
DELTAT->adpcmd = YM_DELTAT_DELTA_DEF;
|
||||
DELTAT->prev_acc = 0;
|
||||
}else{
|
||||
/* set EOS bit in status register */
|
||||
if(DELTAT->status_set_handler)
|
||||
if(DELTAT->status_change_EOS_bit)
|
||||
(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_EOS_bit);
|
||||
|
||||
/* clear PCM BUSY bit (reflected in status register) */
|
||||
DELTAT->PCM_BSY = 0;
|
||||
|
||||
DELTAT->portstate = 0;
|
||||
DELTAT->adpcml = 0;
|
||||
DELTAT->prev_acc = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if( DELTAT->now_addr&1 ) data = DELTAT->now_data & 0x0f;
|
||||
else
|
||||
{
|
||||
DELTAT->now_data = *(DELTAT->memory + (DELTAT->now_addr>>1));
|
||||
data = DELTAT->now_data >> 4;
|
||||
}
|
||||
|
||||
DELTAT->now_addr++;
|
||||
/* 12-06-2001 JB: */
|
||||
/* YM2610 address register is 24 bits wide.*/
|
||||
/* The "+1" is there because we use 1 bit more for nibble calculations.*/
|
||||
/* WARNING: */
|
||||
/* Side effect: we should take the size of the mapped ROM into account */
|
||||
DELTAT->now_addr &= ( (1<<(24+1))-1);
|
||||
|
||||
/* store accumulator value */
|
||||
DELTAT->prev_acc = DELTAT->acc;
|
||||
|
||||
/* Forecast to next Forecast */
|
||||
DELTAT->acc += (ym_deltat_decode_tableB1[data] * DELTAT->adpcmd / 8);
|
||||
YM_DELTAT_Limit(DELTAT->acc,YM_DELTAT_DECODE_MAX, YM_DELTAT_DECODE_MIN);
|
||||
|
||||
/* delta to next delta */
|
||||
DELTAT->adpcmd = (DELTAT->adpcmd * ym_deltat_decode_tableB2[data] ) / 64;
|
||||
YM_DELTAT_Limit(DELTAT->adpcmd,YM_DELTAT_DELTA_MAX, YM_DELTAT_DELTA_MIN );
|
||||
|
||||
/* ElSemi: Fix interpolator. */
|
||||
/*DELTAT->prev_acc = prev_acc + ((DELTAT->acc - prev_acc) / 2 );*/
|
||||
|
||||
}while(--step);
|
||||
|
||||
}
|
||||
|
||||
/* ElSemi: Fix interpolator. */
|
||||
DELTAT->adpcml = DELTAT->prev_acc * (int)((1<<YM_DELTAT_SHIFT)-DELTAT->now_step);
|
||||
DELTAT->adpcml += (DELTAT->acc * (int)DELTAT->now_step);
|
||||
DELTAT->adpcml = (DELTAT->adpcml>>YM_DELTAT_SHIFT) * (int)DELTAT->volume;
|
||||
|
||||
/* output for work of output channels (outd[OPNxxxx])*/
|
||||
*(DELTAT->pan) += DELTAT->adpcml;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static INLINE void YM_DELTAT_synthesis_from_CPU_memory(YM_DELTAT *DELTAT)
|
||||
{
|
||||
UINT32 step;
|
||||
int data;
|
||||
|
||||
DELTAT->now_step += DELTAT->step;
|
||||
if ( DELTAT->now_step >= (1<<YM_DELTAT_SHIFT) )
|
||||
{
|
||||
step = DELTAT->now_step >> YM_DELTAT_SHIFT;
|
||||
DELTAT->now_step &= (1<<YM_DELTAT_SHIFT)-1;
|
||||
do{
|
||||
|
||||
if( DELTAT->now_addr&1 )
|
||||
{
|
||||
data = DELTAT->now_data & 0x0f;
|
||||
|
||||
DELTAT->now_data = DELTAT->CPU_data;
|
||||
|
||||
/* after we used CPU_data, we set BRDY bit in status register,
|
||||
* which means we are ready to accept another byte of data */
|
||||
if(DELTAT->status_set_handler)
|
||||
if(DELTAT->status_change_BRDY_bit)
|
||||
(DELTAT->status_set_handler)(DELTAT->status_change_which_chip, DELTAT->status_change_BRDY_bit);
|
||||
}
|
||||
else
|
||||
{
|
||||
data = DELTAT->now_data >> 4;
|
||||
}
|
||||
|
||||
DELTAT->now_addr++;
|
||||
|
||||
/* store accumulator value */
|
||||
DELTAT->prev_acc = DELTAT->acc;
|
||||
|
||||
/* Forecast to next Forecast */
|
||||
DELTAT->acc += (ym_deltat_decode_tableB1[data] * DELTAT->adpcmd / 8);
|
||||
YM_DELTAT_Limit(DELTAT->acc,YM_DELTAT_DECODE_MAX, YM_DELTAT_DECODE_MIN);
|
||||
|
||||
/* delta to next delta */
|
||||
DELTAT->adpcmd = (DELTAT->adpcmd * ym_deltat_decode_tableB2[data] ) / 64;
|
||||
YM_DELTAT_Limit(DELTAT->adpcmd,YM_DELTAT_DELTA_MAX, YM_DELTAT_DELTA_MIN );
|
||||
|
||||
|
||||
}while(--step);
|
||||
|
||||
}
|
||||
|
||||
/* ElSemi: Fix interpolator. */
|
||||
DELTAT->adpcml = DELTAT->prev_acc * (int)((1<<YM_DELTAT_SHIFT)-DELTAT->now_step);
|
||||
DELTAT->adpcml += (DELTAT->acc * (int)DELTAT->now_step);
|
||||
DELTAT->adpcml = (DELTAT->adpcml>>YM_DELTAT_SHIFT) * (int)DELTAT->volume;
|
||||
|
||||
/* output for work of output channels (outd[OPNxxxx])*/
|
||||
*(DELTAT->pan) += DELTAT->adpcml;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ADPCM B (Delta-T control type) */
|
||||
void YM_DELTAT_ADPCM_CALC(YM_DELTAT *DELTAT)
|
||||
{
|
||||
|
||||
/*
|
||||
some examples:
|
||||
value: START, REC, MEMDAT, REPEAT, SPOFF, x,x,RESET meaning:
|
||||
80 1 0 0 0 0 0 0 0 Synthesis (playing) from CPU (from reg $08) to AUDIO,sample rate in DELTA-N register
|
||||
a0 1 0 1 0 0 0 0 0 Synthesis (playing) from EXT.MEMORY to AUDIO, sample rate in DELTA-N register
|
||||
C8 1 1 0 0 1 0 0 0 Analysis (recording) from AUDIO to CPU (to reg $08), sample rate in PRESCALER register
|
||||
E8 1 1 1 0 1 0 0 0 Analysis (recording) from AUDIO to EXT.MEMORY, sample rate in PRESCALER register
|
||||
|
||||
60 0 1 1 0 0 0 0 0 External memory write via ADPCM data register $08
|
||||
20 0 0 1 0 0 0 0 0 External memory read via ADPCM data register $08
|
||||
|
||||
*/
|
||||
|
||||
if ( (DELTAT->portstate & 0xe0)==0xa0 )
|
||||
{
|
||||
YM_DELTAT_synthesis_from_external_memory(DELTAT);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( (DELTAT->portstate & 0xe0)==0x80 )
|
||||
{
|
||||
/* ADPCM synthesis from CPU-managed memory (from reg $08) */
|
||||
YM_DELTAT_synthesis_from_CPU_memory(DELTAT); /* change output based on data in ADPCM data reg ($08) */
|
||||
return;
|
||||
}
|
||||
|
||||
//todo: ADPCM analysis
|
||||
// if ( (DELTAT->portstate & 0xe0)==0xc0 )
|
||||
// if ( (DELTAT->portstate & 0xe0)==0xe0 )
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef __YMDELTAT_H__
|
||||
#define __YMDELTAT_H__
|
||||
|
||||
#include "blargg_common.h"
|
||||
|
||||
/* compiler dependence */
|
||||
#ifndef __OSDCOMM_H__
|
||||
#define __OSDCOMM_H__
|
||||
typedef unsigned char UINT8; /* unsigned 8bit */
|
||||
typedef unsigned short UINT16; /* unsigned 16bit */
|
||||
typedef unsigned int UINT32; /* unsigned 32bit */
|
||||
typedef signed char INT8; /* signed 8bit */
|
||||
typedef signed short INT16; /* signed 16bit */
|
||||
typedef signed int INT32; /* signed 32bit */
|
||||
|
||||
typedef INT32 stream_sample_t;
|
||||
|
||||
#endif /* __OSDCOMM_H__ */
|
||||
|
||||
#define YM_DELTAT_SHIFT (16)
|
||||
|
||||
#define YM_DELTAT_EMULATION_MODE_NORMAL 0
|
||||
#define YM_DELTAT_EMULATION_MODE_YM2610 1
|
||||
|
||||
|
||||
typedef void (*STATUS_CHANGE_HANDLER)(void *chip, UINT8 status_bits);
|
||||
|
||||
|
||||
/* DELTA-T (adpcm type B) struct */
|
||||
typedef struct deltat_adpcm_state { /* AT: rearranged and tigntened structure */
|
||||
UINT8 *memory;
|
||||
INT32 *output_pointer;/* pointer of output pointers */
|
||||
INT32 *pan; /* pan : &output_pointer[pan] */
|
||||
double freqbase;
|
||||
#if 0
|
||||
double write_time; /* Y8950: 10 cycles of main clock; YM2608: 20 cycles of main clock */
|
||||
double read_time; /* Y8950: 8 cycles of main clock; YM2608: 18 cycles of main clock */
|
||||
#endif
|
||||
UINT32 memory_size;
|
||||
int output_range;
|
||||
UINT32 now_addr; /* current address */
|
||||
UINT32 now_step; /* currect step */
|
||||
UINT32 step; /* step */
|
||||
UINT32 start; /* start address */
|
||||
UINT32 limit; /* limit address */
|
||||
UINT32 end; /* end address */
|
||||
UINT32 delta; /* delta scale */
|
||||
INT32 volume; /* current volume */
|
||||
INT32 acc; /* shift Measurement value*/
|
||||
INT32 adpcmd; /* next Forecast */
|
||||
INT32 adpcml; /* current value */
|
||||
INT32 prev_acc; /* leveling value */
|
||||
UINT8 now_data; /* current rom data */
|
||||
UINT8 CPU_data; /* current data from reg 08 */
|
||||
UINT8 portstate; /* port status */
|
||||
UINT8 control2; /* control reg: SAMPLE, DA/AD, RAM TYPE (x8bit / x1bit), ROM/RAM */
|
||||
UINT8 portshift; /* address bits shift-left:
|
||||
** 8 for YM2610,
|
||||
** 5 for Y8950 and YM2608 */
|
||||
|
||||
UINT8 DRAMportshift; /* address bits shift-right:
|
||||
** 0 for ROM and x8bit DRAMs,
|
||||
** 3 for x1 DRAMs */
|
||||
|
||||
UINT8 memread; /* needed for reading/writing external memory */
|
||||
|
||||
/* handlers and parameters for the status flags support */
|
||||
STATUS_CHANGE_HANDLER status_set_handler;
|
||||
STATUS_CHANGE_HANDLER status_reset_handler;
|
||||
|
||||
/* note that different chips have these flags on different
|
||||
** bits of the status register
|
||||
*/
|
||||
void * status_change_which_chip; /* this chip id */
|
||||
UINT8 status_change_EOS_bit; /* 1 on End Of Sample (record/playback/cycle time of AD/DA converting has passed)*/
|
||||
UINT8 status_change_BRDY_bit; /* 1 after recording 2 datas (2x4bits) or after reading/writing 1 data */
|
||||
UINT8 status_change_ZERO_bit; /* 1 if silence lasts for more than 290 miliseconds on ADPCM recording */
|
||||
|
||||
/* neither Y8950 nor YM2608 can generate IRQ when PCMBSY bit changes, so instead of above,
|
||||
** the statusflag gets ORed with PCM_BSY (below) (on each read of statusflag of Y8950 and YM2608)
|
||||
*/
|
||||
UINT8 PCM_BSY; /* 1 when ADPCM is playing; Y8950/YM2608 only */
|
||||
|
||||
UINT8 reg[16]; /* adpcm registers */
|
||||
UINT8 emulation_mode; /* which chip we're emulating */
|
||||
}YM_DELTAT;
|
||||
|
||||
/*void YM_DELTAT_BRDY_callback(YM_DELTAT *DELTAT);*/
|
||||
|
||||
UINT8 YM_DELTAT_ADPCM_Read(YM_DELTAT *DELTAT) ICODE_ATTR;
|
||||
void YM_DELTAT_ADPCM_Write(YM_DELTAT *DELTAT,int r,int v) ICODE_ATTR;
|
||||
void YM_DELTAT_ADPCM_Reset(YM_DELTAT *DELTAT,int pan,int emulation_mode);
|
||||
void YM_DELTAT_ADPCM_CALC(YM_DELTAT *DELTAT) ICODE_ATTR;
|
||||
|
||||
/*void YM_DELTAT_postload(YM_DELTAT *DELTAT,UINT8 *regs);
|
||||
void YM_DELTAT_savestate(const device_config *device,YM_DELTAT *DELTAT);*/
|
||||
|
||||
#endif /* __YMDELTAT_H__ */
|
||||
Loading…
Add table
Add a link
Reference in a new issue