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