aboutsummaryrefslogtreecommitdiff
path: root/fmdriver/fmdriver_pmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'fmdriver/fmdriver_pmd.c')
-rw-r--r--fmdriver/fmdriver_pmd.c535
1 files changed, 512 insertions, 23 deletions
diff --git a/fmdriver/fmdriver_pmd.c b/fmdriver/fmdriver_pmd.c
index 2a093c2..09630bf 100644
--- a/fmdriver/fmdriver_pmd.c
+++ b/fmdriver/fmdriver_pmd.c
@@ -70,6 +70,7 @@ static uint8_t pmd_opna_read_ssgout(struct fmdriver_work *work) {
return work->opna_readreg(work, 0x07);
}
+/*
// 331f
static void pmd_stop_sound(struct fmdriver_work *work,
struct driver_pmd *pmd) {
@@ -126,7 +127,9 @@ static void pmd_stop_sound(struct fmdriver_work *work,
}
}
}
+*/
+/*
// 11df
static void pmd_mstop(struct fmdriver_work *work,
struct driver_pmd *pmd) {
@@ -137,6 +140,7 @@ static void pmd_mstop(struct fmdriver_work *work,
pmd->fadeout_vol = 0xff;
pmd_stop_sound(work, pmd);
}
+*/
// 1058
static void pmd_reset_state(struct driver_pmd *pmd) {
@@ -1310,8 +1314,6 @@ static void pmd_note_freq_adpcm(
0, 0, 0, 0
};
uint8_t octave = note >> 4;
- int cl = 5 - octave;
- if (cl < 0) cl = 0;
uint16_t tonefreq = adpcm_tonetable[note & 0x0f];
if (octave <= 5) {
tonefreq >>= (5 - octave);
@@ -1327,6 +1329,50 @@ static void pmd_note_freq_adpcm(
part->actual_freq = tonefreq;
}
+// 0c97
+static void pmd_note_freq_ppz8(
+ struct pmd_part *part,
+ uint8_t note
+) {
+ if ((note & 0xf) == 0xf) {
+ // 0cd8
+ part->actual_note = 0xff;
+ if (!part->lfof.freq && !part->lfof_b.freq) {
+ part->actual_freq = 0;
+ part->actual_freq_upper = 0;
+ }
+ return;
+ }
+ part->actual_note = note;
+ static const uint16_t ppz8_tonetable[0x10] = {
+ // 0cf1
+ // documented in ppz8.doc
+ // different from round(0x8000*(2**(i/12)))
+ 0x8000,
+ 0x87a6,
+ 0x8fb3,
+ 0x9838,
+ 0xa146,
+ 0xaade,
+ 0xb4ff,
+ 0xbfcc,
+ 0xcb34,
+ 0xd747,
+ 0xe418,
+ 0xf1a5,
+ 0, 0, 0, 0
+ };
+ int octave = (note >> 4) - 4;
+ uint32_t freq = ppz8_tonetable[note & 0x0f];
+ if (octave < 0) {
+ freq >>= -octave;
+ } else {
+ freq <<= octave;
+ }
+ part->actual_freq = freq;
+ part->actual_freq_upper = freq >> 16;
+}
+
// 14a0
static void pmd_part_calc_gate(
struct driver_pmd *pmd,
@@ -1594,6 +1640,72 @@ static void pmd_adpcm_vol_out(
work->opna_writereg(work, 0x10b, vol);
}
+// 0b33
+static void pmd_ppz8_vol_out(
+ struct fmdriver_work *work,
+ struct driver_pmd *pmd,
+ struct pmd_part *part
+) {
+ uint8_t vol = part->volume_save;
+ if (!vol) vol = part->vol;
+
+ // 0b3f
+ if (pmd->ppz8_voldown) {
+ uint8_t voldown = -pmd->ppz8_voldown;
+ vol = vol * voldown >> 8;
+ }
+ // 0b4c
+ if (pmd->fadeout_vol) {
+ uint8_t fadeout = -pmd->fadeout_vol;
+ vol = vol * fadeout >> 8;
+ }
+ // 0b59
+ if (vol) {
+ if (part->ssg_env_state_old == SSG_ENV_STATE_OLD_NEW) {
+ uint8_t envvol = part->ssg_env_vol;
+ if (!envvol) {
+ vol = 0;
+ // -> 0bd4
+ } else {
+ vol = (vol * (envvol+1)) >> 3;
+ if (vol & 1) {
+ vol >>= 1;
+ vol++;
+ } else {
+ vol >>= 1;
+ }
+ }
+ } else {
+ // 0b7d
+ int newvol = vol + (part->ssg_env_vol << 4);
+ if (newvol > 0xff) newvol = 0xff;
+ if (newvol < 0) newvol = 0;
+ vol = newvol;
+ }
+ // 0ba4
+ if (part->lfof.vol || part->lfof_b.vol) {
+ int32_t lfovol = 0;
+ if (part->lfof.vol) vol += part->lfo_diff;
+ if (part->lfof_b.vol) vol += part->lfo_diff_b;
+ lfovol += vol;
+ vol = lfovol;
+ if (lfovol < 0) {
+ vol = 0;
+ } else if (lfovol > 0xff) {
+ vol = 0xff;
+ }
+ }
+ }
+ // 0bd4
+ if (work->ppz8) {
+ if (vol) {
+ work->ppz8_functbl->channel_volume(work->ppz8, pmd->proc_ch, vol >> 4);
+ } else {
+ work->ppz8_functbl->channel_stop(work->ppz8, pmd->proc_ch);
+ }
+ }
+}
+
// 2985
static void pmd_ssg_freq_out(
struct fmdriver_work *work,
@@ -1675,6 +1787,33 @@ static void pmd_adpcm_freq_out(
work->opna_writereg(work, 0x10a, freq >> 8);
}
+// 0c27
+static void pmd_ppz8_freq_out(
+ struct fmdriver_work *work,
+ struct driver_pmd *pmd,
+ struct pmd_part *part
+) {
+ uint32_t freq = part->actual_freq | (((uint32_t)part->actual_freq_upper) << 16);
+ if (!freq) return;
+ if (part->portamento_diff) {
+ freq += part->portamento_diff * 4;
+ }
+ int32_t det = 0;
+ if (part->lfof.freq || part->lfof_b.freq) {
+ if (part->lfof.freq) det += part->lfo_diff;
+ if (part->lfof_b.freq) det += part->lfo_diff_b;
+ }
+ // 0c6a
+ det += part->detune;
+ det *= freq >> 8;
+ int64_t outfreq = freq + det;
+ if (outfreq < 0) outfreq = 0;
+ if (outfreq > INT32_MAX) outfreq = INT32_MAX;
+ if (work->ppz8) {
+ work->ppz8_functbl->channel_freq(work->ppz8, pmd->proc_ch, outfreq);
+ }
+}
+
// 2c9f
static uint16_t pmd_part_ssg_readout(
struct fmdriver_work *work,
@@ -1756,6 +1895,18 @@ static void pmd_part_adpcm_keyon(
}
}
+// 0bf6
+static void pmd_part_ppz8_keyon(
+ struct fmdriver_work *work,
+ struct driver_pmd *pmd,
+ struct pmd_part *part
+) {
+ if (part->actual_note == 0xff) return;
+ if (work->ppz8) {
+ work->ppz8_functbl->channel_play(work->ppz8, pmd->proc_ch, part->tonenum);
+ }
+}
+
// 2942
static uint32_t pmd_blkfnum_normalize(
uint16_t blk,
@@ -1932,6 +2083,37 @@ static void pmd_part_adpcm_out(
pmd_part_loop_check(pmd, part);
}
+// 0803
+static void pmd_part_ppz8_out(
+ struct fmdriver_work *work,
+ struct driver_pmd *pmd,
+ struct pmd_part *part
+) {
+ if (part->volume_save && part->actual_note != 0xff) {
+ if (!pmd->volume_saved) {
+ part->volume_save = 0;
+ }
+ pmd->volume_saved = false;
+ }
+ pmd_ppz8_vol_out(work, pmd, part);
+ pmd_ppz8_freq_out(work, pmd, part);
+ if (part->keystatus.off) {
+ pmd_part_ppz8_keyon(work, pmd, part);
+ }
+ // 082d
+ part->note_proc++;
+ pmd->no_keyoff = false;
+ pmd->volume_saved = false;
+ part->keystatus.off = false;
+ part->keystatus.off_mask = false;
+ if (pmd->datalen > (part->ptr + 1)) {
+ if (pmd->data[part->ptr] == 0xfb) {
+ part->keystatus.off_mask = true;
+ }
+ }
+ pmd_part_loop_check(pmd, part);
+}
+
// none
static bool pmd_part_masked(
const struct pmd_part *part
@@ -2052,11 +2234,6 @@ static void pmd_cmdff_tonenum_adpcm(
pmd->adpcm_release = 0x8000;
}
-// 0a3c
-static void pmd() {
- // 0790
-}
-
// 0afd
static void pmd_cmdff_tonenum_ppz8(
struct fmdriver_work *work,
@@ -2065,6 +2242,10 @@ static void pmd_cmdff_tonenum_ppz8(
){
part->tonenum = pmd_part_cmdload(pmd, part);
// 0a3c
+ if (work->ppz8) {
+ work->ppz8_functbl->channel_loop_voice(work->ppz8, pmd->proc_ch, part->tonenum);
+ }
+ // set origfreq
}
// 22b3
@@ -2340,7 +2521,7 @@ static void pmd_cmdf1_ppsdrv(
struct driver_pmd *pmd,
struct pmd_part *part
){
- uint8_t data = pmd_part_cmdload(pmd, part);
+ /* uint8_t data = */pmd_part_cmdload(pmd, part);
// TODO: PPSDRV
}
@@ -2447,6 +2628,22 @@ static void pmd_cmdec_pan_adpcm(
part->pan = pmd_part_cmdload(pmd, part) << 6;
}
+// 0aca
+static void pmd_cmdec_pan_ppz8(
+ struct fmdriver_work *work,
+ struct driver_pmd *pmd,
+ struct pmd_part *part
+) {
+ uint8_t pan = pmd_part_cmdload(pmd, part);
+ // 0ced
+ static const uint8_t pantable[4] = {0, 9, 1, 5};
+ part->pan = 0;
+ if (pan < 4) part->pan = pantable[pan];
+ if (work->ppz8) {
+ work->ppz8_functbl->channel_pan(work->ppz8, pmd->proc_ch, part->pan);
+ }
+}
+
// 265d
static void pmd_opnarhythm_inc(uint8_t *incdata, uint8_t val) {
for (int i = 0; i < 6; i++) {
@@ -2838,7 +3035,7 @@ static void pmd_cmdda_portamento_adpcm(
uint8_t n1 = part->actual_note;
note = pmd_part_cmdload(pmd, part);
note = pmd_part_note_transpose(part, note);
- pmd_note_freq_fm(part, note);
+ pmd_note_freq_adpcm(part, note);
uint16_t f2 = part->actual_freq;
part->actual_freq = f1;
part->actual_note = n1;
@@ -2858,6 +3055,42 @@ static void pmd_cmdda_portamento_adpcm(
pmd_part_adpcm_out(work, pmd, part);
}
+// 0a62
+static void pmd_cmdda_portamento_ppz8(
+ struct fmdriver_work *work,
+ struct driver_pmd *pmd,
+ struct pmd_part *part
+){
+ uint8_t note = pmd_part_cmdload(pmd, part);
+ if (pmd_part_masked(part)) return;
+ pmd_part_lfo_init_ssg(work, pmd, part, note);
+ note = pmd_part_note_transpose(part, note);
+ pmd_note_freq_ppz8(part, note);
+ uint32_t f1 = (((uint32_t)part->actual_freq_upper) << 16) | part->actual_freq;
+ uint8_t n1 = part->actual_note;
+ note = pmd_part_cmdload(pmd, part);
+ note = pmd_part_note_transpose(part, note);
+ pmd_note_freq_ppz8(part, note);
+ uint32_t f2 = (((uint32_t)part->actual_freq_upper) << 16) | part->actual_freq;
+ part->actual_freq = f1;
+ part->actual_freq_upper = f1 >> 16;
+ part->actual_note = n1;
+ int16_t freqdiff = u16s16((f2 - f1)>>4);
+ uint8_t clocks = pmd_part_cmdload(pmd, part);
+ part->len = part->len_cnt = clocks;
+ pmd_part_calc_gate(pmd, part);
+ int16_t p_add = 0;
+ int16_t p_rem = 0;
+ if (clocks) {
+ p_add = freqdiff / clocks;
+ p_rem = freqdiff % clocks;
+ }
+ part->portamento_add = p_add;
+ part->portamento_rem = p_rem;
+ part->lfof.portamento = true;
+ pmd_part_ppz8_out(work, pmd, part);
+}
+
// 20bf
static void pmd_cmdd6_md(
struct fmdriver_work *work,
@@ -2990,10 +3223,10 @@ static void pmd_cmdce_adpcm_loop(
struct fmdriver_work *work,
struct driver_pmd *pmd,
struct pmd_part *part
-){
+) {
uint16_t diff = pmd_part_cmdload(pmd, part);
diff |= (uint16_t)pmd_part_cmdload(pmd, part) << 8;
- if (!(diff & 0x80)) diff += pmd->adpcm_start;
+ if (!(diff & 0x8000)) diff += pmd->adpcm_start;
else diff += pmd->adpcm_stop;
pmd->adpcm_start_loop = diff;
diff = pmd_part_cmdload(pmd, part);
@@ -3010,6 +3243,26 @@ static void pmd_cmdce_adpcm_loop(
pmd->adpcm_release = diff;
}
+// 0a04
+static void pmd_cmdce_ppz8_loop(
+ struct fmdriver_work *work,
+ struct driver_pmd *pmd,
+ struct pmd_part *part
+) {
+ uint32_t startoff = pmd_part_cmdload(pmd, part);
+ startoff |= (uint16_t)pmd_part_cmdload(pmd, part) << 8;
+ uint32_t endoff = pmd_part_cmdload(pmd, part);
+ endoff |= (uint16_t)pmd_part_cmdload(pmd, part) << 8;
+ if (work->ppz8) {
+ uint32_t len = work->ppz8_functbl->voice_length(work->ppz8, part->tonenum);
+ if (startoff & 0x8000) startoff = len + u16s16(startoff);
+ if (endoff & 0x8000) endoff = len + u16s16(endoff);
+ work->ppz8_functbl->channel_loopoffset(work->ppz8, pmd->proc_ch, startoff, endoff);
+ }
+ pmd_part_cmdload(pmd, part);
+ pmd_part_cmdload(pmd, part);
+}
+
// 1e1b
static void pmd_cmdcd_env_new(
struct fmdriver_work *work,
@@ -3215,6 +3468,27 @@ static void pmd_cmdc3_pan_ex_adpcm(
part->pan = pan;
}
+// 0ae5
+static void pmd_cmdc3_pan_ex_ppz8(
+ struct fmdriver_work *work,
+ struct driver_pmd *pmd,
+ struct pmd_part *part
+){
+ uint8_t data = pmd_part_cmdload(pmd, part);
+ pmd_part_cmdload(pmd, part);
+ if (!(data & 0x80)) {
+ if (data > 4) data = 4;
+ } else {
+ if (data < 0xfc) data = 0xfc;
+ }
+ data += 5;
+ uint8_t pan = data;
+ part->pan = pan;
+ if (work->ppz8) {
+ work->ppz8_functbl->channel_pan(work->ppz8, pmd->proc_ch, part->pan);
+ }
+}
+
// 2509
static void pmd_cmdc2_lfo_delay(
struct fmdriver_work *work,
@@ -3510,7 +3784,7 @@ static void pmd_cmdc0_mml_mask_adpcm(
struct fmdriver_work *work,
struct driver_pmd *pmd,
struct pmd_part *part
-){
+) {
uint8_t data = pmd_part_cmdload(pmd, part);
if (data >= 2) {
pmd_cmdc0_extended(work, pmd, part, data);
@@ -3532,6 +3806,36 @@ static void pmd_cmdc0_mml_mask_adpcm(
}
}
+// 09d8
+static void pmd_cmdc0_mml_mask_ppz8(
+ struct fmdriver_work *work,
+ struct driver_pmd *pmd,
+ struct pmd_part *part
+) {
+ uint8_t data = pmd_part_cmdload(pmd, part);
+ if (data >= 2) {
+ pmd_cmdc0_extended(work, pmd, part, data);
+ return;
+ } else if (data == 1) {
+ // 09e4
+ part->mask.mml = false;
+ bool masked = pmd_part_masked(part);
+ part->mask.mml = true;
+ if (!masked) {
+ if (work->ppz8) {
+ work->ppz8_functbl->channel_stop(work->ppz8, pmd->proc_ch);
+ }
+ }
+ part->proc_masked = true;
+ // -> 08ca
+ } else {
+ // 09fa
+ part->mask.mml = false;
+ part->proc_masked = pmd_part_masked(part);
+ // -> 07cd
+ }
+}
+
// 1caa
static void pmd_cmdc0_mml_mask_rhythm(
struct fmdriver_work *work,
@@ -4099,8 +4403,8 @@ static const pmd_cmd_func pmd_cmd_table_adpcm[PMD_CMD_CNT] = {
pmd_cmd_null_1,
pmd_cmde3_vol_add_adpcm,
pmd_cmde2_vol_sub,
- pmd_cmde1_ams_pms,
- pmd_cmde0_hlfo,
+ pmd_cmd_null_1,
+ pmd_cmd_null_1,
pmd_cmddf_meas_len,
pmd_cmdde_echo_init_add_adpcm,
pmd_cmddd_echo_init_sub,
@@ -4151,7 +4455,85 @@ static const pmd_cmd_func pmd_cmd_table_adpcm[PMD_CMD_CNT] = {
};
static const pmd_cmd_func pmd_cmd_table_ppz8[PMD_CMD_CNT] = {
-
+ pmd_cmdff_tonenum_ppz8,
+ pmd_cmdfe_gate_abs,
+ pmd_cmdfd_vol,
+ pmd_cmdfc_tempo,
+ pmd_cmdfb_tie,
+ pmd_cmdfa_d5_det,
+ pmd_cmdf9_repeat_reset,
+ pmd_cmdf8_repeat,
+ pmd_cmdf7_repeat_exit,
+ pmd_cmdf6_set_loop,
+ pmd_cmdf5_transpose,
+ pmd_cmdf4_volinc_adpcm,
+ pmd_cmdf3_voldec_adpcm,
+ pmd_cmdf2_lfo,
+ pmd_cmdf1_lfo_switch,
+ pmd_cmdf0_env_old,
+ pmd_cmdef_poke,
+ pmd_cmd_null_1,
+ pmd_cmd_null_1,
+ pmd_cmdec_pan_ppz8,
+ pmd_cmdeb_opnarhythm,
+ pmd_cmdea_opnarhythm_il,
+ pmd_cmde9_opnarhythm_pan,
+ pmd_cmde8_opnarhythm_tl,
+ pmd_cmde7_transpose_rel,
+ pmd_cmde6_opnarhythm_tl_rel,
+ pmd_cmde5_opnarhythm_il_rel,
+ pmd_cmd_null_1,
+ pmd_cmde3_vol_add_adpcm,
+ pmd_cmde2_vol_sub,
+ pmd_cmd_null_1,
+ pmd_cmd_null_1,
+ pmd_cmddf_meas_len,
+ pmd_cmdde_echo_init_add_adpcm,
+ pmd_cmddd_echo_init_sub,
+ pmd_cmddc_status1,
+ pmd_cmddb_status1_add,
+ pmd_cmdda_portamento_ppz8,
+ pmd_cmd_null_1,
+ pmd_cmd_null_1,
+ pmd_cmd_null_1,
+ pmd_cmdd6_md,
+ pmd_cmdfa_d5_det,
+ pmd_cmdd4_ssgeff,
+ pmd_cmdd3_fmeff,
+ pmd_cmdd2_fadeout,
+ pmd_cmd_null_1,
+ pmd_cmd_null_1,
+ pmd_cmd_null_1,
+ pmd_cmdce_ppz8_loop,
+ pmd_cmdcd_env_new,
+ pmd_cmd_null_1,
+ pmd_cmdcb_lfo_waveform,
+ pmd_cmdca_lfo_ext,
+ pmd_cmdc9_env_ext,
+ pmd_cmd_null_3,
+ pmd_cmd_null_3,
+ pmd_cmd_null_6,
+ pmd_cmd_null_1,
+ pmd_cmdc4_gate_rel,
+ pmd_cmdc3_pan_ex_ppz8,
+ pmd_cmdc2_lfo_delay,
+ pmd_cmd_null_0,
+ pmd_cmdc0_mml_mask_ppz8,
+ pmd_cmdbf_lfo2,
+ pmd_cmdbe_lfo2_switch,
+ pmd_cmdbd_lfo2_md,
+ pmd_cmdbc_lfo2_waveform,
+ pmd_cmdbb_lfo2_ext,
+ pmd_cmdba_lfo2_slotmask, // slotmask on PPZ8??
+ pmd_cmdb9_lfo2_delay,
+ pmd_cmd_null_2,
+ pmd_cmdb7_lfo_md_cnt,
+ pmd_cmd_null_1,
+ pmd_cmd_null_2,
+ pmd_cmd_null_16,
+ pmd_cmdb3_gate_min,
+ pmd_cmdb2_transpose_master,
+ pmd_cmdb1_gate_rand_range
};
// 1857
@@ -4210,6 +4592,20 @@ static void pmd_part_cmd_adpcm(
pmd_cmd_table_adpcm[cmd^0xff](work, pmd, part);
}
+// 02c6
+static void pmd_part_cmd_ppz8(
+ struct fmdriver_work *work,
+ struct driver_pmd *pmd,
+ struct pmd_part *part,
+ uint8_t cmd
+) {
+ if (cmd < 0xb1) {
+ part->ptr = 0;
+ return;
+ }
+ pmd_cmd_table_ppz8[cmd^0xff](work, pmd, part);
+}
+
// 20e8
static void pmd_portamento_tick(
struct pmd_part *part
@@ -4375,6 +4771,49 @@ static void pmd_part_proc_adpcm_lfoenv(
pmd_part_loop_check(pmd, part);
}
+// 084c
+static void pmd_part_proc_ppz8_lfoenv(
+ struct fmdriver_work *work,
+ struct driver_pmd *pmd,
+ struct pmd_part *part
+) {
+ static const struct pmd_part_lfo_flags lfof_z;
+ pmd->lfoprocf = lfof_z;
+ pmd->lfoprocf_b = lfof_z;
+ pmd->lfoprocf.portamento = part->lfof.portamento;
+
+ if (part->lfof.freq || part->lfof.vol || part->lfof.sync || part->lfof.portamento ||
+ part->lfof_b.freq || part->lfof_b.vol || part->lfof_b.sync || part->lfof_b.portamento) {
+ // 085a
+ if (part->lfof.freq || part->lfof.vol) {
+ if (pmd_lfo_tick(pmd, part)) {
+ pmd->lfoprocf.freq = part->lfof.freq;
+ pmd->lfoprocf.vol = part->lfof.vol;
+ }
+ }
+ if (part->lfof_b.freq || part->lfof_b.vol) {
+ pmd_part_lfo_flip(part);
+ if (pmd_lfo_tick(pmd, part)) {
+ pmd->lfoprocf_b.freq = part->lfof_b.freq;
+ pmd->lfoprocf_b.vol = part->lfof_b.vol;
+ }
+ pmd_part_lfo_flip(part);
+ }
+ // 088e
+ if (pmd->lfoprocf.freq || pmd->lfoprocf.portamento || pmd->lfoprocf_b.freq) {
+ if (pmd->lfoprocf.portamento) {
+ pmd_portamento_tick(part);
+ }
+ pmd_ppz8_freq_out(work, pmd, part);
+ }
+ }
+ // 08a2
+ if (pmd_ssg_env_proc(pmd, part) || pmd->lfoprocf.vol || pmd->lfoprocf_b.vol || pmd->fadeout_speed) {
+ pmd_ppz8_vol_out(work, pmd, part);
+ }
+ pmd_part_loop_check(pmd, part);
+}
+
// 16d9
static bool pmd_part_ssg_next_masked(
struct fmdriver_work *work,
@@ -4938,36 +5377,70 @@ static void pmd_part_proc_ppz8(
struct driver_pmd *pmd,
struct pmd_part *part
) {
- /*
if (!part->ptr) return;
part->proc_masked = pmd_part_masked(part);
part->len_cnt--;
- if (!part->keystatus.off && !part->keystatus.off_mask) {
+ if (part->proc_masked) {
+ part->keystatus.off = true;
+ part->keystatus.off_mask = true;
+ } else if (!part->keystatus.off && !part->keystatus.off_mask) {
// 07b6
if (part->len_cnt <= part->gate) {
part->keystatus.off = true;
part->keystatus.off_mask = true;
- pmd_part_off_ppz8(work, pmd, part);
+ pmd_part_off_ppz8(part);
}
}
// 07c2
if (part->len_cnt) {
- // 084c
+ if (part->proc_masked) {
+ pmd_part_loop_check(pmd, part);
+ } else {
+ pmd_part_proc_ppz8_lfoenv(work, pmd, part);
+ }
+ return;
}
part->lfof.portamento = false;
for (;;) {
- // 07cd
+ // 07cd / 08ca
uint8_t cmd = pmd_part_cmdload(pmd, part);
if (cmd & 0x80) {
if (cmd != 0x80) {
- pmd_part_cmd_adpcm(work, pmd, part, cmd);
+ pmd_part_cmd_ppz8(work, pmd, part, cmd);
if (cmd == 0xda && !pmd_part_masked(part)) return;
} else {
- // 0187
+ // 07d9 / 08d6
+ part->ptr = 0;
+ part->loop.looped = true;
+ part->loop.ended = true;
+ part->actual_note = 0xff;
+ if (!part->loop_ptr) {
+ if (part->proc_masked) {
+ pmd_part_loop_check_masked(pmd, part);
+ } else {
+ pmd_part_proc_ppz8_lfoenv(work, pmd, part);
+ }
+ return;
+ }
+ part->ptr = part->loop_ptr;
+ part->loop.ended = false;
+ }
+ } else {
+ // 07f3 / 08f3
+ if (part->proc_masked) {
+ part->actual_freq_upper = 0;
+ pmd_part_proc_note_masked(work, pmd, part);
+ } else {
+ pmd_part_lfo_init_ssg(work, pmd, part, cmd);
+ cmd = pmd_part_note_transpose(part, cmd);
+ pmd_note_freq_ppz8(part, cmd);
+ part->len = part->len_cnt = pmd_part_cmdload(pmd, part);
+ pmd_part_calc_gate(pmd, part);
+ pmd_part_ppz8_out(work, pmd, part);
}
+ return;
}
}
- */
}
// 11fd
@@ -5119,6 +5592,7 @@ enum pmd_part_type {
PART_TYPE_FM,
PART_TYPE_SSG,
PART_TYPE_ADPCM,
+ PART_TYPE_PPZ8
};
static const struct {
@@ -5139,6 +5613,14 @@ static const struct {
{PMD_PART_SSG_2, PART_TYPE_SSG, false},
{PMD_PART_SSG_3, PART_TYPE_SSG, false},
{PMD_PART_ADPCM, PART_TYPE_ADPCM, false},
+ {PMD_PART_PPZ_1, PART_TYPE_PPZ8, false},
+ {PMD_PART_PPZ_2, PART_TYPE_PPZ8, false},
+ {PMD_PART_PPZ_3, PART_TYPE_PPZ8, false},
+ {PMD_PART_PPZ_4, PART_TYPE_PPZ8, false},
+ {PMD_PART_PPZ_5, PART_TYPE_PPZ8, false},
+ {PMD_PART_PPZ_6, PART_TYPE_PPZ8, false},
+ {PMD_PART_PPZ_7, PART_TYPE_PPZ8, false},
+ {PMD_PART_PPZ_8, PART_TYPE_PPZ8, false},
};
static void pmd_work_status_update(
@@ -5200,6 +5682,8 @@ static void pmd_work_status_update(
case PART_TYPE_ADPCM:
//track->playing = false;
break;
+ case PART_TYPE_PPZ8:
+ break;
}
}
work->ssg_noise_freq = pmd->ssg_noise_freq_wrote;
@@ -5221,6 +5705,7 @@ static void pmd_opna_interrupt(struct fmdriver_work *work) {
pmd_work_status_update(work, pmd);
}
+/*
// 0f4d
static void pmd_mstart(
struct fmdriver_work *work,
@@ -5242,6 +5727,7 @@ static void pmd_mstart(
// TODO
// 4375??
}
+*/
bool pmd_load(struct driver_pmd *pmd,
uint8_t *data, uint16_t datalen) {
@@ -5353,6 +5839,8 @@ void pmd_init(struct fmdriver_work *work,
if (pcmfile) {
pmd_filenamecopy(pmd->ppcfile, pcmfile);
}
+ fmdriver_fillpcmname(work->pcmname[0], pmd->ppcfile);
+ fmdriver_fillpcmname(work->pcmname[1], pmd->ppzfile);
}
enum {
@@ -5396,4 +5884,5 @@ bool pmd_ppc_load(
work->opna_writereg(work, 0x110, 0x0c);
work->opna_writereg(work, 0x100, 0x01);
+ return true;
}