Skip to content

Commit dd56391

Browse files
authored
Merge pull request #3 from M64GitHub/m64/zig-0.15.2
update to zig 0.15.2
2 parents f3c95aa + dbf98e3 commit dd56391

File tree

13 files changed

+144
-126
lines changed

13 files changed

+144
-126
lines changed

.gitignore

Lines changed: 0 additions & 2 deletions
This file was deleted.

README.md

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# Commodore 64 MOS 6510 Emulator Core
22

33
![Tests](https://github.com/M64GitHub/zig64/actions/workflows/test.yml/badge.svg)
4-
![Version](https://img.shields.io/badge/version-0.4.0-007bff?style=flat)
4+
![Version](https://img.shields.io/badge/version-0.5.0-007bff?style=flat)
55
![Status](https://img.shields.io/badge/status-active-00cc00?style=flat)
66
![License](https://img.shields.io/badge/license-MIT-brightgreen?style=flat)
7-
![Zig](https://img.shields.io/badge/Zig-0.14.0-orange?style=flat)
7+
![Zig](https://img.shields.io/badge/Zig-0.15.2-orange?style=flat)
88

99
A **Commodore 64 MOS 6510 emulator core** implemented in **Zig**, engineered for precision, flexibility, and seamless integration into C64-focused projects. This emulator delivers cycle-accurate CPU execution, detailed raster beam emulation for PAL and NTSC video synchronization, and advanced SID register tracking with change decoding, making it an ideal foundation for C64 software analysis, dissecting SID player routines, analyzing register manipulations, and debugging.
1010

@@ -418,16 +418,7 @@ zig build test
418418
## Using zig64 In Your Project
419419
To add `zig64` as a dependency, use:
420420
```sh
421-
zig fetch --save https://github.com/M64GitHub/zig64/archive/refs/tags/v0.4.0.tar.gz
422-
```
423-
This will add the dependency to your `build.zig.zon`:
424-
```zig
425-
.dependencies = .{
426-
.zig64 = .{
427-
.url = "https://github.com/M64GitHub/zig64/archive/refs/tags/v0.4.0.tar.gz",
428-
.hash = "zig64-0.4.0-v6Fnevh-BADQQLrOWxSwFPI_uzYK_c75MpZtAyP2zosT",
429-
},
430-
},
421+
zig fetch --save https://github.com/M64GitHub/zig64/archive/refs/tags/v0.5.0.tar.gz
431422
```
432423

433424
In your `build.zig`, add the module as follows:
@@ -470,7 +461,6 @@ git clone https://github.com/M64GitHub/zig64.git
470461
cd zig64
471462
zig build
472463
```
473-
Enjoy bringing the **C64 CPU to life in Zig!**
474464

475465

476466

build.zig

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,40 +13,46 @@ pub fn build(b: *std.Build) void {
1313
const mod_flagz = dep_flagz.module("flagz");
1414

1515
// -- Example loadprg
16-
const exe_loadprg = b.addExecutable(.{
17-
.name = "loadprg-example",
18-
.root_source_file = b.path(
19-
"src/examples/loadprg_example.zig",
20-
),
16+
const exe_loadprg_mod = b.addModule("exe_loadprg", .{
17+
.root_source_file = b.path("src/examples/loadprg_example.zig"),
2118
.target = target,
2219
.optimize = optimize,
2320
});
24-
exe_loadprg.root_module.addImport("flagz", mod_flagz);
25-
exe_loadprg.root_module.addImport("zig64", mod_zig64);
21+
exe_loadprg_mod.addImport("flagz", mod_flagz);
22+
exe_loadprg_mod.addImport("zig64", mod_zig64);
23+
24+
const exe_loadprg = b.addExecutable(.{
25+
.name = "loadprg-example",
26+
.root_module = exe_loadprg_mod,
27+
});
2628
b.installArtifact(exe_loadprg);
2729

2830
// -- Example cpu-writebyte
29-
const exe_writebyte = b.addExecutable(.{
30-
.name = "writebyte-example",
31-
.root_source_file = b.path(
32-
"src/examples/cpu-writebyte_example.zig",
33-
),
31+
const exe_writebyte_mod = b.addModule("exe_writebyte", .{
32+
.root_source_file = b.path("src/examples/cpu-writebyte_example.zig"),
3433
.target = target,
3534
.optimize = optimize,
3635
});
37-
exe_writebyte.root_module.addImport("zig64", mod_zig64);
36+
exe_writebyte_mod.addImport("zig64", mod_zig64);
37+
38+
const exe_writebyte = b.addExecutable(.{
39+
.name = "writebyte-example",
40+
.root_module = exe_writebyte_mod,
41+
});
3842
b.installArtifact(exe_writebyte);
3943

4044
// -- Example sid-trace
41-
const exe_sidtrace = b.addExecutable(.{
42-
.name = "sidtrace-example",
43-
.root_source_file = b.path(
44-
"src/examples/sid_trace_example.zig",
45-
),
45+
const exe_sidtrace_mod = b.addModule("exe_sidtrace", .{
46+
.root_source_file = b.path("src/examples/sid_trace_example.zig"),
4647
.target = target,
4748
.optimize = optimize,
4849
});
49-
exe_sidtrace.root_module.addImport("zig64", mod_zig64);
50+
exe_sidtrace_mod.addImport("zig64", mod_zig64);
51+
52+
const exe_sidtrace = b.addExecutable(.{
53+
.name = "sidtrace-example",
54+
.root_module = exe_sidtrace_mod,
55+
});
5056
b.installArtifact(exe_sidtrace);
5157

5258
// -- Run steps for all
@@ -82,14 +88,16 @@ pub fn build(b: *std.Build) void {
8288
run_cmd_sidtrace.step.dependOn(b.getInstallStep());
8389

8490
// -- Test (Cpu)
85-
const test_exe = b.addTest(.{
86-
.root_source_file = b.path(
87-
"src/test/test-cpu.zig",
88-
),
91+
const test_mod = b.addModule("test", .{
92+
.root_source_file = b.path("src/test/test-cpu.zig"),
8993
.target = target,
9094
.optimize = optimize,
9195
});
92-
test_exe.root_module.addImport("zig64", mod_zig64);
96+
test_mod.addImport("zig64", mod_zig64);
97+
98+
const test_exe = b.addTest(.{
99+
.root_module = test_mod,
100+
});
93101

94102
const test_run = b.addRunArtifact(test_exe);
95103
test_run.step.dependOn(b.getInstallStep());

build.zig.zon

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
.{
22
.name = .zig64,
3-
.version = "0.4.0",
4-
.fingerprint = 0xd65e0f9f7a67a1bf,
5-
.minimum_zig_version = "0.14.0",
3+
.version = "0.5.0",
4+
.minimum_zig_version = "0.15.0",
5+
.fingerprint = 0xd65e0f9f3ad8ba3a,
66
.dependencies = .{
77
.flagz = .{
8-
.url = "https://github.com/M64GitHub/flagZ/archive/refs/tags/v1.0.0.tar.gz",
9-
.hash = "flagz-1.0.0-vdU1bCRQAQD3QOyKf6gAVpJuhTnlOoA10UmxO_XTycHm",
8+
.url = "https://github.com/M64GitHub/flagZ/archive/refs/tags/v1.1.0.tar.gz",
9+
.hash = "flagz-1.1.0-vdU1bLhJAQBcZ9qTy1SfJBLoYihjq32fjHjVLR9x_WXV",
1010
},
1111
},
1212
.paths = .{

src/asm.zig

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
const std = @import("std");
2-
const stdout = std.io.getStdOut().writer();
32

43
pub const Asm = @This();
54

@@ -104,7 +103,7 @@ pub fn disassembleForward(mem: []u8, pc_start: u16, count: usize) !void {
104103
const insn = decodeInstruction(&bytes);
105104
var obuf: [32]u8 = undefined;
106105
const str = try disassembleCodeLine(&obuf, pc, insn);
107-
stdout.print("{s}\n", .{str}) catch {};
106+
std.debug.print("{s}\n", .{str});
108107
pc = pc +% getInstructionSize(insn);
109108
}
110109
}

src/cpu.zig

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
const std = @import("std");
2-
const stdout = std.io.getStdOut().writer();
32

43
const Ram64k = @import("mem.zig");
54
const Sid = @import("sid.zig");
@@ -106,11 +105,11 @@ fn doHardReset(cpu: *Cpu) void {
106105
pub fn reset(cpu: *Cpu, hard: bool) void {
107106
if (hard) {
108107
if (cpu.dbg_enabled)
109-
stdout.print("[cpu] hard reset\n", .{}) catch {};
108+
std.debug.print("[cpu] hard reset\n", .{});
110109
cpu.doHardReset();
111110
} else {
112111
if (cpu.dbg_enabled)
113-
stdout.print("[cpu] reset\n", .{}) catch {};
112+
std.debug.print("[cpu] reset\n", .{});
114113
cpu.reset();
115114
}
116115
}
@@ -163,7 +162,7 @@ pub fn printStatus(cpu: *Cpu) void {
163162

164163
const insn_size = Asm.getInstructionSize(insn);
165164

166-
stdout.print("[cpu] PC: {X:0>4} | {s} | {s} | A: {X:0>2} | X: {X:0>2} | Y: {X:0>2} | SP: {X:0>2} | Cycl: {d:0>2} | Cycl-TT: {d} | ", .{
165+
std.debug.print("[cpu] PC: {X:0>4} | {s} | {s} | A: {X:0>2} | X: {X:0>2} | Y: {X:0>2} | SP: {X:0>2} | Cycl: {d:0>2} | Cycl-TT: {d} | ", .{
167166
cpu.pc,
168167
bytesToHex(&cpu.mem.data, cpu.pc, insn_size),
169168
padTo16(disasm, 12, &buf_disasm_pad),
@@ -173,13 +172,13 @@ pub fn printStatus(cpu: *Cpu) void {
173172
cpu.sp,
174173
cpu.cycles_last_step,
175174
cpu.cycles_executed,
176-
}) catch {};
175+
});
177176
printFlags(cpu);
178-
stdout.print("\n", .{}) catch {};
177+
std.debug.print("\n", .{});
179178
}
180179

181180
pub fn printTrace(cpu: *Cpu) void {
182-
stdout.print("PC: {X:0>4} OP: {X:0>2} {X:0>2} {X:0>2} A:{X:0>2} X:{X:0>2} Y:{X:0>2} FL:{X:0>2}", .{
181+
std.debug.print("PC: {X:0>4} OP: {X:0>2} {X:0>2} {X:0>2} A:{X:0>2} X:{X:0>2} Y:{X:0>2} FL:{X:0>2}", .{
183182
cpu.pc,
184183
cpu.mem.data[cpu.pc],
185184
cpu.mem.data[cpu.pc + 1],
@@ -188,13 +187,13 @@ pub fn printTrace(cpu: *Cpu) void {
188187
cpu.x,
189188
cpu.y,
190189
cpu.status,
191-
}) catch {};
192-
stdout.print("\n", .{}) catch {};
190+
});
191+
std.debug.print("\n", .{});
193192
}
194193

195194
pub fn printFlags(cpu: *Cpu) void {
196195
cpu.flagsToPS();
197-
stdout.print("FL: {b:0>8}", .{cpu.status}) catch {};
196+
std.debug.print("FL: {b:0>8}", .{cpu.status});
198197
}
199198

200199
pub fn readByte(cpu: *Cpu, addr: u16) u8 {
@@ -877,17 +876,17 @@ pub fn runStep(cpu: *Cpu) u8 {
877876
cpu.pc = jsr_addr;
878877
cpu.cycles_executed +%= 1; // Matches 6 cycles with fetch and push
879878
if (cpu.dbg_enabled) {
880-
stdout.print("[cpu] JSR {X:0>4}, return to {X:0>4}\n", .{
879+
std.debug.print("[cpu] JSR {X:0>4}, return to {X:0>4}\n", .{
881880
jsr_addr,
882881
ret_addr,
883-
}) catch {};
882+
});
884883
}
885884
},
886885

887886
Asm.rts.opcode => {
888887
if (cpu.sp == 0xFF) {
889888
if (cpu.dbg_enabled) {
890-
stdout.print("[cpu] RTS EXIT!\n", .{}) catch {};
889+
std.debug.print("[cpu] RTS EXIT!\n", .{});
891890
}
892891
cpu.cycles_last_step =
893892
@as(u8, @truncate(cpu.cycles_executed -% cycles_now));
@@ -898,17 +897,17 @@ pub fn runStep(cpu: *Cpu) u8 {
898897
cpu.pc = ret_addr + 1;
899898
cpu.cycles_executed +%= 2;
900899
if (cpu.dbg_enabled) {
901-
stdout.print("[cpu] RTS to {X:0>4}\n", .{
900+
std.debug.print("[cpu] RTS to {X:0>4}\n", .{
902901
ret_addr + 1,
903-
}) catch {};
902+
});
904903
}
905904
},
906905

907906
Asm.jmp_abs.opcode => {
908907
const addr: u16 = addrAbs(cpu);
909908
cpu.pc = addr;
910909
if (cpu.dbg_enabled) {
911-
stdout.print("[cpu] JMP {X:0>4}\n", .{addr}) catch {};
910+
std.debug.print("[cpu] JMP {X:0>4}\n", .{addr});
912911
}
913912
},
914913

@@ -1394,7 +1393,7 @@ pub fn runStep(cpu: *Cpu) u8 {
13941393
if ((cpu.mem.data[0x01] & 0x07) != 0x5 and
13951394
((cpu.pc == 0xea31) or (cpu.pc == 0xea81)))
13961395
{
1397-
stdout.print("[cpu] RTI\n", .{}) catch {};
1396+
std.debug.print("[cpu] RTI\n", .{});
13981397

13991398
return 0;
14001399
}

src/examples/cpu-writebyte_example.zig

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,18 @@ const Asm = C64.Asm;
55

66
pub fn main() !void {
77
const allocator = std.heap.page_allocator;
8-
const stdout = std.io.getStdOut().writer();
98

109
// Initialize the C64 emulator at $0800 with PAL VIC
1110
var c64 = try C64.init(allocator, C64.Vic.Model.pal, 0x0800);
1211
defer c64.deinit(allocator);
1312

1413
// Print initial emulator state
15-
try stdout.print("CPU start address: ${X:0>4}\n", .{c64.cpu.pc});
16-
try stdout.print("VIC model: {s}\n", .{@tagName(c64.vic.model)});
17-
try stdout.print("SID base address: ${X:0>4}\n", .{c64.sid.base_address});
14+
std.debug.print("CPU start address: ${X:0>4}\n", .{c64.cpu.pc});
15+
std.debug.print("VIC model: {s}\n", .{@tagName(c64.vic.model)});
16+
std.debug.print("SID base address: ${X:0>4}\n", .{c64.sid.base_address});
1817

1918
// Write a SID register sweep program to $0800
20-
try stdout.print("\nWriting SID sweep program to $0800...\n", .{});
19+
std.debug.print("\nWriting SID sweep program to $0800...\n", .{});
2120
c64.cpu.writeByte(Asm.lda_imm.opcode, 0x0800); // LDA #$0A ; Load initial value 10
2221
c64.cpu.writeByte(0x0A, 0x0801);
2322
c64.cpu.writeByte(Asm.tax.opcode, 0x0802); // TAX ; X = A (index for SID regs)
@@ -38,10 +37,10 @@ pub fn main() !void {
3837
c64.sid.dbg_enabled = true;
3938

4039
// Step through the program, analyzing SID changes
41-
try stdout.print("\nExecuting SID sweep step-by-step...\n", .{});
40+
std.debug.print("\nExecuting SID sweep step-by-step...\n", .{});
4241
while (c64.cpu.runStep() != 0) {
4342
if (c64.sid.last_change) |change| {
44-
try stdout.print(
43+
std.debug.print(
4544
"SID register {s} changed!\n",
4645
.{@tagName(change.meaning)},
4746
);
@@ -52,27 +51,27 @@ pub fn main() !void {
5251
Sid.FilterModeVolume.fromValue(change.old_value).volume;
5352
const new_vol =
5453
Sid.FilterModeVolume.fromValue(change.new_value).volume;
55-
try stdout.print(
54+
std.debug.print(
5655
"Volume changed: {d} => {d}\n",
5756
.{ old_vol, new_vol },
5857
);
5958
}
6059
if (change.oscWaveformChanged(1)) {
6160
const wf = Sid.WaveformControl.fromValue(change.new_value);
62-
try stdout.print(
61+
std.debug.print(
6362
"Osc1 waveform updated: Pulse={}\n",
6463
.{wf.pulse},
6564
);
6665
}
6766
if (change.oscFreqChanged(1)) {
68-
try stdout.print(
67+
std.debug.print(
6968
"Osc1 freq updated: {X:02} => {X:02}\n",
7069
.{ change.old_value, change.new_value },
7170
);
7271
}
7372
if (change.oscAttackDecayChanged(1)) {
7473
const ad = Sid.AttackDecay.fromValue(change.new_value);
75-
try stdout.print(
74+
std.debug.print(
7675
"Osc1 attack/decay: A={d}, D={d}\n",
7776
.{ ad.attack, ad.decay },
7877
);
@@ -81,6 +80,6 @@ pub fn main() !void {
8180
}
8281

8382
// Final SID state
84-
try stdout.print("\nFinal SID registers:\n", .{});
83+
std.debug.print("\nFinal SID registers:\n", .{});
8584
c64.sid.printRegisters();
8685
}

src/examples/loadprg_example.zig

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ pub fn main() !void {
1010
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
1111
defer _ = gpa.deinit();
1212
const allocator = gpa.allocator();
13-
const stdout = std.io.getStdOut().writer();
1413

1514
const Args = struct {
1615
prg: []const u8,
@@ -19,7 +18,7 @@ pub fn main() !void {
1918
const args = try flagz.parse(Args, allocator);
2019
defer flagz.deinit(args, allocator);
2120

22-
try stdout.print("[EXE] initializing emulator\n", .{});
21+
std.debug.print("[EXE] initializing emulator\n", .{});
2322
var c64 = try C64.init(allocator, C64.Vic.Model.pal, 0x0000);
2423
defer c64.deinit(allocator);
2524

@@ -30,14 +29,14 @@ pub fn main() !void {
3029
// c64.sid.dbg_enabled = true;
3130

3231
// load a .prg file from disk
33-
try stdout.print("[EXE] Loading '{s}'\n", .{args.prg});
32+
std.debug.print("[EXE] Loading '{s}'\n", .{args.prg});
3433
const load_address = try c64.loadPrg(allocator, args.prg, true);
35-
try stdout.print("[EXE] Load address: {X:0>4}\n\n", .{load_address});
34+
std.debug.print("[EXE] Load address: {X:0>4}\n\n", .{load_address});
3635

37-
try stdout.print("[EXE] Disassembling from: {X:0>4}\n", .{load_address});
36+
std.debug.print("[EXE] Disassembling from: {X:0>4}\n", .{load_address});
3837
try Asm.disassembleForward(&c64.mem.data, load_address, 31);
39-
try stdout.print("\n\n", .{});
38+
std.debug.print("\n\n", .{});
4039

41-
try stdout.print("[EXE] RUN\n", .{});
40+
std.debug.print("[EXE] RUN\n", .{});
4241
c64.run();
4342
}

0 commit comments

Comments
 (0)