musix 0.3.3

Music player library for esoteric audio formats (music from C64,Amiga etc)
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
#ifndef _USF_INTERNAL_H_
#define _USF_INTERNAL_H_

#include "osal/preproc.h"

#include "main/main.h"
#include "main/rom.h"

#include "ai/ai_controller.h"
#include "memory/memory.h"
#include "pi/pi_controller.h"

#include "r4300/r4300_core.h"
#include "r4300/ops.h"
#include "r4300/cp0.h"

#include "rdp/rdp_core.h"
#include "ri/ri_controller.h"
#include "rsp/rsp_core.h"
#include "si/si_controller.h"
#include "vi/vi_controller.h"

#include "rsp_hle/hle.h"

#include <stdio.h>

struct usf_state_helper
{
    size_t offset_to_structure;
};

#ifdef DEBUG_INFO
#include <stdio.h>
#endif

#ifndef RCPREG_DEFINED
#define RCPREG_DEFINED
typedef uint32_t RCPREG;
#endif

#if defined(__x86_64__)
typedef struct _jump_table
{
    unsigned int mi_addr;
    unsigned int pc_addr;
    unsigned int absolute64;
} jump_table;

typedef struct _riprelative_table
{
    unsigned int   pc_addr;     /* index in bytes from start of x86_64 code block to the displacement value to write */
    unsigned int   extra_bytes; /* number of remaining instruction bytes (immediate data) after 4-byte displacement */
    unsigned char *global_dst;  /* 64-bit pointer to the data object */
} riprelative_table;
#else
typedef struct _jump_table
{
    unsigned int mi_addr;
    unsigned int pc_addr;
} jump_table;
#endif

#ifndef INTERUPT_STRUCTS
#define INTERUPT_STRUCTS
#define POOL_CAPACITY 16

struct interrupt_event
{
    int type;
    unsigned int count;
};


struct node
{
    struct interrupt_event data;
    struct node *next;
};

struct pool
{
    struct node nodes[POOL_CAPACITY];
    struct node* stack[POOL_CAPACITY];
    size_t index;
};


struct interrupt_queue
{
    struct pool pool;
    struct node* first;
};
#endif

#ifndef TLB_STRUCTS
#define TLB_STRUCTS
typedef struct _tlb
{
    short mask;
    int vpn2;
    char g;
    unsigned char asid;
    int pfn_even;
    char c_even;
    char d_even;
    char v_even;
    int pfn_odd;
    char c_odd;
    char d_odd;
    char v_odd;
    char r;
    //int check_parity_mask;
    
    unsigned int start_even;
    unsigned int end_even;
    unsigned int phys_even;
    unsigned int start_odd;
    unsigned int end_odd;
    unsigned int phys_odd;
} tlb;
#endif

#ifndef PRECOMP_STRUCTS
#define PRECOMP_STRUCTS

#if defined(__x86_64__)
#include "r4300/x86_64/assemble_struct.h"
#else
#include "r4300/x86/assemble_struct.h"
#endif

typedef struct _precomp_instr
{
	void (osal_fastcall *ops)(usf_state_t * state);
    union
    {
        struct
        {
            long long int *rs;
            long long int *rt;
            short immediate;
        } i;
        struct
        {
            unsigned int inst_index;
        } j;
        struct
        {
            long long int *rs;
            long long int *rt;
            long long int *rd;
            unsigned char sa;
            unsigned char nrd;
        } r;
        struct
        {
            unsigned char base;
            unsigned char ft;
            short offset;
        } lf;
        struct
        {
            unsigned char ft;
            unsigned char fs;
            unsigned char fd;
        } cf;
    } f;
    unsigned int addr; /* word-aligned instruction address in r4300 address space */
    unsigned int local_addr; /* byte offset to start of corresponding x86_64 instructions, from start of code block */
    reg_cache_struct reg_cache_infos;
} precomp_instr;

typedef struct _precomp_block
{
    precomp_instr *block;
    unsigned int start;
    unsigned int end;
    unsigned char *code;
    unsigned int code_length;
    unsigned int max_code_length;
    void *jumps_table;
    int jumps_number;
    void *riprel_table;
    int riprel_number;
    //unsigned char md5[16];
    unsigned int adler32;
} precomp_block;
#endif

struct usf_state
{
    // main/main.c
    uint32_t g_rdram[RDRAM_MAX_SIZE/4];
    
    // RSP vector registers, need to be aligned to 16 bytes
    // when SSE2 or SSSE3 is enabled, or for any hope of
    // auto vectorization

    // usf_clear takes care of aligning the structure within
    // the memory block passed into it, treating the pointer
    // as usf_state_helper, and storing an offset from the
    // pointer to the actual usf_state structure. The size
    // which is indicated for allocation accounts for this
    // with two pages of padding.

    int16_t VR[32][8];
    int16_t VACC[3][8];
    
    // RSP virtual registers, also needs alignment
    int32_t SR[32];
    
    // rsp/rsp.c, not necessarily in need of alignment
    RCPREG* CR[16];
    
    // rsp/vu/cf.h, all need alignment
    int16_t ne[8]; /* $vco:  high byte "NOTEQUAL" */
    int16_t co[8]; /* $vco:  low byte "carry/borrow in/out" */
    int16_t clip[8]; /* $vcc:  high byte (clip tests:  VCL, VCH, VCR) */
    int16_t comp[8]; /* $vcc:  low byte (VEQ, VNE, VLT, VGE, VCL, VCH, VCR) */
    int16_t vce[8]; /* $vce:  vector compare extension register */
    
    // All further members of the structure need not be aligned

    // rsp/vu/divrom.h
    int32_t DivIn; /* buffered numerator of division read from vector file */
    int32_t DivOut; /* global division result set by VRCP/VRCPL/VRSQ/VRSQH */
#if (0)
    int32_t MovIn; /* We do not emulate this register (obsolete, for VMOV). */
#endif
    
    int32_t DPH;
    
    // rsp/rsp.h
    int32_t stage; // unused since EMULATE_STATIC_PC is defined by default in rsp/config.h
    int32_t temp_PC;
    int16_t MFC0_count[32];
    
    unsigned char * DMEM;
    unsigned char * IMEM;
    
    // rsp_hle
    struct hle_t hle;

    // options from file tags
    uint32_t enablecompare, enableFIFOfull;
    
    // options for decoding
    uint32_t enable_hle_audio;
    
    // trimming helper
    uint32_t enable_trimming_mode;
    void * barray_rom;
    void * barray_ram_read;
    void * barray_ram_written_first;
    
    // save state
    unsigned char * save_state;
    unsigned int save_state_size;
    
    // buffering for rendered sample data
    size_t sample_buffer_count;
    int16_t * sample_buffer;

    // audio.c
    // SampleRate is usually guaranteed to stay the same for the duration
    // of a given track, and depends on the game.
    int32_t SampleRate;
    // Audio is rendered in whole Audio Interface DMA transfers, which are
    // then copied directly to the caller's buffer. Any left over samples
    // from the last DMA transfer that fills the caller's buffer will be
    // stored here until the next call to usf_render()
    int16_t samplebuf[16384];
    size_t samples_in_buffer;
    
    void * resampler;
    int16_t samplebuf2[8192];
    size_t samples_in_buffer_2;
    
    // This buffer does not really need to be that large, as it is likely
    // to only accumulate a handlful of error messages, at which point
    // emulation is immediately halted and the messages are returned to
    // the caller.
    const char * last_error;
    char error_message[16384];
    
    uint32_t MemoryState;
    
    // main/main.c
    struct ai_controller g_ai;
    struct pi_controller g_pi;
    struct ri_controller g_ri;
    struct si_controller g_si;
    struct vi_controller g_vi;
    struct r4300_core g_r4300;
    struct rdp_core g_dp;
    struct rsp_core g_sp;
    
    // Compatibility with USF sets dictates that these all remain zero
    int g_delay_si/* = 0*/;
    int g_delay_ai/* = 0*/;
    int g_delay_pi/* = 0*/;
    int g_delay_sp/* = 0*/;
    int g_delay_dp/* = 0*/;
    
    // XXX enable this for some USF sets, safe to enable always
    int g_disable_tlb_write_exception;
    
    int g_gs_vi_counter/* = 0*/;
    
    // memory/memory.c
    unsigned int address, cpu_word;
    unsigned char cpu_byte;
    unsigned short cpu_hword;
    unsigned long long cpu_dword, *rdword;
    uint32_t EmptySpace[0x10000/4];
    
    void (osal_fastcall *readmem[0x10000])(usf_state_t *);
	void (osal_fastcall *readmemb[0x10000])(usf_state_t *);
	void (osal_fastcall *readmemh[0x10000])(usf_state_t *);
	void (osal_fastcall *readmemd[0x10000])(usf_state_t *);
	void (osal_fastcall *writemem[0x10000])(usf_state_t *);
	void (osal_fastcall *writememb[0x10000])(usf_state_t *);
	void (osal_fastcall *writememh[0x10000])(usf_state_t *);
	void (osal_fastcall *writememd[0x10000])(usf_state_t *);

    // main/rom.c
    unsigned char* g_rom/* = NULL*/;
    int g_rom_size/* = 0*/;

    m64p_rom_header   ROM_HEADER;
    rom_params        ROM_PARAMS;
    
    // r4300/pure_interp.c
    precomp_instr interp_PC;
    
    // r4300/r4300.c
    unsigned int r4300emu/* = 0*/;
    unsigned int count_per_op/* = COUNT_PER_OP_DEFAULT*/;
    int llbit, rompause;
    int stop;
    long long int reg[32], hi, lo;
    unsigned int next_interupt;
    precomp_instr *PC;
    long long int local_rs;
    unsigned int delay_slot, skip_jump/* = 0*/, dyna_interp/* = 0*/, last_addr;
    
    cpu_instruction_table current_instruction_table;
    
    // r4300/reset.c
    int reset_hard_job/* = 0*/;
    
    // r4300/cp0.c
    unsigned int g_cp0_regs[CP0_REGS_COUNT];
    
    // r4300/cp1.c
    float *reg_cop1_simple[32];
    double *reg_cop1_double[32];
    int FCR0, FCR31;
    long long int reg_cop1_fgr_64[32];
    
    int rounding_mode/* = 0x33F*/;
    // These constants won't be written to, but they need to be located within the struct
    int trunc_mode/* = 0xF3F*/, round_mode/* = 0x33F*/,
        ceil_mode/* = 0xB3F*/, floor_mode/* = 0x73F*/;
    
    // r4300/interupt.c
    int interupt_unsafe_state/* = 0*/;
    int SPECIAL_done/* = 0*/;
    
    struct interrupt_queue q;
    
    // r4300/tlb.c
    tlb tlb_e[32];
    unsigned int tlb_LUT_r[0x100000];
    unsigned int tlb_LUT_w[0x100000];
    
    // r4300/instr_counters.c
#ifdef COUNT_INSTR
    unsigned int instr_count[132];
#endif
    
    // r4300/cached_interp.c
    char invalid_code[0x100000];
    precomp_block *blocks[0x100000];
    precomp_block *actual;
    unsigned int jump_to_address;
    
    // r4300/recomp.c
    precomp_instr *dst; // destination structure for the recompiled instruction
    int code_length; // current real recompiled code length
    int max_code_length; // current recompiled code's buffer length
    unsigned char **inst_pointer; // output buffer for recompiled code
    precomp_block *dst_block; // the current block that we are recompiling
    int src; // the current recompiled instruction
    int fast_memory;
    int no_compiled_jump /* = 0*/; /* use cached interpreter instead of recompiler for jumps */
    
    void (*recomp_func)(usf_state_t *); // pointer to the dynarec's generator
    // function for the latest decoded opcode
    
    int *SRC; // currently recompiled instruction in the input stream
    int check_nop; // next instruction is nop ?
    int delay_slot_compiled/* = 0*/;
    
    int init_length;

#ifdef DYNAREC
#ifdef _MSC_VER
#define __i386__
#endif

    // r4300/(x86|x86_64)/assemble.c
    unsigned int g_jump_start8/* = 0*/;
    unsigned int g_jump_start32/* = 0*/;
    
    jump_table *jumps_table/* = NULL*/;
    int jumps_number/* = 0*/, max_jumps_number/* = 0*/;

    // r4300/x86_64/assemble.c
#if defined(__x86_64__)
    riprelative_table *riprel_table/* = NULL*/;
    int riprel_number/* = 0*/, max_riprel_number/* = 0*/;
#endif
    
    // r4300/(x86|x86_64)/gr4300.c
    precomp_instr fake_instr;
    
    int branch_taken/* = 0*/;
    
    // r4300/(x86|x86_64)/gspecial.c
    unsigned int precomp_instr_size/* = sizeof(precomp_instr)*/;
    
    // r4300/x86/rjump.c
#if defined(__i386__)
    long save_esp;
    long save_eip;
    
    unsigned long *return_address;
#endif
    
    // r4300/x86_64/rjump.c
#if defined(__x86_64__)
    unsigned long long *return_address;

    long long save_rsp/* = 0*/;
    long long save_rip/* = 0*/;
#endif

    // r4300/x86/regcache.c
#if defined(__i386__)
    unsigned int* reg_content[8];
    precomp_instr* last_access[8];
    precomp_instr* free_since[8];
    int dirty[8];
    int r64[8];
    unsigned int* r0;
#endif
    
    // r4300/x86_64/regcache.c
#if defined(__x86_64__)
    unsigned long long * reg_content[8];
    precomp_instr* last_access[8];
    precomp_instr* free_since[8];
    int dirty[8];
    int is64bits[8];
    unsigned long long *r0;
#endif

#endif
    
    // logging
#ifdef DEBUG_INFO
    FILE * debug_log;
#endif
};

void usf_set_audio_format(void *, unsigned int frequency, unsigned int bits);
void usf_push_audio_samples(void *, const void * buffer, size_t size);

#define USF_STATE_HELPER ((usf_state_helper_t *)(state))

#define USF_STATE ((usf_state_t *)(((uint8_t *)(state))+((usf_state_helper_t *)(state))->offset_to_structure))

#endif