1 |
/** M6502: portable 6502 emulator ****************************/ |
2 |
/** **/ |
3 |
/** M6502.h **/ |
4 |
/** **/ |
5 |
/** This file contains declarations relevant to emulation **/ |
6 |
/** of 6502 CPU. **/ |
7 |
/** **/ |
8 |
/** Copyright (C) Marat Fayzullin 1996-2007 **/ |
9 |
/** Alex Krasivsky 1996 **/ |
10 |
/** You are not allowed to distribute this software **/ |
11 |
/** commercially. Please, notify me, if you make any **/ |
12 |
/** changes to this file. **/ |
13 |
/*************************************************************/ |
14 |
#ifndef M6502_H |
15 |
#define M6502_H |
16 |
|
17 |
/* Compilation options: */ |
18 |
/* #define FAST_RDOP */ /* Separate Op6502()/Rd6502() */ |
19 |
/* #define DEBUG */ /* Compile debugging version */ |
20 |
/* #define LSB_FIRST */ /* Compile for low-endian CPU */ |
21 |
|
22 |
/* Loop6502() returns: */ |
23 |
#define INT_NONE 0 /* No interrupt required */ |
24 |
#define INT_IRQ 1 /* Standard IRQ interrupt */ |
25 |
#define INT_NMI 2 /* Non-maskable interrupt */ |
26 |
#define INT_QUIT 3 /* Exit the emulation */ |
27 |
|
28 |
/* 6502 status flags: */ |
29 |
#define C_FLAG 0x01 /* 1: Carry occured */ |
30 |
#define Z_FLAG 0x02 /* 1: Result is zero */ |
31 |
#define I_FLAG 0x04 /* 1: Interrupts disabled */ |
32 |
#define D_FLAG 0x08 /* 1: Decimal mode */ |
33 |
#define B_FLAG 0x10 /* Break [0 on stk after int] */ |
34 |
#define R_FLAG 0x20 /* Always 1 */ |
35 |
#define V_FLAG 0x40 /* 1: Overflow occured */ |
36 |
#define N_FLAG 0x80 /* 1: Result is negative */ |
37 |
|
38 |
/** Simple Datatypes *****************************************/ |
39 |
/** NOTICE: sizeof(byte)=1 and sizeof(word)=2 **/ |
40 |
/*************************************************************/ |
41 |
#ifndef BYTE_TYPE_DEFINED |
42 |
#define BYTE_TYPE_DEFINED |
43 |
typedef unsigned char byte; |
44 |
#endif |
45 |
#ifndef WORD_TYPE_DEFINED |
46 |
#define WORD_TYPE_DEFINED |
47 |
typedef unsigned short word; |
48 |
#endif |
49 |
typedef signed char offset; |
50 |
|
51 |
/** Structured Datatypes *************************************/ |
52 |
/** NOTICE: #define LSB_FIRST for machines where least **/ |
53 |
/** signifcant byte goes first. **/ |
54 |
/*************************************************************/ |
55 |
typedef union |
56 |
{ |
57 |
#ifdef LSB_FIRST |
58 |
struct { byte l,h; } B; |
59 |
#else |
60 |
struct { byte h,l; } B; |
61 |
#endif |
62 |
word W; |
63 |
} pair; |
64 |
|
65 |
typedef struct |
66 |
{ |
67 |
byte A,P,X,Y,S; /* CPU registers and program counter */ |
68 |
pair PC; |
69 |
|
70 |
int IPeriod,ICount; /* Set IPeriod to number of CPU cycles */ |
71 |
/* between calls to Loop6502() */ |
72 |
byte IRequest; /* Set to the INT_IRQ when pending IRQ */ |
73 |
byte AfterCLI; /* Private, don't touch */ |
74 |
int IBackup; /* Private, don't touch */ |
75 |
byte IAutoReset; /* Set to 1 to autom. reset IRequest */ |
76 |
byte TrapBadOps; /* Set to 1 to warn of illegal opcodes */ |
77 |
word Trap; /* Set Trap to address to trace from */ |
78 |
byte Trace; /* Set Trace=1 to start tracing */ |
79 |
void *User; /* Arbitrary user data (ID,RAM*,etc.) */ |
80 |
} M6502; |
81 |
|
82 |
/** Reset6502() **********************************************/ |
83 |
/** This function can be used to reset the registers before **/ |
84 |
/** starting execution with Run6502(). It sets registers to **/ |
85 |
/** their initial values. **/ |
86 |
/*************************************************************/ |
87 |
void Reset6502(register M6502 *R); |
88 |
|
89 |
/** Exec6502() ***********************************************/ |
90 |
/** This function will execute given number of 6502 cycles. **/ |
91 |
/** It will then return the number of cycles left, possibly **/ |
92 |
/** negative, and current register values in R. **/ |
93 |
/*************************************************************/ |
94 |
#ifdef EXEC6502 |
95 |
int Exec6502(register M6502 *R,register int RunCycles); |
96 |
#endif |
97 |
|
98 |
/** Int6502() ************************************************/ |
99 |
/** This function will generate interrupt of a given type. **/ |
100 |
/** INT_NMI will cause a non-maskable interrupt. INT_IRQ **/ |
101 |
/** will cause a normal interrupt, unless I_FLAG set in R. **/ |
102 |
/*************************************************************/ |
103 |
void Int6502(register M6502 *R,register byte Type); |
104 |
|
105 |
/** Run6502() ************************************************/ |
106 |
/** This function will run 6502 code until Loop6502() call **/ |
107 |
/** returns INT_QUIT. It will return the PC at which **/ |
108 |
/** emulation stopped, and current register values in R. **/ |
109 |
/*************************************************************/ |
110 |
#ifndef EXEC6502 |
111 |
word Run6502(register M6502 *R); |
112 |
#endif |
113 |
|
114 |
/** Rd6502()/Wr6502/Op6502() *********************************/ |
115 |
/** These functions are called when access to RAM occurs. **/ |
116 |
/** They allow to control memory access. Op6502 is the same **/ |
117 |
/** as Rd6502, but used to read *opcodes* only, when many **/ |
118 |
/** checks can be skipped to make it fast. It is only **/ |
119 |
/** required if there is a #define FAST_RDOP. **/ |
120 |
/************************************ TO BE WRITTEN BY USER **/ |
121 |
void Wr6502(register word Addr,register byte Value); |
122 |
byte Rd6502(register word Addr); |
123 |
byte Op6502(register word Addr); |
124 |
|
125 |
/** Debug6502() **********************************************/ |
126 |
/** This function should exist if DEBUG is #defined. When **/ |
127 |
/** Trace!=0, it is called after each command executed by **/ |
128 |
/** the CPU, and given the 6502 registers. Emulation exits **/ |
129 |
/** if Debug6502() returns 0. **/ |
130 |
/*************************************************************/ |
131 |
byte Debug6502(register M6502 *R); |
132 |
|
133 |
/** Loop6502() ***********************************************/ |
134 |
/** 6502 emulation calls this function periodically to **/ |
135 |
/** check if the system hardware requires any interrupts. **/ |
136 |
/** This function must return one of following values: **/ |
137 |
/** INT_NONE, INT_IRQ, INT_NMI, or INT_QUIT to exit the **/ |
138 |
/** emulation loop. **/ |
139 |
/************************************ TO BE WRITTEN BY USER **/ |
140 |
byte Loop6502(register M6502 *R); |
141 |
|
142 |
/** Patch6502() **********************************************/ |
143 |
/** Emulation calls this function when it encounters an **/ |
144 |
/** unknown opcode. This can be used to patch the code to **/ |
145 |
/** emulate BIOS calls, such as disk and tape access. The **/ |
146 |
/** function should return 1 if the exception was handled, **/ |
147 |
/** or 0 if the opcode was truly illegal. **/ |
148 |
/************************************ TO BE WRITTEN BY USER **/ |
149 |
byte Patch6502(register byte Op,register M6502 *R); |
150 |
|
151 |
#endif /* M6502_H */ |