/* 6502 - 6502 emulation Copyright (C) 2025 Ian Cowburn This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see ------------------------------------------------------------------------- */ #ifndef C6502_H #define C6502_H #include /* ---------------------------------------- TYPES */ /* Large unsigned type */ typedef unsigned long C6502Val; /* 8-bit type. The emulation will exit with code 2 if this isn't 8 bits. */ typedef unsigned char C6502Byte; /* 8-bit signed type. The emulation will exit with code 2 if this isn't 8 bits. We assume this is 2's complemnt. */ typedef signed char C6502Relative; /* 16-bit type. The emulation will exit with code 2 if this isn't 16 bits. */ typedef unsigned short C6502Word; /* The processor */ struct C6502Private; typedef struct { C6502Word PC; C6502Byte A; C6502Byte X; C6502Byte Y; C6502Byte SP; C6502Byte SR; struct C6502Private *priv; } C6502; /* Interfaces used to handle memory */ typedef C6502Byte (*C6502ReadMemory)(C6502 *cpu, C6502Word address); typedef void (*C6502WriteMemory)(C6502 *cpu, C6502Word address, C6502Byte value); /* Callback. Callback should return TRUE for processing to continue. */ typedef int (*C6502Callback)(C6502 *cpu, C6502Val current_cycles); /* Callback reasons eC6502_Instruction Called before the initial fetch for an instruction (called just to once no matter how many bytes the instruction is made up of). eC6502_BRK Called when a BRK is executed. eC6502_JAM Called when the CPU hits an opcode that jams the CPU. eC6502_RTI Called when the RTI instruction is executed */ typedef enum { eC6502_Instruction, eC6502_BRK, eC6502_JAM, eC6502_RTI, eC6502_NO_CALLBACK } C6502CallbackReason; /* Defines cycle timers */ typedef enum { C6502_TIMER_1, C6502_TIMER_2, C6502_TIMER_3, C6502_NO_TIMERS } C6502Timer; /* Flags in the F register */ typedef enum { eC6502_Carry =0x01, eC6502_Neg =0x02, eC6502_PV =0x04, eC6502_Hidden3 =0x08, eC6502_HalfCarry =0x10, eC6502_Hidden5 =0x20, eC6502_Zero =0x40, eC6502_Sign =0x80 } C6502FlagRegister; /* Disassembly label -- only useful if ENABLE_DISASSEMBLER is set. Labels are stored as an array, where a NULL in the label field marks the end of the list. */ typedef struct { C6502Word address; const char *label; } C6502Label; /* ---------------------------------------- INTERFACES */ /* Initialises the processor. */ #ifdef ENABLE_ARRAY_MEMORY C6502 *C6502Init(void); #else C6502 *C6502Init(C6502ReadMemory read_memory, C6502WriteMemory write_memory, C6502ReadMemory read_for_disassem); #endif /* Resets the processor. */ void C6502Reset(C6502 *cpu); /* Lodge a callback to be invoked after special events. Returns FALSE if the callback couldn't be lodged (there is a max of 10 callbacks per reason). */ int C6502LodgeCallback(C6502 *cpu, C6502CallbackReason reason, C6502Callback callback); /* Remove a callback. Does nothing if reason was not lodged with C6502LodgeCallback() */ void C6502RemoveCallback(C6502 *cpu, C6502CallbackReason reason, C6502Callback callback); /* Cause an interrupt before the next opcode. */ void C6502Interrupt(C6502 *cpu); /* Cause an NMI */ void C6502NMI(C6502 *cpu); /* Execute a single instruction. Returns FALSE if any callback returned FALSE. */ int C6502SingleStep(C6502 *cpu); /* Executes until a callback returns FALSE (never returns otherwise) */ void C6502Exec(C6502 *cpu); /* Manipulate the cylce count of the C6502 */ C6502Val C6502Cycles(C6502 *cpu); void C6502ResetCycles(C6502 *cpu, C6502Val cycles); /* Timers that count in cycle counts */ C6502Val C6502GetTimer(C6502 *cpu, C6502Timer timer); void C6502SetTimer(C6502 *cpu, C6502Timer timer, C6502Val cycles); /* Set address to label mappings for the disassembler */ void C6502SetLabels(C6502Label labels[]); /* Simple disassembly of memory accessed through read_for_disassem, or C6502_MEMORY as appropriate. addr is updated on exit. */ const char *C6502Disassemble(C6502 *cpu, C6502Word *addr); /* Allows the CPU state to be saved/loaded from a stream */ void C6502SaveSnapshot(C6502 *cpu, FILE *fp); void C6502LoadSnapshot(C6502 *cpu, FILE *fp); #endif /* END OF FILE */