blob: cee84c5aae8833665c8cb95b6a4b1af4903781e6 [file] [log] [blame]
swissChili6c61a792020-07-28 16:29:20 -07001#pragma once
2
3#include <stdint.h>
swissChili6264a3b2020-07-30 19:02:07 -07004#include <stdbool.h>
5
6#define REGISTERS R(A) R(X) R(Y) R(SP)
swissChilibb478f12020-08-07 20:45:07 -07007#define CPU_FB_ADDR 0x200
8#define CPU_FB_W 32
9#define CPU_FB_H 32
swissChili6c61a792020-07-28 16:29:20 -070010
11enum // Registers
12{
swissChili6264a3b2020-07-30 19:02:07 -070013 A, X, Y, SP
swissChili6c61a792020-07-28 16:29:20 -070014};
15
16enum // Flags
17{
18 CARRY = 1 << 0,
19 ZERO = 1 << 1,
20 NO_INT = 1 << 2,
21 DECIMAL = 1 << 3,
22 BREAK = 1 << 4,
23 UNUSED = 1 << 5,
24 OVERFLW = 1 << 6,
25 NEGATIV = 1 << 7,
26};
27
28enum // Address Modes
29{
30 AM_ACC, // Accumulator implied as operand
31 AM_IMP, // Implied operand
32 AM_IMM, // Immediate operand (8 bit)
33 AM_ABS, // Absolute operand (16 bit)
34 AM_ZP, // Zero-page operand
35 AM_REL, // Relative operand (signed 8 bit)
36 AM_IND, // Absolute indirect operand (16 bit address of 16 bit address)
37 AM_AX, // Absolute indexed with X
38 AM_AY, // Absolute indexed with Y
39 AM_ZPX, // Zero-page indexed with X
40 AM_ZPY, // Zero-page indexed with Y
41 AM_ZIX, // Zero-page indexed indirect (zp,x)
42 AM_ZIY, // Zero-page indirect indexed (zp),y
43};
44
45enum // Opcodes
46{
47 LDA,
48 LDX,
49 LDY,
50 STA,
51 STX,
52 STY,
53 ADC,
54 SBC,
55 INC,
56 INX,
57 INY,
58 DEC,
59 DEX,
60 DEY,
61 ASL,
62 LSR,
63 ROL,
64 ROR,
65 AND,
66 ORA,
67 EOR,
68 CMP,
69 CPX,
70 CPY,
71 BIT,
72 BCC,
73 BCS,
74 BNE,
75 BEQ,
76 BPL,
77 BMI,
78 BVC,
79 BVS,
80 TAX,
81 TXA,
82 TAY,
83 TYA,
84 TSX,
85 TXS,
86 PHA,
87 PLA,
88 PHP,
89 PLP,
90 JMP,
91 JSR,
92 RTS,
93 RTI,
94 CLC,
95 SEC,
96 CLD,
97 SED,
98 CLI,
99 SEI,
100 CLV,
101 BRK,
102 NOP,
103};
104
swissChili710d18d2020-07-29 19:43:20 -0700105enum // Fetch flags
106{
107 FETCH_NO_INDIRECTION = 1, // Do not follow indirection (used for disassembly)
108};
109
swissChili6264a3b2020-07-30 19:02:07 -0700110// Status register
111typedef struct __attribute__((packed))
112{
113 bool negative : 1;
114 bool overflow : 1;
115 bool unused : 1;
116 bool break_ : 1;
117 bool decimal : 1;
118 bool no_int : 1;
119 bool zero : 1;
120 bool carry : 1;
121} status_t;
122
swissChili6c61a792020-07-28 16:29:20 -0700123// Emulator instance, create with new_cpu()
124typedef struct
125{
swissChili6264a3b2020-07-30 19:02:07 -0700126 uint8_t regs[4]; // A, X, Y, SP registers
swissChili6c61a792020-07-28 16:29:20 -0700127 uint16_t pc;
swissChili6264a3b2020-07-30 19:02:07 -0700128 status_t status;
swissChili6c61a792020-07-28 16:29:20 -0700129 uint8_t *mem;
swissChili6264a3b2020-07-30 19:02:07 -0700130 bool running;
swissChili6c61a792020-07-28 16:29:20 -0700131} cpu_t;
132
133// Argument type, includes both pointer and its value
134typedef struct
135{
136 uint16_t val; // Value at pointer (used by most instructions)
137 uint16_t ptr; // Pointer (used by jumps, etc)
138} arg_t;
139
140cpu_t new_cpu();
swissChili6264a3b2020-07-30 19:02:07 -0700141void step(cpu_t *cpu);
swissChili6c61a792020-07-28 16:29:20 -0700142void free_cpu(cpu_t *cpu);
143void die(const char *message);
swissChilidbbd5402020-08-07 15:07:39 -0700144void reset(cpu_t *cpu);
swissChili6c61a792020-07-28 16:29:20 -0700145void disas(cpu_t *cpu);
swissChilida4803e2020-08-06 20:06:04 -0700146void disas_num(cpu_t *cpu, uint16_t num);
swissChilic51e9222020-08-07 16:09:14 -0700147// Buffer must be freed by user
148char *disas_step(cpu_t *cpu);
swissChilida4803e2020-08-06 20:06:04 -0700149void run(cpu_t *cpu);