blob: 05acebc21c2020213341c626e7da8ff780b4ecf1 [file] [log] [blame]
swissChili6c61a792020-07-28 16:29:20 -07001#pragma once
2
swissChili97b5d8b2020-08-15 20:00:54 -07003#include "mnemonics.h"
4
swissChili6c61a792020-07-28 16:29:20 -07005#include <stdint.h>
swissChili6264a3b2020-07-30 19:02:07 -07006#include <stdbool.h>
swissChilic6b4f7e2020-08-09 16:36:36 -07007#include <mqueue.h>
swissChili6264a3b2020-07-30 19:02:07 -07008
9#define REGISTERS R(A) R(X) R(Y) R(SP)
swissChilibb478f12020-08-07 20:45:07 -070010#define CPU_FB_ADDR 0x200
11#define CPU_FB_W 32
12#define CPU_FB_H 32
swissChili6c61a792020-07-28 16:29:20 -070013
swissChilic6b4f7e2020-08-09 16:36:36 -070014#define MQ_BUF_LEN 512
15#define MQ_NAME "/6502-to-cpu"
16
swissChili6c61a792020-07-28 16:29:20 -070017enum // Registers
18{
swissChili6264a3b2020-07-30 19:02:07 -070019 A, X, Y, SP
swissChili6c61a792020-07-28 16:29:20 -070020};
21
22enum // Flags
23{
24 CARRY = 1 << 0,
25 ZERO = 1 << 1,
26 NO_INT = 1 << 2,
27 DECIMAL = 1 << 3,
28 BREAK = 1 << 4,
29 UNUSED = 1 << 5,
30 OVERFLW = 1 << 6,
31 NEGATIV = 1 << 7,
32};
33
34enum // Address Modes
35{
36 AM_ACC, // Accumulator implied as operand
37 AM_IMP, // Implied operand
38 AM_IMM, // Immediate operand (8 bit)
39 AM_ABS, // Absolute operand (16 bit)
40 AM_ZP, // Zero-page operand
41 AM_REL, // Relative operand (signed 8 bit)
42 AM_IND, // Absolute indirect operand (16 bit address of 16 bit address)
43 AM_AX, // Absolute indexed with X
44 AM_AY, // Absolute indexed with Y
45 AM_ZPX, // Zero-page indexed with X
46 AM_ZPY, // Zero-page indexed with Y
47 AM_ZIX, // Zero-page indexed indirect (zp,x)
48 AM_ZIY, // Zero-page indirect indexed (zp),y
49};
50
51enum // Opcodes
52{
swissChili97b5d8b2020-08-15 20:00:54 -070053#define MN(name) name,
54 MNEMONICS
55#undef MN
swissChili6c61a792020-07-28 16:29:20 -070056};
57
swissChili710d18d2020-07-29 19:43:20 -070058enum // Fetch flags
59{
60 FETCH_NO_INDIRECTION = 1, // Do not follow indirection (used for disassembly)
61};
62
swissChili6264a3b2020-07-30 19:02:07 -070063// Status register
64typedef struct __attribute__((packed))
65{
66 bool negative : 1;
67 bool overflow : 1;
68 bool unused : 1;
69 bool break_ : 1;
70 bool decimal : 1;
71 bool no_int : 1;
72 bool zero : 1;
73 bool carry : 1;
74} status_t;
75
swissChili6c61a792020-07-28 16:29:20 -070076// Emulator instance, create with new_cpu()
77typedef struct
78{
swissChili6264a3b2020-07-30 19:02:07 -070079 uint8_t regs[4]; // A, X, Y, SP registers
swissChili6c61a792020-07-28 16:29:20 -070080 uint16_t pc;
swissChili6264a3b2020-07-30 19:02:07 -070081 status_t status;
swissChili6c61a792020-07-28 16:29:20 -070082 uint8_t *mem;
swissChili6264a3b2020-07-30 19:02:07 -070083 bool running;
swissChilicc27cfe2020-08-08 12:57:57 -070084 bool screen_dirty;
swissChili6c61a792020-07-28 16:29:20 -070085} cpu_t;
86
87// Argument type, includes both pointer and its value
88typedef struct
89{
90 uint16_t val; // Value at pointer (used by most instructions)
91 uint16_t ptr; // Pointer (used by jumps, etc)
92} arg_t;
93
94cpu_t new_cpu();
swissChili6264a3b2020-07-30 19:02:07 -070095void step(cpu_t *cpu);
swissChili6c61a792020-07-28 16:29:20 -070096void free_cpu(cpu_t *cpu);
97void die(const char *message);
swissChilidbbd5402020-08-07 15:07:39 -070098void reset(cpu_t *cpu);
swissChili6c61a792020-07-28 16:29:20 -070099void disas(cpu_t *cpu);
swissChilida4803e2020-08-06 20:06:04 -0700100void disas_num(cpu_t *cpu, uint16_t num);
swissChilic51e9222020-08-07 16:09:14 -0700101// Buffer must be freed by user
swissChili1970cb82020-08-10 13:22:39 -0700102char *disas_step(cpu_t *cpu, uint16_t *pc);
swissChilida4803e2020-08-06 20:06:04 -0700103void run(cpu_t *cpu);
swissChilic6b4f7e2020-08-09 16:36:36 -0700104void run_mq(cpu_t *cpu, mqd_t mq);