|
1 |
| -// zig64 - loadPrg example |
2 | 1 | const std = @import("std");
|
3 | 2 | const C64 = @import("zig64");
|
| 3 | +const Sid = C64.Sid; |
4 | 4 | const Asm = C64.Asm;
|
5 | 5 |
|
6 | 6 | pub fn main() !void {
|
7 |
| - const gpa = std.heap.page_allocator; |
| 7 | + const allocator = std.heap.page_allocator; |
8 | 8 | const stdout = std.io.getStdOut().writer();
|
9 | 9 |
|
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); |
11 | 13 |
|
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}); |
14 | 18 |
|
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 |
26 | 35 |
|
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 |
63 | 37 | 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", .{}); |
64 | 42 | 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)}); |
68 | 45 |
|
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 }); |
75 | 62 | }
|
76 | 63 | }
|
77 | 64 | }
|
78 |
| - try stdout.print("\n\n", .{}); |
| 65 | + |
| 66 | + // Final SID state |
| 67 | + try stdout.print("\nFinal SID registers:\n", .{}); |
| 68 | + c64.sid.printRegisters(); |
79 | 69 | }
|
0 commit comments