Compare commits
No commits in common. "924729dcb10bf7dceda22b052f0bd9fd9be107e7" and "b81a31c2aadc9e9f63f33cfa8acc56606d2b5265" have entirely different histories.
924729dcb1
...
b81a31c2aa
|
@ -46,7 +46,7 @@ iwram: Iwram,
|
||||||
ewram: Ewram,
|
ewram: Ewram,
|
||||||
io: Io,
|
io: Io,
|
||||||
|
|
||||||
cpu: *Arm7tdmi,
|
cpu: ?*Arm7tdmi,
|
||||||
sched: *Scheduler,
|
sched: *Scheduler,
|
||||||
|
|
||||||
pub fn init(self: *Self, allocator: Allocator, sched: *Scheduler, cpu: *Arm7tdmi, paths: FilePaths) !void {
|
pub fn init(self: *Self, allocator: Allocator, sched: *Scheduler, cpu: *Arm7tdmi, paths: FilePaths) !void {
|
||||||
|
@ -82,9 +82,9 @@ pub fn dbgRead(self: *const Self, comptime T: type, address: u32) T {
|
||||||
// General Internal Memory
|
// General Internal Memory
|
||||||
0x00 => blk: {
|
0x00 => blk: {
|
||||||
if (address < Bios.size)
|
if (address < Bios.size)
|
||||||
break :blk self.bios.dbgRead(T, self.cpu.r[15], aligned_addr);
|
break :blk self.bios.dbgRead(T, self.cpu.?.r[15], aligned_addr);
|
||||||
|
|
||||||
break :blk self.openBus(T, address);
|
break :blk self.readOpenBus(T, address);
|
||||||
},
|
},
|
||||||
0x02 => self.ewram.read(T, aligned_addr),
|
0x02 => self.ewram.read(T, aligned_addr),
|
||||||
0x03 => self.iwram.read(T, aligned_addr),
|
0x03 => self.iwram.read(T, aligned_addr),
|
||||||
|
@ -109,63 +109,48 @@ pub fn dbgRead(self: *const Self, comptime T: type, address: u32) T {
|
||||||
|
|
||||||
break :blk @as(T, value) * multiplier;
|
break :blk @as(T, value) * multiplier;
|
||||||
},
|
},
|
||||||
else => self.openBus(T, address),
|
else => self.readOpenBus(T, address),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readIo(self: *const Self, comptime T: type, unaligned_address: u32) T {
|
fn readIo(self: *const Self, comptime T: type, unaligned_address: u32) T {
|
||||||
const maybe_value = io.read(self, T, forceAlign(T, unaligned_address));
|
const maybe_value = io.read(self, T, forceAlign(T, unaligned_address));
|
||||||
return if (maybe_value) |value| value else self.openBus(T, unaligned_address);
|
return if (maybe_value) |value| value else self.readOpenBus(T, unaligned_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn openBus(self: *const Self, comptime T: type, address: u32) T {
|
fn readOpenBus(self: *const Self, comptime T: type, address: u32) T {
|
||||||
const r15 = self.cpu.r[15];
|
const r15 = self.cpu.?.r[15];
|
||||||
|
|
||||||
const word = blk: {
|
const word = blk: {
|
||||||
// If Arm, get the most recently fetched instruction (PC + 8)
|
// If u32 Open Bus, read recently fetched opcode (PC + 8)
|
||||||
if (!self.cpu.cpsr.t.read()) break :blk self.cpu.pipe.stage[1].?;
|
if (!self.cpu.?.cpsr.t.read()) break :blk self.dbgRead(u32, r15 + 4);
|
||||||
|
|
||||||
const page = @truncate(u8, r15 >> 24);
|
const page = @truncate(u8, r15 >> 24);
|
||||||
|
|
||||||
// PC + 2 = stage[0]
|
|
||||||
// PC + 4 = stage[1]
|
|
||||||
// PC + 6 = Need a Debug Read for this?
|
|
||||||
|
|
||||||
switch (page) {
|
switch (page) {
|
||||||
// EWRAM, PALRAM, VRAM, and Game ROM (16-bit)
|
// EWRAM, PALRAM, VRAM, and Game ROM (16-bit)
|
||||||
0x02, 0x05, 0x06, 0x08...0x0D => {
|
0x02, 0x05, 0x06, 0x08...0x0D => {
|
||||||
const halfword: u32 = @truncate(u16, self.cpu.pipe.stage[1].?);
|
// (PC + 4)
|
||||||
break :blk halfword << 16 | halfword;
|
const halfword = self.dbgRead(u16, r15 + 2);
|
||||||
},
|
|
||||||
|
|
||||||
|
break :blk @as(u32, halfword) << 16 | halfword;
|
||||||
|
},
|
||||||
// BIOS or OAM (32-bit)
|
// BIOS or OAM (32-bit)
|
||||||
0x00, 0x07 => {
|
0x00, 0x07 => {
|
||||||
// Aligned: (PC + 6) | (PC + 4)
|
// Aligned: (PC + 6) | (PC + 4)
|
||||||
// Unaligned: (PC + 4) | (PC + 2)
|
// Unaligned: (PC + 4) | (PC + 2)
|
||||||
const aligned = address & 3 == 0b00;
|
const offset: u32 = if (address & 3 == 0b00) 2 else 0;
|
||||||
|
|
||||||
// TODO: What to do on PC + 6?
|
break :blk @as(u32, self.dbgRead(u16, r15 + 2 + offset)) << 16 | self.dbgRead(u16, r15 + offset);
|
||||||
const high: u32 = if (aligned) self.dbgRead(u16, r15 + 4) else @truncate(u16, self.cpu.pipe.stage[1].?);
|
|
||||||
const low: u32 = @truncate(u16, self.cpu.pipe.stage[@boolToInt(aligned)].?);
|
|
||||||
|
|
||||||
break :blk high << 16 | low;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// IWRAM (16-bit but special)
|
// IWRAM (16-bit but special)
|
||||||
0x03 => {
|
0x03 => {
|
||||||
// Aligned: (PC + 2) | (PC + 4)
|
// Aligned: (PC + 2) | (PC + 4)
|
||||||
// Unaligned: (PC + 4) | (PC + 2)
|
// Unaligned: (PC + 4) | (PC + 2)
|
||||||
const aligned = address & 3 == 0b00;
|
const offset: u32 = if (address & 3 == 0b00) 2 else 0;
|
||||||
|
|
||||||
const high: u32 = @truncate(u16, self.cpu.pipe.stage[1 - @boolToInt(aligned)].?);
|
break :blk @as(u32, self.dbgRead(u16, r15 + 2 - offset)) << 16 | self.dbgRead(u16, r15 + offset);
|
||||||
const low: u32 = @truncate(u16, self.cpu.pipe.stage[@boolToInt(aligned)].?);
|
|
||||||
|
|
||||||
break :blk high << 16 | low;
|
|
||||||
},
|
|
||||||
else => {
|
|
||||||
log.err("THUMB open bus read from 0x{X:0>2} page @0x{X:0>8}", .{ page, address });
|
|
||||||
@panic("invariant most-likely broken");
|
|
||||||
},
|
},
|
||||||
|
else => unreachable,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -182,9 +167,9 @@ pub fn read(self: *Self, comptime T: type, address: u32) T {
|
||||||
// General Internal Memory
|
// General Internal Memory
|
||||||
0x00 => blk: {
|
0x00 => blk: {
|
||||||
if (address < Bios.size)
|
if (address < Bios.size)
|
||||||
break :blk self.bios.read(T, self.cpu.r[15], aligned_addr);
|
break :blk self.bios.read(T, self.cpu.?.r[15], aligned_addr);
|
||||||
|
|
||||||
break :blk self.openBus(T, address);
|
break :blk self.readOpenBus(T, address);
|
||||||
},
|
},
|
||||||
0x02 => self.ewram.read(T, aligned_addr),
|
0x02 => self.ewram.read(T, aligned_addr),
|
||||||
0x03 => self.iwram.read(T, aligned_addr),
|
0x03 => self.iwram.read(T, aligned_addr),
|
||||||
|
@ -209,7 +194,7 @@ pub fn read(self: *Self, comptime T: type, address: u32) T {
|
||||||
|
|
||||||
break :blk @as(T, value) * multiplier;
|
break :blk @as(T, value) * multiplier;
|
||||||
},
|
},
|
||||||
else => self.openBus(T, address),
|
else => self.readOpenBus(T, address),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -413,12 +413,6 @@ pub const Arm7tdmi = struct {
|
||||||
self.cpsr.mode.write(@enumToInt(next));
|
self.cpsr.mode.write(@enumToInt(next));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Advances state so that the BIOS is skipped
|
|
||||||
///
|
|
||||||
/// Note: This accesses the CPU's bus ptr so it only may be called
|
|
||||||
/// once the Bus has been properly initialized
|
|
||||||
///
|
|
||||||
/// TODO: Make above notice impossible to do in code
|
|
||||||
pub fn fastBoot(self: *Self) void {
|
pub fn fastBoot(self: *Self) void {
|
||||||
self.r = std.mem.zeroes([16]u32);
|
self.r = std.mem.zeroes([16]u32);
|
||||||
|
|
||||||
|
@ -432,8 +426,6 @@ pub const Arm7tdmi = struct {
|
||||||
|
|
||||||
// self.cpsr.raw = 0x6000001F;
|
// self.cpsr.raw = 0x6000001F;
|
||||||
self.cpsr.raw = 0x0000_001F;
|
self.cpsr.raw = 0x0000_001F;
|
||||||
|
|
||||||
self.bus.bios.addr_latch = 0x0000_00DC + 8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn step(self: *Self) void {
|
pub fn step(self: *Self) void {
|
||||||
|
|
|
@ -49,12 +49,11 @@ pub fn main() anyerror!void {
|
||||||
|
|
||||||
var bus: Bus = undefined;
|
var bus: Bus = undefined;
|
||||||
var cpu = Arm7tdmi.init(&scheduler, &bus, log_file);
|
var cpu = Arm7tdmi.init(&scheduler, &bus, log_file);
|
||||||
|
if (paths.bios == null) cpu.fastBoot();
|
||||||
|
|
||||||
try bus.init(allocator, &scheduler, &cpu, paths);
|
try bus.init(allocator, &scheduler, &cpu, paths);
|
||||||
defer bus.deinit();
|
defer bus.deinit();
|
||||||
|
|
||||||
if (paths.bios == null) cpu.fastBoot();
|
|
||||||
|
|
||||||
var gui = Gui.init(&bus.pak.title, &bus.apu, width, height);
|
var gui = Gui.init(&bus.pak.title, &bus.apu, width, height);
|
||||||
defer gui.deinit();
|
defer gui.deinit();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue