diff --git a/Makefile b/Makefile index a292ce1..543be9c 100644 --- a/Makefile +++ b/Makefile @@ -84,7 +84,9 @@ m68k: m68k/%.bin: m68k $(MAKE) -C m68k $(notdir $@) -scsp/sound_cpu.elf: scsp/sound_cpu.o m68k/slot.bin.o +scsp/sound_cpu__slot.elf: scsp/sound_cpu__slot.o m68k/slot.bin.o + +scsp/sound_cpu__interrupt.elf: scsp/sound_cpu__interrupt.o m68k/interrupt.bin.o # clean clean: clean-sh diff --git a/m68k/Makefile b/m68k/Makefile index 26aedb6..b48bec7 100644 --- a/m68k/Makefile +++ b/m68k/Makefile @@ -9,4 +9,6 @@ include $(LIB)/m68k/common.mk %.pcm.o: %.pcm $(BUILD_BINARY_O) -slot.elf: $(LIB)/m68k/vectors.o slot.o sine-44100-s16be-1ch.pcm.o +slot.elf: $(LIB)/m68k/vectors.o $(LIB)/m68k/handlers.o slot.o sine-44100-s16be-1ch.pcm.o + +interrupt.elf: $(LIB)/m68k/vectors.o $(LIB)/m68k/handlers.o interrupt.o jojo-11025-s16be-1ch.pcm.o diff --git a/m68k/interrupt.cpp b/m68k/interrupt.cpp new file mode 100644 index 0000000..d115e43 --- /dev/null +++ b/m68k/interrupt.cpp @@ -0,0 +1,88 @@ +#include + +#include "scsp.h" + +extern void * _jojo_start __asm("_binary_jojo_11025_s16be_1ch_pcm_start"); + +static volatile int32_t frame = 0; + +extern "C" +void auto_vector_1(void) __attribute__ ((interrupt_handler)); +void auto_vector_1(void) +{ + // reset TIMER_A interrupt + scsp.reg.ctrl.SCIRE = INT__TIMER_A; + + frame++; + //if (frame > 3962) frame = 0; + + const uint16_t * jojo_start = reinterpret_cast(&_jojo_start); + const uint32_t frame_addr = reinterpret_cast(&jojo_start[frame * 8192]); + + scsp_slot& slot = scsp.reg.slot[frame % 32]; + slot.LOOP = 0; + slot.LOOP |= LOOP__KYONEX; + + slot.LOOP = LOOP__KYONB | LOOP__SA(frame_addr); // kx kb sbctl[1:0] ssctl[1:0] lpctl[1:0] 8b sa[19:16] + slot.SA = SA__SA(frame_addr); // start address (bytes) + slot.LSA = 0; // loop start address (samples) + slot.LEA = 8192; // loop end address (samples) + slot.EG = EG__AR(0x1f) | EG__EGHOLD; // d2r d1r ho ar krs dl rr + slot.VOLUME = 0; // stwinh sdir tl + slot.FM = 0; // mdl mdxsl mdysl + slot.PITCH = PITCH__OCT(-2) | PITCH__FNS(0); // oct fns + slot.LFO = 0; // lfof plfows + slot.MIXER = MIXER__DISDL(0b101); // disdl dipan efsdl efpan + + slot.LOOP |= LOOP__KYONEX; + + return; +} + +void main() +{ + for (long i = 0; i < 807; i++) { asm volatile ("nop"); } // wait for (way) more than 30µs + + scsp.reg.ctrl.MIXER = MIXER__MEM4MB | MIXER__MVOL(0xf); + + scsp.reg.ctrl.TIMA = TIMA__TACTL(7); + + // timer A is vector 1 (0b001) + scsp.reg.ctrl.SCILV2 = 0; + scsp.reg.ctrl.SCILV1 = 0; + scsp.reg.ctrl.SCILV0 = SCILV__TIMER_A; + + // enable TIMER_A + scsp.reg.ctrl.SCIRE = INT__TIMER_A; + scsp.reg.ctrl.SCIEB = INT__TIMER_A; + + asm volatile ("move.w #8192,%sr"); + + const uint16_t * jojo_start = reinterpret_cast(&_jojo_start); + const uint32_t frame_addr = reinterpret_cast(&jojo_start[frame * 128]); + + scsp_slot& slot = scsp.reg.slot[0]; + slot.LOOP = 0; + slot.LOOP |= LOOP__KYONEX; + + slot.LOOP = LOOP__KYONB | LOOP__SA(frame_addr); // kx kb sbctl[1:0] ssctl[1:0] lpctl[1:0] 8b sa[19:16] + slot.SA = SA__SA(frame_addr); // start address (bytes) + slot.LSA = 0; // loop start address (samples) + slot.LEA = 128; // loop end address (samples) + slot.EG = EG__AR(0x1f) | EG__EGHOLD; // d2r d1r ho ar krs dl rr + slot.VOLUME = 0; // stwinh sdir tl + slot.FM = 0; // mdl mdxsl mdysl + slot.PITCH = PITCH__OCT(-2) | PITCH__FNS(0); // oct fns + slot.LFO = 0; // lfof plfows + slot.MIXER = MIXER__DISDL(0b101); // disdl dipan efsdl efpan + + slot.LOOP |= LOOP__KYONEX; +} + +extern "C" +void start(void) +{ + main(); + while (1); +} + diff --git a/m68k/jojo-11025-s16be-1ch.pcm b/m68k/jojo-11025-s16be-1ch.pcm new file mode 100644 index 0000000..3d5e604 Binary files /dev/null and b/m68k/jojo-11025-s16be-1ch.pcm differ diff --git a/m68k/slot.cpp b/m68k/slot.cpp index 28b405c..adc9e6b 100644 --- a/m68k/slot.cpp +++ b/m68k/slot.cpp @@ -1,8 +1,6 @@ #include -#include "smpc.h" -#include "scsp.h" -#include "../common/copy.hpp" +#include "scsp.h" extern void * _sine_start __asm("_binary_sine_44100_s16be_1ch_pcm_start"); @@ -15,6 +13,9 @@ void main() const uint32_t sine_start = reinterpret_cast(&_sine_start); scsp_slot& slot = scsp.reg.slot[0]; + slot.LOOP = 0; + slot.LOOP |= LOOP__KYONEX; + slot.LOOP = LOOP__KYONB | LOOP__LPCTL__NORMAL | LOOP__SA(sine_start); // kx kb sbctl[1:0] ssctl[1:0] lpctl[1:0] 8b sa[19:16] slot.SA = SA__SA(sine_start); // start address (bytes) slot.LSA = 0; // loop start address (samples) diff --git a/scsp/sound_cpu.cpp b/scsp/sound_cpu__interrupt.cpp similarity index 71% rename from scsp/sound_cpu.cpp rename to scsp/sound_cpu__interrupt.cpp index 1edd683..1cdc707 100644 --- a/scsp/sound_cpu.cpp +++ b/scsp/sound_cpu__interrupt.cpp @@ -5,8 +5,8 @@ #include "../common/copy.hpp" -extern void * _binary_m68k_slot_bin_start __asm("_binary_m68k_slot_bin_start"); -extern void * _binary_m68k_slot_bin_size __asm("_binary_m68k_slot_bin_size"); +extern void * _m68k_start __asm("_binary_m68k_interrupt_bin_start"); +extern void * _m68k_size __asm("_binary_m68k_interrupt_bin_size"); void main() { @@ -23,8 +23,8 @@ void main() scsp.reg.ctrl.MIXER = MIXER__MEM4MB; - uint32_t * m68k_main_start = (uint32_t *)&_binary_m68k_slot_bin_start; - uint32_t m68k_main_size = (uint32_t)&_binary_m68k_slot_bin_size; + uint32_t * m68k_main_start = reinterpret_cast(&_m68k_start); + uint32_t m68k_main_size = reinterpret_cast(&_m68k_size); copy(&scsp.ram.u32[0], m68k_main_start, m68k_main_size); while ((smpc.reg.SF & 1) != 0); diff --git a/scsp/sound_cpu__slot.cpp b/scsp/sound_cpu__slot.cpp new file mode 100644 index 0000000..a5b6b14 --- /dev/null +++ b/scsp/sound_cpu__slot.cpp @@ -0,0 +1,43 @@ +#include + +#include "smpc.h" +#include "scsp.h" + +#include "../common/copy.hpp" + +extern void * _m68k_start __asm("_binary_m68k_slot_bin_start"); +extern void * _m68k_size __asm("_binary_m68k_slot_bin_size"); + +void main() +{ + /* SEGA SATURN TECHNICAL BULLETIN # 51 + + The document suggests that Sound RAM is (somewhat) preserved + during SNDOFF. + */ + + while ((smpc.reg.SF & 1) != 0); + smpc.reg.SF = 1; + smpc.reg.COMREG = COMREG__SNDOFF; + while (smpc.reg.oreg[31] != OREG31__SNDOFF); + + scsp.reg.ctrl.MIXER = MIXER__MEM4MB; + + uint32_t * m68k_main_start = reinterpret_cast(&_m68k_start); + uint32_t m68k_main_size = reinterpret_cast(&_m68k_size); + copy(&scsp.ram.u32[0], m68k_main_start, m68k_main_size); + + while ((smpc.reg.SF & 1) != 0); + smpc.reg.SF = 1; + smpc.reg.COMREG = COMREG__SNDON; + while (smpc.reg.oreg[31] != OREG31__SNDON); + + // do nothing while the sound CPU manipulates the SCSP +} + +extern "C" +void start(void) +{ + main(); + while (1); +}