initial commit
This commit is contained in:
commit
3e6b7bac22
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 |
|
Loading…
Reference in New Issue