diff --git a/asm/include/main_02071C3C.inc b/asm/include/main_02071CC8.inc similarity index 98% rename from asm/include/main_02071C3C.inc rename to asm/include/main_02071CC8.inc index 15e8429d..d4166821 100644 --- a/asm/include/main_02071C3C.inc +++ b/asm/include/main_02071CC8.inc @@ -30,7 +30,6 @@ .public _022B8330 .public _022B9584 .public _s32_div_f -.public _u32_div_f .public sub_0207C8B8 .public sub_0207C8E0 .public sub_0207CA04 diff --git a/asm/main_02071C3C.s b/asm/main_02071CC8.s similarity index 98% rename from asm/main_02071C3C.s rename to asm/main_02071CC8.s index f791a3f4..008c439a 100644 --- a/asm/main_02071C3C.s +++ b/asm/main_02071CC8.s @@ -1,50 +1,8 @@ .include "asm/macros.inc" - .include "main_02071C3C.inc" + .include "main_02071CC8.inc" .text - arm_func_start DseTrackEvent_SongVolumeFade -DseTrackEvent_SongVolumeFade: ; 0x02071C3C - stmdb sp!, {r4, r5, r6, lr} - mov r5, r0 - ldrb r2, [r5] - ldrb r0, [r5, #1] - mov r4, r1 - add r0, r2, r0, lsl #8 - mov r0, r0, lsl #0x10 - movs r1, r0, lsr #0x10 - moveq r6, #0 - beq _02071C84 - mov r0, #0x3e8 - mul r0, r1, r0 - ldr r1, _02071CC4 ; =DRIVER_WORK - ldrsh r1, [r1, #0x28] - bl _u32_div_f - mov r0, r0, lsl #0x10 - movs r6, r0, lsr #0x10 - moveq r6, #1 -_02071C84: - ldrb r0, [r5, #2] - cmp r6, #0 - mov r1, r0, lsl #0x10 - str r1, [r4, #0x70] - streq r1, [r4, #0x68] - beq _02071CB8 - ldr r0, [r4, #0x68] - subs r0, r1, r0 - moveq r6, #0 - beq _02071CB8 - mov r1, r6 - bl _s32_div_f - str r0, [r4, #0x6c] -_02071CB8: - strh r6, [r4, #0x74] - add r0, r5, #3 - ldmia sp!, {r4, r5, r6, pc} - .align 2, 0 -_02071CC4: .word DRIVER_WORK - arm_func_end DseTrackEvent_SongVolumeFade - arm_func_start DseTrackEvent_RestoreEnvelopeDefaults DseTrackEvent_RestoreEnvelopeDefaults: ; 0x02071CC8 stmdb sp!, {r4, lr} diff --git a/include/dse.h b/include/dse.h index d89dc633..ef0d8861 100644 --- a/include/dse.h +++ b/include/dse.h @@ -1,6 +1,9 @@ #ifndef PMDSKY_DSE_H #define PMDSKY_DSE_H +#include "file.h" +#include "thread.h" + struct dse_fade { s32 current; s32 delta; @@ -24,20 +27,20 @@ struct dse_lfo { u16 lfo_envelope_ticks_left; s32 envelope_level; s32 envelope_delta; - u8 *output_ptr; - u8 *waveform_callback; - struct dse_lfo *next; + u8* output_ptr; + u8* waveform_callback; + struct dse_lfo* next; }; struct dse_lfo_bank { s16 outputs[6]; - struct dse_lfo *lfo_list; + struct dse_lfo* lfo_list; struct dse_lfo lfos[4]; }; struct dse_sub_loop { - u8 *start; - u8 *end; + u8* start; + u8* end; u8 count; u8 octave; u8 field4_0xa; @@ -87,7 +90,7 @@ struct dse_track { u8* position; u8* loop_start; struct dse_sub_loop loop_stack[4]; - struct dse_channel *channel; + struct dse_channel* channel; u8 field_0x58; u8 field_0x59; u8 field_0x5a; @@ -202,7 +205,7 @@ struct dse_channel { struct dse_note_list* held_notes_list; struct dse_wavebank* wavebank; struct dse_instrument* instrument; - struct dse_synth *container; + struct dse_synth* container; }; struct dse_instrument_split { @@ -254,7 +257,7 @@ struct dse_synth { u8 clear_volume_and_timer; u8 field_0xA; u8 num_voices; - struct dse_synth *next; + struct dse_synth* next; struct dse_channel channels[16]; /* flexible */ }; @@ -268,7 +271,7 @@ struct dse_note_parameters { struct dse_note_list { struct dse_note_parameters parameters; s32 duration; - struct dse_note_list *next; + struct dse_note_list* next; }; struct dse_sequence_unk_0x0 { @@ -336,4 +339,126 @@ struct dse_sequence { struct dse_track tracks[16]; }; +struct dse_note { + u8 is_note_on; + u8 is_held; + u8 note_number; + s8 volume; + s32 duration; +}; + +struct dse_note_list_node { + struct dse_note note; + struct dse_note_list_node* next; +}; + +struct dse_se_bank { + void* file; + s16 field_0x4; + u16 id; + struct dse_se_bank* next; + void* seq_location; + void* mcrl_location; + void* bnkl_location; + + u8 field_0x18[4]; +}; + +struct dse_heap_allocator { + void* allocate_fun; + void* free_fun; + void* arg; +}; + +struct dse_mainbank { + u16 id; + u16 num_wavi; + u32 pcm_data_offset; + void* wavi_data; + u32 field_0xC; + u32 field_0x10; + + struct file_stream file; + + struct dse_mainbank* next; +}; + +struct dse_driver_work { + s8 initialized; + u8 stopped; + u16 unknown_0x2; + s32 error_code; + u32 error_data; + u32 error_data2; + s32 error2_code; + u32 error2_data; + u32 error2_data2; + void* error_callback; + void* error2_callback; + u32 field_0x24; + s16 microseconds_per_driver_tick; + u16 field_0x2A; + s32 total_driver_ticks; + s32 driver_tick_rate; + u32 current_rng_seed; + u8 field_0x38; + u8 field_0x39; + u8 last_se_bank_num_sequences; + u8 last_se_bank_tracks_per_sequence; + u8 field_0x3C; + s8 field_0x3D; + u16 field_0x3E; + u8 global_volumes[16]; + struct dse_note_list_node notes[128]; + struct dse_note_list_node* free_notes_list; + u32 field_0x654; + struct dse_synth* synth_list; + u32 field_0x65C; + struct dse_wavebank* loaded_wavebanks_list; + struct dse_sequence* bgm_sequences_list; + struct dse_sequence* se_sequences_list; + struct dse_se_bank* loaded_effect_banks; + u8 field_0x670[132]; + void* heap_node_list; + void* heap_end; + s32 heap_size; + struct dse_heap_allocator heap_allocator; + u8 field_0x70C[36]; + s16 num_voices; + u16 active_voices_bits; + u16 start_voices_bits; + u16 deactivate_voices_bits; + u16 deallocate_voices_bits; + u16 field_0x73C; + + struct dse_voice voices[16]; + + u16 field_0x1CFC; + u16 field_0x1CFE; + s32 num_active_voices; + s32 prev_nom_active_voices; + s32 ticks_until_num_active_voices_timeout; + u32 microseconds_per_driver_tick_2; + u32 field_1D10; + u32 field_1D14; + + struct thread driver_thread; + void* driver_stack; + + u32 field_0x1DDC; + struct dse_mainbank* loaded_mainbanks; + s32 mainbank_max_read_size; + void* mainbank_read_callback; + void* mainbank_read_callback_param; + + u8 loader_thread_priority; + u8 field_0x1DF1; + s8 quit_sample_loader; + s8 is_sample_loader_sleeping; + struct thread sample_loader_thread; + void* sample_loader_thread_stack; + struct dse_wavebank* loading_bank; + void* loading_bank_pcm_data; +}; + #endif //PMDSKY_DSE_H diff --git a/include/main_02071BF4.h b/include/main_02071BF4.h index 9db6b7b1..1d470470 100644 --- a/include/main_02071BF4.h +++ b/include/main_02071BF4.h @@ -5,5 +5,6 @@ u8* DseTrackEvent_Dummy1Byte(u8 *ptr_next_byte, struct dse_sequence *sequence, struct dse_track *track, struct dse_channel *channel); u8* DseTrackEvent_SetInstrument(u8 *ptr_next_byte, struct dse_sequence *sequence, struct dse_track *track, struct dse_channel *channel); +u8* DseTrackEvent_SongVolumeFade(u8 *ptr_next_byte, struct dse_sequence *sequence, struct dse_track *track, struct dse_channel *channel); #endif //PMDSKY_MAIN_02071BF4_H diff --git a/include/thread.h b/include/thread.h new file mode 100644 index 00000000..59ad06d1 --- /dev/null +++ b/include/thread.h @@ -0,0 +1,94 @@ +#ifndef PMDSKY_THREAD_H +#define PMDSKY_THREAD_H + +// Specifies a function called when a thread exits +typedef void (*thread_exit_fn_t)(void); + +// Contains information about a running thread +struct thread { + s32 flags; // Probably a flags field. Usually 0x1F. + struct thread* field_0x4; // r2 parameter in ThreadStart + u32 field_0x8; // Initialized to 0 + u32 field_0xC; // Initialized to 0 + u32 field_0x10; // Initialized to 0 + u32 field_0x14; // Initialized to 0 + u32 field_0x18; // Initialized to 0 + u32 field_0x1C; // Initialized to 0 + u32 field_0x20; // Initialized to 0 + u32 field_0x24; // Initialized to 0 + u32 field_0x28; // Initialized to 0 + u32 field_0x2C; // Initialized to 0 + u32 field_0x30; // Initialized to 0 + u32 field_0x34; // Initialized to 0 + // 0x38: Points to the area of the allocated stack area that can actually be used to store data. + // This is equal to stack_pointer - 0x44, with an additional - 4 if the resulting addess is not + // aligned to 8 bytes. + void* usable_stack_pointer; + // 0x3C: Address of the function to return to once the thread exits. Usually ThreadExit. + thread_exit_fn_t exit_function; + void* function_address_plus_4; // 0x40: Pointer to the function to run + 4 + void* stack_pointer_minus_4; // 0x44: Pointer to the start of the stack area - 4 + u8 field_0x48; + u8 field_0x49; + u8 field_0x4A; + u8 field_0x4B; + u8 field_0x4C; + u8 field_0x4D; + u8 field_0x4E; + u8 field_0x4F; + u8 field_0x50; + u8 field_0x51; + u8 field_0x52; + u8 field_0x53; + u8 field_0x54; + u8 field_0x55; + u8 field_0x56; + u8 field_0x57; + u8 field_0x58; + u8 field_0x59; + u8 field_0x5A; + u8 field_0x5B; + u8 field_0x5C; + u8 field_0x5D; + u8 field_0x5E; + u8 field_0x5F; + u8 field_0x60; + u8 field_0x61; + u8 field_0x62; + u8 field_0x63; + u32 field_0x64; // Initialized to 0 + // 0x68: Pointer to the next thread. This forms a linked list sorted in ascending order + // according to sorting_order + struct thread* next_thread; + // 0x6C: Seems to be a thread ID that gets incremented for each new thread created. + s32 thread_id; + s32 sorting_order; // 0x70: Unknown. Used to sort threads. + u32 field_0x74; // Initialized to 0 + u32 field_0x78; // Initialized to 0 + u32 field_0x7C; // Initialized to 0 + u32 field_0x80; // Initialized to 0 + u32 field_0x84; // Initialized to 0 + u32 field_0x88; // Initialized to 0 + u32 field_0x8C; // Initialized to 0 + void* stack_end_pointer; // 0x90: Pointer to the end of the stack area (exclusive) + void* stack_pointer; // 0x94: Pointer to the start of the stack area (inclusive) + u32 field_0x98; // Initialized to 0 + u32 field_0x9C; // Initialized to 0 + u32 field_0xA0; // Initialized to 0 + // Initialized to 0. Actually part of a separate struct alongside field_0xA8 and field_0xAC. + u32 field_0xA4; + u32 field_0xA8; // Initialized to 0 + u32 field_0xAC; // Initialized to 0 + u32 field_0xB0; // Initialized to 0 + u32 field_0xB4; // Initialized to 0 + u8 field_0xB8; + u8 field_0xB9; + u8 field_0xBA; + u8 field_0xBB; + u8 field_0xBC; + u8 field_0xBD; + u8 field_0xBE; + u8 field_0xBF; +}; + +#endif //PMDSKY_THREAD_H diff --git a/main.lsf b/main.lsf index 3afabe00..c5d5e3bc 100644 --- a/main.lsf +++ b/main.lsf @@ -80,7 +80,7 @@ Static main Object src/main_02071A98.o Object asm/main_02071AC0.o Object src/main_02071BF4.o - Object asm/main_02071C3C.o + Object asm/main_02071CC8.o Object lib/DSE/src/dc_envelope.o Object lib/DSE/src/dc_lfo.o Object lib/DSE/asm/dc_lfo_1.o diff --git a/src/main_02071BF4.c b/src/main_02071BF4.c index b1c7d79b..f27c1b40 100644 --- a/src/main_02071BF4.c +++ b/src/main_02071BF4.c @@ -1,12 +1,16 @@ #include "main_02071BF4.h" +extern struct dse_driver_work DRIVER_WORK; + +extern u32 DseChannel_SetInstrument(struct dse_channel *channel, u16 instrument_index); +extern u32 _u32_div_f(u32 dividend, u32 divisor); +extern u32 _s32_div_f(s32 dividend, s32 divisor); + u8* DseTrackEvent_Dummy1Byte(u8 *ptr_next_byte, struct dse_sequence *sequence, struct dse_track *track, struct dse_channel *channel) { return ptr_next_byte + 1; } -extern u32 DseChannel_SetInstrument(struct dse_channel *channel, u16 instrument_index); - u8* DseTrackEvent_SetInstrument(u8 *ptr_next_byte, struct dse_sequence *sequence, struct dse_track *track, struct dse_channel *channel) { s32 iVar1; @@ -17,3 +21,38 @@ u8* DseTrackEvent_SetInstrument(u8 *ptr_next_byte, struct dse_sequence *sequence } return ptr_next_byte + 1; } + +u8* DseTrackEvent_SongVolumeFade(u8 *ptr_next_byte, struct dse_sequence *sequence, struct dse_track *track, struct dse_channel *channel) +{ + s32 iVar2; + u32 uVar3; + u16 uVar4; + + uVar4 = (u32)*ptr_next_byte + (u32)ptr_next_byte[1] * 0x100 & 0xffff; + if (uVar4 == 0) { + uVar4 = 0; + } + else { + uVar4 = _u32_div_f(uVar4 * 1000,DRIVER_WORK.microseconds_per_driver_tick); + if (uVar4 == 0) { + uVar4 = 1; + } + } + iVar2 = (u32)ptr_next_byte[2] * 0x10000; + (sequence->volume).target = iVar2; + if (uVar4 == 0) { + (sequence->volume).current = iVar2; + } + else { + iVar2 = iVar2 - (sequence->volume).current; + if (iVar2 == 0) { + uVar4 = 0; + } + else { + uVar3 = _s32_div_f(iVar2,uVar4); + (sequence->volume).delta = uVar3; + } + } + (sequence->volume).ticks_remaining = (short)uVar4; + return ptr_next_byte + 3; +}