DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
src/hardware/snd_pc98/cbus/pcm86io.c
00001 #include        "compiler.h"
00002 #include        "cpucore.h"
00003 #include        "pccore.h"
00004 #include        "iocore.h"
00005 #include        "pcm86io.h"
00006 #include        "sound.h"
00007 #include        "fmboard.h"
00008 
00009 
00010 extern  PCM86CFG        pcm86cfg;
00011 
00012 
00013 static const UINT8 pcm86bits[] = {1, 1, 1, 2, 0, 0, 0, 1};
00014 static const SINT32 pcm86rescue[] = {PCM86_RESCUE * 32, PCM86_RESCUE * 24,
00015                                                                          PCM86_RESCUE * 16, PCM86_RESCUE * 12,
00016                                                                          PCM86_RESCUE *  8, PCM86_RESCUE *  6,
00017                                                                          PCM86_RESCUE *  4, PCM86_RESCUE *  3};
00018 
00019 
00020 static void IOOUTCALL pcm86_oa460(UINT port, REG8 val) {
00021 
00022 //      TRACEOUT(("86pcm out %.4x %.2x", port, val));
00023         pcm86.extfunc = val;
00024         fmboard_extenable((REG8)(val & 1));
00025         (void)port;
00026 }
00027 
00028 static void IOOUTCALL pcm86_oa466(UINT port, REG8 val) {
00029 
00030 //      TRACEOUT(("86pcm out %.4x %.2x", port, val));
00031         if ((val & 0xe0) == 0xa0) {
00032                 sound_sync();
00033                 pcm86.vol5 = (~val) & 15;
00034                 pcm86.volume = pcm86cfg.vol * pcm86.vol5;
00035         }
00036         (void)port;
00037 }
00038 
00039 static void IOOUTCALL pcm86_oa468(UINT port, REG8 val) {
00040 
00041         REG8    xchgbit;
00042 
00043 //      TRACEOUT(("86pcm out %.4x %.2x", port, val));
00044         sound_sync();
00045         xchgbit = pcm86.fifo ^ val;
00046         // バッファリセット判定
00047         if ((xchgbit & 8) && (val & 8)) {
00048                 pcm86.readpos = 0;                              // バッファリセット
00049                 pcm86.wrtpos = 0;
00050                 pcm86.realbuf = 0;
00051                 pcm86.virbuf = 0;
00052                 pcm86.lastclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
00053                 pcm86.lastclock <<= 6;
00054         }
00055         if ((xchgbit & 0x10) && (!(val & 0x10))) {
00056                 pcm86.irqflag = 0;
00057 //              pcm86.write = 0;
00058 //              pcm86.reqirq = 0;
00059         }
00060         // サンプリングレート変更
00061         if (xchgbit & 7) {
00062                 pcm86.rescue = pcm86rescue[val & 7] << pcm86.stepbit;
00063                 pcm86_setpcmrate(val);
00064         }
00065 #if 1   // これ重大なバグ....
00066         pcm86.fifo = val;
00067 #else
00068         pcm86.fifo = val & (~0x10);
00069 #endif
00070         if ((xchgbit & 0x80) && (val & 0x80)) {
00071                 pcm86.lastclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
00072                 pcm86.lastclock <<= 6;
00073         }
00074         pcm86_setnextintr();
00075         (void)port;
00076 }
00077 
00078 static void IOOUTCALL pcm86_oa46a(UINT port, REG8 val) {
00079 
00080 //      TRACEOUT(("86pcm out %.4x %.2x", port, val));
00081         sound_sync();
00082         if (pcm86.fifo & 0x20) {
00083 #if 1
00084                 if (val != 0xff) {
00085                         pcm86.fifosize = (UINT16)((val + 1) << 7);
00086                 }
00087                 else {
00088                         pcm86.fifosize = 0x7ffc;
00089                 }
00090 #else
00091                 if (!val) {
00092                         val++;
00093                 }
00094                 pcm86.fifosize = (WORD)(val) << 7;
00095 #endif
00096         }
00097         else {
00098                 pcm86.dactrl = val;
00099                 pcm86.stepbit = pcm86bits[(val >> 4) & 7];
00100                 pcm86.stepmask = (1 << pcm86.stepbit) - 1;
00101                 pcm86.rescue = pcm86rescue[pcm86.fifo & 7] << pcm86.stepbit;
00102         }
00103         pcm86_setnextintr();
00104         (void)port;
00105 }
00106 
00107 static void IOOUTCALL pcm86_oa46c(UINT port, REG8 val) {
00108 
00109 //      TRACEOUT(("86pcm out %.4x %.2x", port, val));
00110 #if 1
00111         if (pcm86.virbuf < PCM86_LOGICALBUF) {
00112                 pcm86.virbuf++;
00113         }
00114         pcm86.buffer[pcm86.wrtpos] = val;
00115         pcm86.wrtpos = (pcm86.wrtpos + 1) & PCM86_BUFMSK;
00116         pcm86.realbuf++;
00117         // バッファオーバーフローの監視
00118         if (pcm86.realbuf >= PCM86_REALBUFSIZE) {
00119 #if 1
00120                 pcm86.realbuf -= 4;
00121                 pcm86.readpos = (pcm86.readpos + 4) & PCM86_BUFMSK;
00122 #else
00123                 pcm86.realbuf &= 3;                             // align4決めウチ
00124                 pcm86.realbuf += PCM86_REALBUFSIZE - 4;
00125 #endif
00126         }
00127 //      pcm86.write = 1;
00128         pcm86.reqirq = 1;
00129 #else
00130         if (pcm86.virbuf < PCM86_LOGICALBUF) {
00131                 pcm86.virbuf++;
00132                 pcm86.buffer[pcm86.wrtpos] = val;
00133                 pcm86.wrtpos = (pcm86.wrtpos + 1) & PCM86_BUFMSK;
00134                 pcm86.realbuf++;
00135                 // バッファオーバーフローの監視
00136                 if (pcm86.realbuf >= PCM86_REALBUFSIZE) {
00137                         pcm86.realbuf &= 3;                             // align4決めウチ
00138                         pcm86.realbuf += PCM86_REALBUFSIZE - 4;
00139                 }
00140 //              pcm86.write = 1;
00141                 pcm86.reqirq = 1;
00142         }
00143 #endif
00144         (void)port;
00145 }
00146 
00147 static REG8 IOINPCALL pcm86_ia460(UINT port) {
00148 
00149         (void)port;
00150         return(0x40 | (pcm86.extfunc & 1));
00151 }
00152 
00153 static REG8 IOINPCALL pcm86_ia466(UINT port) {
00154 
00155         UINT32  past;
00156         UINT32  cnt;
00157         UINT32  stepclock;
00158         REG8    ret;
00159 
00160         past = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
00161         past <<= 6;
00162         past -= pcm86.lastclock;
00163         stepclock = pcm86.stepclock;
00164         if (past >= stepclock) {
00165                 cnt = past / stepclock;
00166                 pcm86.lastclock += (cnt * stepclock);
00167                 past -= cnt * stepclock;
00168                 if (pcm86.fifo & 0x80) {
00169                         sound_sync();
00170                         RECALC_NOWCLKWAIT(cnt);
00171                 }
00172         }
00173         ret = ((past << 1) >= stepclock)?1:0;
00174         if (pcm86.virbuf >= PCM86_LOGICALBUF) {                 // バッファフル
00175                 ret |= 0x80;
00176         }
00177         else if (!pcm86.virbuf) {                                               // バッファ0
00178                 ret |= 0x40;                                                            // ちと変…
00179         }
00180         (void)port;
00181 //      TRACEOUT(("86pcm in %.4x %.2x", port, ret));
00182         return(ret);
00183 }
00184 
00185 static REG8 IOINPCALL pcm86_ia468(UINT port) {
00186 
00187         REG8    ret;
00188 
00189         ret = pcm86.fifo & (~0x10);
00190 #if 1
00191         if (pcm86gen_intrq()) {
00192                 ret |= 0x10;
00193         }
00194 #elif 1         // むしろこう?
00195         if (pcm86.fifo & 0x20) {
00196                 sound_sync();
00197                 if (pcm86.virbuf <= pcm86.fifosize) {
00198                         if (pcm86.write) {
00199                                 pcm86.write = 0;
00200                         }
00201                         else {
00202                                 ret |= 0x10;
00203                         }
00204                 }
00205         }
00206 #else
00207         if ((pcm86.write) && (pcm86.fifo & 0x20)) {
00208 //              pcm86.write = 0;
00209                 sound_sync();
00210                 if (pcm86.virbuf <= pcm86.fifosize) {
00211                         pcm86.write = 0;
00212                         ret |= 0x10;
00213                 }
00214         }
00215 #endif
00216         (void)port;
00217 //      TRACEOUT(("86pcm in %.4x %.2x", port, ret));
00218         return(ret);
00219 }
00220 
00221 static REG8 IOINPCALL pcm86_ia46a(UINT port) {
00222 
00223         (void)port;
00224 //      TRACEOUT(("86pcm in %.4x %.2x", port, pcm86.dactrl));
00225         return(pcm86.dactrl);
00226 }
00227 
00228 static REG8 IOINPCALL pcm86_inpdummy(UINT port) {
00229 
00230         (void)port;
00231         return(0);
00232 }
00233 
00234 
00235 // ----
00236 
00237 void pcm86io_bind(void) {
00238 
00239         sound_streamregist(&pcm86, (SOUNDCB)pcm86gen_getpcm);
00240 
00241         iocore_attachout(0xa460, pcm86_oa460);
00242         iocore_attachout(0xa466, pcm86_oa466);
00243         iocore_attachout(0xa468, pcm86_oa468);
00244         iocore_attachout(0xa46a, pcm86_oa46a);
00245         iocore_attachout(0xa46c, pcm86_oa46c);
00246 
00247         iocore_attachinp(0xa460, pcm86_ia460);
00248         iocore_attachinp(0xa462, pcm86_inpdummy);
00249         iocore_attachinp(0xa464, pcm86_inpdummy);
00250         iocore_attachinp(0xa466, pcm86_ia466);
00251         iocore_attachinp(0xa468, pcm86_ia468);
00252         iocore_attachinp(0xa46a, pcm86_ia46a);
00253         iocore_attachinp(0xa46c, pcm86_inpdummy);
00254         iocore_attachinp(0xa46e, pcm86_inpdummy);
00255 }
00256