Skip to content

Commit

Permalink
Revamp the APU and implement the PSG channels 1, 2 and 4.
Browse files Browse the repository at this point in the history
Fix #61
Fix #62
Fix #63
  • Loading branch information
Arignir committed Dec 24, 2023
1 parent 1bf3016 commit 518fec6
Show file tree
Hide file tree
Showing 17 changed files with 998 additions and 174 deletions.
114 changes: 101 additions & 13 deletions include/gba/apu.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,88 @@

#include <pthread.h>

#define FIFO_CAPACITY 32
#define FIFO_CAPACITY 32

// TODO: This should be dynamically set to a least 3x the value contained in `have.samples` (see `gui/sdl/audio.c`)
#define APU_RBUFFER_CAPACITY (2048 * 3)
#define APU_RBUFFER_CAPACITY (2048 * 3)

enum fifo_idx {
FIFO_A = 0,
FIFO_B = 1,
};

struct fifo {
struct apu_fifo {
int8_t data[FIFO_CAPACITY];
size_t read_idx;
size_t write_idx;
size_t size;
};

struct wave {
struct apu_counter {
bool enabled;

uint32_t value;
};

struct apu_sweep {
uint32_t shifts;
bool direction;
uint32_t time;

uint32_t step;
uint32_t frequency;
uint32_t shadow_frequency;
};

struct apu_envelope {
uint32_t step_time;
bool direction;
int32_t initial_volume;

bool enabled;

uint32_t step;
int32_t volume;
};

struct apu_tone_and_sweep {
bool enabled;

struct apu_sweep sweep;
struct apu_counter counter;
struct apu_envelope envelope;

uint32_t step;
event_handler_t step_handler;
};

struct apu_tone {
bool enabled;

struct apu_counter counter;
struct apu_envelope envelope;

uint32_t step;
uint32_t length;
event_handler_t step_handler;
event_handler_t counter_handler;
};

struct apu_wave {
bool enabled;

uint32_t step;
event_handler_t step_handler;
struct apu_counter counter;
};

struct apu_noise {
bool enabled;

struct apu_counter counter;
struct apu_envelope envelope;

uint32_t lfsr;

event_handler_t step_handler;
};

struct apu_rbuffer {
Expand All @@ -43,23 +103,51 @@ struct apu_rbuffer {
};

struct apu {
struct fifo fifos[2];
struct wave wave;
struct apu_fifo fifos[2];
struct apu_tone_and_sweep tone_and_sweep;
struct apu_tone tone;
struct apu_wave wave;
struct apu_noise noise;

uint32_t modules_step;

struct {
int16_t fifo[2];
int16_t wave;
int16_t channel_1;
int16_t channel_2;
int16_t channel_3;
int16_t channel_4;
} latch;
};

/* gba/apu/apu.c */
void apu_reset_fifo(struct gba *gba, enum fifo_idx fifo_idx);
void apu_fifo_write8(struct gba *gba, enum fifo_idx fifo_idx, uint8_t val);
uint32_t apu_rbuffer_pop(struct apu_rbuffer *rbuffer);
void apu_on_timer_overflow(struct gba *gba, uint32_t timer_id);
void apu_sequencer(struct gba *gba, struct event_args args);
void apu_resample(struct gba *gba, struct event_args args);

/* gba/apu/fifo.c */
void apu_reset_fifo(struct gba *gba, enum fifo_idx fifo_idx);
void apu_fifo_write8(struct gba *gba, enum fifo_idx fifo_idx, uint8_t val);
void apu_fifo_timer_overflow(struct gba *gba, uint32_t timer_id);

/* gba/apu/modules.c */
void apu_modules_step(struct gba *gba, struct event_args args);
void apu_modules_sweep_reset(struct apu_sweep *sweep, uint32_t frequency, uint32_t shifts, bool direction, uint32_t time);
void apu_modules_counter_reset(struct apu_counter *counter, bool enabled, uint32_t value);
void apu_modules_envelope_reset(struct apu_envelope *envelope, uint32_t step_time, bool direction, uint32_t initial_volume);

/* gba/apu/noise.c */
void apu_noise_reset(struct gba *gba);
void apu_noise_stop(struct gba *gba);
void apu_noise_step(struct gba *gba, struct event_args args);

/* gba/apu/tone.c */
void apu_tone_and_sweep_reset(struct gba *gba);
void apu_tone_and_sweep_stop(struct gba *gba);
void apu_tone_and_sweep_step(struct gba *gba, struct event_args args);
void apu_tone_reset(struct gba *gba);
void apu_tone_stop(struct gba *gba);
void apu_tone_step(struct gba *gba, struct event_args args);

/* gba/apu/wave.c */
void apu_wave_reset(struct gba *gba);
void apu_wave_stop(struct gba *gba);
Expand Down
2 changes: 1 addition & 1 deletion include/gba/gba.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#define GBA_SCREEN_REAL_HEIGHT 228
#define GBA_CYCLES_PER_PIXEL 4
#define GBA_CYCLES_PER_FRAME (CYCLES_PER_PIXEL * GBA_SCREEN_REAL_WIDTH * GBA_SCREEN_REAL_HEIGHT)
#define GBA_CYCLES_PER_SECOND (16 * 1024 * 1024)
#define GBA_CYCLES_PER_SECOND ((uint64_t)(16 * 1024 * 1024))

#include "hades.h"
#include "gba/channel.h"
Expand Down
99 changes: 96 additions & 3 deletions include/gba/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,17 @@ enum io_regs {
/* Serial Communication (2) */
IO_REG_SIOCNT = 0x04000128,
IO_REG_RCNT = 0x04000134,
IO_REG_IR = 0x04000136,
IO_REG_UNKNOWN_1 = 0x04000142,
IO_REG_UNKNOWN_2 = 0x0400015A,

/* Interrupts */

IO_REG_IE = 0x04000200,
IO_REG_IF = 0x04000202,
IO_REG_WAITCNT = 0x04000204,
IO_REG_IME = 0x04000208,
IO_REG_UNKNOWN_3 = 0x04000302,

/* System */

Expand Down Expand Up @@ -487,6 +491,68 @@ struct io {
uint8_t bytes[2];
} bldy;

// REG_SOUND1CNT_L
union {
struct {
uint16_t sweep_shift_number: 3;
uint16_t sweep_direction: 1;
uint16_t sweep_step_time: 3;
uint16_t : 9;
} __packed;
uint16_t raw;
uint8_t bytes[2];
} sound1cnt_l;

// REG_SOUND1CNT_H
union {
struct {
uint16_t length: 6;
uint16_t duty: 2;
uint16_t eveloppe_step_time: 3;
uint16_t envelope_direction: 1;
uint16_t envelope_initial_volume: 4;
} __packed;
uint16_t raw;
uint8_t bytes[2];
} sound1cnt_h;

// REG_SOUND1CNT_X
union {
struct {
uint16_t sample_rate: 11;
uint16_t : 3;
uint16_t use_length: 1;
uint16_t reset: 1;
} __packed;
uint16_t raw;
uint8_t bytes[2];
} sound1cnt_x;

// REG_SOUND2CNT_L
union {
struct {
uint16_t length: 6;
uint16_t duty: 2;
uint16_t eveloppe_step_time: 3;
uint16_t envelope_direction: 1;
uint16_t envelope_initial_volume: 4;
} __packed;
uint16_t raw;
uint8_t bytes[2];
} sound2cnt_l;

// REG_SOUND2CNT_H
union {
struct {
uint16_t sample_rate: 11;
uint16_t : 3;
uint16_t use_length: 1;
uint16_t reset: 1;
} __packed;
uint16_t raw;
uint8_t bytes[2];
} sound2cnt_h;

// REG_SOUND3CNT_L
union {
struct {
Expand Down Expand Up @@ -524,12 +590,39 @@ struct io {
uint8_t bytes[2];
} sound3cnt_x;

// REG_SOUND4CNT_L
union {
struct {
uint16_t length: 6;
uint16_t : 2;
uint16_t eveloppe_step_time: 3;
uint16_t envelope_direction: 1;
uint16_t envelope_initial_volume: 4;
} __packed;
uint16_t raw;
uint8_t bytes[2];
} sound4cnt_l;

// REG_SOUND4CNT_H
union {
struct {
uint16_t frequency_ratio: 3;
uint16_t width: 1;
uint16_t frequency_shift: 4;
uint16_t : 6;
uint16_t use_length: 1;
uint16_t reset: 1;
} __packed;
uint16_t raw;
uint8_t bytes[2];
} sound4cnt_h;

// REG_SOUNDCNT_L
union {
struct {
uint16_t sound_right_volume: 3;
uint16_t channel_right_volume: 3;
uint16_t : 1;
uint16_t sound_left_volume: 3;
uint16_t channel_left_volume: 3;
uint16_t : 1;
uint16_t enable_sound_1_right: 1;
uint16_t enable_sound_2_right: 1;
Expand All @@ -547,7 +640,7 @@ struct io {
// REG_SOUNDCNT_H
union {
struct {
uint16_t volume_sounds: 2;
uint16_t volume_channels: 2;
uint16_t volume_fifo_a: 1;
uint16_t volume_fifo_b: 1;
uint16_t : 4;
Expand Down
5 changes: 4 additions & 1 deletion include/gba/scheduler.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@ enum sched_event_kind {
SCHED_EVENT_PPU_HBLANK,
SCHED_EVENT_TIMER_OVERFLOW,
SCHED_EVENT_TIMER_STOP,
SCHED_EVENT_APU_SEQUENCER,
SCHED_EVENT_APU_RESAMPLE,
SCHED_EVENT_APU_MODULES_STEP,
SCHED_EVENT_APU_TONE_AND_SWEEP_STEP,
SCHED_EVENT_APU_TONE_STEP,
SCHED_EVENT_APU_WAVE_STEP,
SCHED_EVENT_APU_NOISE_STEP,
SCHED_EVENT_DMA_ADD_PENDING,
};

Expand Down
12 changes: 6 additions & 6 deletions source/app/dbg/cmd/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ debugger_cmd_io_dump_reg(
bitfield = &reg->bitfield[i];
value = bitfield_get_range(val, bitfield->start, bitfield->end + 1);
printf(
"%s%3i%s | %-30s %s\n",
"%s%4i%s | %-30s %s\n",
value ? g_light_magenta : g_dark_gray,
value,
g_reset,
Expand All @@ -144,9 +144,9 @@ debugger_cmd_io(
size_t i;

printf(
"|%.12s|%.10s|%.20s|%.20s|%.8s|\n"
"| %-10s | %-8s | %-18s | %-18s | %-6s |\n"
"|%.12s|%.10s|%.20s|%.20s|%.8s|\n",
"|%.12s|%.14s|%.30s|%.20s|%.8s|\n"
"| %-10s | %-12s | %-28s | %-18s | %-6s |\n"
"|%.12s|%.14s|%.30s|%.20s|%.8s|\n",
"-------------------------------------",
"-------------------------------------",
"-------------------------------------",
Expand All @@ -171,7 +171,7 @@ debugger_cmd_io(
val = debugger_cmd_io_read_register(app, reg);

printf(
"| 0x%08x | %s%-8s%s | %-18s | ",
"| 0x%08x | %s%-12s%s | %-28s | ",
reg->address,
g_light_green,
mem_io_reg_name(reg->address),
Expand All @@ -185,7 +185,7 @@ debugger_cmd_io(
}

printf(
"|%.12s|%.10s|%.20s|%.20s|%.8s|\n",
"|%.12s|%.14s|%.30s|%.20s|%.8s|\n",
"-------------------------------------",
"-------------------------------------",
"-------------------------------------",
Expand Down
Loading

0 comments on commit 518fec6

Please sign in to comment.