/* 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 ------------------------------------------------------------------------- 6502 */ #include #include #include "6502.h" /* ---------------------------------------- MACROS */ #define PRIV cpu->priv #define MAX_PER_CALLBACK 10 #define TRUE 1 #define FALSE 0 #define CALLBACK(r,d) do \ { \ int f; \ \ for(f = 0; f < MAX_PER_CALLBACK; f++) \ if (PRIV->callback[r][f]) \ PRIV->last_cb &= \ PRIV->callback[r][f](cpu,d);\ } while(0) /* ---------------------------------------- PRIVATE DATA AND TYPES */ struct C6502Private { C6502Val cycles; C6502Val timer[e6502_NO_TIMERS]; C6502ReadMemory mread; C6502WriteMemory mwrite; C6502ReadMemory disread; C6502Callback callback[e6502_NO_CALLBACK][MAX_PER_CALLBACK]; C6502Label *labels; int last_cb; }; /* ---------------------------------------- PRIVATE FUNCTIONS */ static void InitTables() { static int init=FALSE; if (init) return; init=TRUE; /* TODO */ } static void C6502_CheckInterrupt(C6502 *cpu) { /* TODO */ } /* ---------------------------------------- INTERFACES */ C6502 *C6502Init(C6502ReadMemory read_memory, C6502WriteMemory write_memory, C6502ReadMemory read_for_disassem) { C6502 *cpu; int f; int r; InitTables(); cpu = malloc(sizeof *cpu); if (cpu) { PRIV = malloc(sizeof *cpu->priv); if (PRIV) { PRIV->mread = read_memory; PRIV->mwrite = write_memory; PRIV->disread = read_for_disassem; for(f = 0; f < eC6502_NO_CALLBACK; f++) for(r = 0; r < MAX_PER_CALLBACK; r++) PRIV->callback[f][r] = NULL; C6502Reset(cpu); } else { free(cpu); cpu = NULL; } } return cpu; } void Z80Reset(Z80 *cpu) { PRIV->cycle = 0; PRIV->timer[e6502_TIMER_1] = 0; PRIV->timer[e6502_TIMER_2] = 0; PRIV->timer[e6502_TIMER_3] = 0; cpu->PC = 0; /* TODO */ } C6502Val C6502Cycles(C6502 *cpu) { return PRIV->cycle; } void C6502ResetCycles(C6502 *cpu, C6502Val cycles) { PRIV->cycle = cycles; } C6502Val C6502GetTimer(C6502 *cpu, C6502Timer timer) { return PRIV->timer[timer]; } void C6502SetTimer(C6502 *cpu, C6502Timer timer, C6502Val cycles) { PRIV->timer[timer] = cycles; } int C6502LodgeCallback(C6502 *cpu, C6502CallbackReason reason, C6502Callback callback) { int f; for(f = 0; f < MAX_PER_CALLBACK; f++) { if (!PRIV->callback[reason][f]) { PRIV->callback[reason][f] = callback; return TRUE; } } return FALSE; } void C6502RemoveCallback(C6502 *cpu, C6502CallbackReason reason, C6502Callback callback) { int f; for(f = 0; f < MAX_PER_CALLBACK; f++) { if (PRIV->callback[reason][f] == callback) { PRIV->callback[reason][f] = NULL; } } } void C6502Interrupt(C6502 *cpu) { PRIV->raise = TRUE; PRIV->nmi = FALSE; } void C6502NMI(C6502 *cpu) { PRIV->raise = TRUE; PRIV->nmi = TRUE; } int C6502SingleStep(C6502 *cpu) { C6502_CheckInterrupt(cpu); CALLBACK(eC6502_Instruction, PRIV->cycle); INC_R; opcode=FETCH_BYTE; C6502_Decode(cpu,opcode); return PRIV->last_cb; } void C6502Exec(C6502 *cpu) { while (C6502SingleStep(cpu)); } void C6502SetLabels(C6502 *cpu, C6502Label labels[]) { PRIV->labels = labels; } const char *C6502Disassemble(C6502 *cpu, C6502Word *pc) { #ifdef ENABLE_DISASSEM C6502Byte C6502_Dis_FetchByte(C6502 *cpu, C6502Word *pc); static char s[80]; C6502Word opc,npc; C6502Byte op; int f; opc=*pc; op=C6502_Dis_FetchByte(cpu,pc); dis_opcode_z80[op](cpu,op,pc); npc=*pc; strcpy(s,C6502_Dis_Printf("%-5s",C6502_Dis_GetOp())); strcat(s,C6502_Dis_Printf("%-40s ;",C6502_Dis_GetArg())); for(f=0;f<5 && opc!=npc;f++) { #ifdef ENABLE_ARRAY_MEMORY strcat(s,C6502_Dis_Printf(" %.2x",(int)C6502_MEMORY[opc++])); #else strcat(s,C6502_Dis_Printf(" %.2x",(int)PRIV->disread(cpu,opc++))); #endif } if (opc!=npc) for(f=1;f<3;f++) s[strlen(s)-f]='.'; return s; #else (*pc)+=4; return "NO DISASSEMBLER"; #endif } /* END OF FILE */