From 3e6b7bac222c324372f2a52ff4faa54d412fb103 Mon Sep 17 00:00:00 2001 From: mothcompute Date: Wed, 16 Aug 2023 06:16:32 -0700 Subject: [PATCH] initial commit --- bnk.c | 42 ++++++++++++++++++++++++++++++++++ bnkdoc | 33 +++++++++++++++++++++++++++ ench.s | 20 ++++++++++++++++ goldsmp.c | 51 +++++++++++++++++++++++++++++++++++++++++ rl2.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ rl2doc | 46 +++++++++++++++++++++++++++++++++++++ 6 files changed, 260 insertions(+) create mode 100644 bnk.c create mode 100644 bnkdoc create mode 100644 ench.s create mode 100644 goldsmp.c create mode 100644 rl2.c create mode 100644 rl2doc diff --git a/bnk.c b/bnk.c new file mode 100644 index 0000000..5f4f966 --- /dev/null +++ b/bnk.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + uint8_t magic0[3]; + uint8_t name[12]; + uint8_t magic1[5]; + uint16_t dptr; + uint8_t magic2[6]; +} __attribute__((packed)) goldopl; + +int main(int argc, char** argv) { + int fd; + uint8_t* fm; + struct stat s; + int a = 0; + for(int f = 1; f < argc; f++) { + if((fd = open(argv[f], O_RDONLY)) >= 0) { + fstat(fd, &s); + fm = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0); + goldopl* map = fm + 48; + int lp = 0x34B0; + while(map->magic0[0] == 'O' && map->magic0[1] == '3' && map->magic0[2] == '_') { + printf("%03u\t%.12s%c\t", a++, map->name, strlen(map->name) < 8 ? '\t' : ' '); + //printf("\t%.12s", map->name); + for(int i = 0; i < 28; i++) printf("%02X ", fm[map->dptr + i]); + putchar('\n'); + lp = map->dptr; + map++; + } + printf("\n%u instruments\n", a); +cln: munmap(fm, s.st_size); + close(fd); + } + } +} diff --git a/bnkdoc b/bnkdoc new file mode 100644 index 0000000..fde43bb --- /dev/null +++ b/bnkdoc @@ -0,0 +1,33 @@ +note: this is a continuation of rl2doc! see that first for more context + +opl3 data table entry +offset | size | token | description +----------|----------|-------|-------------------------------------------------- + 0 | 28 | | opl3 parameters + + +instrument entry +offset | size | token | description +----------|----------|-------|-------------------------------------------------- + 0 | 3 | | ascii signature 'O3_' + 3 | 12 | | null padded, null terminated instrument name + 15 | 5 | | unknown (always 01 00 00 00 00) + 21 | 2 | | offset into file (inside opl3 data table) + 23 | 2 | | unknown (all zero) + 25 | 2 | | unknown (either size of this table or size of + | | | opl3 data table entry; always 28) + 27 | 2 | | unknown (either size of this table or size of + | | | opl3 data table entry; always 28) +TODO: offsets are wrong! sizes are correct + +main header +offset | size | token | description +----------|----------|-------|-------------------------------------------------- + 0 | 30 | | ascii signature 'Accomp. Bank, (C) AdLib Inc\x00 + | | | \x01\x01' + 31 | 10 | | unknown (all zero) + 41 | 2 | | multiply by 28, then add 48 to get offset + | | | to the start of the opl3 data table + 42 | 2 | is | number of defined instruments + 44 | 4 | | unknown (all zero) + 48 | [is]*28 | int | instrument name table diff --git a/ench.s b/ench.s new file mode 100644 index 0000000..daabfa5 --- /dev/null +++ b/ench.s @@ -0,0 +1,20 @@ +; script to enable both adlib gold channels in pcem +; (maybe real hardware? the official drivers never +; actually set it so i really dont know) +pusha + +mov dx, 0x38A +mov al, 0xFF +out dx, al + +; select control register 8 +mov al, 8 +out dx, al + +inc dx; 0x38B +in al, dx +or al, 6 ; both channels enabled +out dx, al + +popa +ret diff --git a/goldsmp.c b/goldsmp.c new file mode 100644 index 0000000..2b3ed33 --- /dev/null +++ b/goldsmp.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +// theorized (datatypes may be different) +typedef struct { + uint8_t magic[14]; + uint32_t fmt; + uint32_t rate; + uint32_t size; + uint16_t zero[9]; +} __attribute__((packed)) igoldsmp; + +int main(int argc, char** argv) { + int fd; + igoldsmp* fm; + struct stat s; + int a = 0; + for(int f = 1; f < argc; f++) { + if((fd = open(argv[f], O_RDONLY)) >= 0) { + fstat(fd, &s); + fm = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0); + for(int i = 0; i < 9; i++) {a += fm->zero[i];} + if( + memcmp(fm, "GOLD SAMPLE \x01\x01", 14) || + a || + 44 + fm->size < s.st_size + ) { + printf("%s incomplete or invalid gold sample\n", argv[f]); + goto cln; + } + printf( + "gold sample %s\n" + "format:\t%u bits\n" + "rate:\t%uhz\n" + "size:\t%u bytes (+44 header)\n", + argv[f], + 8 << fm->fmt, + fm->rate, + fm->size + ); +cln: munmap(fm, s.st_size); + close(fd); + } + } +} diff --git a/rl2.c b/rl2.c new file mode 100644 index 0000000..22efb71 --- /dev/null +++ b/rl2.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + uint8_t signature[27]; + uint8_t unknown0[37]; + uint8_t unused[22]; + uint8_t name[40]; + uint8_t unknown1[28]; + uint16_t songsize; + uint8_t unknown2[274]; + uint16_t num_inst; +} __attribute__((packed)) rl2_main0; + +typedef struct { + uint8_t flags[3]; + uint8_t name[11]; +} __attribute__((packed)) rl2_instrument; + +typedef struct { + uint8_t pad[28]; + uint8_t oplparams[28]; // TODO +} __attribute__((packed)) rl2_embedded_instrument; + +int main(int argc, char** argv) { + for(int f = 1; f < argc; f++) { + int fd; + uint8_t* m; + struct stat s; + assert((fd = open(argv[f], O_RDWR)) > 0); + assert(!fstat(fd, &s)); + assert((m = mmap(0, s.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) != MAP_FAILED); + +#define hm0 ((rl2_main0*)m) + if(memcmp(m, ">>> VC2, (C) ADLIB INC <<<\x0E", 27)) { + printf("%s not an rl2\n", argv[f]); + goto cln; + } + + printf("song name: %.40s\n", hm0->name); + printf("number of instruments: %hu\n", hm0->num_inst); + rl2_instrument* hminst = m + sizeof(rl2_main0); + int num_einst = hm0->num_inst; + for(int i = 0; i < hm0->num_inst; i++) { + printf("instrument %02i name: %.11s (flags %02X%02X%02X) ", i, hminst[i].name, hminst[i].flags[0],hminst[i].flags[1],hminst[i].flags[2]); + if(hminst[i].flags[2] & 1) num_einst -= !!printf("(should have file)"); + putchar('\n'); + } + printf("%Xh file instruments, %Xh embedded instruments (size: %u)\n", hm0->num_inst-num_einst, num_einst, num_einst*sizeof(rl2_instrument)); + rl2_embedded_instrument* hme = hminst + hm0->num_inst; + for(int i = 0; i < num_einst; i++) { + printf("embedded instrument %02i (parameters: ", i); + for(int c = 0; c < 28; c++) printf("%02X ", hme[i].oplparams[c]); + printf("\b)\n"); + } + uint8_t* hmdat = hme + num_einst; + printf("header was %u bytes, %u bytes follow (file says %hu)\n", s.st_size-hm0->songsize, s.st_size-(((long)hmdat)-((long)m)), hm0->songsize); + +cln: munmap(m, s.st_size); + close(fd); + } +} diff --git a/rl2doc b/rl2doc new file mode 100644 index 0000000..611a33b --- /dev/null +++ b/rl2doc @@ -0,0 +1,46 @@ +notes: +- when offset is given as token+constant, take the offset of the *last* byte of + the token rather than the first when calculating the offset +- everything is in little endian; jukebox gold was made for 8086 + +instrument +offset | size | token | description +----------|----------|-------|-------------------------------------------------- + 0 | 3 | | flags uuuuuuuu uuuuuuuu uuuuuuuf + | | | u - unknown + | | | f - instrument is a pcm sample. if unset, the + | | | instrument is found in opl3.bnk (? TODO) + 3 | 11 | | null padded instrument name + +adlib instrument +offset | size | token | description +----------|----------|-------|-------------------------------------------------- + 0 | 28 | | 0xAA repeated + 28 | 28 | | unknown (possibly opl3 parameters?) + +main header +offset | size | token | description +----------|----------|-------|-------------------------------------------------- + 0 | 27 | | ascii signature '>>> VC2, (C) ADLIB INC <<<\x0E' + 27 | 1 | | always 0 + 28 | 1 | | unknown + 29 | 3 | | always 0, 2, 0 + 32 | 2 | | unknown, likely tempo? + 34 | 1 | | unknown + 35 | 2 | | always 1, 0 + 37 | 1 | | unknown + 38 | 2 | | always 0 + 40 | 24 | | unknown + 64 | 22 | | 0x7F repeated + 86 | 40 | | null padded song name + 126 | 1 | | unknown + 127 | 2 | | always 0xFFFF + 129 | 23 | | always 0 + 152 | 2 | | unknown + 154 | 2 | | size of song data + 156 | 274 | | unknown + 430 | 2 | is | number of instruments + 432 | [is]*14 | it | instrument table + it+1 | itn*56 | ait | adlib instrument table. itn is calculated as the + | | | number of instruments that do not have flag f set + ait+1 |