NP2kai/sound/s98.c
Tomohiro Yoshidomi 1a7840e6df fix merge miss
2017-08-23 02:47:22 +09:00

255 lines
5.4 KiB
C
Raw Blame History

/**
* @file s98.cpp
* @brief Interface of logging PC-98 sound
* for S98amp S98 Input plugin for Winamp Version 1.3.1+ by Mamiya
*/
#include "compiler.h"
#if defined(SUPPORT_S98)
#include "s98.h"
#include "pccore.h"
#include "nevent.h"
#include "dosio.h"
#include "fmboard.h"
#define S98LOG_BUFSIZE (32 * 1024)
typedef struct {
UINT8 magic[3];
UINT8 formatversion;
UINT8 timerinfo[4];
UINT8 timerinfo2[4];
UINT8 compressing[4];
UINT8 offset[4];
UINT8 dumpdata[4];
UINT8 looppoint[4];
UINT8 headerreserved[0x24];
UINT8 devicecount[4];
UINT8 device1type[4];
UINT8 device1clock[4];
UINT8 device1pan[4];
UINT8 device1reserved[4];
UINT8 device2type[4];
UINT8 device2clock[4];
UINT8 device2pan[4];
UINT8 device2reserved[4];
UINT8 device3type[4];
UINT8 device3clock[4];
UINT8 device3pan[4];
UINT8 device3reserved[4];
UINT8 title[0x30];
} S98HDR;
static struct {
FILEH fh;
UINT32 intcount;
SINT32 clock;
UINT p;
UINT8 buf[S98LOG_BUFSIZE];
} s98log;
static void s98timer(NEVENTITEM item);
static void sets98event(NEVENTPOSITION absolute) {
s98log.intcount++;
nevent_set(NEVENT_S98TIMER, s98log.clock, s98timer, NEVENT_RELATIVE);
(void)absolute;
}
static void s98timer(NEVENTITEM item) {
if (s98log.fh != FILEH_INVALID) {
sets98event(NEVENT_RELATIVE);
}
(void)item;
}
static void S98_flush(void) {
if (s98log.p) {
file_write(s98log.fh, s98log.buf, s98log.p);
s98log.p = 0;
}
}
static void S98_putc(REG8 data) {
s98log.buf[s98log.p++] = data;
if (s98log.p == S98LOG_BUFSIZE) {
S98_flush();
}
}
static void S98_putint(void) {
if (s98log.intcount) {
if (s98log.intcount == 1) {
S98_putc(0xFF); /* SYNC(1) */
}
else if (s98log.intcount == 2) {
S98_putc(0xFF); /* SYNC(1) */
S98_putc(0xFF); /* SYNC(1) */
}
else {
S98_putc(0xFE); /* SYNC(n) */
s98log.intcount -= 2;
while (s98log.intcount > 0x7f) {
S98_putc((REG8)(0x80 | (s98log.intcount & 0x7f)));
s98log.intcount >>= 7;
}
S98_putc((REG8)(s98log.intcount & 0x7f));
}
s98log.intcount = 0;
}
}
// ----
void S98_init(void) {
s98log.fh = FILEH_INVALID;
}
void S98_trash(void) {
S98_close();
}
BRESULT S98_open(const OEMCHAR *filename) {
UINT i;
S98HDR hdr;
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̃I<CC83>[<5B>v<EFBFBD><76>
s98log.fh = file_create(filename);
if (s98log.fh == FILEH_INVALID) {
return(FAILURE);
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
s98log.clock = pccore.realclock / 1000;
s98log.p = 0;
// <20>w<EFBFBD>b<EFBFBD>_<EFBFBD>̕ۑ<CC95>
ZeroMemory(&hdr, sizeof(hdr));
hdr.magic[0] = 'S';
hdr.magic[1] = '9';
hdr.magic[2] = '8';
STOREINTELDWORD(hdr.timerinfo, 1);
STOREINTELDWORD(hdr.dumpdata, sizeof(S98HDR));
switch(g_nSoundID) {
case 0x02:
case 0x22:
hdr.formatversion = '3';
STOREINTELDWORD(hdr.devicecount, 1);
STOREINTELDWORD(hdr.device1type, 2);
STOREINTELDWORD(hdr.device1clock, OPNA_CLOCK);
break;
case 0x06:
hdr.formatversion = '3';
STOREINTELDWORD(hdr.devicecount, 2);
STOREINTELDWORD(hdr.device1type, 4);
STOREINTELDWORD(hdr.device2type, 2);
STOREINTELDWORD(hdr.device1clock, OPNA_CLOCK*2);
STOREINTELDWORD(hdr.device2clock, OPNA_CLOCK);
break;
case 0x40:
hdr.formatversion = '3';
STOREINTELDWORD(hdr.devicecount, 2);
STOREINTELDWORD(hdr.device1type, 4);
STOREINTELDWORD(hdr.device2type, 3);
STOREINTELDWORD(hdr.device1clock, OPNA_CLOCK*2);
STOREINTELDWORD(hdr.device2clock, OPNA_CLOCK*2);
break;
case 0x80:
hdr.formatversion = '3';
STOREINTELDWORD(hdr.devicecount, 3);
STOREINTELDWORD(hdr.device1type, 0xf);
STOREINTELDWORD(hdr.device2type, 0xf);
STOREINTELDWORD(hdr.device3type, 0xf);
STOREINTELDWORD(hdr.device1clock, 2000000);
STOREINTELDWORD(hdr.device2clock, 2000000);
STOREINTELDWORD(hdr.device3clock, 2000000);
STOREINTELDWORD(hdr.device1pan, 0x21);
STOREINTELDWORD(hdr.device2pan, 0x21);
STOREINTELDWORD(hdr.device3pan, 0x21);
break;
case 0x32:
hdr.formatversion = '3';
STOREINTELDWORD(hdr.devicecount, 2);
STOREINTELDWORD(hdr.device1type, 2);
STOREINTELDWORD(hdr.device2type, 8);
STOREINTELDWORD(hdr.device1clock, OPNA_CLOCK);
STOREINTELDWORD(hdr.device2clock, OPNA_CLOCK);
STOREINTELDWORD(hdr.device1pan, 0x40);
STOREINTELDWORD(hdr.device2pan, 0x02);
break;
case 0x41:
hdr.formatversion = '3';
STOREINTELDWORD(hdr.devicecount, 1);
STOREINTELDWORD(hdr.device1type, 9);
STOREINTELDWORD(hdr.device1clock, 14400000);
break;
case 0x82:
hdr.formatversion = '3';
STOREINTELDWORD(hdr.devicecount, 2);
STOREINTELDWORD(hdr.device1type, 2);
STOREINTELDWORD(hdr.device2type, 10);
STOREINTELDWORD(hdr.device1clock, OPNA_CLOCK);
STOREINTELDWORD(hdr.device2clock, OPNA_CLOCK);
STOREINTELDWORD(hdr.device1pan, 0x40);
STOREINTELDWORD(hdr.device2pan, 0x02);
break;
default:
hdr.formatversion = '1';
STOREINTELDWORD(hdr.offset, offsetof(S98HDR, title));
break;
}
for (i=0; i<sizeof(hdr); i++) {
S98_putc(*(((UINT8 *)&hdr) + i));
}
// <20><EFBFBD>p<EFBFBD>f<EFBFBD>B<EFBFBD><42><EFBFBD>O
s98log.intcount = 10;
sets98event(NEVENT_ABSOLUTE);
return(SUCCESS);
}
void S98_close(void) {
if (s98log.fh != FILEH_INVALID) {
S98_putint();
S98_putc(0xFD); /* END MARK */
S98_flush();
nevent_reset(NEVENT_S98TIMER);
file_close(s98log.fh);
s98log.fh = FILEH_INVALID;
}
}
void S98_put(REG8 module, UINT addr, REG8 data) {
if (s98log.fh != FILEH_INVALID) {
S98_putint();
S98_putc(module);
S98_putc((UINT8)addr);
S98_putc(data);
}
}
void S98_sync(void) {
}
BOOL S98_isopened(void)
{
return (s98log.fh != FILEH_INVALID) ? TRUE : FALSE;
}
#endif