initial commit

This commit is contained in:
'mr software' 2023-08-16 06:16:32 -07:00
commit 3e6b7bac22
6 changed files with 260 additions and 0 deletions

42
bnk.c Normal file
View File

@ -0,0 +1,42 @@
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
#include <assert.h>
#include <string.h>
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);
}
}
}

33
bnkdoc Normal file
View File

@ -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

20
ench.s Normal file
View File

@ -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

51
goldsmp.c Normal file
View File

@ -0,0 +1,51 @@
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
#include <assert.h>
#include <string.h>
// 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);
}
}
}

68
rl2.c Normal file
View File

@ -0,0 +1,68 @@
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
#include <assert.h>
#include <string.h>
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);
}
}

46
rl2doc Normal file
View File

@ -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 |