65C02 Instructions

This commit is contained in:
tudnai 2020-07-28 17:37:27 -07:00
parent c948865ece
commit bca5d074db
10 changed files with 396 additions and 559 deletions

View File

@ -11,11 +11,11 @@
320B3FC424AD88B0005EA133 /* power.png in Copy Image Files */ = {isa = PBXBuildFile; fileRef = 320B3FC324AD88B0005EA133 /* power.png */; };
320B4FC124B182DE00070038 /* Apple Disk II.png in Copy Image Files */ = {isa = PBXBuildFile; fileRef = 320B4FC024B182DD00070038 /* Apple Disk II.png */; };
320F2A8824CFD74100671B35 /* Steve2Icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 320F2A8724CFD74000671B35 /* Steve2Icon.icns */; };
320F2A8D24D0FB9200671B35 /* 6502.c in Sources */ = {isa = PBXBuildFile; fileRef = 32439F7422ECD8AD0077AAE0 /* 6502.c */; };
3213936624079C30007F5C4A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 32BFFB6022EACC660003B53F /* Main.storyboard */; };
323D042E248980600086A901 /* Preferences.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 323D042D248980600086A901 /* Preferences.storyboard */; };
323D043024898AB70086A901 /* PreferencesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 323D042F24898AB70086A901 /* PreferencesViewController.swift */; };
323D04332489BFD80086A901 /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 323D04312489BFD80086A901 /* PreferencesWindowController.swift */; };
323D0437248B6BEA0086A901 /* 6502.c in Sources */ = {isa = PBXBuildFile; fileRef = 32439F7422ECD8AD0077AAE0 /* 6502.c */; };
323D04442490B3930086A901 /* dotmatrix_effect.png in Copy Image Files */ = {isa = PBXBuildFile; fileRef = 323D04432490B3930086A901 /* dotmatrix_effect.png */; };
323E2DCF245531E600156805 /* Apple2e_Enhanced.rom in Resources */ = {isa = PBXBuildFile; fileRef = 323E2DCC245531E500156805 /* Apple2e_Enhanced.rom */; };
323E2DD1245531E600156805 /* Apple2e.rom in Resources */ = {isa = PBXBuildFile; fileRef = 323E2DCD245531E500156805 /* Apple2e.rom */; };
@ -312,6 +312,7 @@
320F2A8724CFD74000671B35 /* Steve2Icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = Steve2Icon.icns; sourceTree = "<group>"; };
320F2A8924CFFBE300671B35 /* 6502_std.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = 6502_std.h; sourceTree = "<group>"; };
320F2A8A24D0001600671B35 /* 6502_und.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = 6502_und.h; sourceTree = "<group>"; };
320F2A8B24D0828600671B35 /* 6502_C.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 6502_C.h; sourceTree = "<group>"; };
323D042D248980600086A901 /* Preferences.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Preferences.storyboard; sourceTree = "<group>"; };
323D042F24898AB70086A901 /* PreferencesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesViewController.swift; sourceTree = "<group>"; };
323D04312489BFD80086A901 /* PreferencesWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesWindowController.swift; sourceTree = "<group>"; };
@ -679,6 +680,7 @@
32439F7422ECD8AD0077AAE0 /* 6502.c */,
320F2A8924CFFBE300671B35 /* 6502_std.h */,
320F2A8A24D0001600671B35 /* 6502_und.h */,
320F2A8B24D0828600671B35 /* 6502_C.h */,
32440B69247CA1CE000F9DA1 /* 65C02.c */,
32440B67247CA1AF000F9DA1 /* 6502_vanilla.c */,
);
@ -1208,13 +1210,13 @@
32E3126D24AC033A00E61891 /* ToolBarController.swift in Sources */,
323D043024898AB70086A901 /* PreferencesViewController.swift in Sources */,
323D04332489BFD80086A901 /* PreferencesWindowController.swift in Sources */,
320F2A8D24D0FB9200671B35 /* 6502.c in Sources */,
32E3126924A98B9300E61891 /* dsk2woz.c in Sources */,
325EB63623F8F78300C6B4A4 /* disk.c in Sources */,
325EB62F23F8856F00C6B4A4 /* woz.c in Sources */,
32A9F74A2467B60B004902A1 /* speaker.c in Sources */,
325EB63923F9E48100C6B4A4 /* common.c in Sources */,
32BFFB5D22EACC630003B53F /* ViewController.swift in Sources */,
323D0437248B6BEA0086A901 /* 6502.c in Sources */,
325EB69323FE6C6200C6B4A4 /* HiRes.swift in Sources */,
32440BA32480D5C0000F9DA1 /* LoRes.swift in Sources */,
32C45306232E3EEF0000EBA1 /* RepeatingTimer.swift in Sources */,

61
src/cpu/6502_C.h Normal file
View File

@ -0,0 +1,61 @@
//
// 6502_und.h
// A2Mac
//
// Created by Tamas Rudnai on 7/27/20.
// Copyright © 2020 GameAlloy. All rights reserved.
//
#ifndef _6502_C_h
#define _6502_C_h
// 6502 instructions with additional addressing modes
// ADC AND CMP EOR LDA ORA SBC STA - (zp) addressing mode
case 0x12: ORA( src_zp_0() ); return 5; // ORA (zpg)
case 0x32: AND( src_zp_0() ); return 5; // AND (zpg)
case 0x52: EOR( src_zp_0() ); return 5; // EOR (zpg)
case 0x72: ADC( src_zp_0() ); return 5; // ADC (zpg)
case 0x92: STA( src_zp_0() ); return 5; // STA (zpg)
case 0xB2: LDA( src_zp_0() ); return 5; // LDA (zpg)
case 0xD2: CMP( src_zp_0() ); return 5; // CMP (zpg)
case 0xF2: SBC( src_zp_0() ); return 5; // SBC (zpg)
// BIT - imm abs,X zp,X addressing modes
case 0x34: BIT( src_zp_X() ); return 4; // BIT zpg,X
case 0x3C: BIT( src_abs_X() ); return 4; // BIT abs,X
case 0x89: BIT( imm() ); return 2; // BIT imm
// DEC INC - acc addressing mode
case 0x1A: INA(); return 2; // INA imm (INC A)
case 0x3A: DEA(); return 2; // DEA imm (DEC A)
// JMP - (abs,X) addressing mode
case 0x7C: JMP( addr_abs_X() ); return 6; // JMP abs,X
// Additional instructions
// BRA - BRanch Always
case 0x80: JMP( rel_addr() ); return 3; // BRA reladdr
// PHX PHY PLX PLY - PusH or PulL X or Y register
case 0x5A: PHY(); return 3; // PHY
case 0x7A: PLY(); return 4; // PLY
case 0xDA: PHX(); return 3; // PHX
case 0xFA: PLX(); return 4; // PLX
// STZ - STore Zero
case 0x64: STZ( addr_zp() ); return 3; // STZ zpg
case 0x74: STZ( addr_zp_X() ); return 4; // STZ zpg,X
case 0x9C: STZ( addr_abs() ); return 4; // STZ abs
case 0x9E: STZ( addr_abs_X() ); return 5; // STZ abs,X
// TRB - Test and Reset Bits
case 0x04: TSB( addr_zp() ); return 5; // TSB zpg
case 0x0C: TSB( addr_abs() ); return 6; // TSB abs
case 0x14: TRB( addr_zp() ); return 5; // TRB zpg
case 0x1C: TRB( addr_abs() ); return 6; // TRB abs
#endif /* _6502_C_h */

View File

@ -6,8 +6,8 @@
// Copyright © 2020 GameAlloy. All rights reserved.
//
#ifndef _502_std_h
#define _502_std_h
#ifndef _6502_std_h
#define _6502_std_h
case 0x00: BRK(); return 7; // BRK
case 0x01: ORA( src_X_ind() ); return 6; // ORA X,ind
@ -226,4 +226,4 @@
case 0xFE: INC( addr_abs_X() ); return 7; // INC abs,X
#endif /* _502_std_h */
#endif /* _6502_std_h */

View File

@ -6,8 +6,8 @@
// Copyright © 2020 GameAlloy. All rights reserved.
//
#ifndef _502_und_h
#define _502_und_h
#ifndef _6502_und_h
#define _6502_und_h
case 0x02: HLT(); return 0; // HLT* - Halts / Hangs / Jams / Kills the CPU (undocumented)
case 0x03: SLO( addr_zp_X() ); return 8; // SLO* zpg,X (undocumented)
@ -180,4 +180,4 @@
case 0xFF: ISB( addr_abs_X() ); return 7; // ISB* abx 7 (undocumented)
#endif /* _502_und_h */
#endif /* _6502_und_h */

View File

@ -20,6 +20,13 @@
// You should have received a copy of the GNU General Public License
// along with Steve ][. If not, see <https://www.gnu.org/licenses/>.
//
// Documentations:
//
// http://nesdev.com/6502_cpu.txt
// http://www.oxyron.de/html/opcodes02.html
// https://macgui.com/kb/article/46
// https://www.masswerk.at/6502/6502_instruction_set.html
//
#define CLK_WAIT
@ -29,7 +36,6 @@
#include <string.h>
#include <time.h>
#include "6502.h"
#include "woz.h"
#include "speaker.h"
@ -37,6 +43,10 @@ void ViewController_spk_up_play(void);
void ViewController_spk_dn_play(void);
volatile cpuMode_s cpuMode = cpuMode_normal;
volatile cpuState_s cpuState = cpuState_unknown;
#include "../util/common.h"
@ -49,12 +59,17 @@ void ViewController_spk_dn_play(void);
const unsigned long long int iterations = G;
unsigned long long int inst_cnt = 0;
//const unsigned int fps = 30;
const unsigned long long default_MHz_6502 = 1.023 * M; // 2 * M; // 4 * M; // 8 * M; // 16 * M; // 128 * M; // 256 * M; // 512 * M;
const unsigned long long startup_MHz_6502 = 32 * M;
unsigned long long MHz_6502 = default_MHz_6502;
unsigned long long clk_6502_per_frm = default_MHz_6502 / fps;
unsigned long long clk_6502_per_frm_set = default_MHz_6502 / fps;
unsigned int video_fps_divider = DEF_VIDEO_DIV;
unsigned int fps = DEFAULT_FPS;
const double default_MHz_6502 = 1.023; // 2 * M; // 4 * M; // 8 * M; // 16 * M; // 128 * M; // 256 * M; // 512 * M;
const double iigs_MHz_6502 = 2.8;
const double iicplus_MHz_6502 = 4;
const double startup_MHz_6502 = 32;
double MHz_6502 = default_MHz_6502;
unsigned long long clk_6502_per_frm = FRAME_INIT( default_MHz_6502 );
unsigned long long clk_6502_per_frm_set = FRAME_INIT( default_MHz_6502 );
unsigned long long clk_6502_per_frm_max_sound = 4 * FRAME_INIT( default_MHz_6502 );
unsigned long long clk_6502_per_frm_max = 0;
@ -81,13 +96,13 @@ m6502_t m6502 = {
0, // res
0, // V
0, // N
0, // PC
0, // SP
0, // clktime
0, // clklast
0, // trace
0, // step
0, // brk
@ -154,7 +169,7 @@ typedef struct {
!!!! `his has to be here!!!
This idea is that "INLINE" would work only if it is
located in the same source file -- hence the include...
**/
**/
INLINE flags_t getFlags() {
flags_t f = {
@ -167,7 +182,7 @@ INLINE flags_t getFlags() {
m6502.V != 0, // Overflow Flag ???
m6502.N != 0, // Negative Flag
};
return f;
}
@ -188,7 +203,7 @@ INLINE void setFlags( uint8_t byte ) {
#include "6502_instructions.h"
INLINE int m6502_Step() {
#ifdef DEBUG___
switch ( m6502.PC ) {
@ -203,7 +218,7 @@ INLINE int m6502_Step() {
default:
break;
}
switch ( m6502.PC ) {
case 0xE000:
@ -227,458 +242,18 @@ INLINE int m6502_Step() {
}
#endif
#ifdef FUNCTIONTEST
switch ( m6502.PC ) {
case 0x400:
dbgPrintf("START...\n");
break;
case 0x0438:
dbgPrintf2("*** TEST 1 (%04X)\n", m6502.PC);
break;
case 0x0581:
dbgPrintf2("*** TEST 2 (%04X)\n", m6502.PC);
break;
case 0x05C8:
dbgPrintf2("*** TEST 3 (%04X)\n", m6502.PC);
break;
case 0x05FC:
dbgPrintf2("*** TEST 4 (%04X)\n", m6502.PC);
break;
case 0x0776:
dbgPrintf2("*** TEST 5 (%04X)\n", m6502.PC);
break;
case 0x0872:
dbgPrintf2("*** TEST 6 (%04X)\n", m6502.PC);
break;
case 0x08A6:
dbgPrintf2("*** TEST 7 (%04X)\n", m6502.PC);
break;
case 0x08F0:
dbgPrintf2("*** TEST 8 (%04X)\n", m6502.PC);
break;
case 0x0946:
dbgPrintf2("*** TEST 9 (%04X)\n", m6502.PC);
break;
case 0x0982:
dbgPrintf2("*** TEST 10 (%04X)\n", m6502.PC);
break;
case 0x09B9:
dbgPrintf2("*** TEST 11 (%04X)\n", m6502.PC);
break;
case 0x0A11:
dbgPrintf2("*** TEST 12 (%04X)\n", m6502.PC);
break;
case 0x0AB7:
dbgPrintf2("*** TEST 13 (%04X)\n", m6502.PC);
break;
case 0x0D7D:
dbgPrintf2("*** TEST 14 (%04X)\n", m6502.PC);
break;
case 0x0E46:
dbgPrintf2("*** TEST 15 (%04X)\n", m6502.PC);
break;
case 0x0F01:
dbgPrintf2("*** TEST 16 (%04X)\n", m6502.PC);
break;
case 0x0F43:
dbgPrintf2("*** TEST 17 (%04X)\n", m6502.PC);
break;
case 0x0FFA:
dbgPrintf2("*** TEST 18 (%04X)\n", m6502.PC);
break;
case 0x103A:
dbgPrintf2("*** TEST 19 (%04X)\n", m6502.PC);
break;
case 0x1330:
dbgPrintf2("*** TEST 20 (%04X)\n", m6502.PC);
break;
case 0x162A:
dbgPrintf2("*** TEST 21 (%04X)\n", m6502.PC);
break;
case 0x16DB:
dbgPrintf2("*** TEST 22 (%04X)\n", m6502.PC);
break;
case 0x17FA:
dbgPrintf2("*** TEST 23 (%04X)\n", m6502.PC);
break;
case 0x1899:
dbgPrintf2("*** TEST 24 (%04X)\n", m6502.PC);
break;
case 0x1B63:
dbgPrintf2("*** TEST 25 (%04X)\n", m6502.PC);
break;
case 0x1CB7:
dbgPrintf2("*** TEST 26 (%04X)\n", m6502.PC);
break;
case 0x1DC5:
dbgPrintf("*** TEST 27 (%04X)\n", m6502.PC);
break;
case 0x1ED3:
dbgPrintf2("*** TEST 28 (%04X)\n", m6502.PC);
break;
case 0x22B7:
dbgPrintf2("*** TEST 29 (%04X)\n", m6502.PC);
break;
case 0x23FB:
dbgPrintf2("*** TEST 30 (%04X)\n", m6502.PC);
break;
case 0x257B:
dbgPrintf2("*** TEST 31 (%04X)\n", m6502.PC);
break;
case 0x271F:
dbgPrintf2("*** TEST 32 (%04X)\n", m6502.PC);
break;
case 0x289F:
dbgPrintf2("*** TEST 33 (%04X)\n", m6502.PC);
break;
case 0x2A43:
dbgPrintf2("*** TEST 34 (%04X)\n", m6502.PC);
break;
case 0x2AED:
dbgPrintf2("*** TEST 35 (%04X)\n", m6502.PC);
break;
case 0x2BA7:
dbgPrintf2("*** TEST 36 (%04X)\n", m6502.PC);
break;
case 0x2C55:
dbgPrintf2("*** TEST 37 (%04X)\n", m6502.PC);
break;
case 0x2D13:
dbgPrintf2("*** TEST 38 (%04X)\n", m6502.PC);
break;
case 0x3103:
dbgPrintf2("*** TEST 40 (%04X)\n", m6502.PC);
break;
case 0x32FC:
dbgPrintf2("*** TEST 41 (%04X)\n", m6502.PC);
break;
case 0x3361:
dbgPrintf2("*** TEST 42 (%04X)\n", m6502.PC);
break;
case 0x3405:
dbgPrintf2("*** TEST 43 (%04X)\n", m6502.PC);
break;
case 0x345D:
dbgPrintf2("*** TEST 44 (%04X)\n", m6502.PC);
break;
case 0x3469:
dbgPrintf2("*** TEST PASSED (%04X)\n", m6502.PC);
break;
default:
break;
}
#endif
disNewInstruction();
switch ( fetch() ) {
case 0x00: BRK(); return 7; // BRK
case 0x01: ORA( src_X_ind() ); return 6; // ORA X,ind
// case 0x02: // t jams
// case 0x03: // SLO* (undocumented)
// case 0x04: // NOP* (undocumented)
case 0x05: ORA( src_zp() ); return 3; // ORA zpg
case 0x06: ASL( addr_zp() ); return 5; // ASL zpg
// case 0x07: // SLO* (undocumented)
case 0x08: PHP(); return 3; // PHP
case 0x09: ORA( imm() ); return 2; // ORA imm
case 0x0A: ASLA(); return 2; // ASL A
// case 0x0B: // ANC** (undocumented)
// case 0x0C: // NOP* (undocumented)
case 0x0D: ORA( src_abs() ); return 4; // ORA abs
case 0x0E: ASL( addr_abs() ); return 6; // ASL abs
// case 0x0F: // SLO* (undocumented)
case 0x10: BPL( rel_addr() ); return 3; // BPL rel
case 0x11: ORA( src_ind_Y() ); return 5; // ORA ind,Y
// case 0x12: // t jams
// case 0x13: // SLO* (undocumented)
// case 0x14: // NOP* (undocumented)
case 0x15: ORA( src_zp_X() ); return 4; // ORA zpg,X
case 0x16: ASL( addr_zp_X() ); return 6; // ASL zpg,X
// case 0x17: // SLO* (undocumented)
case 0x18: CLC(); return 2; // CLC
case 0x19: ORA( src_abs_Y() ); return 4; // ORA abs,Y
// case 0x1A: // NOP* (undocumented)
// case 0x1B: // SLO* (undocumented)
// case 0x1C: // NOP* (undocumented)
case 0x1D: ORA( src_abs_X() ); return 4; // ORA abs,X
case 0x1E: ASL( addr_abs_X() ); return 7; // ASL abs,X
// case 0x1F: // SLO* (undocumented)
case 0x20: JSR( abs_addr() ); return 6; // JSR abs
case 0x21: AND( src_X_ind() ); return 6; // AND X,ind
// case 0x22: HLT* - Halts / Hangs / Jams / Kills the CPU (undocumented)
// case 0x23: RLA izx 8
case 0x24: BIT( src_zp() ); return 3; // BIT zpg
case 0x25: AND( src_zp() ); return 3; // AND zpg
case 0x26: ROL( addr_zp() ); return 5; // ROL zpg
// case 0x27: RLA zp 5
case 0x28: PLP(); return 4; // PLP
case 0x29: AND( imm() ); return 2; // AND imm
case 0x2A: ROLA(); return 2; // ROL A
// case 0x2B: ANC imm 2
case 0x2C: BIT( src_abs() ); return 4; // BIT abs
case 0x2D: AND( src_abs() ); return 4; // AND abs
case 0x2E: ROL( addr_abs() ); return 6; // ROL abs
// case 0x2F: RLA abs 6
case 0x30: BMI( rel_addr() ); return 3; // BMI rel
case 0x31: AND( src_ind_Y() ); return 5; // AND ind,Y
// case 0x32: HLT* - Halts / Hangs / Jams / Kills the CPU (undocumented)
// case 0x33: RLA izy 8
// case 0x34: NOP zpx 4
case 0x35: AND( src_zp_X() ); return 4; // AND zpg,X
case 0x36: ROL( addr_zp_X() ); return 6; // ROL zpg,X
// case 0x37: RLA zpx 6
case 0x38: SEC(); return 2; // SEC
case 0x39: AND( src_abs_Y() ); return 4; // AND abs,Y
// case 0x3A: NOP 2
// case 0x3B: RLA aby 7
// case 0x3C: NOP abx 4
case 0x3D: AND( src_abs_X() ); return 4; // AND abs,X
case 0x3E: ROL( addr_abs_X() ); return 7; // ROL abs,X
// case 0x3F: RLA abx 7
case 0x40: RTI(); return 6; // RTI
case 0x41: EOR( src_X_ind() ); return 6; // EOR X,ind
// case 0x42: HLT* - Halts / Hangs / Jams / Kills the CPU (undocumented)
// case 0x43: SRE izx 8
// case 0x44: NOP zp 3
case 0x45: EOR( src_zp() ); return 3; // EOR zpg
case 0x46: LSR( addr_zp() ); return 5; // LSR zpg
// case 0x47: SRE zp 5
case 0x48: PHA(); return 3; // PHA
case 0x49: EOR( imm() ); return 2; // EOR imm
case 0x4A: LSRA(); return 2; // LSR A
// case 0x4B: ALR imm 2
case 0x4C: JMP( abs_addr() ); return 3; // JMP abs
case 0x4D: EOR( src_abs() ); return 4; // EOR abs
case 0x4E: LSR( addr_abs() ); return 6; // LSR abs
// case 0x4F: SRE abs 6
case 0x50: BVC( rel_addr() ); return 3; // BVC rel
case 0x51: EOR( src_ind_Y() ); return 5; // EOR ind,Y
// case 0x52: HLT* - Halts / Hangs / Jams / Kills the CPU (undocumented)
// case 0x53: SRE izy 8
// case 0x54: NOP zpx 4
case 0x55: EOR( src_zp_X() ); return 4; // AND zpg,X
case 0x56: LSR( addr_zp_X() ); return 6; // LSR zpg,X
// case 0x57: SRE zpx 6
case 0x58: CLI(); return 2; // CLI
case 0x59: EOR( src_abs_Y() ); return 4; // EOR abs,Y
// case 0x5A: NOP 2
// case 0x5B: SRE aby 7
// case 0x5C: NOP abx 4
case 0x5D: EOR( src_abs_X() ); return 4; // EOR abs,X
case 0x5E: LSR( addr_abs_X() ); return 7; // LSR abs,X
// case 0x5F: SRE abx 7
case 0x60: RTS(); return 6; // RTS
case 0x61: ADC( src_X_ind() ); return 6; // ADC X,ind
// case 0x62: HLT* - Halts / Hangs / Jams / Kills the CPU (undocumented)
// case 0x63: RRA izx 8
// case 0x64: NOP zp 3
case 0x65: ADC( src_zp() ); return 3; // ADC zpg
case 0x66: ROR( addr_zp() ); return 5; // ROR zpg
// case 0x67: RRA zp 5
case 0x68: PLA(); break; // PLA
case 0x69: ADC( imm() ); return 2; // ADC imm
case 0x6A: RORA(); return 2; // ROR A
// case 0x6B: ARR imm 2
case 0x6C: JMP( ind_addr() ); return 5; // JMP ind
case 0x6D: ADC( src_abs() ); return 4; // ADC abs
case 0x6E: ROR( addr_abs() ); return 6; // ROR abs
// case 0x6F: RRA abs 6
case 0x70: BVS( rel_addr() ); return 3; // BVS rel
case 0x71: ADC( src_ind_Y() ); return 5; // ADC ind,Y
// case 0x72:
// case 0x73:
// case 0x74:
case 0x75: ADC( src_zp_X() ); return 4; // ADC zpg,X
case 0x76: ROR( addr_zp_X() ); return 6; // ROR zpg,X
// case 0x77:
case 0x78: SEI(); return 2; // SEI
case 0x79: ADC( src_abs_Y() ); return 4; // ADC abs,Y
// case 0x7A:
// case 0x7B:
// case 0x7C:
case 0x7D: ADC( src_abs_X() ); return 4; // ADC abs,X
case 0x7E: ROR( addr_abs_X() ); return 7; // ROR abs,X
// case 0x7F:
// case 0x80:
case 0x81: STA( addr_X_ind() ) ; return 6; // STA X,ind
// case 0x82:
// case 0x83:
case 0x84: STY( addr_zp() ); return 3; // STY zpg
case 0x85: STA( addr_zp() ); return 3; // STA zpg
case 0x86: STX( addr_zp() ); return 3; // STX zpg
// case 0x87:
case 0x88: DEY(); return 2; // DEY
// case 0x89: NOP(); imm(); return 4; // NOP imm
case 0x8A: TXA(); return 2; // TXA
// case 0x8B:
case 0x8C: STY( addr_abs() ); return 4; // STY abs
case 0x8D: STA( addr_abs() ); return 4; // STA abs
case 0x8E: STX( addr_abs() ); return 4; // STX abs
// case 0x8F:
case 0x90: BCC( rel_addr() ); return 3; // BCC rel
case 0x91: STA( addr_ind_Y() ); return 6; // STA ind,Y
// case 0x92:
// case 0x93:
case 0x94: STY( addr_zp_X() ); return 4; // STY zpg,X
case 0x95: STA( addr_zp_X() ); return 4; // STA zpg,X
case 0x96: STX( addr_zp_Y() ); return 4; // STX zpg,Y
// case 0x97:
case 0x98: TYA(); return 2; // TYA
case 0x99: STA( addr_abs_Y() ); return 5; // STA abs,Y
case 0x9A: TXS(); return 2; // TXS
// case 0x9B:
// case 0x9C:
case 0x9D: STA( addr_abs_X() ); return 5; // STA abs,X
// case 0x9E:
// case 0x9F:
case 0xA0: LDY( imm() ); return 2; // LDY imm
case 0xA1: LDA( src_X_ind() ) ; return 6; // LDA X,ind
case 0xA2: LDX( imm() ); return 2; // LDX imm
// case 0xA3:
case 0xA4: LDY( src_zp() ); return 3; // LDY zpg
case 0xA5: LDA( src_zp() ); return 3; // LDA zpg
case 0xA6: LDX( src_zp() ); return 3; // LDX zpg
// case 0xA7:
case 0xA8: TAY(); return 2; // TAY
case 0xA9: LDA( imm() ); return 2; // LDA imm
case 0xAA: TAX(); return 2; // TAX
// case 0xAB:
case 0xAC: LDY( src_abs() ); return 4; // LDY abs
case 0xAD: LDA( src_abs() ); return 4; // LDA abs
case 0xAE: LDX( src_abs() ); return 4; // LDX abs
// case 0xAF:
case 0xB0: BCS( rel_addr() ); return 3; // BCS rel
case 0xB1: LDA( src_ind_Y() ); return 5; // LDA ind,Y
// case 0xB2:
// case 0xB3:
case 0xB4: LDY( src_zp_X() ); return 4; // LDY zpg,X
case 0xB5: LDA( src_zp_X() ); return 4; // LDA zpg,X
case 0xB6: LDX( src_zp_Y() ); return 4; // LDX zpg,Y
// case 0xB7:
case 0xB8: CLV(); return 2; // CLV
case 0xB9: LDA( src_abs_Y() ); return 4; // LDA abs,Y
case 0xBA: TSX(); return 2; // TSX
// case 0xBB:
case 0xBC: LDY( src_abs_X() ); return 4; // LDY abs,X
case 0xBD: LDA( src_abs_X() ); return 4; // LDA abs,X
case 0xBE: LDX( src_abs_Y() ); return 4; // LDX abs,Y
// case 0xBF:
case 0xC0: CPY( imm() ); return 2; // CPY imm
case 0xC1: CMP( src_X_ind() ) ; return 6; // LDA X,ind
// case 0xC2:
// case 0xC3:
case 0xC4: CPY( src_zp() ); return 3; // CPY zpg
case 0xC5: CMP( src_zp() ); return 3; // CMP zpg
case 0xC6: DEC( addr_zp() ); return 5; // DEC zpg
// case 0xC7:
case 0xC8: INY(); return 2; // INY
case 0xC9: CMP( imm() ); return 2; // CMP imm
case 0xCA: DEX(); return 2; // DEX
// case 0xCB:
case 0xCC: CPY( src_abs() ); return 4; // CPY abs
case 0xCD: CMP( src_abs() ); return 4; // CMP abs
case 0xCE: DEC( addr_abs() ); return 6; // DEC abs
// case 0xCF:
case 0xD0: BNE( rel_addr() ); return 3; // BNE rel
case 0xD1: CMP( src_ind_Y() ); return 5; // CMP ind,Y
// case 0xD2:
// case 0xD3:
// case 0xD4:
case 0xD5: CMP( src_zp_X() ); return 4; // CMP zpg,X
case 0xD6: DEC( addr_zp_X() ); return 6; // DEC zpg,X
// case 0xD7:
case 0xD8: CLD(); return 2; // CLD
case 0xD9: CMP( src_abs_Y() ); return 4; // CMP abs,Y
// case 0xDA:
// case 0xDB:
// case 0xDC:
case 0xDD: CMP( src_abs_X() ); return 4; // CMP abs,X
case 0xDE: DEC( addr_abs_X() ); return 7; // DEC abs,X
// case 0xDF:
case 0xE0: CPX( imm() ); return 2; // CPX imm
case 0xE1: SBC( src_X_ind() ) ; return 6; // SBC (X,ind)
// case 0xE2:
// case 0xE3:
case 0xE4: CPX( src_zp() ); return 3; // CPX zpg
case 0xE5: SBC( src_zp() ); return 3; // SBC zpg
case 0xE6: INC( addr_zp() ); return 5; // INC zpg
// case 0xE7:
case 0xE8: INX(); return 2; // INX
case 0xE9: SBC( imm() ); return 2; // SBC imm
case 0xEA: NOP(); return 2; // NOP
// case 0xEB:
case 0xEC: CPX( src_abs() ); return 4; // CPX abs
case 0xED: SBC( src_abs() ); return 4; // SBC abs
case 0xEE: INC( addr_abs() ); return 6; // INC abs
// case 0xEF:
case 0xF0: BEQ( rel_addr() ); return 3; // BEQ rel
case 0xF1: SBC( src_ind_Y() ); return 5; // SBC ind,Y
// case 0xF2:
// case 0xF3:
// case 0xF4:
case 0xF5: SBC( src_zp_X() ); return 4; // SBC zpg,X
case 0xF6: INC( addr_zp_X() ); return 6; // INC zpg,X
// case 0xF7:
case 0xF8: SED(); return 2; // SED
case 0xF9: SBC( src_abs_Y() ); return 4; // SBC abs,Y
// case 0xFA:
// case 0xFB:
// case 0xFC:
case 0xFD: SBC( src_abs_X() ); return 4; // SBC abs,X
case 0xFE: INC( addr_abs_X() ); return 7; // INC abs,X
// case 0xFF:
#include "6502_std.h" // standard instructions
#include "6502_C.h" // 65"C"02 extended instructions
default:
dbgPrintf("%04X: Unimplemented Instruction 0x%02X\n", m6502.PC -1, memread( m6502.PC -1 ));
return 2;
}
// } // fetch16
// } // fetch16
return 2;
}
@ -717,22 +292,24 @@ void hardReset() {
}
void softReset() {
// m6502.PC = memread16(SOFTRESET_VECTOR);
// m6502.PC = memread16(SOFTRESET_VECTOR);
m6502.PC = memread16( RESET_VECTOR );
m6502.SP = 0xFF;
// N V - B D I Z C
// 0 0 1 0 0 1 0 1
setFlags(0x25);
spkr_stopAll();
}
void m6502_Run() {
// init time
//#ifdef CLK_WAIT
// unsigned long long elpased = (unsigned long long)-1LL;
//#endif
//#ifdef CLK_WAIT
// unsigned long long elpased = (unsigned long long)-1LL;
//#endif
#ifdef SPEEDTEST
for ( inst_cnt = 0; inst_cnt < iterations ; inst_cnt++ )
#elif defined( CLK_WAIT )
@ -740,44 +317,48 @@ void m6502_Run() {
// we will also use this to pause the simulation if not finished by the end of the frame
for ( clk_6502_per_frm_max = clk_6502_per_frm; clkfrm < clk_6502_per_frm_max ; clkfrm += m6502_Step() )
#else
// this is for max speed only -- WARNING! It works only if simulation runs in a completely different thread from the Update()
for ( ; ; )
// this is for max speed only -- WARNING! It works only if simulation runs in a completely different thread from the Update()
for ( ; ; )
#endif
{
{
// TODO: clkfrm is already increamented!!!
printDisassembly(outdev);
#ifdef INTERRUPT_CHECK_PER_STEP
if ( m6502.IF ) {
switch (m6502.interrupt) {
case HALT:
// CPU is haletd, nothing to do here...
return;
if ( m6502.IF ) {
switch (m6502.interrupt) {
case HALT:
// CPU is haletd, nothing to do here...
return;
case IRQ:
interrupt_IRQ();
break;
case NMI:
interrupt_NMI();
break;
case HARDRESET:
hardReset();
break;
case SOFTRESET:
softReset();
break;
default:
break;
}
case IRQ:
interrupt_IRQ();
break;
case NMI:
interrupt_NMI();
break;
case HARDRESET:
hardReset();
break;
case SOFTRESET:
softReset();
break;
default:
break;
}
m6502.IF = 0;
}
m6502.IF = 0;
}
#endif // INTERRUPT_CHECK_PER_STEP
}
}
// TODO: WHat if we dynamically reduce or increace CPU speed?
m6502.clktime += clk_6502_per_frm;
if( diskAccelerator_count ) {
@ -787,9 +368,11 @@ void m6502_Run() {
clk_6502_per_frm = clk_6502_per_frm_set;
}
}
// play the entire sound buffer for this frame
spkr_update();
// this will take care of turning off disk motor sound when time is up
spkr_update_disk_sfx();
}
void read_rom( const char * bundlePath, const char * filename, uint8_t * rom, const uint16_t addr ) {
@ -799,7 +382,7 @@ void read_rom( const char * bundlePath, const char * filename, uint8_t * rom, co
strcpy( fullPath, bundlePath );
strcat( fullPath, "/");
strcat( fullPath, filename );
FILE * f = fopen(fullPath, "rb");
if (f == NULL) {
perror("Failed to read ROM: ");
@ -809,10 +392,10 @@ void read_rom( const char * bundlePath, const char * filename, uint8_t * rom, co
fseek(f, 0L, SEEK_END);
uint16_t flen = ftell(f);
fseek(f, 0L, SEEK_SET);
fread( rom + addr, 1, flen, f);
fclose(f);
}
@ -826,7 +409,7 @@ size_t getFileSize ( const char * fullPath ) {
fseek(f, 0L, SEEK_END);
size_t flen = ftell(f);
fseek(f, 0L, SEEK_SET);
fclose(f);
return flen;
@ -839,7 +422,7 @@ void rom_loadFile( const char * bundlePath, const char * filename ) {
strcpy( fullPath, bundlePath );
strcat( fullPath, "/");
strcat( fullPath, filename );
size_t flen = getFileSize(fullPath);
if ( flen == 0 ) {
@ -855,17 +438,33 @@ void rom_loadFile( const char * bundlePath, const char * filename ) {
read_rom( bundlePath, filename, Apple2_16K_ROM, 0x1000);
memcpy(Apple2_64K_MEM + 0xD000, Apple2_16K_ROM + 0x1000, 12 * KB);
}
}
void openLog() {
#ifdef DISASSEMBLY
outdev = fopen("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/disassembly_new.log", "w+");
#endif
// for DEBUG ONLY!!! -- use stdout if could not create log file
// if (outdev == NULL) {
// outdev = stdout;
// }
}
void closeLog() {
if ( ( outdev ) && ( outdev != stdout ) && ( outdev != stderr ) ) {
fclose(outdev);
}
}
void m6502_ColdReset( const char * bundlePath, const char * romFileName ) {
inst_cnt = 0;
mhz = (double)MHz_6502 / M;
spkr_init();
unsigned long long saved_frm_set = clk_6502_per_frm_set;
clk_6502_per_frm =
clk_6502_per_frm_max =
clk_6502_per_frm_set = 0;
@ -873,35 +472,22 @@ void m6502_ColdReset( const char * bundlePath, const char * romFileName ) {
// wait 100ms to be sure simulation has been halted
usleep(100000);
printf("Bundlepath: %s\n", bundlePath);
// epoch = rdtsc();
// sleep(1);
// unsigned long long e = rdtsc();
// tick_per_sec = e - epoch;
// tick_6502_per_sec = tick_per_sec / MHz_6502;
// printf("Bundlepath: %s\n", bundlePath);
// epoch = rdtsc();
// sleep(1);
// unsigned long long e = rdtsc();
// tick_per_sec = e - epoch;
// tick_6502_per_sec = tick_per_sec / MHz_6502;
resetMemory();
outdev = fopen("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/disassembly_new.log", "w+");
if (outdev == NULL) {
outdev = stdout;
}
#ifdef FUNCTIONTEST
FILE * f = fopen("/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/6502_functional_test.bin", "rb");
if (f == NULL) {
perror("Failed: ");
return;
}
fread( RAM, 1, 65536, f);
fclose(f);
read_rom( bundlePath, "6502_functional_test.bin", Apple2_64K_RAM, 0);
memcpy(Apple2_64K_MEM, Apple2_64K_RAM, 65536);
m6502.PC = 0x400;
#else
// Apple ][+ ROM
@ -911,7 +497,7 @@ void m6502_ColdReset( const char * bundlePath, const char * romFileName ) {
read_rom( bundlePath, "DISK_II_C600.ROM", Apple2_64K_RAM, 0xC600);
memcpy(Apple2_64K_MEM + 0xC600, Apple2_64K_RAM + 0xC600, 0x100);
// read_rom( "/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/", "DISK_II_C600.ROM", Apple2_64K_MEM, 0xC600);
// read_rom( "/Users/trudnai/Library/Containers/com.gamealloy.A2Mac/Data/", "DISK_II_C600.ROM", Apple2_64K_MEM, 0xC600);
m6502.A = m6502.X = m6502.Y = 0xFF;
// reset vector
@ -925,30 +511,30 @@ void m6502_ColdReset( const char * bundlePath, const char * romFileName ) {
// memory size
//*((uint16_t*)(&RAM[0x73])) = 0xC000;
m6502.PC = memread16( RESET_VECTOR );
#endif
uint8_t counter[] = {
// 1 * COUNTER2
// 2
// 3 ORG $1000
// 4 SCREEN EQU $400
// 5 HOME EQU $FC58
// 6 DIGITS EQU $06
// 7 ZERO EQU $B0
// 8 CARRY EQU $BA
// 9 RDKEY EQU $FD0C
//10
// 1 * COUNTER2
// 2
// 3 ORG $1000
// 4 SCREEN EQU $400
// 5 HOME EQU $FC58
// 6 DIGITS EQU $06
// 7 ZERO EQU $B0
// 8 CARRY EQU $BA
// 9 RDKEY EQU $FD0C
//10
// I have placed NOP to keep addresses
0xA0, 0x09, 0xEA, //11 LDY #$09 ; NOP
0x84, 0x06, //12 STY #DIGITS
0xEA, 0xEA, //13 NOP NOP
0xEA, 0xEA, 0xEA, //14 NOP NOP NOP
0xA6, 0x06, //15 LDY DIGITS
0xA9, 0xB0, //16 CLEAR LDA #ZERO
0x99, 0x00, 0x04, //17 STA SCREEN,Y
@ -973,7 +559,7 @@ void m6502_ColdReset( const char * bundlePath, const char * romFileName ) {
0x4C, 0x20, 0x10, //33 JMP NEXT
0x60, //34 END RTS
0xB9, 0x00, 0x04, //36 INC LDA SCREEN,Y
0xAA, //37 TAX
0xE8, //38 INX
@ -981,7 +567,7 @@ void m6502_ColdReset( const char * bundlePath, const char * romFileName ) {
0x99, 0x00, 0x04, //40 STA SCREEN,Y
0x60, //41 RTS
};
uint8_t counter_fast[] = {
// 1 * COUNTER2
@ -994,7 +580,7 @@ void m6502_ColdReset( const char * bundlePath, const char * romFileName ) {
// 8 CARRY EQU $BA
// 9 RDKEY EQU $FD0C
//10
// I have placed NOP to keep addresses
0xA0, 0x06, // 00 LDY #$09
@ -1027,11 +613,17 @@ void m6502_ColdReset( const char * bundlePath, const char * romFileName ) {
0x60, // 2E END RTS
};
// set the default speed
clk_6502_per_frm_set = clk_6502_per_frm = default_MHz_6502 / fps;
clk_6502_per_frm_set = clk_6502_per_frm = FRAME(default_MHz_6502);
// Initialize Paddle / Game Controller / Joystick / Mouse Buttons
setIO(0xC061, 0);
setIO(0xC062, 0);
setIO(0xC063, 1 << 7); // inverted (bit 7: not pressed)
}
@ -1042,7 +634,7 @@ void tst6502() {
m6502_ColdReset( "", "" );
// clock_t start = clock();
// epoch = rdtsc();
// epoch = rdtsc();
m6502_Run();
// clock_t end = clock();
// double execution_time = ((double) (end - start)) / CLOCKS_PER_SEC;
@ -1055,7 +647,7 @@ void tst6502() {
double mips = inst_cnt / (execution_time * M);
double mhz = m6502.clktime / (execution_time * M);
printf("clk:%llu Elpased time: (%llu / %u / %llu), %.3lfs (%.3lf MIPS, %.3lf MHz)\n", iterations *3, tick_per_sec, MHz_6502, tick_6502_per_sec, execution_time, mips, mhz);
// printf(" dd:%llu ee:%llu nn:%llu\n", dd, ee, ee - dd);
// printf(" dd:%llu ee:%llu nn:%llu\n", dd, ee, ee - dd);
#endif
}

View File

@ -46,6 +46,62 @@ INLINE void BIT( uint8_t src ) {
set_flags_Z(m6502.A & src);
}
/**
TRB - Test and Reset Bits
TRB can be one the more confusing instructions for a couple of reasons.
First, the term reset is used to refer to the clearing of a bit, whereas the term clear had been used consistently before, such as CLC
which stands for CLear Carry. Second, the effect on the Z flag is determined by a different function than the effect on memory.
TRB has the same effect on the Z flag that a BIT instruction does. Specifically, it is based on whether the result of a bitwise AND of the
accumulator with the contents of the memory location specified in the operand is zero. Also, like BIT, the accumulator is not affected.
The accumulator determines which bits in the memory location specified in the operand are cleared and which are not affected.
The bits in the accumulator that are ones are cleared (in memory), and the bits that are zeros (in the accumulator) are not affected (in memory).
This is the same as saying that the resulting memory contents are the bitwise AND of the memory contents with the complement of the
accumulator (i.e. the exclusive-or of the accululator with $FF).
OP LEN CYC MODE FLAGS SYNTAX
-- --- --- ---- ----- ------
14 2 5 zp ......Z. TRB $12
1C 3 6 abs ......Z. TRB $3456
**/
INLINE void TRB( uint16_t addr ) {
dbgPrintf("TRB(%02X) ", src);
disPrintf(disassembly.inst, "TRB");
set_flags_Z( WRLOMEM[addr] & m6502.A );
WRLOMEM[addr] &= ~m6502.A;
}
/**
TSB - Test and Set Bits
TSB, like TRB, can be confusing. For one, like TRB, the effect on the Z flag is determined by a different function than the effect on memory.
TSB, like TRB, has the same effect on the Z flag that a BIT instruction does. Specifically, it is based on whether the result of a bitwise AND
of the accumulator with the contents of the memory location specified in the operand is zero. Also, like BIT (and TRB), the accumulator is not affected.
The accumulator determines which bits in the memory location specified in the operand are set and which are not affected. The bits in the
accumulator that are ones are set to one (in memory), and the bits that are zeros (in the accumulator) are not affected (in memory).
This is the same as saying that the resulting memory contents are the bitwise OR of the memory contents with the accumulator.
Flags affected: Z
OP LEN CYC MODE FLAGS SYNTAX
-- --- --- ---- ----- ------
04 2 5 zp ......Z. TSB $12
0C 3 6 abs ......Z. TSB $3456
**/
INLINE void TSB( uint16_t addr ) {
dbgPrintf("TSB(%02X) ", src);
disPrintf(disassembly.inst, "TSB");
set_flags_Z( WRLOMEM[addr] & m6502.A );
WRLOMEM[addr] |= m6502.A;
}
/**
CMP Compare Memory with Accumulator

View File

@ -80,6 +80,23 @@ INLINE void INY() {
dbgPrintf("%02X ", m6502.Y);
}
/**
INA Increment Accumulator by One
A + 1 -> A N Z C I D V
+ + - - - -
addressing assembler opc bytes cyles
--------------------------------------------
implied INA C8 1 2
**/
INLINE void INA() {
dbgPrintf("INA %02X -> ", m6502.A);
disPrintf(disassembly.inst, "INA");
set_flags_NZ( ++m6502.A );
dbgPrintf("%02X ", m6502.A);
}
/**
DEC Decrement Memory by One
@ -135,5 +152,22 @@ INLINE void DEY() {
dbgPrintf("%02X ", m6502.Y);
}
/**
DEA Decrement Accumulator by One
A - 1 -> A N Z C I D V
+ + - - - -
addressing assembler opc bytes cyles
--------------------------------------------
implied DEC 88 1 2
**/
INLINE void DEA() {
dbgPrintf("DEA %02X -> ", m6502.A);
disPrintf(disassembly.inst, "DEA");
set_flags_NZ( --m6502.A );
dbgPrintf("%02X ", m6502.A);
}
#endif // __6502_INSTR_INC_DEC_H__

View File

@ -168,5 +168,24 @@ INLINE void STY( uint16_t addr ) {
STR(addr, m6502.Y);
}
/**
STZ Store Zero (0) in Memory
0 -> M N Z C I D V
- - - - - -
OP LEN CYC MODE FLAGS SYNTAX
-- --- --- ---- ----- ------
64 2 3 zp ........ STZ $12
74 2 4 zp,X ........ STZ $12,X
9C 3 4 abs ........ STZ $3456
9E 3 5 abs,X ........ STZ $3456,X
**/
INLINE void STZ( uint16_t addr ) {
dbgPrintf("STZ ");
disPrintf(disassembly.inst, "STZ");
STR(addr, 0);
}
#endif // __6502_INSTR_LOAD_STORE_H__

View File

@ -63,6 +63,38 @@ INLINE void PHA() {
PUSH( m6502.A );
}
/**
PHX Push index X on Stack
push X N Z C I D V
- - - - - -
addressing assembler opc bytes cyles
--------------------------------------------
implied PHX 48 1 3
**/
INLINE void PHX() {
dbgPrintf("PHX %02X ", m6502.X);
disPrintf(disassembly.inst, "PHX");
PUSH( m6502.X );
}
/**
PHY Push index Y on Stack
push Y N Z C I D V
- - - - - -
addressing assembler opc bytes cyles
--------------------------------------------
implied PHY 48 1 3
**/
INLINE void PHY() {
dbgPrintf("PHY %02X ", m6502.Y);
disPrintf(disassembly.inst, "PHY");
PUSH( m6502.Y );
}
/**
PLA Pull Accumulator from Stack
@ -80,6 +112,40 @@ INLINE void PLA() {
set_flags_NZ( m6502.A );
}
/**
PLX Pull index X from Stack
pull X N Z C I D V
+ + - - - -
addressing assembler opc bytes cyles
--------------------------------------------
implied PLX 68 1 4
**/
INLINE void PLX() {
m6502.X = POP();
dbgPrintf("PLX %02X ", m6502.X);
disPrintf(disassembly.inst, "PLX");
set_flags_NZ( m6502.X );
}
/**
PLY Pull index Y from Stack
pull Y N Z C I D V
+ + - - - -
addressing assembler opc bytes cyles
--------------------------------------------
implied PLY 68 1 4
**/
INLINE void PLY() {
m6502.Y = POP();
dbgPrintf("PLY %02X ", m6502.Y);
disPrintf(disassembly.inst, "PLY");
set_flags_NZ( m6502.Y );
}
/**
PHP Push Processor Status on Stack

View File

@ -1396,6 +1396,13 @@ INLINE uint8_t src_zp_Y() {
// return WRLOMEM + addr_zp_Y();
//}
/**
(zpg) .... zeropage OPC $LL
operand is zeropage address;
**/
INLINE uint8_t src_zp_0() {
return memread8_low(addr_zp());
}
#endif // __APPLE2_MMIO_H__