Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 100 additions & 10 deletions dmp_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@
#include "dmp_file.h"
#include "tools.h"

int dmp_file_load(struct dmp_file *f, uint8_t *data, size_t data_len, int system) {
void dmp_file_init(struct dmp_file *f) {
memset(f, 0, sizeof(*f));
}

int dmp_file_load(struct dmp_file *f, uint8_t *data, size_t data_len) {
memset(f, 0, sizeof(struct dmp_file));

if(data[0] != 9) {
if(data[0] < 9) {
fprintf(stderr, "Unsupported version 0x%02x (%d)\n", data[0], data[0]);
return -1;
}
Expand All @@ -18,17 +22,34 @@ int dmp_file_load(struct dmp_file *f, uint8_t *data, size_t data_len, int system
return -1;
}

f->system = DMP_SYSTEM_YM2612_OPN;
f->version = data[0];
f->mode = data[1];
if (data[0] <= 10) {
f->mode = data[1];
} else {
f->system = data[1];
f->mode = data[2];
}

if (f->system != DMP_SYSTEM_YM2612_OPN && f->system != DMP_SYSTEM_YM2151_OPM) {
fprintf(stderr, "Unsupported system %d\n", f->system);
return -1;
}

if(f->mode == 1) {
uint8_t *p = data + 2;
f->num_operators = *p++ == 0 ? 2 : 4;
if (f->version < 10) {
f->num_operators = *p++ == 0 ? 2 : 4;
} else {
f->num_operators = 4;
}
f->lfo = *p++;
f->fb = *p++;
f->alg = *p++;
if(system == DMP_FILE_GENESIS) {
if(f->version >= 10) {
f->lfo2 = *p++;
} else {
f->lfo2 = 0;
}

for(int i = 0; i < f->num_operators; i++) {
Expand All @@ -39,7 +60,7 @@ int dmp_file_load(struct dmp_file *f, uint8_t *data, size_t data_len, int system
f->operators[i].sl = *p++;
f->operators[i].rr = *p++;
f->operators[i].am = *p++;
if(system == DMP_FILE_GENESIS) {
if(f->version >= 10) {
f->operators[i].ksr = *p++;
f->operators[i].dt = *p++;
f->operators[i].d2r = *p++;
Expand All @@ -54,6 +75,31 @@ int dmp_file_load(struct dmp_file *f, uint8_t *data, size_t data_len, int system
return 0;
}

int dmp_file_save(struct dmp_file *f, int (*write_fn)(void *, size_t, void *), void *data_ptr) {
uint8_t buf[50] = { 0 };
uint8_t* p = buf;
*p++ = 0x0a; // version 10
*p++ = 1; // instrument type, 1 = FM
*p++ = f->lfo;
*p++ = f->fb;
*p++ = f->alg;
*p++ = f->lfo2;
for(int i = 0; i < f->num_operators; i++) {
*p++ = f->operators[i].mult;
*p++ = f->operators[i].tl;
*p++ = f->operators[i].ar;
*p++ = f->operators[i].dr;
*p++ = f->operators[i].sl;
*p++ = f->operators[i].rr;
*p++ = f->operators[i].am;
*p++ = f->operators[i].ksr;
*p++ = f->operators[i].dt;
*p++ = f->operators[i].d2r;
*p++ = f->operators[i].ssg;
}
return write_fn(buf, 50, data_ptr);
}

#ifdef HAVE_STDIO
void dmp_file_dump(struct dmp_file *dmp) {
printf("version=%d mode=%d\n", dmp->version, dmp->mode);
Expand Down Expand Up @@ -85,11 +131,55 @@ void dmp_file_dump(struct dmp_file *dmp) {
#include "loader.h"

static int load(void *data, int data_len, struct fm_voice_bank *bank) {
return -1;
struct dmp_file f;
int r = dmp_file_load(&f, (uint8_t*)data, data_len);
if(r) return r;
struct opn_voice *voice = fm_voice_bank_reserve_opn_voices(bank, 1);
if(!voice) return -1;
voice->slot = 0x0f;
voice->fb_con = (f.fb & 0x07) << 3 | (f.alg & 0x07);
voice->lr_ams_pms = (f.lfo & 0x07) << 4 | (f.lfo2 & 0x03);
for(int i = 0; i < f.num_operators; i++) {
struct opn_voice_operator *op = &voice->operators[i];
struct dmp_file_operator *fop = &f.operators[i];
op->dt_mul = (fop->dt & 0x07) << 3 | (fop->mult & 0x07);
op->tl = fop->tl & 0x7f;
op->ks_ar = fop->ksr << 6 | (fop->ar & 0x1f);
op->am_dr = fop->dr & 0x1f;
op->sr = fop->d2r;
op->sl_rr = fop->sl << 4 | (fop->rr & 0x0f);
op->ssg_eg = fop->ssg;
}
return 0;
}

static int save(struct fm_voice_bank *bank, struct fm_voice_bank_position *pos, int (*write_fn)(void *, size_t, void *), void *data_ptr) {
return -1;
if(bank->num_opn_voices <= pos->opn) return -1;
struct dmp_file f;
dmp_file_init(&f);
struct opn_voice* voice = &bank->opn_voices[pos->opn];
if (!voice) return -1;

f.fb = opn_voice_get_fb(voice);
f.alg = opn_voice_get_con(voice);
f.lfo = opn_voice_get_ams(voice);
f.lfo2 = opn_voice_get_pms(voice);
for(int i = 0; i < 4; i++) {
struct dmp_file_operator *fop = &f.operators[i];
fop->dt = opn_voice_get_operator_dt(voice, i);
fop->mult = opn_voice_get_operator_mul(voice, i);
fop->tl = opn_voice_get_operator_tl(voice, i);
fop->ksr = opn_voice_get_operator_ks(voice, i);
fop->ar = opn_voice_get_operator_ar(voice, i);
fop->dr = opn_voice_get_operator_dr(voice, i);
fop->am = opn_voice_get_operator_am(voice, i);
fop->d2r = opn_voice_get_operator_sr(voice, i);
fop->sl = opn_voice_get_operator_sl(voice, i);
fop->rr = opn_voice_get_operator_rr(voice, i);
fop->ssg = opn_voice_get_operator_ssg_eg(voice, i);
}
pos->opn++;
return dmp_file_save(&f, write_fn, data_ptr);
}

struct loader dmp_file_loader = {
Expand All @@ -98,8 +188,8 @@ struct loader dmp_file_loader = {
.name = "DMP",
.description = "DefleMask Preset Format",
.file_ext = "dmp",
.max_opl_voices = 1,
.max_opl_voices = 0,
.max_opm_voices = 0,
.max_opn_voices = 0,
.max_opn_voices = 1,
};
#endif
7 changes: 4 additions & 3 deletions dmp_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

#include <stdint.h>

#define DMP_FILE_GENESIS 1
#define DMP_SYSTEM_YM2612_OPN 0x02
#define DMP_SYSTEM_YM2151_OPM 0x08

struct dmp_file_operator {
uint8_t
Expand All @@ -13,14 +14,14 @@ struct dmp_file_operator {
};

struct dmp_file {
uint8_t version, mode;
uint8_t version, mode, system;
uint8_t num_operators, lfo, fb, alg;
uint8_t lfo2;
struct dmp_file_operator operators[4];
};

void dmp_file_init(struct dmp_file *f);
int dmp_file_load(struct dmp_file *f, uint8_t *data, size_t data_len, int system);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain why you removed this field?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As written above, the older versions of the DMP file format supported only YM2612 systems anyway, and for newer versions, the system information is part of the file itself, so it is not needed as a parameter.

int dmp_file_load(struct dmp_file *f, uint8_t *data, size_t data_len);
int dmp_file_save(struct dmp_file *f, int (*write_fn)(void *buf, size_t len, void *data_ptr), void *data_ptr);
void dmp_file_dump(struct dmp_file *f);

Expand Down
2 changes: 1 addition & 1 deletion dmpdump.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ int main(int argc, char **argv) {
continue;
}
struct dmp_file dmp;
if(dmp_file_load(&dmp, data, data_len, DMP_FILE_GENESIS) != 0) {
if(dmp_file_load(&dmp, data, data_len) != 0) {
fprintf(stderr, "Could not load %s\n", argv[i]);
continue;
}
Expand Down
2 changes: 1 addition & 1 deletion ins_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ static int load(void *data, int data_len, struct fm_voice_bank *bank) {
}

static int save(struct fm_voice_bank *bank, struct fm_voice_bank_position *pos, int (*write_fn)(void *, size_t, void *), void *data_ptr) {
struct ins_file ins;
if(bank->num_opn_voices <= pos->opn) return -1;
struct ins_file ins;
ins.name = strdup(bank->opn_voices[pos->opn].name);
if(!ins.name) return -1;
ins.name_len = strlen(bank->opn_voices[pos->opn].name);
Expand Down
2 changes: 1 addition & 1 deletion md5.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#include <sys/types.h>

# include <string.h>
#if STDC_HEADERS || defined _LIBC
#if STDC_HEADERS || defined _LIBC || defined _MSC_VER
# include <stdlib.h>
#else
# ifndef HAVE_MEMCPY
Expand Down
2 changes: 1 addition & 1 deletion md5.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

#include <stdio.h>

#if defined HAVE_LIMITS_H || _LIBC
#if defined HAVE_LIMITS_H || defined _LIBC || defined _MSC_VER
# include <limits.h>
#endif

Expand Down
69 changes: 68 additions & 1 deletion op3_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,43 @@ int op3_file_load(struct op3_file *f, uint8_t *data, size_t data_len) {
return 0;
}

int op3_file_save(struct op3_file *f, int (*write_fn)(void *, size_t, void *), void *data_ptr) {
uint8_t buf[8192] = { 0 };
strcpy((char*)&buf[0], "Junglevision Patch File\x1A");
uint8_t* p = buf;
*p++ = f->count_melodic & 0xff;
*p++ = f->count_melodic >> 8;
*p++ = f->count_percussive & 0xff;
*p++ = f->count_percussive >> 8;
*p++ = f->start_melodic & 0xff;
*p++ = f->start_melodic >> 8;
*p++ = f->start_percussive & 0xff;
*p++ = f->start_percussive >> 8;

#define WRITE_OP(o) \
*p++ = inst->op[o].ave_kvm; \
*p++ = inst->op[o].ksl_tl; \
*p++ = inst->op[o].ar_dr; \
*p++ = inst->op[o].sl_rr; \
*p++ = inst->op[o].ws;

#define WRITE_SET(type) \
for(int i = 0; i < f->count_##type; i++) { \
struct op3_file_instrument *inst = &f->type[i]; \
*p++ = inst->en_4op; \
*p++ = inst->percnotenum; \
WRITE_OP(0) \
*p++ = inst->fb_con12; \
WRITE_OP(1) \
WRITE_OP(2) \
*p++ = inst->fb_con34; \
WRITE_OP(3) \
}

WRITE_SET(melodic)
WRITE_SET(percussive)
return 0;
}
#ifdef HAVE_STDIO
static void op3_dump_instrument(struct op3_file_instrument *inst) {
printf("en_4op=%d percnotenum=%d\n", inst->en_4op, inst->percnotenum);
Expand Down Expand Up @@ -107,6 +144,23 @@ static int opl_voice_from_op3_file_instrument(struct opl_voice *v, struct op3_fi
return 0;
}

static int op3_file_instrument_from_opl_voice(struct op3_file_instrument *inst, struct opl_voice *v) {
inst->en_4op = v->en_4op;
inst->percnotenum = v->perc_inst;
inst->fb_con12 = v->ch_fb_cnt[0] & ~0xf0;
inst->fb_con34 = v->ch_fb_cnt[1] & ~0xf0;
for(int i = 0; i < 4; i++) {
struct opl_voice_operator *op = &v->operators[i];
struct op3_file_instrument_op *op3 = &inst->op[i];
op3->ave_kvm = op->am_vib_eg_ksr_mul;
op3->ksl_tl = op->ksl_tl;
op3->ar_dr = op->ar_dr;
op3->sl_rr = op->sl_rr;
op3->ws = op->ws;
}
return 0;
}

static int load(void *data, int data_len, struct fm_voice_bank *bank) {
struct op3_file f;
int r = op3_file_load(&f, data, data_len);
Expand All @@ -125,7 +179,20 @@ static int load(void *data, int data_len, struct fm_voice_bank *bank) {
}

static int save(struct fm_voice_bank *bank, struct fm_voice_bank_position *pos, int (*write_fn)(void *, size_t, void *), void *data_ptr) {
return -1;
if(bank->num_opl_voices <= pos->opl) return -1;
struct op3_file f;
op3_file_init(&f);
struct opl_voice *voice = &bank->opl_voices[pos->opl];
f.count_melodic = bank->num_opl_voices;
f.count_percussive = 0;
f.start_melodic = 0;
f.start_percussive = 0;
for(int i = 0; i < f.count_melodic; i++) {
op3_file_instrument_from_opl_voice(&f.melodic[i], voice);
voice++;
}
pos->opl++;
return op3_file_save(&f, write_fn, data_ptr);
}

struct loader op3_file_loader = {
Expand Down
1 change: 1 addition & 0 deletions opm_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@ static int load(void *data, int data_len, struct fm_voice_bank *bank) {
}

static int save(struct fm_voice_bank *bank, struct fm_voice_bank_position *pos, int (*write_fn)(void *, size_t, void *), void *data_ptr) {
if(bank->num_opm_voices <= pos->opm) return -1;
struct opm_file opm_file;
opm_file_init(&opm_file);
for(int i = pos->opm; i < bank->num_opm_voices; i++) {
Expand Down
46 changes: 43 additions & 3 deletions sbi_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ void sbi_file_init(struct sbi_file *f) {

int sbi_file_load(struct sbi_file *f, uint8_t *data, size_t data_len) {
if(data_len < 47 || data_len > 52) return -1;

if(data[0] != 'S' || data[1] != 'B' || data[2] != 'I' || (data[3] != 0x1a && data[3] != 0x1d)) return -1;

memcpy(f->name, &data[4], 32);

uint8_t *b = data + 36;
Expand All @@ -33,6 +31,32 @@ int sbi_file_load(struct sbi_file *f, uint8_t *data, size_t data_len) {
return 0;
}

int sbi_file_save(struct sbi_file *f, int (*write_fn)(void *, size_t, void *), void *data_ptr) {
uint8_t buf[52] = { 0 };
uint8_t* p = buf;
*p++ = 'S';
*p++ = 'B';
*p++ = 'I';
*p++ = 0x1a;
memcpy(p, f->name, 32);
p += 32;
*p++ = f->am_vib_eg_ksr_mul[0];
*p++ = f->am_vib_eg_ksr_mul[1];
*p++ = f->ksl_tl[0];
*p++ = f->ksl_tl[1];
*p++ = f->ar_dr[0];
*p++ = f->ar_dr[1];
*p++ = f->sl_rr[0];
*p++ = f->sl_rr[1];
*p++ = f->ws[0];
*p++ = f->ws[1];
*p++ = f->fb_con;
*p++ = f->perc_voice;
*p++ = f->transpose;
*p++ = f->perc_pitch;
return write_fn(buf, 52, data_ptr);
}

#ifdef HAVE_STDIO
void sbi_file_dump(struct sbi_file *f) {
printf("name=%.32s\n", f->name);
Expand Down Expand Up @@ -84,7 +108,23 @@ static int load(void *data, int data_len, struct fm_voice_bank *bank) {
}

static int save(struct fm_voice_bank *bank, struct fm_voice_bank_position *pos, int (*write_fn)(void *, size_t, void *), void *data_ptr) {
return -1;
if(bank->num_opl_voices <= pos->opl) return -1;
struct sbi_file f;
sbi_file_init(&f);
struct opl_voice *voice = &bank->opl_voices[pos->opl];
memcpy(f.name, voice->name, 32);
f.perc_voice = voice->perc_inst;
f.fb_con = voice->ch_fb_cnt[0];
for(int i = 0; i < 2; i++) {
struct opl_voice_operator *op = &voice->operators[i];
f.am_vib_eg_ksr_mul[i] = op->am_vib_eg_ksr_mul;
f.ksl_tl[i] = op->ksl_tl;
f.ar_dr[i] = op->ar_dr;
f.sl_rr[i] = op->sl_rr;
f.ws[i] = op->ws;
}
pos->opl++;
return sbi_file_save(&f, write_fn, data_ptr);
}

struct loader sbi_file_loader = {
Expand Down
Loading