blob: cfcd89dad2947528b1eddce71981333999e3f2a9 [file] [log] [blame]
swissChili6c61a792020-07-28 16:29:20 -07001#include "cpu.h"
2#include "instructions.h"
swissChili94ba1f52020-08-08 11:39:10 -07003#define SCREEN_ONLY_SDL
4#include "screen.h"
swissChili6c61a792020-07-28 16:29:20 -07005
6#include <endian.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10
11#define die(m, ...) \
swissChili6264a3b2020-07-30 19:02:07 -070012 printf("\033[31m" m "\033[0m\n", ##__VA_ARGS__); \
swissChili6c61a792020-07-28 16:29:20 -070013 exit(1);
14
swissChili6264a3b2020-07-30 19:02:07 -070015#define warn(m, ...) \
16 printf("\033[33m" m "\033[0m\n", ##__VA_ARGS__);
17
swissChili94ba1f52020-08-08 11:39:10 -070018
19sdl_screen_t *g_scr = NULL;
20
21
swissChilidbbd5402020-08-07 15:07:39 -070022void reset(cpu_t *cpu)
23{
24 cpu->regs[SP] = 0xFD; // stack at is 0x100 + SP
swissChilibb478f12020-08-07 20:45:07 -070025 cpu->pc = 0x600; // arbitrary program counter start
swissChilidbbd5402020-08-07 15:07:39 -070026 cpu->running = true;
27}
28
swissChili6c61a792020-07-28 16:29:20 -070029cpu_t new_cpu()
30{
31 cpu_t cpu = { 0 };
swissChili6c61a792020-07-28 16:29:20 -070032 cpu.regs[SP] = 0xFD; // stack at is 0x100 + SP
swissChilibb478f12020-08-07 20:45:07 -070033 cpu.pc = 0x600; // arbitrary program counter start
swissChili6264a3b2020-07-30 19:02:07 -070034 cpu.running = true;
swissChili6c61a792020-07-28 16:29:20 -070035 cpu.mem = malloc(0xFFFF);
36 memset(cpu.mem, 0, 0xFFFF);
37
38 if (!cpu.mem)
39 {
40 die("Could not allocate memory for CPU");
41 }
42
43 return cpu;
44}
45
swissChilida4803e2020-08-06 20:06:04 -070046uint16_t le_to_native(uint8_t a, uint8_t b)
47{
48#ifdef LITTLE_ENDIAN
49 return b << 8 | a;
50#else
51 return a << 8 | b;
52#endif
53}
54
55void native_to_le(uint16_t n, uint8_t *a, uint8_t *b)
56{
57#ifdef LITTLE_ENDIAN
58 *a = n >> 8;
59 *b = n & 0xFF;
60#else
61 *a = n & 0xFF;
62 *b = n >> 8;
63#endif
64}
65
swissChili6264a3b2020-07-30 19:02:07 -070066void stack_push(cpu_t *cpu, uint8_t v)
67{
68 cpu->mem[cpu->regs[SP]-- + 0x100] = v;
69}
70
swissChilida4803e2020-08-06 20:06:04 -070071void stack_pushle(cpu_t *cpu, uint16_t v)
72{
73 uint8_t a, b;
74 native_to_le(v, &a, &b);
75 // push in "reverse" order so that the address is stored as LE
76 stack_push(cpu, b);
77 stack_push(cpu, a);
78}
79
swissChili6264a3b2020-07-30 19:02:07 -070080uint8_t stack_pop(cpu_t *cpu)
81{
82 return cpu->mem[cpu->regs[SP]++ + 0x100];
83}
84
swissChilida4803e2020-08-06 20:06:04 -070085uint16_t stack_pople(cpu_t *cpu)
86{
87 uint8_t a = stack_pop(cpu);
88 uint8_t b = stack_pop(cpu);
89 return le_to_native(a, b);
90}
91
swissChili6c61a792020-07-28 16:29:20 -070092void free_cpu(cpu_t *cpu)
93{
94 free(cpu->mem);
95}
96
swissChilida4803e2020-08-06 20:06:04 -070097// rotate right
swissChili94ba1f52020-08-08 11:39:10 -070098inline uint8_t ror(uint8_t a, uint8_t n)
swissChilida4803e2020-08-06 20:06:04 -070099{
100 return (a >> n) | (a << (8 - n));
101}
102
103// rotate left
swissChili94ba1f52020-08-08 11:39:10 -0700104inline uint8_t rol(uint8_t a, uint8_t n)
swissChilida4803e2020-08-06 20:06:04 -0700105{
106 return (a << n) | (a >> (8 - n));
107}
108
swissChili94ba1f52020-08-08 11:39:10 -0700109inline void stat_nz(cpu_t *cpu, int8_t v)
swissChili6c61a792020-07-28 16:29:20 -0700110{
swissChili6264a3b2020-07-30 19:02:07 -0700111 cpu->status.negative = v < 0;
112 cpu->status.zero = v == 0;
113}
114
115// Used to check for overflow, is c unique?
swissChili94ba1f52020-08-08 11:39:10 -0700116inline bool last_unique(bool a, bool b, bool c)
swissChili6264a3b2020-07-30 19:02:07 -0700117{
118 return a == b && a != c;
119}
120
swissChili94ba1f52020-08-08 11:39:10 -0700121inline void stat_cv(cpu_t *cpu, uint8_t a, uint8_t b, uint8_t c)
swissChili6264a3b2020-07-30 19:02:07 -0700122{
123 cpu->status.overflow = last_unique(a >> 7, b >> 7, c >> 7);
124 cpu->status.carry = c < a || c < b;
125}
126
swissChili94ba1f52020-08-08 11:39:10 -0700127inline void cmp(cpu_t *cpu, uint8_t reg, uint8_t mem)
swissChilida4803e2020-08-06 20:06:04 -0700128{
129 cpu->status.negative = 0;
130 cpu->status.zero = 0;
131 cpu->status.carry = 0;
132 if (cpu->regs[reg] < mem)
133 {
134 cpu->status.negative = 1;
135 }
136 else if (cpu->regs[reg] == mem)
137 {
138 cpu->status.zero = 1;
139 cpu->status.carry = 1;
140 }
141 else
142 {
143 cpu->status.carry = 1;
144 }
145}
146
147void execute(cpu_t *cpu, const char *mnemonic, uint8_t op, arg_t a, uint8_t am)
swissChili6264a3b2020-07-30 19:02:07 -0700148{
149 // used to save space
150 #define REGS \
151 R(X) R(A) R(Y)
152
swissChili710d18d2020-07-29 19:43:20 -0700153 switch (op) {
swissChili6264a3b2020-07-30 19:02:07 -0700154 // Load and store instructions:
155 #define R(reg) \
156 case LD##reg: \
157 cpu->regs[reg] = a.val; \
158 stat_nz(cpu, a.val); \
159 break;
160
161 REGS
162
163 #undef R
164
165 #define R(reg) \
166 case ST##reg: \
167 cpu->mem[a.ptr] = cpu->regs[reg]; \
168 break; \
169
170 REGS
171
172 #undef R
173
174 // Arithmetic instructions:
175 // NOTE: binary coded decimals are NOT SUPPORTED because I don't want
176 // to implement them.
177 case ADC:
178 {
179 uint8_t sum = cpu->regs[A] + a.val + cpu->status.carry;
180 // signed overflow
181 stat_cv(cpu, cpu->regs[A], a.val + cpu->status.carry, sum);
182 stat_nz(cpu, sum);
183 cpu->regs[A] = sum;
184 break;
185 }
186
187 case SBC:
188 {
189 uint8_t diff = cpu->regs[A] - a.val - !cpu->status.carry;
190 stat_cv(cpu, cpu->regs[A], a.val - !cpu->status.carry, diff);
191 stat_nz(cpu, diff);
192 cpu->regs[A] = diff;
193 break;
194 }
195
196 case INC:
197 cpu->mem[a.ptr]++;
198 stat_nz(cpu, cpu->mem[a.ptr]);
199 break;
200
201 case INX:
202 cpu->regs[X]++;
203 stat_nz(cpu, cpu->regs[X]);
204 break;
205
206 case INY:
207 cpu->regs[Y]++;
208 stat_nz(cpu, cpu->regs[Y]);
209 break;
210
211 case DEC:
212 cpu->mem[a.ptr]--;
213 stat_nz(cpu, cpu->mem[a.ptr]);
214 break;
swissChilida4803e2020-08-06 20:06:04 -0700215
216 case DEX:
217 cpu->regs[X]--;
218 stat_nz(cpu, cpu->regs[X]);
219 break;
220
221 case DEY:
222 cpu->regs[Y]--;
223 stat_nz(cpu, cpu->regs[Y]);
224 break;
225
226 case ASL:
227 // This check must be done here unfortunately, it would be nice
228 // to do this while decoding operands but it would require
229 // a substantial change to the architecture of the emulator
230 if (am == AM_ACC)
231 {
232 cpu->status.carry = cpu->regs[A] >> 7;
233 cpu->regs[A] <<= 1;
234 stat_nz(cpu, cpu->regs[A]);
235 }
236 else
237 {
238 cpu->status.carry = cpu->mem[a.val] >> 7;
239 cpu->mem[a.ptr] <<= 1;
240 stat_nz(cpu, cpu->mem[a.ptr]);
241 }
242 break;
243
244 case LSR:
245 if (am == AM_ACC)
246 {
247 cpu->status.carry = cpu->regs[A] & 1;
248 cpu->regs[A] >>= 1;
249 stat_nz(cpu, cpu->regs[A]);
250 }
251 else
252 {
253 cpu->status.carry = cpu->mem[a.val] & 7;
254 cpu->mem[a.ptr] >>= 1;
255 stat_nz(cpu, cpu->mem[a.ptr]);
256 }
257 break;
258
259 case ROL:
260 if (am == AM_ACC)
261 {
262 cpu->status.carry = cpu->regs[A] >> 7;
263 cpu->regs[A] = rol(cpu->regs[A], 1);
264 stat_nz(cpu, cpu->regs[A]);
265 }
266 else
267 {
268 cpu->status.carry = cpu->mem[a.val] >> 7;
269 cpu->mem[a.ptr] = rol(a.val, 1);
270 stat_nz(cpu, cpu->mem[a.ptr]);
271 }
272 break;
273
274 case ROR:
275 if (am == AM_ACC)
276 {
277 cpu->status.carry = cpu->regs[A] & 1;
278 cpu->regs[A] = ror(cpu->regs[A], 1);
279 stat_nz(cpu, cpu->regs[A]);
280 }
281 else
282 {
283 cpu->status.carry = cpu->mem[a.val] & 1;
284 cpu->mem[a.ptr] = ror(a.val, 1);
285 stat_nz(cpu, cpu->mem[a.ptr]);
286 }
287 break;
288
289 case AND:
290 cpu->regs[A] &= a.val;
291 stat_nz(cpu, cpu->regs[A]);
292 break;
293
294 case ORA:
295 cpu->regs[A] |= a.val;
296 stat_nz(cpu, cpu->regs[A]);
297 break;
298
299 case EOR:
300 cpu->regs[A] ^= a.val;
301 stat_nz(cpu, cpu->regs[A]);
302 break;
303
304 case CMP:
305 cmp(cpu, A, a.val);
306 break;
307
308 case CPX:
309 cmp(cpu, X, a.val);
310 break;
311
312 case CPY:
313 cmp(cpu, Y, a.val);
314 break;
315
316 // TODO: implement BIT here
317
318 #define BRANCHES \
319 B(BCC, carry == 0) \
320 B(BCS, carry == 1) \
321 B(BNE, zero == 0) \
322 B(BEQ, zero == 1) \
323 B(BPL, negative == 0) \
324 B(BMI, negative == 1) \
325 B(BVC, overflow == 0) \
326 B(BVS, overflow == 1)
327
328 #define B(i, c) \
329 case i: \
330 if (cpu->status . c) \
331 cpu->pc = a.ptr;\
332 break;
333
334 BRANCHES
335
336 #undef B
337 #undef BRANCHES
338
339 #define TRANSFERS \
340 T(A, X) \
341 T(X, A) \
342 T(A, Y) \
343 T(Y, A)
344
345 #define T(a, b) \
346 case T ## a ## b: \
347 cpu->regs[b] = cpu->regs[a]; \
348 stat_nz(cpu, cpu->regs[b]); \
349 break;
350
351 TRANSFERS
352
353 #undef T
354 #undef TRANSFERS
355
356 case TSX:
357 cpu->regs[X] = cpu->regs[SP];
358 stat_nz(cpu, cpu->regs[X]);
359 break;
360
361 case TXS:
362 cpu->regs[SP] = cpu->regs[X];
363 stat_nz(cpu, cpu->regs[X]);
364 break;
365
366 case PHA:
367 stack_push(cpu, cpu->regs[A]);
368 break;
369
370 case PLA:
371 cpu->regs[A] = stack_pop(cpu);
372 stat_nz(cpu, cpu->regs[A]);
373 break;
374
375 case PHP:
376 stack_push(cpu, *(uint8_t *)(&cpu->status));
377 break;
378
379 case PLP:
380 {
381 uint8_t s = stack_pop(cpu);
382 *(uint8_t *)(&cpu->status) = s;
383 }
384
385 case JMP:
386 cpu->pc = a.ptr;
387 break;
388
389 case JSR:
390 stack_pushle(cpu, cpu->pc);
391 break;
392
393 case RTS:
394 cpu->pc = stack_pople(cpu);
395 break;
396
397 // TODO: implement RTI
398 // TODO: implement flag instructions
399
400 case BRK:
401 // TODO: trigger an interrupt
402 cpu->running = false;
403 break;
404
405 case NOP:
406 break;
407
408 default:
409 die("Unsupported opcode: %x\n", op);
swissChili710d18d2020-07-29 19:43:20 -0700410 }
swissChili6264a3b2020-07-30 19:02:07 -0700411 #undef REGS
swissChili6c61a792020-07-28 16:29:20 -0700412}
413
swissChili94ba1f52020-08-08 11:39:10 -0700414inline uint16_t fetch_le(cpu_t *cpu)
swissChili6c61a792020-07-28 16:29:20 -0700415{
416 uint8_t a = cpu->mem[cpu->pc++];
417 uint8_t b = cpu->mem[cpu->pc++];
418 return le_to_native(a, b);
419}
420
swissChili94ba1f52020-08-08 11:39:10 -0700421inline arg_t arg_imm(uint16_t a)
swissChili710d18d2020-07-29 19:43:20 -0700422{
423 return (arg_t){ a, a };
424}
425
swissChili94ba1f52020-08-08 11:39:10 -0700426inline arg_t arg_ptr(cpu_t *c, uint flags, uint16_t p)
swissChili710d18d2020-07-29 19:43:20 -0700427{
428 if (flags & FETCH_NO_INDIRECTION)
429 return arg_imm(p);
430
431 return (arg_t){ c->mem[p], p };
432}
433
swissChili94ba1f52020-08-08 11:39:10 -0700434inline arg_t arg(uint16_t v, uint16_t a)
swissChili710d18d2020-07-29 19:43:20 -0700435{
436 return (arg_t){ v, a };
437}
438
439arg_t fetch_addr(cpu_t *cpu, uint8_t am, uint f)
swissChili6c61a792020-07-28 16:29:20 -0700440{
441 switch (am)
442 {
443 case AM_ACC:
444 case AM_IMP:
swissChili710d18d2020-07-29 19:43:20 -0700445 return arg_imm(0);
swissChili6c61a792020-07-28 16:29:20 -0700446
447 // In both cases return immediate 8 bit value
448 case AM_IMM:
449 case AM_ZP:
swissChili710d18d2020-07-29 19:43:20 -0700450 return arg_imm(cpu->mem[cpu->pc++]);
swissChili6c61a792020-07-28 16:29:20 -0700451
452 case AM_ABS:
swissChili710d18d2020-07-29 19:43:20 -0700453 return arg_ptr(cpu, f, fetch_le(cpu));
swissChili6c61a792020-07-28 16:29:20 -0700454
455 case AM_REL:
456 {
swissChili6264a3b2020-07-30 19:02:07 -0700457 // Aparently, PC should will point to the NEXT opcode
458 // I can't find any documentation on this unfortunately, but
459 // I have discovered this through testing the output of other
460 // assemblers.
461 uint16_t pc = cpu->pc + 1;
462 return arg_ptr(cpu, f, (int8_t)cpu->mem[cpu->pc++] + pc);
swissChili6c61a792020-07-28 16:29:20 -0700463 }
464
465 case AM_IND:
466 {
467 uint16_t addr = fetch_le(cpu);
swissChili6264a3b2020-07-30 19:02:07 -0700468
469 if (f & FETCH_NO_INDIRECTION)
470 return arg_imm(addr);
471
swissChili6c61a792020-07-28 16:29:20 -0700472 uint8_t low = cpu->mem[addr],
473 high = cpu->mem[addr + 1];
474
swissChili710d18d2020-07-29 19:43:20 -0700475 return arg_ptr(cpu, f, le_to_native(low, high));
swissChili6c61a792020-07-28 16:29:20 -0700476 }
477
478 case AM_AX:
swissChili94ba1f52020-08-08 11:39:10 -0700479 if (f & FETCH_NO_INDIRECTION)
480 return arg_ptr(cpu, f, fetch_le(cpu));
481
swissChili710d18d2020-07-29 19:43:20 -0700482 return arg_ptr(cpu, f, fetch_le(cpu) + cpu->regs[X]);
swissChili6c61a792020-07-28 16:29:20 -0700483
484 case AM_AY:
swissChili94ba1f52020-08-08 11:39:10 -0700485 if (f & FETCH_NO_INDIRECTION)
486 return arg_ptr(cpu, f, fetch_le(cpu));
487
swissChili710d18d2020-07-29 19:43:20 -0700488 return arg_ptr(cpu, f, fetch_le(cpu) + cpu->regs[Y]);
swissChili6c61a792020-07-28 16:29:20 -0700489
490 case AM_ZPX:
swissChili94ba1f52020-08-08 11:39:10 -0700491 if (f & FETCH_NO_INDIRECTION)
492 return arg_ptr(cpu, f, cpu->mem[cpu->pc++]);
swissChili710d18d2020-07-29 19:43:20 -0700493 return arg_ptr(cpu, f, cpu->mem[cpu->pc++] + cpu->regs[X]);
swissChili6c61a792020-07-28 16:29:20 -0700494
495 case AM_ZPY:
swissChili94ba1f52020-08-08 11:39:10 -0700496 if (f & FETCH_NO_INDIRECTION)
497 return arg_ptr(cpu, f, cpu->mem[cpu->pc++]);
swissChili710d18d2020-07-29 19:43:20 -0700498 return arg_ptr(cpu, f, cpu->mem[cpu->pc++] + cpu->regs[Y]);
swissChili6c61a792020-07-28 16:29:20 -0700499
500 case AM_ZIX:
501 {
502 uint8_t zp = cpu->mem[cpu->pc++];
swissChili6264a3b2020-07-30 19:02:07 -0700503
504 if (f & FETCH_NO_INDIRECTION)
505 return arg_imm(zp);
506
swissChili710d18d2020-07-29 19:43:20 -0700507 uint16_t addr = zp + cpu->regs[X];
508 uint16_t indirect = le_to_native(cpu->mem[addr], cpu->mem[addr + 1]);
509 return arg_ptr(cpu, f, indirect);
swissChili6c61a792020-07-28 16:29:20 -0700510 }
511
512 case AM_ZIY:
513 {
514 uint8_t zp = cpu->mem[cpu->pc++];
swissChili6264a3b2020-07-30 19:02:07 -0700515
516 if (f & FETCH_NO_INDIRECTION)
517 return arg_imm(zp);
518
swissChili6c61a792020-07-28 16:29:20 -0700519 uint16_t base = le_to_native(cpu->mem[zp], cpu->mem[zp + 1]);
swissChili710d18d2020-07-29 19:43:20 -0700520 return arg_ptr(cpu, f, base + cpu->regs[Y]);
swissChili6c61a792020-07-28 16:29:20 -0700521 }
522
523 default:
524 die("Unknown address mode %x", am);
swissChili710d18d2020-07-29 19:43:20 -0700525 __builtin_unreachable();
swissChili6c61a792020-07-28 16:29:20 -0700526 }
527}
528
swissChili94ba1f52020-08-08 11:39:10 -0700529inline void step(cpu_t *cpu)
swissChili6c61a792020-07-28 16:29:20 -0700530{
swissChili94ba1f52020-08-08 11:39:10 -0700531 static int steps;
532 steps++;
swissChili6c61a792020-07-28 16:29:20 -0700533 switch (cpu->mem[cpu->pc++])
534 {
535#define INST(mn, am, op) \
536 case op: \
swissChilida4803e2020-08-06 20:06:04 -0700537 execute(cpu, #mn, mn, fetch_addr(cpu, am, 0), am); \
swissChili6c61a792020-07-28 16:29:20 -0700538 break;
539
540 INSTRUCTIONS
541
542#undef INST
543
544 default:
545 die("Undefined opcode");
546 }
swissChili94ba1f52020-08-08 11:39:10 -0700547
548 if (steps % 100 == 0)
549 printf("%d\n", steps);
550
551 if (g_scr)
552 {
553 sdl_screen(g_scr, cpu->mem + CPU_FB_ADDR);
554 }
swissChili6c61a792020-07-28 16:29:20 -0700555}
556
swissChilic51e9222020-08-07 16:09:14 -0700557int dump_inst(cpu_t *cpu, char *buf, const char *mn, uint16_t addr, uint8_t am)
swissChili6c61a792020-07-28 16:29:20 -0700558{
swissChilic51e9222020-08-07 16:09:14 -0700559 char *end = buf;
560 end += sprintf(end, "%s ", mn);
swissChili6c61a792020-07-28 16:29:20 -0700561
562 switch (am)
563 {
564 case AM_IMM:
swissChilic51e9222020-08-07 16:09:14 -0700565 end += sprintf(end, "#");
swissChili6c61a792020-07-28 16:29:20 -0700566 case AM_REL:
567 case AM_ABS:
568 case AM_ZP:
swissChilic51e9222020-08-07 16:09:14 -0700569 end += sprintf(end, "$%x", addr);
swissChili6c61a792020-07-28 16:29:20 -0700570 break;
571
572 case AM_IND:
swissChilic51e9222020-08-07 16:09:14 -0700573 end += sprintf(end, "($%x)", addr);
swissChili6c61a792020-07-28 16:29:20 -0700574 break;
575
576 case AM_AX:
577 case AM_ZPX:
swissChilic51e9222020-08-07 16:09:14 -0700578 end += sprintf(end, "$%x, X", addr);
swissChili6c61a792020-07-28 16:29:20 -0700579 break;
580
581 case AM_AY:
582 case AM_ZPY:
swissChilic51e9222020-08-07 16:09:14 -0700583 end += sprintf(end, "$%x, Y", addr);
swissChili6c61a792020-07-28 16:29:20 -0700584 break;
585
586 case AM_ZIX:
swissChilic51e9222020-08-07 16:09:14 -0700587 end += sprintf(end, "($%x, X)", addr);
swissChili6c61a792020-07-28 16:29:20 -0700588 break;
589
590 case AM_ZIY:
swissChilic51e9222020-08-07 16:09:14 -0700591 end += sprintf(end, "($%x), Y", addr);
swissChili6c61a792020-07-28 16:29:20 -0700592 break;
593 }
594
swissChilic51e9222020-08-07 16:09:14 -0700595 return end - buf;
swissChili6c61a792020-07-28 16:29:20 -0700596}
597
swissChilic51e9222020-08-07 16:09:14 -0700598char *disas_step(cpu_t *cpu)
swissChili6c61a792020-07-28 16:29:20 -0700599{
swissChilic51e9222020-08-07 16:09:14 -0700600 char *buffer = malloc(80);
601 char *end = buffer;
602
603 // end += sprintf(buffer, "$%x", cpu->pc);
swissChili6c61a792020-07-28 16:29:20 -0700604 uint8_t op = cpu->mem[cpu->pc++];
605 switch (op)
606 {
607#define INST(mn, am, op) \
608 case op: \
swissChilic51e9222020-08-07 16:09:14 -0700609 end += dump_inst(cpu, end, #mn, \
swissChili710d18d2020-07-29 19:43:20 -0700610 fetch_addr(cpu, am, FETCH_NO_INDIRECTION).ptr, am); \
swissChili6c61a792020-07-28 16:29:20 -0700611 break;
612
613 INSTRUCTIONS
614
615#undef INST
616
617 default:
swissChilic51e9222020-08-07 16:09:14 -0700618 end += sprintf(end, "Undefined opcode %x", op);
swissChili6c61a792020-07-28 16:29:20 -0700619 }
swissChilic51e9222020-08-07 16:09:14 -0700620
621 *end = 0;
622
623 return buffer;
swissChili6c61a792020-07-28 16:29:20 -0700624}
625
swissChilida4803e2020-08-06 20:06:04 -0700626void disas_num(cpu_t *cpu, uint16_t num)
627{
swissChilic51e9222020-08-07 16:09:14 -0700628 uint16_t pc = cpu->pc;
swissChilida4803e2020-08-06 20:06:04 -0700629 for (int i = 0; i < num; i++)
630 {
swissChilic51e9222020-08-07 16:09:14 -0700631 uint16_t last_pc = cpu->pc;
632 char *line = disas_step(cpu);
633 printf("$%x\t%s\n", last_pc, line);
634 free(line);
swissChilida4803e2020-08-06 20:06:04 -0700635 }
swissChilic51e9222020-08-07 16:09:14 -0700636 cpu->pc = pc;
swissChilida4803e2020-08-06 20:06:04 -0700637}
638
swissChili6c61a792020-07-28 16:29:20 -0700639void disas(cpu_t *cpu)
640{
swissChilic51e9222020-08-07 16:09:14 -0700641 uint16_t pc = cpu->pc;
swissChili6264a3b2020-07-30 19:02:07 -0700642 // Raw binary, no way to know what's code what isn't
swissChili6c61a792020-07-28 16:29:20 -0700643 while (cpu->pc < 0xFFFF)
644 {
swissChilic51e9222020-08-07 16:09:14 -0700645 uint16_t last_pc = cpu->pc;
646 char *line = disas_step(cpu);
647 printf("$%x\t%s\n", last_pc, line);
648 free(line);
swissChili6c61a792020-07-28 16:29:20 -0700649 }
swissChilic51e9222020-08-07 16:09:14 -0700650 cpu->pc = pc;
swissChili6c61a792020-07-28 16:29:20 -0700651}
swissChilic51e9222020-08-07 16:09:14 -0700652
swissChilida4803e2020-08-06 20:06:04 -0700653void run(cpu_t *cpu)
654{
655 while (cpu->running)
656 {
657 step(cpu);
658 }
659
660 printf("CPU Halted\n");
661}