aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2022-10-20 21:59:09 +0200
committerBad Diode <bd@badd10de.dev>2022-10-20 21:59:09 +0200
commit98b84781ebe0ceafe434dbeb90dc790c00ce6cb0 (patch)
tree6318fc521e7c38e9fb7d8507a3c51b4f25569273
parentbc14ac83a5ad898aafd312e4d5f8fe8f43c60b0f (diff)
downloaduxn64-98b84781ebe0ceafe434dbeb90dc790c00ce6cb0.tar.gz
uxn64-98b84781ebe0ceafe434dbeb90dc790c00ce6cb0.zip
Add initial audio implementation
-rw-r--r--src/main.c135
1 files changed, 99 insertions, 36 deletions
diff --git a/src/main.c b/src/main.c
index 9a75498..b3187ac 100644
--- a/src/main.c
+++ b/src/main.c
@@ -33,11 +33,24 @@ OSPiHandle *rom_handle;
33// UXN. 33// UXN.
34// 34//
35 35
36#include "ppu.c"
37#include "uxn/src/uxn.c" 36#include "uxn/src/uxn.c"
37#include "uxn/src/devices/audio.c"
38#include "ppu.c"
38 39
39#include "rom.c" 40#include "rom.c"
40 41
42#define N_AUDIO_BUF 3
43#define AUDIO_RATE 44100
44#define MAX_AUDIO_LENGTH KB(4)
45#define AUDIO_BUF_SIZE (MAX_AUDIO_LENGTH * sizeof(s32))
46static s16 audio_samples[N_AUDIO_BUF] = {0, 0, 0};
47static s16 audio_buffers[N_AUDIO_BUF][AUDIO_BUF_SIZE] __attribute__((aligned(64)));
48static s32 active_audio = 0;
49static s32 frame_size = 0;
50static s32 min_frame_size = 0;
51static s32 samples_left = 0;
52static int pause_audio = 0;
53
41#define CLAMP(X, MIN, MAX) ((X) <= (MIN) ? (MIN) : (X) > (MAX) ? (MAX): (X)) 54#define CLAMP(X, MIN, MAX) ((X) <= (MIN) ? (MIN) : (X) > (MAX) ? (MAX): (X))
42 55
43static u8 uxn_ram[0x10000]; 56static u8 uxn_ram[0x10000];
@@ -45,6 +58,7 @@ static Uxn u;
45static Device *devscreen; 58static Device *devscreen;
46static Device *devctrl; 59static Device *devctrl;
47static Device *devmouse; 60static Device *devmouse;
61static Device *devaudio;
48 62
49#define MOUSE_DELTA 1 63#define MOUSE_DELTA 1
50typedef struct Mouse { 64typedef struct Mouse {
@@ -57,7 +71,7 @@ typedef struct Mouse {
57static Mouse mouse = {0}; 71static Mouse mouse = {0};
58 72
59int 73int
60uxn_halt(Uxn *u, Uint8 error, Uint16 addr) { 74uxn_halt(Uxn *u, u8 error, u16 addr) {
61 (void)u; 75 (void)u;
62 (void)error; 76 (void)error;
63 (void)addr; 77 (void)addr;
@@ -100,25 +114,25 @@ screen_palette(Device *d) {
100 114
101u8 115u8
102system_dei(Device *d, u8 port) { 116system_dei(Device *d, u8 port) {
103 switch(port) { 117 switch(port) {
104 case 0x2: return d->u->wst.ptr; 118 case 0x2: return d->u->wst.ptr;
105 case 0x3: return d->u->rst.ptr; 119 case 0x3: return d->u->rst.ptr;
106 default: return d->dat[port]; 120 default: return d->dat[port];
107 } 121 }
108} 122}
109 123
110void 124void
111system_deo(Device *d, u8 port) { 125system_deo(Device *d, u8 port) {
112 switch(port) { 126 switch(port) {
113 case 0x2: d->u->wst.ptr = d->dat[port]; break; 127 case 0x2: d->u->wst.ptr = d->dat[port]; break;
114 case 0x3: d->u->rst.ptr = d->dat[port]; break; 128 case 0x3: d->u->rst.ptr = d->dat[port]; break;
115 case 0xe: break; 129 case 0xe: break;
116 default: { 130 default: {
117 if(port > 0x7 && port < 0xe) { 131 if(port > 0x7 && port < 0xe) {
118 screen_palette(d); 132 screen_palette(d);
119 } 133 }
120 } break; 134 } break;
121 } 135 }
122} 136}
123 137
124static void 138static void
@@ -141,20 +155,6 @@ screen_dei(Device *d, u8 port) {
141void 155void
142screen_deo(Device *d, u8 port) { 156screen_deo(Device *d, u8 port) {
143 switch(port) { 157 switch(port) {
144 // case 0x3:
145 // if(!FIXED_SIZE) {
146 // Uint16 w;
147 // DEVPEEK16(w, 0x2);
148 // screen_resize(&uxn_screen, clamp(w, 1, 1024), uxn_screen.height);
149 // }
150 // break;
151 // case 0x5:
152 // if(!FIXED_SIZE) {
153 // Uint16 h;
154 // DEVPEEK16(h, 0x4);
155 // screen_resize(&uxn_screen, uxn_screen.width, clamp(h, 1, 1024));
156 // }
157 // break;
158 case 0xe: { 158 case 0xe: {
159 u16 x, y; 159 u16 x, y;
160 u8 layer = d->dat[0xe] & 0x40; 160 u8 layer = d->dat[0xe] & 0x40;
@@ -193,10 +193,30 @@ screen_deo(Device *d, u8 port) {
193 DEVPOKE16(0x8, x + dx); /* auto x+8 */ 193 DEVPOKE16(0x8, x + dx); /* auto x+8 */
194 DEVPOKE16(0xa, y + dy); /* auto y+8 */ 194 DEVPOKE16(0xa, y + dy); /* auto y+8 */
195 } break; 195 } break;
196 } 196 }
197 reqdraw = 1; 197 reqdraw = 1;
198} 198}
199 199
200static u8
201audio_dei(Device *d, u8 port) {
202 int instance = d - devaudio;
203 switch(port) {
204 case 0x4: return audio_get_vu(instance);
205 case 0x2: DEVPOKE16(0x2, audio_get_position(instance)); /* fall through */
206 default: return d->dat[port];
207 }
208}
209
210static void
211audio_deo(Device *d, u8 port) {
212 int instance = d - devaudio;
213 if(port == 0xf) {
214 // TODO: stop the audio before audio_start
215 audio_start(instance, d);
216 pause_audio = 0;
217 }
218}
219
200void 220void
201init_ctrl(void) { 221init_ctrl(void) {
202 osCreateMesgQueue(&ctrl_msg_queue, ctrl_msg, 1); 222 osCreateMesgQueue(&ctrl_msg_queue, ctrl_msg, 1);
@@ -352,10 +372,10 @@ poll_input() {
352void 372void
353init_uxn(Uxn *u) { 373init_uxn(Uxn *u) {
354 // Setup UXN memory. 374 // Setup UXN memory.
355 for (size_t i = 0; i < sizeof(uxn_ram); i++) { 375 for (size_t i = 0; i < sizeof(uxn_ram); i++) {
356 uxn_ram[i] = 0; 376 uxn_ram[i] = 0;
357 } 377 }
358 uxn_boot(u, uxn_ram); 378 uxn_boot(u, uxn_ram);
359 379
360 // Copy rom to VM. 380 // Copy rom to VM.
361 // memcpy(u->ram + PAGE_PROGRAM, uxn_rom, sizeof(uxn_rom)); 381 // memcpy(u->ram + PAGE_PROGRAM, uxn_rom, sizeof(uxn_rom));
@@ -369,10 +389,10 @@ init_uxn(Uxn *u) {
369 /* system */ uxn_port(u, 0x0, system_dei, system_deo); 389 /* system */ uxn_port(u, 0x0, system_dei, system_deo);
370 /* console */ uxn_port(u, 0x1, nil_dei, console_deo); 390 /* console */ uxn_port(u, 0x1, nil_dei, console_deo);
371 /* screen */ devscreen = uxn_port(u, 0x2, screen_dei, screen_deo); 391 /* screen */ devscreen = uxn_port(u, 0x2, screen_dei, screen_deo);
372 /* audio0 */ uxn_port(u, 0x3, nil_dei, nil_deo); 392 /* audio0 */ devaudio = uxn_port(u, 0x3, audio_dei, audio_deo);
373 /* audio1 */ uxn_port(u, 0x4, nil_dei, nil_deo); 393 /* audio1 */ uxn_port(u, 0x4, audio_dei, audio_deo);
374 /* audio2 */ uxn_port(u, 0x5, nil_dei, nil_deo); 394 /* audio2 */ uxn_port(u, 0x5, audio_dei, audio_deo);
375 /* audio3 */ uxn_port(u, 0x6, nil_dei, nil_deo); 395 /* audio3 */ uxn_port(u, 0x6, audio_dei, audio_deo);
376 /* unused */ uxn_port(u, 0x7, nil_dei, nil_deo); 396 /* unused */ uxn_port(u, 0x7, nil_dei, nil_deo);
377 /* control */ devctrl = uxn_port(u, 0x8, nil_dei, nil_deo); 397 /* control */ devctrl = uxn_port(u, 0x8, nil_dei, nil_deo);
378 /* mouse */ devmouse = uxn_port(u, 0x9, nil_dei, nil_deo); 398 /* mouse */ devmouse = uxn_port(u, 0x9, nil_dei, nil_deo);
@@ -385,22 +405,65 @@ init_uxn(Uxn *u) {
385 uxn_eval(u, PAGE_PROGRAM); 405 uxn_eval(u, PAGE_PROGRAM);
386} 406}
387 407
408void
409init_audio(void) {
410 s32 audio_rate = osAiSetFrequency(AUDIO_RATE);
411 osWritebackDCache(audio_buffers, sizeof(audio_buffers));
412}
413
414void
415handle_audio(void) {
416 if (pause_audio) {
417 return;
418 }
419
420 u32 status = osAiGetStatus();
421 if (status & AI_STATUS_FIFO_FULL > 0) {
422 return;
423 }
424
425 int running = 0;
426 s16 *samples = &audio_buffers[active_audio];
427 for (size_t i = 0; i < AUDIO_BUF_SIZE; i++) {
428 samples[i] = 0;
429 }
430 for(int channel = 0; channel < POLYPHONY; channel++) {
431 running += audio_render(channel, samples, samples + AUDIO_BUF_SIZE / 2);
432 }
433 if(!running) {
434 pause_audio = 1;
435 }
436
437 osAiSetNextBuffer(audio_buffers[active_audio], AUDIO_BUF_SIZE);
438 active_audio++;
439 if (active_audio == N_AUDIO_BUF) {
440 active_audio = 0;
441 }
442}
443
388static void 444static void
389main_proc(void *arg) { 445main_proc(void *arg) {
390 (void)arg; 446 (void)arg;
391 init_ppu(); 447 init_ppu();
448 init_audio();
392 init_ctrl(); 449 init_ctrl();
393 init_uxn(&u); 450 init_uxn(&u);
394 451
395 // Main loop. 452 // Main loop.
396 while (true) { 453 while (true) {
397 poll_input(); 454 poll_input();
455 handle_audio();
398 uxn_eval(&u, GETVECTOR(devscreen)); 456 uxn_eval(&u, GETVECTOR(devscreen));
399 blit_framebuffer(); 457 blit_framebuffer();
400 swap_buffers(); 458 swap_buffers();
401 } 459 }
402} 460}
403 461
462void
463audio_finished_handler(int instance) {
464 (void)instance;
465}
466
404static void 467static void
405idle_proc(void *arg) { 468idle_proc(void *arg) {
406 (void)arg; 469 (void)arg;