Compare commits
2 Commits
472457b9f3
...
2bce02baaa
Author | SHA1 | Date |
---|---|---|
Rekai Nyangadzayi Musuka | 2bce02baaa | |
Rekai Nyangadzayi Musuka | bdebfc0ed7 |
|
@ -9,6 +9,9 @@ const Bit = @import("bitfield").Bit;
|
|||
const Bitfield = @import("bitfield").Bitfield;
|
||||
const Bus = @import("../Bus.zig");
|
||||
|
||||
const getHalf = util.getHalf;
|
||||
const setHalf = util.setHalf;
|
||||
|
||||
const log = std.log.scoped(.@"I/O");
|
||||
|
||||
pub const Io = struct {
|
||||
|
@ -19,6 +22,7 @@ pub const Io = struct {
|
|||
ie: InterruptEnable,
|
||||
irq: InterruptRequest,
|
||||
postflg: PostFlag,
|
||||
waitcnt: WaitControl,
|
||||
haltcnt: HaltControl,
|
||||
keyinput: KeyInput,
|
||||
|
||||
|
@ -28,6 +32,7 @@ pub const Io = struct {
|
|||
.ie = .{ .raw = 0x0000 },
|
||||
.irq = .{ .raw = 0x0000 },
|
||||
.keyinput = .{ .raw = 0x03FF },
|
||||
.waitcnt = .{ .raw = 0x0000_0000 },
|
||||
.postflg = .FirstBoot,
|
||||
.haltcnt = .Execute,
|
||||
};
|
||||
|
@ -64,8 +69,10 @@ pub fn read(bus: *const Bus, comptime T: type, address: u32) ?T {
|
|||
0x0400_0150 => util.io.read.todo(log, "Read {} from JOY_RECV", .{T}),
|
||||
|
||||
// Interrupts
|
||||
0x0400_0200 => @as(T, bus.io.irq.raw) << 16 | bus.io.ie.raw,
|
||||
0x0400_0200 => @as(u32, bus.io.irq.raw) << 16 | bus.io.ie.raw,
|
||||
0x0400_0204 => bus.io.waitcnt.raw,
|
||||
0x0400_0208 => @boolToInt(bus.io.ime),
|
||||
|
||||
else => util.io.read.undef(T, log, "Tried to perform a {} read to 0x{X:0>8}", .{ T, address }),
|
||||
},
|
||||
u16 => switch (address) {
|
||||
|
@ -93,8 +100,10 @@ pub fn read(bus: *const Bus, comptime T: type, address: u32) ?T {
|
|||
// Interrupts
|
||||
0x0400_0200 => bus.io.ie.raw,
|
||||
0x0400_0202 => bus.io.irq.raw,
|
||||
0x0400_0204 => util.io.read.todo(log, "Read {} from WAITCNT", .{T}),
|
||||
0x0400_0204 => @truncate(T, bus.io.waitcnt.raw),
|
||||
0x0400_0206 => null,
|
||||
0x0400_0208 => @boolToInt(bus.io.ime),
|
||||
0x0400_020A => null,
|
||||
else => util.io.read.undef(T, log, "Tried to perform a {} read to 0x{X:0>8}", .{ T, address }),
|
||||
},
|
||||
u8 => return switch (address) {
|
||||
|
@ -120,7 +129,13 @@ pub fn read(bus: *const Bus, comptime T: type, address: u32) ?T {
|
|||
0x0400_0135 => util.io.read.todo(log, "Read {} from RCNT_H", .{T}),
|
||||
|
||||
// Interrupts
|
||||
0x0400_0200 => @truncate(T, bus.io.ie.raw),
|
||||
0x0400_0200, 0x0400_0201 => @truncate(T, bus.io.ie.raw >> getHalf(@truncate(u8, address))),
|
||||
0x0400_0202, 0x0400_0203 => @truncate(T, bus.io.irq.raw >> getHalf(@truncate(u8, address))),
|
||||
0x0400_0204, 0x0400_0205 => @truncate(T, bus.io.waitcnt.raw >> getHalf(@truncate(u8, address))),
|
||||
0x0400_0206, 0x0400_0207 => null,
|
||||
0x0400_0208, 0x0400_0209 => @truncate(T, @as(u16, @boolToInt(bus.io.ime)) >> getHalf(@truncate(u8, address))),
|
||||
0x0400_020A, 0x0400_020B => null,
|
||||
|
||||
0x0400_0300 => @enumToInt(bus.io.postflg),
|
||||
else => util.io.read.undef(T, log, "Tried to perform a {} read to 0x{X:0>8}", .{ T, address }),
|
||||
},
|
||||
|
@ -168,9 +183,8 @@ pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void {
|
|||
|
||||
// Interrupts
|
||||
0x0400_0200 => bus.io.setIrqs(value),
|
||||
0x0400_0204 => log.debug("Wrote 0x{X:0>8} to WAITCNT", .{value}),
|
||||
0x0400_0204 => bus.io.waitcnt.raw = value,
|
||||
0x0400_0208 => bus.io.ime = value & 1 == 1,
|
||||
0x0400_020C...0x0400_021C => {}, // Unused
|
||||
else => util.io.write.undef(log, "Tried to write 0x{X:0>8}{} to 0x{X:0>8}", .{ value, T, address }),
|
||||
},
|
||||
u16 => switch (address) {
|
||||
|
@ -210,9 +224,11 @@ pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void {
|
|||
// Interrupts
|
||||
0x0400_0200 => bus.io.ie.raw = value,
|
||||
0x0400_0202 => bus.io.irq.raw &= ~value,
|
||||
0x0400_0204 => log.debug("Wrote 0x{X:0>4} to WAITCNT", .{value}),
|
||||
0x0400_0204 => bus.io.waitcnt.raw = value,
|
||||
0x0400_0206 => {},
|
||||
0x0400_0208 => bus.io.ime = value & 1 == 1,
|
||||
0x0400_0206, 0x0400_020A => {}, // Not Used
|
||||
0x0400_020A => {},
|
||||
|
||||
else => util.io.write.undef(log, "Tried to write 0x{X:0>4}{} to 0x{X:0>8}", .{ value, T, address }),
|
||||
},
|
||||
u8 => switch (address) {
|
||||
|
@ -237,8 +253,15 @@ pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void {
|
|||
0x0400_0140 => log.debug("Wrote 0x{X:0>2} to JOYCNT_L", .{value}),
|
||||
|
||||
// Interrupts
|
||||
0x0400_0200, 0x0400_0201 => bus.io.ie.raw = setHalf(u16, bus.io.ie.raw, @truncate(u8, address), value),
|
||||
0x0400_0202 => bus.io.irq.raw &= ~@as(u16, value),
|
||||
0x0400_0203 => bus.io.irq.raw &= ~@as(u16, value) << 8, // TODO: Is this good?
|
||||
0x0400_0204, 0x0400_0205 => bus.io.waitcnt.raw = setHalf(u16, @truncate(u16, bus.io.waitcnt.raw), @truncate(u8, address), value),
|
||||
0x0400_0206, 0x0400_0207 => {},
|
||||
0x0400_0208 => bus.io.ime = value & 1 == 1,
|
||||
0x0400_0209 => {},
|
||||
0x0400_020A, 0x0400_020B => {},
|
||||
|
||||
0x0400_0300 => bus.io.postflg = std.meta.intToEnum(PostFlag, value & 1) catch unreachable,
|
||||
0x0400_0301 => bus.io.haltcnt = if (value >> 7 & 1 == 0) .Halt else std.debug.panic("TODO: Implement STOP", .{}),
|
||||
|
||||
|
@ -576,3 +599,19 @@ pub const SoundBias = extern union {
|
|||
sampling_cycle: Bitfield(u16, 14, 2),
|
||||
raw: u16,
|
||||
};
|
||||
|
||||
/// Read / Write
|
||||
pub const WaitControl = extern union {
|
||||
sram_cnt: Bitfield(u32, 0, 2),
|
||||
s0_first: Bitfield(u32, 2, 2),
|
||||
s0_second: Bit(u32, 4),
|
||||
s1_first: Bitfield(u32, 5, 2),
|
||||
s1_second: Bit(u32, 7),
|
||||
s2_first: Bitfield(u32, 8, 2),
|
||||
s2_second: Bit(u32, 10),
|
||||
phi_out: Bitfield(u32, 11, 2),
|
||||
|
||||
prefetch_enable: Bit(u32, 14),
|
||||
pak_kind: Bit(u32, 15),
|
||||
raw: u32,
|
||||
};
|
||||
|
|
|
@ -105,8 +105,8 @@ pub fn runFrame(sched: *Scheduler, cpu: *Arm7tdmi) void {
|
|||
}
|
||||
|
||||
fn audioSync(audio_sync: bool, stream: *SDL.SDL_AudioStream, is_buffer_full: *bool) void {
|
||||
comptime std.debug.assert(@import("../platform.zig").sample_format == SDL.AUDIO_F32);
|
||||
const sample_size = 2 * @sizeOf(f32);
|
||||
comptime std.debug.assert(@import("../platform.zig").sample_format == SDL.AUDIO_U16);
|
||||
const sample_size = 2 * @sizeOf(u16);
|
||||
const max_buf_size: c_int = 0x400;
|
||||
|
||||
// Determine whether the APU is busy right at this moment
|
||||
|
|
|
@ -14,8 +14,8 @@ const span = @import("util.zig").span;
|
|||
const gba_width = @import("core/ppu.zig").width;
|
||||
const gba_height = @import("core/ppu.zig").height;
|
||||
|
||||
pub const sample_rate = 44100;
|
||||
pub const sample_format = SDL.AUDIO_F32;
|
||||
pub const sample_rate = 1 << 15;
|
||||
pub const sample_format = SDL.AUDIO_U16;
|
||||
|
||||
const default_title: []const u8 = "ZBA";
|
||||
|
||||
|
@ -203,8 +203,8 @@ pub const Gui = struct {
|
|||
SDL.SDLK_RETURN => io.keyinput.start.set(),
|
||||
SDL.SDLK_RSHIFT => io.keyinput.select.set(),
|
||||
SDL.SDLK_i => {
|
||||
comptime std.debug.assert(sample_format == SDL.AUDIO_F32);
|
||||
log.err("Sample Count: {}", .{@intCast(u32, SDL.SDL_AudioStreamAvailable(cpu.bus.apu.stream)) / (2 * @sizeOf(f32))});
|
||||
comptime std.debug.assert(sample_format == SDL.AUDIO_U16);
|
||||
log.err("Sample Count: {}", .{@intCast(u32, SDL.SDL_AudioStreamAvailable(cpu.bus.apu.stream)) / (2 * @sizeOf(u16))});
|
||||
},
|
||||
SDL.SDLK_j => log.err("Scheduler Capacity: {} | Scheduler Event Count: {}", .{ scheduler.queue.capacity(), scheduler.queue.count() }),
|
||||
SDL.SDLK_k => {
|
||||
|
@ -271,8 +271,8 @@ const Audio = struct {
|
|||
want.callback = Self.callback;
|
||||
want.userdata = apu;
|
||||
|
||||
std.debug.assert(sample_format == SDL.AUDIO_F32);
|
||||
log.info("Host Sample Rate: {}Hz, Host Format: SDL.AUDIO_F32", .{sample_rate});
|
||||
std.debug.assert(sample_format == SDL.AUDIO_U16);
|
||||
log.info("Host Sample Rate: {}Hz, Host Format: SDL.AUDIO_U16", .{sample_rate});
|
||||
|
||||
const device = SDL.SDL_OpenAudioDevice(null, 0, &want, &have, 0);
|
||||
if (device == 0) panic();
|
||||
|
|
Loading…
Reference in New Issue