Compare commits

..

13 Commits

16 changed files with 49 additions and 68 deletions

View File

@ -14,7 +14,8 @@ jobs:
build: build:
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest] # os: [ubuntu-latest, windows-latest, macos-latest]
os: [ubuntu-latest, windows-latest]
runs-on: ${{matrix.os}} runs-on: ${{matrix.os}}
steps: steps:
- uses: goto-bus-stop/setup-zig@v2 - uses: goto-bus-stop/setup-zig@v2
@ -39,7 +40,7 @@ jobs:
with: with:
submodules: true submodules: true
- name: build - name: build
run: zig build -Doptimize=ReleaseSafe run: zig build -Doptimize=ReleaseSafe -Dcpu=baseline
- name: upload - name: upload
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:

View File

@ -96,7 +96,7 @@ Use `git submodule update --init` from the project root to pull the git relevant
Be sure to provide SDL2 using: Be sure to provide SDL2 using:
- Linux: Your distro's package manager - Linux: Your distro's package manager
- MacOS: `brew` (install [this formula](https://formulae.brew.sh/formula/sdl2)) - macOS: ¯\\\_(ツ)_/¯ (try [this formula](https://formulae.brew.sh/formula/sdl2)?)
- Windows: [`vcpkg`](https://github.com/Microsoft/vcpkg) (install `sdl2:x64-windows`) - Windows: [`vcpkg`](https://github.com/Microsoft/vcpkg) (install `sdl2:x64-windows`)
`SDL.zig` will provide a helpful compile error if the zig compiler is unable to find SDL2. `SDL.zig` will provide a helpful compile error if the zig compiler is unable to find SDL2.

@ -1 +1 @@
Subproject commit 6d6a109a086361d300da675db8445ede74be58f6 Subproject commit acb59994fcfb83d36efef47810a9dc791c6e542e

@ -1 +1 @@
Subproject commit 272d8e2088b2cae037349fb260dc05ec46bba422 Subproject commit 861de651f3e1314973b1273ac7856e96b2625ff3

@ -1 +1 @@
Subproject commit 932d2845210644ca736faf35f5bea31eb1a15465 Subproject commit bf0ae0c27cfe92fdd9a92c8f1ac6d1939ae60c77

View File

@ -105,7 +105,7 @@ pub fn deinit(self: *Self) void {
fn fillReadTable(self: *Self, table: *[table_len]?*const anyopaque) void { fn fillReadTable(self: *Self, table: *[table_len]?*const anyopaque) void {
const vramMirror = @import("ppu/Vram.zig").mirror; const vramMirror = @import("ppu/Vram.zig").mirror;
for (table) |*ptr, i| { for (table, 0..) |*ptr, i| {
const addr = @intCast(u32, page_size * i); const addr = @intCast(u32, page_size * i);
ptr.* = switch (addr) { ptr.* = switch (addr) {
@ -132,7 +132,7 @@ fn fillWriteTable(self: *Self, comptime T: type, table: *[table_len]?*const anyo
comptime std.debug.assert(T == u32 or T == u16 or T == u8); comptime std.debug.assert(T == u32 or T == u16 or T == u8);
const vramMirror = @import("ppu/Vram.zig").mirror; const vramMirror = @import("ppu/Vram.zig").mirror;
for (table) |*ptr, i| { for (table, 0..) |*ptr, i| {
const addr = @intCast(u32, page_size * i); const addr = @intCast(u32, page_size * i);
ptr.* = switch (addr) { ptr.* = switch (addr) {

View File

@ -213,6 +213,7 @@ fn guessDevice(buf: []const u8) Gpio.Device.Kind {
// Try to Guess if ROM uses RTC // Try to Guess if ROM uses RTC
const needle = "RTC_V"; // I was told SIIRTC_V, though Pokemen Firered (USA) is a false negative const needle = "RTC_V"; // I was told SIIRTC_V, though Pokemen Firered (USA) is a false negative
// TODO: Use new for loop syntax?
var i: usize = 0; var i: usize = 0;
while ((i + needle.len) < buf.len) : (i += 1) { while ((i + needle.len) < buf.len) : (i += 1) {
if (std.mem.eql(u8, needle, buf[i..(i + needle.len)])) return .Rtc; if (std.mem.eql(u8, needle, buf[i..(i + needle.len)])) return .Rtc;

View File

@ -137,6 +137,7 @@ pub const Backup = struct {
for (backup_kinds) |needle| { for (backup_kinds) |needle| {
const needle_len = needle.str.len; const needle_len = needle.str.len;
// TODO: Use new for loop syntax?
var i: usize = 0; var i: usize = 0;
while ((i + needle_len) < rom.len) : (i += 1) { while ((i + needle_len) < rom.len) : (i += 1) {
if (std.mem.eql(u8, needle.str, rom[i..][0..needle_len])) return needle.kind; if (std.mem.eql(u8, needle.str, rom[i..][0..needle_len])) return needle.kind;

View File

@ -339,10 +339,7 @@ fn DmaController(comptime id: u2) type {
} }
pub fn onBlanking(bus: *Bus, comptime kind: DmaKind) void { pub fn onBlanking(bus: *Bus, comptime kind: DmaKind) void {
comptime var i: usize = 0; inline for (0..4) |i| bus.dma[i].poll(kind);
inline while (i < 4) : (i += 1) {
bus.dma[i].poll(kind);
}
} }
const Adjustment = enum(u2) { const Adjustment = enum(u2) {

View File

@ -293,13 +293,13 @@ pub const Clock = struct {
self.cpu.sched.push(.RealTimeClock, (1 << 24) -| late); // Reschedule self.cpu.sched.push(.RealTimeClock, (1 << 24) -| late); // Reschedule
const now = DateTime.now(); const now = DateTime.now();
self.year = bcd(u8, @intCast(u8, now.date.year - 2000)); self.year = bcd(@intCast(u8, now.date.year - 2000));
self.month = bcd(u5, now.date.month); self.month = @truncate(u5, bcd(now.date.month));
self.day = bcd(u6, now.date.day); self.day = @truncate(u6, bcd(now.date.day));
self.weekday = bcd(u3, (now.date.weekday() + 1) % 7); // API is Monday = 0, Sunday = 6. We want Sunday = 0, Saturday = 6 self.weekday = @truncate(u3, bcd((now.date.weekday() + 1) % 7)); // API is Monday = 0, Sunday = 6. We want Sunday = 0, Saturday = 6
self.hour = bcd(u6, now.time.hour); self.hour = @truncate(u6, bcd(now.time.hour));
self.minute = bcd(u7, now.time.minute); self.minute = @truncate(u7, bcd(now.time.minute));
self.second = bcd(u7, now.time.second); self.second = @truncate(u7, bcd(now.time.second));
} }
fn step(self: *Self, value: Data) u4 { fn step(self: *Self, value: Data) u4 {
@ -449,16 +449,8 @@ pub const Clock = struct {
} }
}; };
fn bcd(comptime T: type, value: u8) T { /// Converts an 8-bit unsigned integer to its BCD representation.
var input = value; /// Note: Algorithm only works for values between 0 and 99 inclusive.
var ret: u8 = 0; fn bcd(value: u8) u8 {
var shift: u3 = 0; return ((value / 10) << 4) + (value % 10);
while (input > 0) {
ret |= (input % 10) << (shift << 2);
shift += 1;
input /= 10;
}
return @truncate(T, ret);
} }

View File

@ -39,13 +39,12 @@ pub const arm = struct {
} }
fn populate() [0x1000]InstrFn { fn populate() [0x1000]InstrFn {
return comptime { comptime {
@setEvalBranchQuota(0xE000); @setEvalBranchQuota(0xE000);
var ret = [_]InstrFn{und} ** 0x1000; var table = [_]InstrFn{und} ** 0x1000;
var i: usize = 0; for (&table, 0..) |*handler, i| {
while (i < ret.len) : (i += 1) { handler.* = switch (@as(u2, i >> 10)) {
ret[i] = switch (@as(u2, i >> 10)) {
0b00 => if (i == 0x121) blk: { 0b00 => if (i == 0x121) blk: {
break :blk branchExchange; break :blk branchExchange;
} else if (i & 0xFCF == 0x009) blk: { } else if (i & 0xFCF == 0x009) blk: {
@ -107,8 +106,8 @@ pub const arm = struct {
}; };
} }
return ret; return table;
}; }
} }
}; };
@ -136,13 +135,12 @@ pub const thumb = struct {
} }
fn populate() [0x400]InstrFn { fn populate() [0x400]InstrFn {
return comptime { comptime {
@setEvalBranchQuota(5025); // This is exact @setEvalBranchQuota(5025); // This is exact
var ret = [_]InstrFn{und} ** 0x400; var table = [_]InstrFn{und} ** 0x400;
var i: usize = 0; for (&table, 0..) |*handler, i| {
while (i < ret.len) : (i += 1) { handler.* = switch (@as(u3, i >> 7 & 0x7)) {
ret[i] = switch (@as(u3, i >> 7 & 0x7)) {
0b000 => if (i >> 5 & 0x3 == 0b11) blk: { 0b000 => if (i >> 5 & 0x3 == 0b11) blk: {
const I = i >> 4 & 1 == 1; const I = i >> 4 & 1 == 1;
const is_sub = i >> 3 & 1 == 1; const is_sub = i >> 3 & 1 == 1;
@ -230,8 +228,8 @@ pub const thumb = struct {
}; };
} }
return ret; return table;
}; }
} }
}; };
@ -385,8 +383,7 @@ pub const Arm7tdmi = struct {
const now = getModeChecked(self, self.cpsr.mode.read()); const now = getModeChecked(self, self.cpsr.mode.read());
// Bank R8 -> r12 // Bank R8 -> r12
var i: usize = 0; for (0..5) |i| {
while (i < 5) : (i += 1) {
self.bank.fiq[Bank.fiqIdx(i, now)] = self.r[8 + i]; self.bank.fiq[Bank.fiqIdx(i, now)] = self.r[8 + i];
} }
@ -404,8 +401,7 @@ pub const Arm7tdmi = struct {
} }
// Grab R8 -> R12 // Grab R8 -> R12
i = 0; for (0..5) |i| {
while (i < 5) : (i += 1) {
self.r[8 + i] = self.bank.fiq[Bank.fiqIdx(i, next)]; self.r[8 + i] = self.bank.fiq[Bank.fiqIdx(i, next)];
} }
@ -470,8 +466,7 @@ pub const Arm7tdmi = struct {
} }
pub fn stepDmaTransfer(self: *Self) bool { pub fn stepDmaTransfer(self: *Self) bool {
comptime var i: usize = 0; inline for (0..4) |i| {
inline while (i < 4) : (i += 1) {
if (self.bus.dma[i].in_progress) { if (self.bus.dma[i].in_progress) {
self.bus.dma[i].step(self); self.bus.dma[i].step(self);
return true; return true;

View File

@ -92,8 +92,7 @@ pub fn fmt15(comptime L: bool, comptime rb: u3) InstrFn {
inline fn countRlist(opcode: u16) u32 { inline fn countRlist(opcode: u16) u32 {
var count: u32 = 0; var count: u32 = 0;
comptime var i: u4 = 0; inline for (0..8) |i| {
inline while (i < 8) : (i += 1) {
if (opcode >> (7 - i) & 1 == 1) count += 1; if (opcode >> (7 - i) & 1 == 1) count += 1;
} }

View File

@ -146,9 +146,8 @@ fn sleep(timer: *Timer, wake_time: u64) ?u64 {
const step = 2 * std.time.ns_per_ms; // Granularity of 2ms const step = 2 * std.time.ns_per_ms; // Granularity of 2ms
const times = sleep_for / step; const times = sleep_for / step;
var i: usize = 0;
while (i < times) : (i += 1) { for (0..times) |_| {
std.time.sleep(step); std.time.sleep(step);
// Upon wakeup, check to see if this particular sleep was longer than expected // Upon wakeup, check to see if this particular sleep was longer than expected

View File

@ -625,8 +625,7 @@ pub const Ppu = struct {
const framebuf_base = width * @as(usize, scanline); const framebuf_base = width * @as(usize, scanline);
if (obj_enable) self.fetchSprites(); if (obj_enable) self.fetchSprites();
var layer: usize = 0; for (0..4) |layer| {
while (layer < 4) : (layer += 1) {
self.drawSprites(@truncate(u2, layer)); self.drawSprites(@truncate(u2, layer));
if (layer == self.bg[0].cnt.priority.read() and bg_enable & 1 == 1) self.drawBackground(0); if (layer == self.bg[0].cnt.priority.read() and bg_enable & 1 == 1) self.drawBackground(0);
if (layer == self.bg[1].cnt.priority.read() and bg_enable >> 1 & 1 == 1) self.drawBackground(1); if (layer == self.bg[1].cnt.priority.read() and bg_enable >> 1 & 1 == 1) self.drawBackground(1);
@ -640,8 +639,7 @@ pub const Ppu = struct {
const framebuf_base = width * @as(usize, scanline); const framebuf_base = width * @as(usize, scanline);
if (obj_enable) self.fetchSprites(); if (obj_enable) self.fetchSprites();
var layer: usize = 0; for (0..4) |layer| {
while (layer < 4) : (layer += 1) {
self.drawSprites(@truncate(u2, layer)); self.drawSprites(@truncate(u2, layer));
if (layer == self.bg[0].cnt.priority.read() and bg_enable & 1 == 1) self.drawBackground(0); if (layer == self.bg[0].cnt.priority.read() and bg_enable & 1 == 1) self.drawBackground(0);
if (layer == self.bg[1].cnt.priority.read() and bg_enable >> 1 & 1 == 1) self.drawBackground(1); if (layer == self.bg[1].cnt.priority.read() and bg_enable >> 1 & 1 == 1) self.drawBackground(1);
@ -654,8 +652,7 @@ pub const Ppu = struct {
const framebuf_base = width * @as(usize, scanline); const framebuf_base = width * @as(usize, scanline);
if (obj_enable) self.fetchSprites(); if (obj_enable) self.fetchSprites();
var layer: usize = 0; for (0..4) |layer| {
while (layer < 4) : (layer += 1) {
self.drawSprites(@truncate(u2, layer)); self.drawSprites(@truncate(u2, layer));
if (layer == self.bg[2].cnt.priority.read() and bg_enable >> 2 & 1 == 1) self.drawAffineBackground(2); if (layer == self.bg[2].cnt.priority.read() and bg_enable >> 2 & 1 == 1) self.drawAffineBackground(2);
if (layer == self.bg[3].cnt.priority.read() and bg_enable >> 3 & 1 == 1) self.drawAffineBackground(3); if (layer == self.bg[3].cnt.priority.read() and bg_enable >> 3 & 1 == 1) self.drawAffineBackground(3);
@ -671,7 +668,7 @@ pub const Ppu = struct {
const vram_buf = @ptrCast([*]const u16, @alignCast(@alignOf(u16), self.vram.buf)); const vram_buf = @ptrCast([*]const u16, @alignCast(@alignOf(u16), self.vram.buf));
const framebuf = @ptrCast([*]u32, @alignCast(@alignOf(u32), self.framebuf.get(.Emulator))); const framebuf = @ptrCast([*]u32, @alignCast(@alignOf(u32), self.framebuf.get(.Emulator)));
for (vram_buf[vram_base .. vram_base + width]) |bgr555, i| { for (vram_buf[vram_base .. vram_base + width], 0..) |bgr555, i| {
framebuf[framebuf_base + i] = rgba888(bgr555); framebuf[framebuf_base + i] = rgba888(bgr555);
} }
}, },
@ -685,7 +682,7 @@ pub const Ppu = struct {
const pal_buf = @ptrCast([*]const u16, @alignCast(@alignOf(u16), self.palette.buf)); const pal_buf = @ptrCast([*]const u16, @alignCast(@alignOf(u16), self.palette.buf));
const framebuf = @ptrCast([*]u32, @alignCast(@alignOf(u32), self.framebuf.get(.Emulator))); const framebuf = @ptrCast([*]u32, @alignCast(@alignOf(u32), self.framebuf.get(.Emulator)));
for (self.vram.buf[vram_base .. vram_base + width]) |pal_id, i| { for (self.vram.buf[vram_base .. vram_base + width], 0..) |pal_id, i| {
framebuf[framebuf_base + i] = rgba888(pal_buf[pal_id]); framebuf[framebuf_base + i] = rgba888(pal_buf[pal_id]);
} }
}, },
@ -701,8 +698,7 @@ pub const Ppu = struct {
const vram_buf = @ptrCast([*]const u16, @alignCast(@alignOf(u16), self.vram.buf)); const vram_buf = @ptrCast([*]const u16, @alignCast(@alignOf(u16), self.vram.buf));
const framebuf = @ptrCast([*]u32, @alignCast(@alignOf(u32), self.framebuf.get(.Emulator))); const framebuf = @ptrCast([*]u32, @alignCast(@alignOf(u32), self.framebuf.get(.Emulator)));
var i: usize = 0; for (0..width) |i| {
while (i < width) : (i += 1) {
const bgr555 = if (scanline < m5_height and i < m5_width) vram_buf[vram_base + i] else self.palette.backdrop(); const bgr555 = if (scanline < m5_height and i < m5_width) vram_buf[vram_base + i] else self.palette.backdrop();
framebuf[framebuf_base + i] = rgba888(bgr555); framebuf[framebuf_base + i] = rgba888(bgr555);
} }
@ -718,7 +714,7 @@ pub const Ppu = struct {
// FIXME: @ptrCast between slices changing the length isn't implemented yet // FIXME: @ptrCast between slices changing the length isn't implemented yet
const framebuf = @ptrCast([*]u32, @alignCast(@alignOf(u32), self.framebuf.get(.Emulator))); const framebuf = @ptrCast([*]u32, @alignCast(@alignOf(u32), self.framebuf.get(.Emulator)));
for (self.scanline.top()) |maybe_top, i| { for (self.scanline.top(), 0..) |maybe_top, i| {
const maybe_btm = self.scanline.btm()[i]; const maybe_btm = self.scanline.btm()[i];
const bgr555 = self.getBgr555(maybe_top, maybe_btm); const bgr555 = self.getBgr555(maybe_top, maybe_btm);

View File

@ -73,7 +73,7 @@ pub const Scheduler = struct {
/// Removes the **first** scheduled event of type `needle` /// Removes the **first** scheduled event of type `needle`
pub fn removeScheduledEvent(self: *Self, needle: EventKind) void { pub fn removeScheduledEvent(self: *Self, needle: EventKind) void {
for (self.queue.items) |event, i| { for (self.queue.items, 0..) |event, i| {
if (std.meta.eql(event.kind, needle)) { if (std.meta.eql(event.kind, needle)) {
// invalidates the slice we're iterating over // invalidates the slice we're iterating over

View File

@ -133,7 +133,7 @@ pub fn main() void {
} }
} }
pub fn handleArguments(allocator: Allocator, data_path: []const u8, result: *const clap.Result(clap.Help, &params, clap.parsers.default)) !FilePaths { fn handleArguments(allocator: Allocator, data_path: []const u8, result: *const clap.Result(clap.Help, &params, clap.parsers.default)) !FilePaths {
const rom_path = romPath(result); const rom_path = romPath(result);
log.info("ROM path: {s}", .{rom_path}); log.info("ROM path: {s}", .{rom_path});