| 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: RMW_ZP(DEC;CMP); |
| 350 | case 0xD7: RMW_ZPX(DEC;CMP); |
| 351 | case 0xCF: RMW_AB(DEC;CMP); |
| 352 | case 0xDF: RMW_ABX(DEC;CMP); |
| 353 | case 0xDB: RMW_ABY(DEC;CMP); |
| 354 | case 0xC3: RMW_IX(DEC;CMP); |
| 355 | case 0xD3: RMW_IY(DEC;CMP); |
| 356 | |
| 357 | /* ISC */ |
| 358 | case 0xE7: RMW_ZP(INC;SBC); |
| 359 | case 0xF7: RMW_ZPX(INC;SBC); |
| 360 | case 0xEF: RMW_AB(INC;SBC); |
| 361 | case 0xFF: RMW_ABX(INC;SBC); |
| 362 | case 0xFB: RMW_ABY(INC;SBC); |
| 363 | case 0xE3: RMW_IX(INC;SBC); |
| 364 | case 0xF3: RMW_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); |