Skip to content

Commit c8fd4c6

Browse files
committed
sid reg change decoding
1 parent d4a6bed commit c8fd4c6

File tree

7 files changed

+683
-95
lines changed

7 files changed

+683
-95
lines changed

build.zig

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,27 @@ pub fn build(b: *std.Build) void {
3737
exe_writebyte.root_module.addImport("zig64", mod_zig64);
3838
b.installArtifact(exe_writebyte);
3939

40+
// -- 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+
),
46+
.target = target,
47+
.optimize = optimize,
48+
});
49+
exe_sidtrace.root_module.addImport("zig64", mod_zig64);
50+
b.installArtifact(exe_sidtrace);
51+
4052
// -- Run steps for all
4153
const run_cmd_loadprg = b.addRunArtifact(exe_loadprg);
4254
const run_cmd_writebyte = b.addRunArtifact(exe_writebyte);
55+
const run_cmd_sidtrace = b.addRunArtifact(exe_sidtrace);
4356

4457
if (b.args) |args| {
4558
run_cmd_loadprg.addArgs(args);
4659
run_cmd_writebyte.addArgs(args);
60+
run_cmd_sidtrace.addArgs(args);
4761
}
4862

4963
const run_step_loadprg = b.step(
@@ -54,11 +68,18 @@ pub fn build(b: *std.Build) void {
5468
"run-writebyte",
5569
"Run the cpu-writebyte example",
5670
);
71+
const run_step_sidtrace = b.step(
72+
"run-sidtrace",
73+
"Run the sid-trace example",
74+
);
5775

5876
run_step_loadprg.dependOn(&run_cmd_loadprg.step);
5977
run_step_writebyte.dependOn(&run_cmd_writebyte.step);
78+
run_step_sidtrace.dependOn(&run_cmd_sidtrace.step);
79+
6080
run_cmd_loadprg.step.dependOn(b.getInstallStep());
6181
run_cmd_writebyte.step.dependOn(b.getInstallStep());
82+
run_cmd_sidtrace.step.dependOn(b.getInstallStep());
6283

6384
// -- Test (Cpu)
6485
const test_exe = b.addTest(.{

build.zig.zon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.{
22
.name = .zig64,
3-
.version = "0.3.0",
3+
.version = "0.4.0",
44
.fingerprint = 0xd65e0f9f7a67a1bf,
55
.minimum_zig_version = "0.14.0",
66
.dependencies = .{

src/cpu.zig

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,6 @@ cycles_executed: u32,
2020
cycles_since_vsync: u16,
2121
cycles_since_hsync: u8,
2222
cycles_last_step: u8,
23-
sid_reg_changed: bool,
24-
sid_reg_written: bool,
25-
ext_sid_reg_written: bool,
26-
ext_sid_reg_changed: bool,
2723
mem: *Ram64k,
2824
sid: *Sid,
2925
vic: *Vic,
@@ -72,10 +68,6 @@ pub fn init(mem: *Ram64k, sid: *Sid, vic: *Vic, pc_start: u16) Cpu {
7268
.cycles_executed = 0,
7369
.cycles_last_step = 0,
7470
.opcode_last = 0x00, // No opcode executed yet
75-
.sid_reg_changed = false,
76-
.sid_reg_written = false,
77-
.ext_sid_reg_written = false,
78-
.ext_sid_reg_changed = false,
7971
.cycles_since_vsync = 0,
8072
.cycles_since_hsync = 0,
8173
.mem = mem,
@@ -226,20 +218,9 @@ pub fn readWordZP(cpu: *Cpu, addr: u8) u16 {
226218

227219
pub fn writeByte(cpu: *Cpu, val: u8, addr: u16) void {
228220
const sid_base = cpu.sid.base_address;
221+
// check sid reg writes
229222
if ((addr >= sid_base) and (addr <= (sid_base + 25))) {
230-
cpu.sid_reg_written = true;
231-
cpu.ext_sid_reg_written = true;
232-
cpu.sid.registers[addr - sid_base] = val;
233-
if (cpu.sid.dbg_enabled) {
234-
std.debug.print(
235-
"[DEBUG] Write ${X:04} = {X:02}, PC={X:04}\n",
236-
.{ addr, val, cpu.pc },
237-
);
238-
}
239-
if (cpu.mem.data[addr] != val) {
240-
cpu.sid_reg_changed = true;
241-
cpu.ext_sid_reg_changed = true;
242-
}
223+
cpu.sid.writeRegisterCycle(addr - sid_base, val, cpu.cycles_executed);
243224
}
244225
cpu.mem.data[addr] = val;
245226
cpu.cycles_executed +%= 1;
@@ -252,7 +233,7 @@ pub fn writeWord(cpu: *Cpu, val: u16, addr: u16) void {
252233
}
253234

254235
pub fn sidRegWritten(cpu: *Cpu) bool {
255-
return cpu.sid_reg_written;
236+
return cpu.sid.reg_written;
256237
}
257238

258239
fn flagsToPS(cpu: *Cpu) void {
@@ -625,8 +606,9 @@ fn cmpReg(cpu: *Cpu, op: u8, reg_val: u8) void {
625606
}
626607

627608
pub fn runStep(cpu: *Cpu) u8 {
628-
cpu.sid_reg_written = false;
629-
cpu.sid_reg_changed = false;
609+
cpu.sid.reg_written = false;
610+
cpu.sid.reg_changed = false;
611+
cpu.sid.last_change = null;
630612
cpu.vic.vsync_happened = false;
631613
cpu.vic.hsync_happened = false;
632614
cpu.vic.badline_happened = false;
@@ -1430,10 +1412,6 @@ pub fn runStep(cpu: *Cpu) u8 {
14301412
cpu.vic.printStatus();
14311413
}
14321414

1433-
if (cpu.sid.dbg_enabled and cpu.sid_reg_written) {
1434-
cpu.sid.printRegisters();
1435-
}
1436-
14371415
// return from interrupt vector
14381416
if ((cpu.mem.data[0x01] & 0x07) != 0x5 and
14391417
((cpu.pc == 0xea31) or (cpu.pc == 0xea81)))
Lines changed: 52 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,69 @@
1-
// zig64 - loadPrg example
21
const std = @import("std");
32
const C64 = @import("zig64");
3+
const Sid = C64.Sid;
44
const Asm = C64.Asm;
55

66
pub fn main() !void {
7-
const gpa = std.heap.page_allocator;
7+
const allocator = std.heap.page_allocator;
88
const stdout = std.io.getStdOut().writer();
99

10-
try stdout.print("[EXE] initializing emulator\n", .{});
10+
// Initialize the C64 emulator at $0800 with PAL VIC
11+
var c64 = try C64.init(allocator, C64.Vic.Model.pal, 0x0800);
12+
defer c64.deinit(allocator);
1113

12-
var c64 = try C64.init(gpa, C64.Vic.Model.pal, 0x0800);
13-
defer c64.deinit(gpa);
14+
// 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});
1418

15-
try stdout.print("[EXE] cpu init address: {X:0>4}\n", .{
16-
c64.cpu.pc,
17-
});
18-
try stdout.print("[EXE] c64 vic type: {s}\n", .{
19-
@tagName(c64.vic.model),
20-
});
21-
try stdout.print("[EXE] c64 sid base address: {X:0>4}\n", .{
22-
c64.sid.base_address,
23-
});
24-
try stdout.print("[EXE] cpu status:\n", .{});
25-
c64.cpu.printStatus();
19+
// Write a SID register sweep program to $0800
20+
try stdout.print("\nWriting SID sweep program to $0800...\n", .{});
21+
c64.cpu.writeByte(Asm.lda_imm.opcode, 0x0800); // LDA #$0A ; Load initial value 10
22+
c64.cpu.writeByte(0x0A, 0x0801);
23+
c64.cpu.writeByte(Asm.tax.opcode, 0x0802); // TAX ; X = A (index for SID regs)
24+
c64.cpu.writeByte(Asm.adc_imm.opcode, 0x0803); // ADC #$1E ; Add 30 to A
25+
c64.cpu.writeByte(0x1E, 0x0804);
26+
c64.cpu.writeByte(Asm.sta_absx.opcode, 0x0805); // STA $D400,X ; Store A to SID reg X
27+
c64.cpu.writeByte(0x00, 0x0806);
28+
c64.cpu.writeByte(0xD4, 0x0807);
29+
c64.cpu.writeByte(Asm.inx.opcode, 0x0808); // INX ; Increment X
30+
c64.cpu.writeByte(Asm.cpx_imm.opcode, 0x0809); // CPX #$19 ; Compare X with 25
31+
c64.cpu.writeByte(0x19, 0x080A);
32+
c64.cpu.writeByte(Asm.bne.opcode, 0x080B); // BNE $0803 ; Loop back if X < 25
33+
c64.cpu.writeByte(0xF6, 0x080C); // (offset -10)
34+
c64.cpu.writeByte(Asm.rts.opcode, 0x080D); // RTS ; Return
2635

27-
try stdout.print("\n", .{});
28-
29-
// -- manually write a program into memory
30-
31-
try stdout.print("[EXE] Writing program ...\n", .{});
32-
33-
// 0800: A9 0A LDA #$0A ; 2
34-
// 0802: AA TAX ; 2
35-
// 0803: 69 1E ADC #$1E ; 2 loop start:
36-
// 0805: 9D 00 D4 STA $D400,X ; 5 write sid register X
37-
// 0808: E8 INX ; 2
38-
// 0809: E0 19 CPX #$19 ; 2
39-
// 080B: D0 F6 BNE $0803 ; 2/3 loop
40-
// 080D: 60 RTS ; 6
41-
42-
c64.cpu.writeByte(Asm.lda_imm.opcode, 0x0800); // LDA
43-
c64.cpu.writeByte(0x0a, 0x0801); // #0A ; 10
44-
c64.cpu.writeByte(Asm.tax.opcode, 0x0802); // TAX
45-
c64.cpu.writeByte(Asm.adc_imm.opcode, 0x0803); // ADC
46-
c64.cpu.writeByte(0x1e, 0x0804); // #$1E
47-
c64.cpu.writeByte(Asm.sta_absx.opcode, 0x0805); // STA $
48-
c64.cpu.writeByte(0x00, 0x0806); // 00
49-
c64.cpu.writeByte(0xd4, 0x0807); // D4
50-
c64.cpu.writeByte(Asm.inx.opcode, 0x0808); // INX
51-
c64.cpu.writeByte(Asm.cpx_imm.opcode, 0x0809); // CPX
52-
c64.cpu.writeByte(0x19, 0x080A); // #19
53-
c64.cpu.writeByte(Asm.bne.opcode, 0x080B); // BNE
54-
c64.cpu.writeByte(0xf6, 0x080C); // $0803 (-10)
55-
c64.cpu.writeByte(Asm.rts.opcode, 0x080D); // RTS
56-
c64.cpu.printStatus();
57-
58-
// manually execute single steps, print cpu status
59-
// and check sid register modifications
60-
61-
try stdout.print("[EXE] Executing program ...\n", .{});
62-
var sid_volume_old = c64.sid.getRegisters()[24];
36+
// Enable debugging for CPU and SID
6337
c64.cpu.dbg_enabled = true;
38+
c64.sid.dbg_enabled = true;
39+
40+
// Step through the program, analyzing SID changes
41+
try stdout.print("\nExecuting SID sweep step-by-step...\n", .{});
6442
while (c64.cpu.runStep() != 0) {
65-
if (c64.cpu.sidRegWritten()) {
66-
try stdout.print("[EXE] sid register written!\n", .{});
67-
c64.sid.printRegisters();
43+
if (c64.sid.last_change) |change| {
44+
try stdout.print("SID register {s} changed!\n", .{@tagName(change.meaning)});
6845

69-
const sid_registers = c64.sid.getRegisters();
70-
if (sid_volume_old != sid_registers[24]) {
71-
try stdout.print("[EXE] sid volume changed: {X:0>2}\n", .{
72-
sid_registers[24],
73-
});
74-
sid_volume_old = sid_registers[24];
46+
// Check specific changes using static Sid functions
47+
if (Sid.volumeChanged(change)) {
48+
const old_vol = Sid.FilterModeVolume.fromValue(change.old_value).volume;
49+
const new_vol = Sid.FilterModeVolume.fromValue(change.new_value).volume;
50+
try stdout.print("Volume changed: {d} => {d}\n", .{ old_vol, new_vol });
51+
}
52+
if (Sid.oscWaveformChanged(change, 1)) {
53+
const wf = Sid.WaveformControl.fromValue(change.new_value);
54+
try stdout.print("Osc1 waveform updated: Pulse={}\n", .{wf.pulse});
55+
}
56+
if (Sid.oscFreqChanged(change, 1)) {
57+
try stdout.print("Osc1 freq updated: {X:02} => {X:02}\n", .{ change.old_value, change.new_value });
58+
}
59+
if (Sid.oscAttackDecayChanged(change, 1)) {
60+
const ad = Sid.AttackDecay.fromValue(change.new_value);
61+
try stdout.print("Osc1 attack/decay: A={d}, D={d}\n", .{ ad.attack, ad.decay });
7562
}
7663
}
7764
}
78-
try stdout.print("\n\n", .{});
65+
66+
// Final SID state
67+
try stdout.print("\nFinal SID registers:\n", .{});
68+
c64.sid.printRegisters();
7969
}

0 commit comments

Comments
 (0)