From: notaz Date: Sat, 1 Mar 2025 21:22:52 +0000 (+0200) Subject: s3k_ss, s3d_dd kinda works X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=51061b66370e157cc4d92adc736bc9ceed503a05;p=picodrive.git s3k_ss, s3d_dd kinda works --- diff --git a/.gitmodules b/.gitmodules index 5d28012a..568b0fc1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "platform/libpicofe"] path = platform/libpicofe - url = https://github.com/irixxxx/libpicofe.git + url = https://github.com/notaz/libpicofe.git [submodule "cpu/cyclone"] path = cpu/cyclone url = https://github.com/irixxxx/cyclone68000.git diff --git a/mkbd_s3d_dd.sh b/mkbd_s3d_dd.sh new file mode 100755 index 00000000..548c9a00 --- /dev/null +++ b/mkbd_s3d_dd.sh @@ -0,0 +1,3 @@ +#!/bin/sh +exec ./picodrive -load 3 -mk_c 0 -mk_ce 4 -mk_transpose -12 -mk_ar_min 62 \ + -mk_echo_on 11 -mk_echo_off 12 "$@" diff --git a/mkbd_s3k_ss.sh b/mkbd_s3k_ss.sh new file mode 100755 index 00000000..bd6b1c75 --- /dev/null +++ b/mkbd_s3k_ss.sh @@ -0,0 +1,2 @@ +#!/bin/sh +exec ./picodrive -load 2 -mk_c 4 -mk_ce 3 -mk_echo_on 13 -mk_echo_off 21 "$@" diff --git a/pico/pico.c b/pico/pico.c index 1d93d60d..2b2f2679 100644 --- a/pico/pico.c +++ b/pico/pico.c @@ -250,6 +250,7 @@ void PicoLoopPrepare(void) } #include "pico_cmn.c" +#include "sound/mkbd.h" /* sync z80 to 68k */ PICO_INTERNAL void PicoSyncZ80(unsigned int m68k_cycles_done) @@ -259,6 +260,8 @@ PICO_INTERNAL void PicoSyncZ80(unsigned int m68k_cycles_done) m68k_cnt = m68k_cycles_done - Pico.t.m68c_frame_start; Pico.t.z80c_aim = cycles_68k_to_z80(m68k_cnt); + if (mkbd_stop_z80) + Pico.t.z80c_cnt = Pico.t.z80c_aim; cnt = Pico.t.z80c_aim - Pico.t.z80c_cnt; pprof_start(z80); diff --git a/pico/sound/mkbd.h b/pico/sound/mkbd.h new file mode 100644 index 00000000..57de899f --- /dev/null +++ b/pico/sound/mkbd.h @@ -0,0 +1,19 @@ + +extern int mkbd_stolen_channels; +extern int mkbd_kbd_channel; +extern int mkbd_kbd_echo_channel; +extern int mkbd_echo_delay_on; +extern int mkbd_echo_delay_off; +extern int mkbd_transpose; +extern int mkbd_ar_min; +extern int mkbd_stop_z80; + +void mkbd_steal_toggle(int c, int shift); +void mkbd_snd_inject(int c, unsigned int octave, unsigned int key, int is_on, + int echo_c, int echo_frames); +void mkbd_snd_adj_start(int c, int step); +void mkbd_snd_do_frame(void); + +void sn76496h_steal(int c, int is_stolen); + +void mkbd_tempo_kdown(int tempo_increase, int is_kdown); diff --git a/pico/sound/sn76496.c b/pico/sound/sn76496.c index 1624d136..2c3cee84 100644 --- a/pico/sound/sn76496.c +++ b/pico/sound/sn76496.c @@ -21,6 +21,7 @@ #endif #include "sn76496.h" +#include "mkbd.h" #define MAX_OUTPUT 0x4800 // was 0x7fff @@ -57,6 +58,8 @@ struct SN76496 int Count[4]; int Output[4]; int Panning; + int mkbd_bk_Volume[4]; + char mkbd_stolen[4]; }; static struct SN76496 ono_sn; // one and only SN76496 @@ -103,6 +106,9 @@ void SN76496Write(int data) case 5: /* tone 2 : volume */ case 7: /* noise : volume */ R->Volume[c] = R->VolTable[data & 0x0f]; + R->mkbd_bk_Volume[c] = R->Volume[c]; + if (R->mkbd_stolen[c]) + R->Volume[c] = 0; break; case 6: /* noise : frequency, mode */ n = data; @@ -322,3 +328,13 @@ int SN76496_init(int clock,int sample_rate) return 0; } +#undef NDEBUG +#include + +void sn76496h_steal(int c, int is_stolen) +{ + assert((unsigned)c < 4u); + ono_sn.mkbd_stolen[c] = is_stolen; + ono_sn.Volume[c] = is_stolen ? 0 : ono_sn.mkbd_bk_Volume[c]; +} + diff --git a/pico/sound/sound.c b/pico/sound/sound.c index 447d9dd2..d8bbe183 100644 --- a/pico/sound/sound.c +++ b/pico/sound/sound.c @@ -291,6 +291,9 @@ PICO_INTERNAL void PsndDoDAC(int cyc_to) if (len <= 0) return; + if (mkbd_stolen_channels & (1u << 5)) + ; + else // fill buffer, applying a rather weak order 1 bessel IIR on the way // y[n] = (x[n] + x[n-1])*(1/2) (3dB cutoff at 11025 Hz, no gain) // 1 sample delay for correct IIR filtering over audio frame boundaries @@ -502,6 +505,61 @@ PICO_INTERNAL void PsndClear(void) memset32(PsndBuffer, 0, PicoIn.opt & POPT_EN_STEREO ? len*2 : len); } +static int g_tempo_kdown; +static int g_tempo_increase; + +static int is_rom(const char *name) +{ + const char *rn = (const char *)Pico.rom + 0x150; + int i; + for (i = 0; name[i]; i++) + if (rn[i^1] != name[i]) + return 0; + return 1; +} + +static void smps_set_init_tempo(u32 base, u8 val) +{ + Pico.rom[(base + 5)^1] = val; +} + +static void do_tempo_adj(void) +{ + static int step; + //u8 *mem = &Pico.rom[Pico.m.z80_bank68k << 15]; + //u8 *mem = &Pico.rom[0x0EBE80]; + //mem[5^1]--; + if (!g_tempo_kdown) + return; + if (step++ < 2) + return; + step = 0; + if (g_tempo_increase) + PicoMem.zram[0x1c24]--; + else + PicoMem.zram[0x1c24]++; + //printf("tempo %02x\n", PicoMem.zram[0x1c24]); + if (is_rom("SONIC & KNUCKLES")) { + smps_set_init_tempo(0x0EBE80, PicoMem.zram[0x1c24]); // ssz + } + else if (is_rom("SONIC 3D FLICKIES")) { + smps_set_init_tempo(0x0C7091, PicoMem.zram[0x1c24]); // diamond dust1 + } +} + +void mkbd_tempo_kdown(int tempo_up, int is_kdown) +{ + g_tempo_kdown = is_kdown; + g_tempo_increase = tempo_up; + //u16 mp = PicoMem.zram[0x1618] | (PicoMem.zram[0x1619] << 8); +#if 0 + int i; + for (i = 0; i < 0x2000-1; i++) + if (PicoMem.zram[i] == 0x80 && PicoMem.zram[i+1] == 0xbe) + printf("%04x\n", i); +#endif +} + #include #include #include @@ -541,22 +599,26 @@ static int midi_init(void) static void do_note(uint8_t note, int is_down) { - static uint32_t state[96/8/4]; + static uint32_t state[128/8/4]; int i, v = 0, release_all = 0; - if (note >= 96) + note += mkbd_transpose; + if (note >= 128u) return; if (is_down) { state[note / 8 / 4] |= 1u << (note % 32u); - //ym2612h_inject(4, 0, 0, 0, -1, 0); - ym2612h_inject(4, note / 12, note % 12, 1, 3, 13); + //mkbd_snd_inject(4, 0, 0, 0, -1, 0); + if (mkbd_kbd_channel >= 0) + mkbd_snd_inject(mkbd_kbd_channel, note / 12, note % 12, 1, + mkbd_kbd_echo_channel, mkbd_echo_delay_on); } else { state[note / 8 / 4] &= ~(1u << (note % 32u)); for (i = 0; i < ARRAY_SIZE(state); i++) v |= state[i]; release_all = !v; - if (release_all) - ym2612h_inject(4, 0, 0, 0, 3, 21); + if (release_all && mkbd_kbd_channel >= 0) + mkbd_snd_inject(mkbd_kbd_channel, 0, 0, 0, + mkbd_kbd_echo_channel, mkbd_echo_delay_off); } } @@ -573,8 +635,8 @@ static void mkbd_update(void) } note; int ret; - ym2612h_adj_step(); - ym2612h_echo_step(); + do_tempo_adj(); + mkbd_snd_do_frame(); for (;;) { @@ -611,7 +673,7 @@ static void mkbd_update(void) if (read(mkbd_fd, &data, sizeof(data)) != sizeof(data)) cfail("read", NULL); //printf("p %02x %02x\n", data[0], data[1]); - ym2612h_adj_start(4, 4); + mkbd_snd_adj_start(4, 4); break; case 0xf0: switch (status) { @@ -666,6 +728,9 @@ static int PsndRender(int offset, int length) // Fill up DAC output in case of missing samples (Q rounding errors) if (length-daclen > 0 && PicoIn.sndOut) { Pico.snd.dac_pos += (length-daclen) << 20; + if (mkbd_stolen_channels & (1u << 5)) + ; + else if (PicoIn.opt & POPT_EN_STEREO) { s16 *d = PicoIn.sndOut + daclen*2; int pan = ym2612.REGS[YM2612_CH6PAN]; diff --git a/pico/sound/ym2612.c b/pico/sound/ym2612.c index a7812cb7..05c08aee 100644 --- a/pico/sound/ym2612.c +++ b/pico/sound/ym2612.c @@ -515,6 +515,20 @@ static UINT32 fn_table[4096]; /* fnumber->increment counter */ static int g_lfo_ampm; + +#undef NDEBUG +#include +#include "mkbd.h" + +int mkbd_stolen_channels; +int mkbd_kbd_channel = -1; +int mkbd_kbd_echo_channel = -1; +int mkbd_echo_delay_on; +int mkbd_echo_delay_off; +int mkbd_transpose; +int mkbd_ar_min; +int mkbd_stop_z80; + /* register number to channel number , slot offset */ #define OPN_CHAN(N) (N&3) #define OPN_SLOT(N) ((N>>2)&3) @@ -620,7 +634,15 @@ static INLINE void set_ar_ksr(FM_CH *CH, FM_SLOT *SLOT, int v) UINT8 old_KSR = SLOT->KSR; int eg_sh_ar, eg_sel_ar; - SLOT->ar = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0; + int c = CH - ym2612.CH; + int ar = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0; + if (c == mkbd_kbd_channel || c == mkbd_kbd_echo_channel) + if (ar < mkbd_ar_min) + ar = mkbd_ar_min; + //if (c == 0 && SLOT->ar != ar) + // printf("%d,%ld %d->%d\n", c, SLOT - CH->SLOT, SLOT->ar, ar); + + SLOT->ar = ar; SLOT->ar_ksr = SLOT->ar + SLOT->ksr; SLOT->KSR = 3-(v>>6); @@ -1618,20 +1640,18 @@ static void OPNSetPres(int pres) } } -#undef NDEBUG -#include -#include "mkbd.h" - static const char *keys[] = { "c", "c#", "d", "d#", "e", "f", "f#", "g", "g#", "a", "a#", "b" }; // 643.8 682.1 722.6 765.6 811.1 859.3 910.4 964.6 1021.9 1082.7 1147.1 1215.3 static int fns[] = { 644, 682, 723, 766, 811, 860, 910, 965, 1022, 1083, 1147, 1215 }; -int mkbd_stolen_channels = (1<<3) | (1<<4); static int mkbd_blk_fn_overide[6+4]; static int mkbd_fn_adj_step[6+4]; static int mkbd_fn_adj[6+4]; +static int mkbd_ym_kon_mask; // on now +static int mkbd_ym_kon_next_mask; // on on next frame +static int mkbd_ym_cooldown_mask; // (144 * fnote * 2^20 / φM) / 2^(B-1) // x *144*2097152/7670443 / 16 @@ -1691,6 +1711,14 @@ static void do_log_note(int c) static void do_key_onoff(int c, int v) { + assert((u32)c < 6); + if (v & 0xf0) + mkbd_ym_kon_mask |= 1 << c; + else + mkbd_ym_kon_mask &= ~(1 << c); + //if (c==4) return; + //printf("%d c%d k%s %02x\n", Pico.m.frame_count, + // c, (v & 0xf0) ? "on " : "off", v); if(v&0x10) FM_KEYON(c,SLOT1); else FM_KEYOFF(c,SLOT1); if(v&0x20) FM_KEYON(c,SLOT2); else FM_KEYOFF(c,SLOT2); if(v&0x40) FM_KEYON(c,SLOT3); else FM_KEYOFF(c,SLOT3); @@ -1711,7 +1739,7 @@ static void set_blk_fn(int c, int blk_fn) static void echo_add(int c, int blk_fn, int frame_delay); -void ym2612h_inject(int c, unsigned int octave, unsigned int key, int is_on, +static void ym2612h_inject(int c, unsigned int octave, unsigned int key, int is_on, int echo_c, int echo_frames) { UINT32 val = 0; @@ -1719,23 +1747,36 @@ void ym2612h_inject(int c, unsigned int octave, unsigned int key, int is_on, //printf("%s %d %d,%d %d\n", __func__, c, octave, key, is_on); assert(octave < 8); assert(key < ARRAY_SIZE(fns)); + + mkbd_ym_kon_next_mask &= ~(1 << c); + if (mkbd_ym_kon_mask & (1 << c)) + mkbd_ym_cooldown_mask |= 1 << c; + mkbd_blk_fn_overide[c] = 0; + do_key_onoff(c, 0); if (is_on) { val = fns[key]; // + mkbd_fn_adj[c]; assert(val < (1u << 11)); val |= octave << 11; mkbd_blk_fn_overide[c] = val; - do_key_onoff(c, 0); set_blk_fn(c, val); + if (!(mkbd_ym_cooldown_mask & (1 << c))) + do_key_onoff(c, 0xf0); + else + // give a frame for adsr to update + mkbd_ym_kon_next_mask |= 1 << c; } - else - mkbd_blk_fn_overide[c] = 0; mkbd_fn_adj[c] = mkbd_fn_adj_step[c] = 0; - do_key_onoff(c, is_on ? 0xf0 : 0); - - if (echo_c >= 0) + if (echo_c >= 0) { + if (is_on) { + // must do it always as there might be an older + // koff that we need to override + echo_add(echo_c, 0, echo_frames); + echo_frames++; + } echo_add(echo_c, val, echo_frames); + } } static struct @@ -1743,20 +1784,28 @@ static struct int c; int blk_fn; u32 frame; -} echo_ev[8]; +} echo_ev[12]; #define ECHO_MAX_FRAMES 60u static void echo_add(int c, int blk_fn, int frame_delay) { u32 now = Pico.m.frame_count; - int i; + int i, di; assert((u32)frame_delay <= ECHO_MAX_FRAMES); if (now + (u32)frame_delay == 0) frame_delay++; - if (blk_fn) - memset(echo_ev, 0, sizeof(echo_ev)); + + // as kon and koff delays may differ, and kon generates a koff event, + // kill any older event + for (i = 0; i < ARRAY_SIZE(echo_ev); i++) { + if (echo_ev[i].frame == 0 || echo_ev[i].c != c) + continue; + di = echo_ev[i].frame - now; + if (di >= frame_delay && !echo_ev[i].blk_fn == !blk_fn) + echo_ev[i].frame = 0; + } for (i = 0; i < ARRAY_SIZE(echo_ev); i++) { if (echo_ev[i].frame != 0 && echo_ev[i].frame - now <= ECHO_MAX_FRAMES) @@ -1771,7 +1820,7 @@ static void echo_add(int c, int blk_fn, int frame_delay) printf("echo overflow\n"); } -void ym2612h_echo_step(void) +static void ym2612h_echo_do_step(void) { u32 now = Pico.m.frame_count; int i, c, val; @@ -1785,7 +1834,6 @@ void ym2612h_echo_step(void) if (val) { mkbd_blk_fn_overide[c] = val; set_blk_fn(c, val); - do_key_onoff(c, 0); } do_key_onoff(c, val ? 0xf0 : 0); echo_ev[i].frame = 0; @@ -1798,10 +1846,18 @@ void ym2612h_adj_start(int c, int step) mkbd_fn_adj_step[c] = step; } -void ym2612h_adj_step(void) +static void ym2612h_do_frame(void) { int c; + mkbd_ym_cooldown_mask = 0; + for (c = 0; c < 6; c++) { + if (!(mkbd_ym_kon_next_mask & (1 << c))) + continue; + mkbd_ym_kon_next_mask &= ~(1 << c); + do_key_onoff(c, 0xf0); + } + for (c = 0; c < 6; c++) { if (mkbd_fn_adj_step[c] == 0) continue; @@ -1815,6 +1871,61 @@ void ym2612h_adj_step(void) } } +void mkbd_steal_toggle(int c, int shift) +{ + if (shift) { + mkbd_stolen_channels |= 1u << c; + if (c == mkbd_kbd_channel) { + mkbd_kbd_channel = -1; + mkbd_kbd_echo_channel = c; + } + else if (c == mkbd_kbd_echo_channel) + mkbd_kbd_echo_channel = -1; + else + mkbd_kbd_channel = c; + } + else { + mkbd_stolen_channels ^= 1u << c; + if (!(mkbd_stolen_channels & (1u << c))) { + if (c == mkbd_kbd_channel) + mkbd_kbd_channel = -1; + if (c == mkbd_kbd_echo_channel) + mkbd_kbd_echo_channel = -1; + } + } + if (c >= 6) { + sn76496h_steal(c - 6, !!(mkbd_stolen_channels & (1u << c))); + return; + } + if (mkbd_stolen_channels & (1u << c)) + do_key_onoff(c, 0); +} + +void mkbd_snd_inject(int c, unsigned int octave, unsigned int key, int is_on, + int echo_c, int echo_frames) +{ + if (c < 6) + ym2612h_inject(c, octave, key, is_on, echo_c, echo_frames); + else + ; +} + +void mkbd_snd_adj_start(int c, int step) +{ + if (c < 6) + ym2612h_adj_start(c, step); + else + ; +} + +void mkbd_snd_do_frame(void) +{ + ym2612h_do_frame(); + ym2612h_echo_do_step(); +} + +// ----------------- + /* write a OPN register (0x30-0xff) */ static int OPNWriteReg(int r, int v, int injecting) { @@ -2169,8 +2280,8 @@ int YM2612Write_(unsigned int a, unsigned int v) if( c == 3 ) { ret=0; break; } if( v&0x04 ) c+=3; if (is_stolen(c)) { ret = 0; break; } - //if (c == 3 || c == 4) - // printf("%d %d konoff %02x\n", Pico.m.frame_count, c, v); + //if (c == 0 || c == 4) + // printf("%d %d k%s %02x\n", Pico.m.frame_count, c, (v & 0xf0) ? "on " : "off", v); if(v&0x10) FM_KEYON(c,SLOT1); else FM_KEYOFF(c,SLOT1); if(v&0x20) FM_KEYON(c,SLOT2); else FM_KEYOFF(c,SLOT2); if(v&0x40) FM_KEYON(c,SLOT3); else FM_KEYOFF(c,SLOT3); diff --git a/platform/common/emu.c b/platform/common/emu.c index 799aa313..a6f5fede 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -1589,6 +1589,8 @@ static void emu_loop_prep(void) #define get_ticks() plat_get_ticks_us() #define vsync_delay ms_to_ticks(1) +#include "../../pico/sound/mkbd.h" + void emu_loop(void) { int frames_done, frames_shown; /* actual frames for fps counter */ @@ -1683,6 +1685,22 @@ void emu_loop(void) #ifdef PFRAMES sprintf(fpsbuff, "%i", Pico.m.frame_count); #endif + int i; + char buf_c[32]; + notice_msg = buf_c; + for (i = 0; i < 10; i++) { + char c = '0' + i; + if (i == mkbd_kbd_channel) + c = '*'; + else if (i == mkbd_kbd_echo_channel) + c = '_'; + else if (mkbd_stolen_channels & (1u << i)) + c = '.'; + notice_msg[i] = c; + } + i += snprintf(buf_c + i, sizeof(buf_c) - i, " %02x", + PicoMem.zram[0x1c24]); // tempo + notice_msg[i] = 0; diff = timestamp_aim - timestamp; diff --git a/platform/common/main.c b/platform/common/main.c index 8e6987e4..62286904 100644 --- a/platform/common/main.c +++ b/platform/common/main.c @@ -20,6 +20,7 @@ #include "emu.h" #include "version.h" #include +#include "pico/sound/mkbd.h" static int load_state_slot = -1; char **g_argv; @@ -46,6 +47,22 @@ void parse_cmd_line(int argc, char *argv[]) else if (strcasecmp(argv[x], "-pdb_connect") == 0) { if (x+2 < argc) { pdb_net_connect(argv[x+1], argv[x+2]); x += 2; } } + else if (strcmp(argv[x], "-mk_c") == 0) { + mkbd_kbd_channel = atoi(argv[++x]); + mkbd_stolen_channels |= 1u << mkbd_kbd_channel; + } + else if (strcmp(argv[x], "-mk_ce") == 0) { + mkbd_kbd_echo_channel = atoi(argv[++x]); + mkbd_stolen_channels |= 1u << mkbd_kbd_echo_channel; + } + else if (strcmp(argv[x], "-mk_echo_on") == 0) + mkbd_echo_delay_on = atoi(argv[++x]); + else if (strcmp(argv[x], "-mk_echo_off") == 0) + mkbd_echo_delay_off = atoi(argv[++x]); + else if (strcmp(argv[x], "-mk_transpose") == 0) + mkbd_transpose = atoi(argv[++x]); + else if (strcmp(argv[x], "-mk_ar_min") == 0) + mkbd_ar_min = atoi(argv[++x]); else { unrecognized = plat_parse_arg(argc, argv, &x); } diff --git a/platform/libpicofe b/platform/libpicofe index 023d7e89..1dd77072 160000 --- a/platform/libpicofe +++ b/platform/libpicofe @@ -1 +1 @@ -Subproject commit 023d7e890f1c4386ff3bc095efd96eb65fafe389 +Subproject commit 1dd770727c32898135d5dca81d54f0ca1dfd28ed