85 lines
2.3 KiB
Zig
85 lines
2.3 KiB
Zig
const std = @import("std");
|
|
|
|
pub const screen_width: u16 = 256;
|
|
pub const screen_height: u16 = 240;
|
|
|
|
pub const Region = enum {
|
|
ntsc,
|
|
pal,
|
|
|
|
/// Native CPU clock frequency in Hz.
|
|
pub fn cpuClockRate(self: Region) u32 {
|
|
return switch (self) {
|
|
.ntsc => 1_789_773,
|
|
.pal => 1_662_607,
|
|
};
|
|
}
|
|
|
|
/// Total scanlines per frame (262 for NTSC, 312 for PAL).
|
|
pub fn totalScanlines(self: Region) u16 {
|
|
return switch (self) {
|
|
.ntsc => 262,
|
|
.pal => 312,
|
|
};
|
|
}
|
|
|
|
/// Scanline index of the pre-render scanline (261 for NTSC, 311 for PAL).
|
|
pub fn preRenderScanline(self: Region) u16 {
|
|
return switch (self) {
|
|
.ntsc => 261,
|
|
.pal => 311,
|
|
};
|
|
}
|
|
|
|
/// Number of VBlank scanlines.
|
|
pub fn vblankScanlines(self: Region) u16 {
|
|
return switch (self) {
|
|
.ntsc => 20,
|
|
.pal => 70,
|
|
};
|
|
}
|
|
|
|
/// CPU cycles to suppress PPU register writes after power/reset (~1 frame).
|
|
pub fn powerUpSuppressionCycles(self: Region) u32 {
|
|
return switch (self) {
|
|
.ntsc => 29_658,
|
|
.pal => 33_132,
|
|
};
|
|
}
|
|
};
|
|
|
|
/// Nametable mirroring mode used by PPU CIRAM and Cartridge mappers.
|
|
pub const Mirroring = enum {
|
|
horizontal,
|
|
vertical,
|
|
single_screen_lower,
|
|
single_screen_upper,
|
|
four_screen,
|
|
};
|
|
|
|
/// Standard 8-button NES controller layout.
|
|
pub const Button = enum(u8) {
|
|
a = 1 << 0,
|
|
b = 1 << 1,
|
|
select = 1 << 2,
|
|
start = 1 << 3,
|
|
up = 1 << 4,
|
|
down = 1 << 5,
|
|
left = 1 << 6,
|
|
right = 1 << 7,
|
|
};
|
|
|
|
test "region properties" {
|
|
const ntsc: Region = .ntsc;
|
|
try std.testing.expectEqual(@as(u32, 1_789_773), ntsc.cpuClockRate());
|
|
try std.testing.expectEqual(@as(u16, 262), ntsc.totalScanlines());
|
|
try std.testing.expectEqual(@as(u16, 261), ntsc.preRenderScanline());
|
|
try std.testing.expectEqual(@as(u32, 29_658), ntsc.powerUpSuppressionCycles());
|
|
|
|
const pal: Region = .pal;
|
|
try std.testing.expectEqual(@as(u32, 1_662_607), pal.cpuClockRate());
|
|
try std.testing.expectEqual(@as(u16, 312), pal.totalScanlines());
|
|
try std.testing.expectEqual(@as(u16, 311), pal.preRenderScanline());
|
|
try std.testing.expectEqual(@as(u32, 33_132), pal.powerUpSuppressionCycles());
|
|
}
|