Blaster Master + other fixes
[fceu.git] / ops.h
1 /* FCE Ultra - NES/Famicom Emulator
2  *
3  * Copyright notice for this file:
4  *  Copyright (C) 2002 Ben Parnell
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 case 0x00:  /* BRK */
22             _PC++;
23             PUSH(_PC>>8);
24             PUSH(_PC);
25             _P|=B_FLAG;
26             PUSH(_P|U_FLAG);
27             _P|=I_FLAG;
28             _PC=RdMem(0xFFFE);
29             _PC|=RdMem(0xFFFF)<<8;
30             break;
31
32 case 0x40:  /* RTI */
33             _P=POP();
34             _PI=_P;
35             _PC=POP();
36             _PC|=POP()<<8;
37             break;
38
39 case 0x60:  /* RTS */
40             _PC=POP();
41             _PC|=POP()<<8;
42             _PC++;
43             break;
44
45 case 0x48: /* PHA */
46            PUSH(_A);
47            break;
48 case 0x08: /* PHP */
49            PUSH(_P|U_FLAG|B_FLAG);
50            break;
51 case 0x68: /* PLA */
52            _A=POP();
53            X_ZN(_A);
54            break;
55 case 0x28: /* PLP */
56            _P=POP();
57            break;
58 case 0x4C:
59           {
60            uint16 ptmp=_PC;
61            unsigned int npc;
62
63            npc=RdMem(ptmp);
64            ptmp++;
65            npc|=RdMem(ptmp)<<8;
66            _PC=npc;
67           }
68           break; /* JMP ABSOLUTE */
69 case 0x6C:
70            {
71             uint32 tmp;
72             GetAB(tmp);
73             _PC=RdMem(tmp);
74             _PC|=RdMem( ((tmp+1)&0x00FF) | (tmp&0xFF00))<<8;
75            }
76            break;
77 case 0x20: /* JSR */
78            {
79             uint8 npc;
80             npc=RdMem(_PC++);
81             PUSH(_PC>>8);
82             PUSH(_PC);
83             _PC=RdMem(_PC)<<8;
84             _PC|=npc;
85            }
86            break;
87
88 case 0xAA: /* TAX */
89            _X=_A;
90            X_ZN(_A);
91            break;
92
93 case 0x8A: /* TXA */
94            _A=_X;
95            X_ZN(_A);
96            break;
97
98 case 0xA8: /* TAY */
99            _Y=_A;
100            X_ZN(_A);
101            break;
102 case 0x98: /* TYA */
103            _A=_Y;
104            X_ZN(_A);
105            break;
106
107 case 0xBA: /* TSX */
108            _X=_S;
109            X_ZN(_X);
110            break;
111 case 0x9A: /* TXS */
112            _S=_X;
113            break;
114
115 case 0xCA: /* DEX */
116            _X--;
117            X_ZN(_X);
118            break;
119 case 0x88: /* DEY */
120            _Y--;
121            X_ZN(_Y);
122            break;
123
124 case 0xE8: /* INX */
125            _X++;
126            X_ZN(_X);
127            break;
128 case 0xC8: /* INY */
129            _Y++;
130            X_ZN(_Y);
131            break;
132
133 case 0x18: /* CLC */
134            _P&=~C_FLAG;
135            break;
136 case 0xD8: /* CLD */
137            _P&=~D_FLAG;
138            break;
139 case 0x58: /* CLI */
140            _P&=~I_FLAG;
141            break;
142 case 0xB8: /* CLV */
143            _P&=~V_FLAG;
144            break;
145
146 case 0x38: /* SEC */
147            _P|=C_FLAG;
148            break;
149 case 0xF8: /* SED */
150            _P|=D_FLAG;
151            break;
152 case 0x78: /* SEI */
153            _P|=I_FLAG;
154            break;
155
156 case 0xEA: /* NOP */
157            break;
158
159 case 0x0A: RMW_A(ASL);
160 case 0x06: RMW_ZP(ASL);
161 case 0x16: RMW_ZPX(ASL);
162 case 0x0E: RMW_AB(ASL);
163 case 0x1E: RMW_ABX(ASL);
164
165 case 0xC6: RMW_ZP(DEC);
166 case 0xD6: RMW_ZPX(DEC);
167 case 0xCE: RMW_AB(DEC);
168 case 0xDE: RMW_ABX(DEC);
169
170 case 0xE6: RMW_ZP(INC);
171 case 0xF6: RMW_ZPX(INC);
172 case 0xEE: RMW_AB(INC);
173 case 0xFE: RMW_ABX(INC);
174
175 case 0x4A: RMW_A(LSR);
176 case 0x46: RMW_ZP(LSR);
177 case 0x56: RMW_ZPX(LSR);
178 case 0x4E: RMW_AB(LSR);
179 case 0x5E: RMW_ABX(LSR);
180
181 case 0x2A: RMW_A(ROL);
182 case 0x26: RMW_ZP(ROL);
183 case 0x36: RMW_ZPX(ROL);
184 case 0x2E: RMW_AB(ROL);
185 case 0x3E: RMW_ABX(ROL);
186
187 case 0x6A: RMW_A(ROR);
188 case 0x66: RMW_ZP(ROR);
189 case 0x76: RMW_ZPX(ROR);
190 case 0x6E: RMW_AB(ROR);
191 case 0x7E: RMW_ABX(ROR);
192
193 case 0x69: LD_IM(ADC);
194 case 0x65: LD_ZP(ADC);
195 case 0x75: LD_ZPX(ADC);
196 case 0x6D: LD_AB(ADC);
197 case 0x7D: LD_ABX(ADC);
198 case 0x79: LD_ABY(ADC);
199 case 0x61: LD_IX(ADC);
200 case 0x71: LD_IY(ADC);
201
202 case 0x29: LD_IM(AND);
203 case 0x25: LD_ZP(AND);
204 case 0x35: LD_ZPX(AND);
205 case 0x2D: LD_AB(AND);
206 case 0x3D: LD_ABX(AND);
207 case 0x39: LD_ABY(AND);
208 case 0x21: LD_IX(AND);
209 case 0x31: LD_IY(AND);
210
211 case 0x24: LD_ZP(BIT);
212 case 0x2C: LD_AB(BIT);
213
214 case 0xC9: LD_IM(CMP);
215 case 0xC5: LD_ZP(CMP);
216 case 0xD5: LD_ZPX(CMP);
217 case 0xCD: LD_AB(CMP);
218 case 0xDD: LD_ABX(CMP);
219 case 0xD9: LD_ABY(CMP);
220 case 0xC1: LD_IX(CMP);
221 case 0xD1: LD_IY(CMP);
222
223 case 0xE0: LD_IM(CPX);
224 case 0xE4: LD_ZP(CPX);
225 case 0xEC: LD_AB(CPX);
226
227 case 0xC0: LD_IM(CPY);
228 case 0xC4: LD_ZP(CPY);
229 case 0xCC: LD_AB(CPY);
230
231 case 0x49: LD_IM(EOR);
232 case 0x45: LD_ZP(EOR);
233 case 0x55: LD_ZPX(EOR);
234 case 0x4D: LD_AB(EOR);
235 case 0x5D: LD_ABX(EOR);
236 case 0x59: LD_ABY(EOR);
237 case 0x41: LD_IX(EOR);
238 case 0x51: LD_IY(EOR);
239
240 case 0xA9: LD_IM(LDA);
241 case 0xA5: LD_ZP(LDA);
242 case 0xB5: LD_ZPX(LDA);
243 case 0xAD: LD_AB(LDA);
244 case 0xBD: LD_ABX(LDA);
245 case 0xB9: LD_ABY(LDA);
246 case 0xA1: LD_IX(LDA);
247 case 0xB1: LD_IY(LDA);
248
249 case 0xA2: LD_IM(LDX);
250 case 0xA6: LD_ZP(LDX);
251 case 0xB6: LD_ZPY(LDX);
252 case 0xAE: LD_AB(LDX);
253 case 0xBE: LD_ABY(LDX);
254
255 case 0xA0: LD_IM(LDY);
256 case 0xA4: LD_ZP(LDY);
257 case 0xB4: LD_ZPX(LDY);
258 case 0xAC: LD_AB(LDY);
259 case 0xBC: LD_ABX(LDY);
260
261 case 0x09: LD_IM(ORA);
262 case 0x05: LD_ZP(ORA);
263 case 0x15: LD_ZPX(ORA);
264 case 0x0D: LD_AB(ORA);
265 case 0x1D: LD_ABX(ORA);
266 case 0x19: LD_ABY(ORA);
267 case 0x01: LD_IX(ORA);
268 case 0x11: LD_IY(ORA);
269
270 case 0xEB:      /* (undocumented) */
271 case 0xE9: LD_IM(SBC);
272 case 0xE5: LD_ZP(SBC);
273 case 0xF5: LD_ZPX(SBC);
274 case 0xED: LD_AB(SBC);
275 case 0xFD: LD_ABX(SBC);
276 case 0xF9: LD_ABY(SBC);
277 case 0xE1: LD_IX(SBC);
278 case 0xF1: LD_IY(SBC);
279
280 case 0x85: ST_ZP(_A);
281 case 0x95: ST_ZPX(_A);
282 case 0x8D: ST_AB(_A);
283 case 0x9D: ST_ABX(_A);
284 case 0x99: ST_ABY(_A);
285 case 0x81: ST_IX(_A);
286 case 0x91: ST_IY(_A);
287
288 case 0x86: ST_ZP(_X);
289 case 0x96: ST_ZPY(_X);
290 case 0x8E: ST_AB(_X);
291
292 case 0x84: ST_ZP(_Y);
293 case 0x94: ST_ZPX(_Y);
294 case 0x8C: ST_AB(_Y);
295
296 /* BCC */
297 case 0x90: if(_P&C_FLAG) _PC++; else {JR();} break;
298
299 /* BCS */
300 case 0xB0: if(_P&C_FLAG) {JR();} else _PC++; break;
301
302 /* BEQ */
303 case 0xF0: if(_P&Z_FLAG) {JR();} else _PC++; break;
304
305 /* BNE */
306 case 0xD0: if(_P&Z_FLAG) _PC++; else {JR();} break;
307
308 /* BMI */
309 case 0x30: if(_P&N_FLAG) {JR();} else _PC++; break;
310
311 /* BPL */
312 case 0x10: if(_P&N_FLAG) _PC++; else {JR();} break;
313
314 /* BVC */
315 case 0x50: if(_P&V_FLAG) _PC++; else {JR();} break;
316
317 /* BVS */
318 case 0x70: if(_P&V_FLAG) {JR();} else _PC++; break;
319
320 /* Here comes the undocumented instructions.  Note that this implementation
321    may be "wrong".  If so, please tell me.
322 */
323
324 /* AAC */
325 case 0x2B:
326 case 0x0B: LD_IM(AND;_P&=~C_FLAG;_P|=_A>>7);
327
328 /* AAX */
329 case 0x87: ST_ZP(_A&_X);
330 case 0x97: ST_ZPY(_A&_X);
331 case 0x8F: ST_AB(_A&_X);
332 case 0x83: ST_IX(_A&_X);
333
334 /* ARR - ARGH, MATEY! */
335 case 0x6B: {
336              uint8 arrtmp;
337              LD_IM(AND;_P&=~V_FLAG;_P|=(_A^(_A>>1))&0x40;arrtmp=_A>>7;_A>>=1;_A|=(_P&C_FLAG)<<7;_P&=~C_FLAG;_P|=arrtmp;X_ZN(_A));
338            }
339 /* ASR */
340 case 0x4B: LD_IM(AND;LSRA);
341
342 /* ATX(OAL) Is this(OR with $EE) correct? */
343 case 0xAB: LD_IM(_A|=0xEE;AND;_X=_A);
344
345 /* AXS */
346 case 0xCB: LD_IM(AXS);
347
348 /* DCP */
349 case 0xC7: LD_ZP(DEC;CMP);
350 case 0xD7: LD_ZPX(DEC;CMP);
351 case 0xCF: LD_AB(DEC;CMP);
352 case 0xDF: LD_ABX(DEC;CMP);
353 case 0xDB: LD_ABY(DEC;CMP);
354 case 0xC3: LD_IX(DEC;CMP);
355 case 0xD3: LD_IY(DEC;CMP);
356
357 /* ISC */
358 case 0xE7: LD_ZP(INC;SBC);
359 case 0xF7: LD_ZPX(INC;SBC);
360 case 0xEF: LD_AB(INC;SBC);
361 case 0xFF: LD_ABX(INC;SBC);
362 case 0xFB: LD_ABY(INC;SBC);
363 case 0xE3: LD_IX(INC;SBC);
364 case 0xF3: LD_IY(INC;SBC);
365
366 /* DOP */
367
368 case 0x04: _PC++;break;
369 case 0x14: _PC++;break;
370 case 0x34: _PC++;break;
371 case 0x44: _PC++;break;
372 case 0x54: _PC++;break;
373 case 0x64: _PC++;break;
374 case 0x74: _PC++;break;
375
376 case 0x80: _PC++;break;
377 case 0x82: _PC++;break;
378 case 0x89: _PC++;break;
379 case 0xC2: _PC++;break;
380 case 0xD4: _PC++;break;
381 case 0xE2: _PC++;break;
382 case 0xF4: _PC++;break;
383
384 /* KIL */
385
386 case 0x02:
387 case 0x12:
388 case 0x22:
389 case 0x32:
390 case 0x42:
391 case 0x52:
392 case 0x62:
393 case 0x72:
394 case 0x92:
395 case 0xB2:
396 case 0xD2:
397 case 0xF2:ADDCYC(0xFF);
398           _jammed=1;
399           _PC--;
400           break;
401
402 /* LAR */
403 case 0xBB: RMW_ABY(_S&=x;_A=_X=_S;X_ZN(_X));
404
405 /* LAX */
406 case 0xA7: LD_ZP(LDA;LDX);
407 case 0xB7: LD_ZPY(LDA;LDX);
408 case 0xAF: LD_AB(LDA;LDX);
409 case 0xBF: LD_ABY(LDA;LDX);
410 case 0xA3: LD_IX(LDA;LDX);
411 case 0xB3: LD_IY(LDA;LDX);
412
413 /* NOP */
414 case 0x1A:
415 case 0x3A:
416 case 0x5A:
417 case 0x7A:
418 case 0xDA:
419 case 0xFA: break;
420
421 /* RLA */
422 case 0x27: RMW_ZP(ROL;AND);
423 case 0x37: RMW_ZPX(ROL;AND);
424 case 0x2F: RMW_AB(ROL;AND);
425 case 0x3F: RMW_ABX(ROL;AND);
426 case 0x3B: RMW_ABY(ROL;AND);
427 case 0x23: RMW_IX(ROL;AND);
428 case 0x33: RMW_IY(ROL;AND);
429
430 /* RRA */
431 case 0x67: RMW_ZP(ROR;ADC);
432 case 0x77: RMW_ZPX(ROR;ADC);
433 case 0x6F: RMW_AB(ROR;ADC);
434 case 0x7F: RMW_ABX(ROR;ADC);
435 case 0x7B: RMW_ABY(ROR;ADC);
436 case 0x63: RMW_IX(ROR;ADC);
437 case 0x73: RMW_IY(ROR;ADC);
438
439 /* SLO */
440 case 0x07: RMW_ZP(ASL;ORA);
441 case 0x17: RMW_ZPX(ASL;ORA);
442 case 0x0F: RMW_AB(ASL;ORA);
443 case 0x1F: RMW_ABX(ASL;ORA);
444 case 0x1B: RMW_ABY(ASL;ORA);
445 case 0x03: RMW_IX(ASL;ORA);
446 case 0x13: RMW_IY(ASL;ORA);
447
448 /* SRE */
449 case 0x47: RMW_ZP(LSR;EOR);
450 case 0x57: RMW_ZPX(LSR;EOR);
451 case 0x4F: RMW_AB(LSR;EOR);
452 case 0x5F: RMW_ABX(LSR;EOR);
453 case 0x5B: RMW_ABY(LSR;EOR);
454 case 0x43: RMW_IX(LSR;EOR);
455 case 0x53: RMW_IY(LSR;EOR);
456
457 /* AXA - SHA */
458 case 0x93: ST_IY(_A&_X&(((A-_Y)>>8)+1));
459 case 0x9F: ST_ABY(_A&_X&(((A-_Y)>>8)+1));
460
461 /* SYA */
462 case 0x9C: ST_ABX(_Y&(((A-_X)>>8)+1));
463
464 /* SXA */
465 case 0x9E: ST_ABY(_X&(((A-_Y)>>8)+1));
466
467 /* XAS */
468 case 0x9B: _S=_A&_X;ST_ABY(_S& (((A-_Y)>>8)+1) );
469
470 /* TOP */
471 case 0x0C: LD_AB(;);
472 case 0x1C:
473 case 0x3C:
474 case 0x5C:
475 case 0x7C:
476 case 0xDC:
477 case 0xFC: LD_ABX(;);
478
479 /* XAA - BIG QUESTION MARK HERE */
480 case 0x8B: _A|=0xEE; _A&=_X; LD_IM(AND);