DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/hardware/snd_pc98/sound/adpcmc.c
00001 #include    "np2glue.h"
00002 //#include      "compiler.h"
00003 #include        "sound.h"
00004 #include        "opngen.h"
00005 #include        "adpcm.h"
00006 
00007 
00008         ADPCMCFG        adpcmcfg;
00009 
00010 void adpcm_initialize(UINT rate) {
00011 
00012         adpcmcfg.rate = rate;
00013 }
00014 
00015 void adpcm_setvol(UINT vol) {
00016 
00017         adpcmcfg.vol = vol;
00018 }
00019 
00020 void adpcm_reset(ADPCM ad) {
00021 
00022         ZeroMemory(ad, sizeof(_ADPCM));
00023         ad->mask = 0;                                   // (UINT8)~0x1c;
00024         ad->delta = 127;
00025         STOREINTELWORD(ad->reg.stop, 0x0002);
00026         STOREINTELWORD(ad->reg.limit, 0xffff);
00027         ad->stop = 0x000060;
00028         ad->limit = 0x200000;
00029         adpcm_update(ad);
00030 }
00031 
00032 void adpcm_update(ADPCM ad) {
00033 
00034         UINT32  addr;
00035 
00036         if (adpcmcfg.rate) {
00037                 ad->base = ADTIMING * (OPNA_CLOCK / 72) / adpcmcfg.rate;
00038         }
00039         addr = LOADINTELWORD(ad->reg.delta);
00040         addr = (addr * ad->base) >> 16;
00041         if (addr < 0x80) {
00042                 addr = 0x80;
00043         }
00044         ad->step = addr;
00045         ad->pertim = (1 << (ADTIMING_BIT * 2)) / addr;
00046         ad->level = (ad->reg.level * adpcmcfg.vol) >> 4;
00047 }
00048 
00049 void adpcm_setreg(ADPCM ad, UINT reg, REG8 value) {
00050 
00051         UINT32  addr;
00052 
00053         sound_sync();
00054         ((UINT8 *)(&ad->reg))[reg] = value;
00055         switch(reg) {
00056                 case 0x00:                                                              // control1
00057                         if ((value & 0x80) && (!ad->play)) {
00058                                 ad->play = 0x20;
00059                                 ad->pos = ad->start;
00060                                 ad->samp = 0;
00061                                 ad->delta = 127;
00062                                 ad->remain = 0;
00063                         }
00064                         if (value & 1) {
00065                                 ad->play = 0;
00066                         }
00067                         break;
00068 
00069                 case 0x01:                                                              // control2
00070                         break;
00071 
00072                 case 0x02:      case 0x03:                                      // start address
00073                         addr = (LOADINTELWORD(ad->reg.start)) << 5;
00074                         ad->pos = addr;
00075                         ad->start = addr;
00076                         break;
00077 
00078                 case 0x04:      case 0x05:                                      // stop address
00079                         addr = (LOADINTELWORD(ad->reg.stop) + 1) << 5;
00080                         ad->stop = addr;
00081                         break;
00082 
00083                 case 0x08:                                                              // data
00084                         if ((ad->reg.ctrl1 & 0x60) == 0x60) {
00085                                 adpcm_datawrite(ad, value);
00086                         }
00087                         break;
00088 
00089                 case 0x09:      case 0x0a:                                      // delta
00090                         addr = LOADINTELWORD(ad->reg.delta);
00091                         addr = (addr * ad->base) >> 16;
00092                         if (addr < 0x80) {
00093                                 addr = 0x80;
00094                         }
00095                         ad->step = addr;
00096                         ad->pertim = (1 << (ADTIMING_BIT * 2)) / addr;
00097                         break;
00098 
00099                 case 0x0b:                                                              // level
00100                         ad->level = (value * adpcmcfg.vol) >> 4;
00101                         break;
00102 
00103                 case 0x0c:      case 0x0d:                                      // limit address
00104                         addr = (LOADINTELWORD(ad->reg.limit) + 1) << 5;
00105                         ad->limit = addr;
00106                         break;
00107 
00108                 case 0x10:                                                              // flag
00109                         if (value & 0x80) {
00110                                 ad->status = 0;
00111                         }
00112                         else {
00113                                 ad->mask = ~(value & 0x1f);
00114                         }
00115                         break;
00116         }
00117 }
00118 
00119 REG8 adpcm_status(ADPCM ad) {
00120 
00121         return(((ad->status | 8) & ad->mask) | ad->play);
00122 }
00123