DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/hardware/snd_pc98/sound/s98.c
00001 //
00002 //  PC-98 Sound logging
00003 //    for S98amp S98 Input plugin for Winamp Version 1.3.1+ by Mamiya
00004 //
00005 
00006 #include        "compiler.h"
00007 
00008 #if defined(SUPPORT_S98)
00009 
00010 #include        "dosio.h"
00011 #include        "pccore.h"
00012 #include        "iocore.h"
00013 #include        "sound.h"
00014 #include        "fmboard.h"
00015 #include        "s98.h"
00016 
00017 
00018 #define S98LOG_BUFSIZE (32 * 1024)
00019 
00020 typedef struct {
00021         UINT8   magic[3];
00022         UINT8   formatversion;
00023         UINT8   timerinfo[4];
00024         UINT8   timerinfo2[4];
00025         UINT8   compressing[4];
00026         UINT8   offset[4];
00027         UINT8   dumpdata[4];
00028         UINT8   looppoint[4];
00029         UINT8   headerreserved[0x24];
00030         UINT8   title[0x40];
00031 } S98HDR;
00032 
00033 static struct {
00034         FILEH   fh;
00035         UINT32  intcount;
00036         SINT32  clock;
00037         UINT    p;
00038         UINT8   buf[S98LOG_BUFSIZE];
00039 } s98log;
00040 
00041 
00042 static void s98timer(NEVENTITEM item);
00043 
00044 static void sets98event(BOOL absolute) {
00045 
00046         s98log.intcount++;
00047         nevent_set(NEVENT_S98TIMER, s98log.clock, s98timer, NEVENT_RELATIVE);
00048         (void)absolute;
00049 }
00050 
00051 static void s98timer(NEVENTITEM item) {
00052 
00053         if (s98log.fh != FILEH_INVALID) {
00054                 sets98event(NEVENT_RELATIVE);
00055         }
00056         (void)item;
00057 }
00058 
00059 static void S98_flush(void) {
00060 
00061         if (s98log.p) {
00062                 file_write(s98log.fh, s98log.buf, s98log.p);
00063                 s98log.p = 0;
00064         }
00065 }
00066 
00067 static void S98_putc(REG8 data) {
00068 
00069         s98log.buf[s98log.p++] = data;
00070         if (s98log.p == S98LOG_BUFSIZE) {
00071                 S98_flush();
00072         }
00073 }
00074 
00075 static void S98_putint(void) {
00076 
00077         if (s98log.intcount) {
00078                 if (s98log.intcount == 1) {
00079                         S98_putc(0xFF);                                 /* SYNC(1) */
00080                 }
00081                 else if (s98log.intcount == 2) {
00082                         S98_putc(0xFF);                                 /* SYNC(1) */
00083                         S98_putc(0xFF);                                 /* SYNC(1) */
00084                 }
00085                 else {
00086                         S98_putc(0xFE);                                 /* SYNC(n) */
00087                         s98log.intcount -= 2;
00088                         while (s98log.intcount > 0x7f) {
00089                                 S98_putc((REG8)(0x80 | (s98log.intcount & 0x7f)));
00090                                 s98log.intcount >>= 7;
00091                         }
00092                         S98_putc((REG8)(s98log.intcount & 0x7f));
00093                 }
00094                 s98log.intcount = 0;
00095         }
00096 }
00097 
00098 
00099 // ----
00100 
00101 void S98_init(void) {
00102 
00103         s98log.fh = FILEH_INVALID;
00104 }
00105 
00106 void S98_trash(void) {
00107 
00108         S98_close();
00109 }
00110 
00111 BRESULT S98_open(const OEMCHAR *filename) {
00112 
00113         UINT    i;
00114         S98HDR  hdr;
00115 
00116         // ファイルのオープン
00117         s98log.fh = file_create(filename);
00118         if (s98log.fh == FILEH_INVALID) {
00119                 return(FAILURE);
00120         }
00121 
00122         // 初期化
00123         s98log.clock = pccore.realclock / 1000;
00124         s98log.p = 0;
00125 
00126         // ヘッダの保存
00127         ZeroMemory(&hdr, sizeof(hdr));
00128         hdr.magic[0] = 'S';
00129         hdr.magic[1] = '9';
00130         hdr.magic[2] = '8';
00131         hdr.formatversion = '1';
00132         STOREINTELDWORD(hdr.timerinfo, 1);
00133         STOREINTELDWORD(hdr.offset, offsetof(S98HDR, title));
00134         STOREINTELDWORD(hdr.dumpdata, sizeof(S98HDR));
00135         for (i=0; i<sizeof(hdr); i++) {
00136                 S98_putc(*(((UINT8 *)&hdr) + i));
00137         }
00138 
00139 #if 1
00140         // FM
00141         for (i=0x30; i<0xb6; i++) {
00142                 if ((i & 3) != 3) {
00143                         S98_putc(NORMAL2608);
00144                         S98_putc((REG8)i);
00145                         S98_putc(opn.reg[i]);
00146 
00147                         S98_putc(EXTEND2608);
00148                         S98_putc((REG8)i);
00149                         S98_putc(opn.reg[i+0x100]);
00150                 }
00151         }
00152         // PSG
00153         for (i=0x00; i<0x0e; i++) {
00154                 S98_putc(NORMAL2608);
00155                 S98_putc((REG8)i);
00156                 S98_putc(((UINT8 *)&psg1.reg)[i]);
00157         }
00158 #endif
00159 
00160         // 一応パディング
00161         s98log.intcount = 10;
00162 
00163         sets98event(NEVENT_ABSOLUTE);
00164         return(SUCCESS);
00165 }
00166 
00167 void S98_close(void) {
00168 
00169         if (s98log.fh != FILEH_INVALID) {
00170                 S98_putint();
00171                 S98_putc(0xFD);                         /* END MARK */
00172                 S98_flush();
00173                 nevent_reset(NEVENT_S98TIMER);
00174                 file_close(s98log.fh);
00175                 s98log.fh = FILEH_INVALID;
00176         }
00177 }
00178 
00179 void S98_put(REG8 module, UINT addr, REG8 data) {
00180 
00181         if (s98log.fh != FILEH_INVALID) {
00182                 S98_putint();
00183                 S98_putc(module);
00184                 S98_putc((UINT8)addr);
00185                 S98_putc(data);
00186         }
00187 }
00188 
00189 void S98_sync(void) {
00190 }
00191 #endif
00192