From 8e82eb670534ba55af40a9d8e994ffc8de4e3885 Mon Sep 17 00:00:00 2001 From: Damian Peckett Date: Wed, 8 Apr 2015 22:56:14 +1000 Subject: [PATCH] Building a proper 6502 vm --- .DS_Store | Bin 0 -> 12292 bytes 6502tests/.DS_Store | Bin 0 -> 6148 bytes 6502tests/test/.DS_Store | Bin 0 -> 12292 bytes APPLEII/.DS_Store | Bin 0 -> 6148 bytes APPLEII/addressing.ino | 54 ++++++++++ APPLEII/cpu.ino | 61 +++++------- APPLEII/fastcpu.ino | 209 +++++++++++++++++++++++++++++++++++++++ APPLEII/flags.ino | 16 +++ APPLEII/memory.ino | 90 +++++++++++------ APPLEII/softswitch.ino | 14 +++ 10 files changed, 377 insertions(+), 67 deletions(-) create mode 100644 .DS_Store create mode 100644 6502tests/.DS_Store create mode 100644 6502tests/test/.DS_Store create mode 100644 APPLEII/.DS_Store create mode 100644 APPLEII/addressing.ino create mode 100644 APPLEII/fastcpu.ino create mode 100644 APPLEII/flags.ino create mode 100644 APPLEII/softswitch.ino diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..96aeeeda919506cab36567fcc3d400a077c34bfb GIT binary patch literal 12292 zcmeHLOK%)S5Uz3zo+SyMyuiGYA-+V4l{oPOEP+^W?BEqnym(Dw6DMYNr@bC!JiVHk zwUd|)D=r{$;s@{pIPnAc0~|O>H#tkkdjV|QBO8Im;q*h8DIvO0cPN7V1V{) zCC*>$`zFeo8DIwfmkg-)gGWta-eSw3esz%2M*zZpa%&-*&H=i{vzWKoGN?;wOmlib zTZ;CGfu@||o=PXoTWlFL<$$If&|Vqs2?h1lsm{~sfO&(gnE_^?mjSi+=U@^hU=%Js zetwtLN+c^3r3Hn*5S~%??k?$lD=OP*-B$cisYhX&jgCIRz61R)yg1tP(o z?SgE?L3*RSA-Bt6AS!-xQ`?!JHPV8g=t#-WHYlR)B`G7aS8ew7FvvF6+@YPFiK(#> zZ|ve^bHv+uXL4%98y}l!Hgk@XbH8y;oIdy7+>-x!^ZpkteanFM%>jo^zoWk-Yaa@> z%1Io_xJFS`IRMj8qQ7~Vg(4J-(GvtMQidXE&=S;@{qK`AH8DQoU3ho&pCG5}$Ar}_ z`=s&r_LKh2bvw`crGtkKzdYz3IeP5)iC117dhPW$-hAuisgrB&v5H^4T}#vixFjQ) z6rzT>QA@(0T=%PCTwBh>ova+*6Kn3#uGB>l+}d+3-K|s3@jZtg?!!cgSdX``zMhI~ z`7wKC%^gguiHxF>Ov5ac@ycpSQ?Qtc&0@SR>55yS*j}isP!!W!&0}D2sPyJ2M=jpkPPQPY8z^%kaR-so;hqn6zmxJ zxt6va7dy_SSjHkZoG+QI9POTGX@XvXYj7Lx!ME@od=EduPw*@J0grG1T|A9vaU9>r z%Q%N06m&mAfXBk@(AkFw?XnvQ)WQEkUWz5`;C3oj@@;fA z0MGt2LigQGF$3dlvH+ xTLvjY@*jK%;Qe1S&x#pf2ABb6fEi#0m;q*h8DIvO0cL<1U_#gJ*BXyBEEB((0bxML=)Hh?z>dzv`;$nyD|{)6;|yh?jEL2vG?k z3O0_BR_uNu+|SzyX^@sCMBq8*Y-VO{mc=no7)r=M$iTnN0N=Y2;uA_d;vd_;Gw8dD zt@-0vOPOhqKN^bU^PoJ|?eD|`D@@uCFqb0nlgVhvuPQZK_YH)R>{xmLy}Rjn7&+ScB2 zrc*uJ)!oy3?tEYWg^QOi4-9A-wL5E=>jjrrcbD1BjoT%nmtJ{c6@CLk{!pvkcwVAzKYgbW;IpfMP#{QSR%d-yl^|D%(_QOH2Zz<QmskxDEhyoSfS@7l KLI(aS13v%&CfVo! literal 0 HcmV?d00001 diff --git a/6502tests/test/.DS_Store b/6502tests/test/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..fa63f08f043375d096cfd4a0b91298b4f7249083 GIT binary patch literal 12292 zcmeI0OKuZE5QeL5FANqD2nm9CXh0D041^O5j)N2wi6~}`h#eym9NWYOncWa-5dNxe*^sJPLQtrdW@tSy0axH(PylN-mwL&%AD{Z!6>tUqO9gm-$Z&AX zQ!HYXsRJk30wC6KTMDkR4-h6xF;B6GQBeG5+&zSZhP1^95y$h4t0U$q7BNPgLc}Sg z%pvVif@BAmNp%W&jDB_nTmh{B@7?P(p&pHK{$>B(=?^=2hT&BCj^T8O>-$GX@&jjP z^`FrWbwPD`$3G|NIqKcTv1||nFq-(9h{pyoroJY^Rw6DaqKP&ctqR`~amOUaI!EPo zB5oT*k3JX#w30VpGKgJK_?TAJy+k}Ph<$udQCd}hB%*E*130M&@#71qdj>JG)Ft+V ziL(ZAK<{-9@q>wmL3}FpgNX%`DD#7fbBSoodg3bHqDR|wpj*cMSKg(n@~q-()kqWK z3FoPOSQnxRdlrX!JSX`cXsm2y8^8SCV{QLijx6>Qo3b+D) zPJvKswOdX6e%f2BOuX05aJ<36h3geD3WAet#}R9|&Chv-mxAkzFA(z-ix_bS<*$DT z@b&+VFUaUnu+kcAD0I8Gn9q1zZ7Fz!h)>Tme_W6>tSy0aw5ka0Og})2qNw DagaHn literal 0 HcmV?d00001 diff --git a/APPLEII/.DS_Store b/APPLEII/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..04bc5b6060914cab99ad9e0f39d35d3029949d62 GIT binary patch literal 6148 zcmeHK%}&BV5S~>Mkpl7Pu}4oPzCk5mLgK;b3kap65h$s}pIaZphw=e@8~tW>W45rE zcrnJzY-Ydhc0Pvrn(lUq$n;i|6QTnmYQh;CEp!3n`|KOG<7PTQBfpW+1KJ%eXu1)t z6RLnJ@YfXJcehI;nxGZrzrV-w9_PbZo{nev7;(HvoWYMi#4sX?=#(zd&S^kHv@q*! zjn$?UIeD$fs6@-cJaf6m+XHV&t1Z#*Yta$iNS5+DmQ?iWRkRP*47@4+-S%pHMhCIC zu9BP{aWx7vr5>NzrhD*SXiPac1)f1Lqv6VYUW?}7&A}?b4sy6I)AZ_!Bz}RXS_&`B z!jr18T2LWHmJDqX&cs#KI9+gZs8|A@Bwq@Bg88_z8aD!GiCiO5rUzQ~l%)fm907n0Op9U6p9#!~9VQMdi?{RY#div6bd@G9m{~X;zPI??!`O+CJrl$n1Shs NfXJYoD)6fcd;)y!$iDyp literal 0 HcmV?d00001 diff --git a/APPLEII/addressing.ino b/APPLEII/addressing.ino new file mode 100644 index 0000000..d70908e --- /dev/null +++ b/APPLEII/addressing.ino @@ -0,0 +1,54 @@ +// In fastcpu ino +extern unsigned short PC; +extern unsigned char X, Y; + +// Addressing Modes +unsigned short inline a_abs() { + PC += 2; + return read16(PC-2); +} + +unsigned short inline a_absx() { + PC += 2; + return (read16(PC-2) + (unsigned short)X); +} + +unsigned short inline a_absy() { + PC += 2; + return (read16(PC-2) + (unsigned short)Y); +} + +unsigned short inline a_imm() { + return PC++; +} + +//ignore page wrap bug +unsigned short inline a_ind() { + PC += 2; + return read16(read16(PC-2)); +} + +unsigned short inline a_indx() { + return read16(((unsigned short)read8(PC++) + (unsigned short)X)&0xFF); +} + +unsigned short inline a_indy() { + return read16(((unsigned short)read8(PC++) + (unsigned short)Y)&0xFF); +} + +unsigned short inline a_rel() { + unsigned short addr = (unsigned short)read8(PC++); + return addr | ((addr&0x80)?0xFF00:0x0000); +} + +unsigned short inline a_zpg() { + return (unsigned short)read8(PC++); +} + +unsigned short inline a_zpgx() { + return ((unsigned short)read8(PC++) + (unsigned short)X)&0xFF; +} + +unsigned short inline a_zpgy() { + return ((unsigned short)read8(PC++) + (unsigned short)Y)&0xFF; +} diff --git a/APPLEII/cpu.ino b/APPLEII/cpu.ino index 561a4e8..9fc8e6c 100644 --- a/APPLEII/cpu.ino +++ b/APPLEII/cpu.ino @@ -1,6 +1,6 @@ // μ6502 - Barebones 6502 Emulator By Damian Peckett // dpeckett.com, - +/* // Address Modes #define AD_IMP 0x01 #define AD_A 0x02 @@ -42,24 +42,28 @@ //high nibble SR flags, low nibble address mode const unsigned char flags[] PROGMEM = { - AD_IMP, AD_INDX, UNDF, UNDF, UNDF, FL_ZN|AD_ZPG, FL_ZNC|AD_ZPG, UNDF, AD_IMP, FL_ZN|AD_IMM, FL_ZNC|AD_A, UNDF, UNDF, FL_ZN|AD_ABS, FL_ZNC|AD_ABS, UNDF, - AD_REL, FL_ZN|AD_INDY, UNDF, UNDF, UNDF, FL_ZN|AD_ZPGX, FL_ZNC|AD_ZPGX, UNDF, AD_IMP, FL_ZN|AD_ABSY, UNDF, UNDF, UNDF, FL_ZN|AD_ABSX, FL_ZNC|AD_ABSX, UNDF, - AD_ABS, FL_ZN|AD_INDX, UNDF, UNDF, FL_Z|AD_ZPG, FL_ZN|AD_ZPG, FL_ZNC|AD_ZPG, UNDF, AD_IMP, FL_ZN|AD_IMM, FL_ZNC|AD_A, UNDF, FL_Z|AD_ABS, FL_ZN|AD_ABS, FL_ZNC|AD_ABS, UNDF, - AD_REL, FL_ZN|AD_INDY, UNDF, UNDF, UNDF, FL_ZN|AD_ZPGX, FL_ZNC|AD_ZPGX, UNDF, AD_IMP, FL_ZN|AD_ABSY, UNDF, UNDF, UNDF, FL_ZN|AD_ABSX, FL_ZNC|AD_ABSX, UNDF, - AD_IMP, FL_ZN|AD_INDX, UNDF, UNDF, UNDF, FL_ZN|AD_ZPG, FL_ZNC|AD_ZPG, UNDF, AD_IMP, FL_ZN|AD_IMM, FL_ZNC|AD_A, UNDF, AD_ABS, FL_ZN|AD_ABS, FL_ZNC|AD_ABS, UNDF, - AD_REL, FL_ZN|AD_INDY, UNDF, UNDF, UNDF, FL_ZN|AD_ZPGX, FL_ZNC|AD_ZPGX, UNDF, AD_IMP, FL_ZN|AD_ABSY, UNDF, UNDF, UNDF, FL_ZN|AD_ABSX, FL_ZNC|AD_ABSX, UNDF, - AD_IMP, FL_ALL|AD_INDX, UNDF, UNDF, UNDF, FL_ALL|AD_ZPG, FL_ZNC|AD_ZPG, UNDF, FL_ZN|AD_IMP, FL_ALL|AD_IMM, FL_ZNC|AD_A,UNDF, AD_IND, FL_ALL|AD_ABS, FL_ZNC|AD_ABS, UNDF, - AD_REL, FL_ALL|AD_INDY, UNDF, UNDF, UNDF, FL_ALL|AD_ZPGX, FL_ZNC|AD_ZPGX, UNDF, AD_IMP, FL_ALL|AD_ABSY, UNDF, UNDF, UNDF, FL_ALL|AD_ABSX, FL_ZNC|AD_ABSX, UNDF, - UNDF, AD_INDX, UNDF, UNDF, AD_ZPG, AD_ZPG, AD_ZPG, UNDF, FL_ZN|AD_IMP, UNDF, FL_ZN|AD_IMP, UNDF, AD_ABS, AD_ABS, AD_ABS, UNDF, - AD_REL, AD_INDY, UNDF, UNDF, AD_ZPGX, AD_ZPGX, AD_ZPGY, UNDF, FL_ZN|AD_IMP, AD_ABSY, AD_IMP, UNDF, UNDF, AD_ABSX, UNDF, UNDF, - FL_ZN|AD_IMM, FL_ZN|AD_INDX, FL_ZN|AD_IMM, UNDF, FL_ZN|AD_ZPG, FL_ZN|AD_ZPG, FL_ZN|AD_ZPG, UNDF, FL_ZN|AD_IMP, FL_ZN|AD_IMM, FL_ZN|AD_IMP, UNDF, FL_ZN|AD_ABS, FL_ZN|AD_ABS, FL_ZN|AD_ABS, UNDF, - AD_REL, FL_ZN|AD_INDY, UNDF, UNDF, FL_ZN|AD_ZPGX, FL_ZN|AD_ZPGX, FL_ZN|AD_ZPGY, UNDF, AD_IMP, FL_ZN|AD_ABSY, FL_ZN|AD_IMP, UNDF, FL_ZN|AD_ABSX, FL_ZN|AD_ABSX, FL_ZN|AD_ABSY, UNDF, - FL_ZNC|AD_IMM, FL_ZNC|AD_INDX, UNDF, UNDF, FL_ZNC|AD_ZPG, FL_ZNC|AD_ZPG, FL_ZN|AD_ZPG, UNDF, FL_ZN|AD_IMP, FL_ZNC|AD_IMM, FL_ZN|AD_IMP, UNDF, FL_ZNC|AD_ABS, FL_ZNC|AD_ABS, FL_ZN|AD_ABS, UNDF, - AD_REL, FL_ZNC|AD_INDY, UNDF, UNDF, UNDF, FL_ZNC|AD_ZPGX, FL_ZN|AD_ZPGX, UNDF, AD_IMP, FL_ZNC|AD_ABSY, UNDF, UNDF, UNDF, FL_ZNC|AD_ABSX, FL_ZN|AD_ABSX, UNDF, - FL_ZNC|AD_IMM, FL_ALL|AD_INDX, UNDF, UNDF, FL_ZNC|AD_ZPG, FL_ALL|AD_ZPG, FL_ZN|AD_ZPG, UNDF, FL_ZN|AD_IMP, FL_ALL|AD_IMM, AD_IMP, UNDF, FL_ZNC|AD_ABS, FL_ALL|AD_ABS, FL_ZN|AD_ABS, UNDF, - AD_REL, FL_ALL|AD_INDY, UNDF, UNDF, UNDF, FL_ALL|AD_ZPGX, FL_ZN|AD_ZPGX, UNDF, AD_IMP, FL_ALL|AD_ABSY, UNDF, UNDF, UNDF, FL_ALL|AD_ABSX, FL_ZN|AD_ABSX, UNDF + AD_IMP, AD_INDX, UNDF, UNDF, UNDF, FL_ZN|AD_ZPG, FL_ZNC|AD_ZPG, UNDF, AD_IMP, FL_ZN|AD_IMM, FL_ZNC|AD_A, UNDF, UNDF, FL_ZN|AD_ABS, FL_ZNC|AD_ABS, UNDF, + AD_REL, FL_ZN|AD_INDY, UNDF, UNDF, UNDF, FL_ZN|AD_ZPGX, FL_ZNC|AD_ZPGX, UNDF, AD_IMP, FL_ZN|AD_ABSY, UNDF, UNDF, UNDF, FL_ZN|AD_ABSX, FL_ZNC|AD_ABSX, UNDF, + AD_ABS, FL_ZN|AD_INDX, UNDF, UNDF, FL_Z|AD_ZPG, FL_ZN|AD_ZPG, FL_ZNC|AD_ZPG, UNDF, AD_IMP, FL_ZN|AD_IMM, FL_ZNC|AD_A, UNDF, FL_Z|AD_ABS, FL_ZN|AD_ABS, FL_ZNC|AD_ABS, UNDF, + AD_REL, FL_ZN|AD_INDY, UNDF, UNDF, UNDF, FL_ZN|AD_ZPGX, FL_ZNC|AD_ZPGX, UNDF, AD_IMP, FL_ZN|AD_ABSY, UNDF, UNDF, UNDF, FL_ZN|AD_ABSX, FL_ZNC|AD_ABSX, UNDF, + AD_IMP, FL_ZN|AD_INDX, UNDF, UNDF, UNDF, FL_ZN|AD_ZPG, FL_ZNC|AD_ZPG, UNDF, AD_IMP, FL_ZN|AD_IMM, FL_ZNC|AD_A, UNDF, AD_ABS, FL_ZN|AD_ABS, FL_ZNC|AD_ABS, UNDF, + AD_REL, FL_ZN|AD_INDY, UNDF, UNDF, UNDF, FL_ZN|AD_ZPGX, FL_ZNC|AD_ZPGX, UNDF, AD_IMP, FL_ZN|AD_ABSY, UNDF, UNDF, UNDF, FL_ZN|AD_ABSX, FL_ZNC|AD_ABSX, UNDF, + AD_IMP, FL_ALL|AD_INDX, UNDF, UNDF, UNDF, FL_ALL|AD_ZPG, FL_ZNC|AD_ZPG, UNDF, FL_ZN|AD_IMP, FL_ALL|AD_IMM, FL_ZNC|AD_A,UNDF, AD_IND, FL_ALL|AD_ABS, FL_ZNC|AD_ABS, UNDF, + AD_REL, FL_ALL|AD_INDY, UNDF, UNDF, UNDF, FL_ALL|AD_ZPGX, FL_ZNC|AD_ZPGX, UNDF, AD_IMP, FL_ALL|AD_ABSY, UNDF, UNDF, UNDF, FL_ALL|AD_ABSX, FL_ZNC|AD_ABSX, UNDF, + UNDF, AD_INDX, UNDF, UNDF, AD_ZPG, AD_ZPG, AD_ZPG, UNDF, FL_ZN|AD_IMP, UNDF, FL_ZN|AD_IMP, UNDF, AD_ABS, AD_ABS, AD_ABS, UNDF, + AD_REL, AD_INDY, UNDF, UNDF, AD_ZPGX, AD_ZPGX, AD_ZPGY, UNDF, FL_ZN|AD_IMP, AD_ABSY, AD_IMP, UNDF, UNDF, AD_ABSX, UNDF, UNDF, + FL_ZN|AD_IMM, FL_ZN|AD_INDX, FL_ZN|AD_IMM, UNDF, FL_ZN|AD_ZPG, FL_ZN|AD_ZPG, FL_ZN|AD_ZPG, UNDF, FL_ZN|AD_IMP, FL_ZN|AD_IMM, FL_ZN|AD_IMP, UNDF, FL_ZN|AD_ABS, FL_ZN|AD_ABS, FL_ZN|AD_ABS, UNDF, + AD_REL, FL_ZN|AD_INDY, UNDF, UNDF, FL_ZN|AD_ZPGX, FL_ZN|AD_ZPGX, FL_ZN|AD_ZPGY, UNDF, AD_IMP, FL_ZN|AD_ABSY, FL_ZN|AD_IMP, UNDF, FL_ZN|AD_ABSX, FL_ZN|AD_ABSX, FL_ZN|AD_ABSY, UNDF, + FL_ZNC|AD_IMM, FL_ZNC|AD_INDX, UNDF, UNDF, FL_ZNC|AD_ZPG, FL_ZNC|AD_ZPG, FL_ZN|AD_ZPG, UNDF, FL_ZN|AD_IMP, FL_ZNC|AD_IMM, FL_ZN|AD_IMP, UNDF, FL_ZNC|AD_ABS, FL_ZNC|AD_ABS, FL_ZN|AD_ABS, UNDF, + AD_REL, FL_ZNC|AD_INDY, UNDF, UNDF, UNDF, FL_ZNC|AD_ZPGX, FL_ZN|AD_ZPGX, UNDF, AD_IMP, FL_ZNC|AD_ABSY, UNDF, UNDF, UNDF, FL_ZNC|AD_ABSX, FL_ZN|AD_ABSX, UNDF, + FL_ZNC|AD_IMM, FL_ALL|AD_INDX, UNDF, UNDF, FL_ZNC|AD_ZPG, FL_ALL|AD_ZPG, FL_ZN|AD_ZPG, UNDF, FL_ZN|AD_IMP, FL_ALL|AD_IMM, AD_IMP, UNDF, FL_ZNC|AD_ABS, FL_ALL|AD_ABS, FL_ZN|AD_ABS, UNDF, + AD_REL, FL_ALL|AD_INDY, UNDF, UNDF, UNDF, FL_ALL|AD_ZPGX, FL_ZN|AD_ZPGX, UNDF, AD_IMP, FL_ALL|AD_ABSY, UNDF, UNDF, UNDF, FL_ALL|AD_ABSX, FL_ZN|AD_ABSX, UNDF }; +const void *opcode[] PROGMEM = { + +} + // CPU registers unsigned short PC; unsigned char STP = 0xFD, A = 0x00, X = 0x00, Y = 0x00, SR = SR_FIXED_BITS; @@ -89,25 +93,6 @@ void setflags() { if(opflags&0x40) SR |= ((result^((unsigned short)A))&(result^value16)&0x0080)>>1; } -// Stack functions -void push16(unsigned short pushval) { - write8(STP_BASE + (STP--), (pushval>>8)&0xFF); - write8(STP_BASE + (STP--), pushval&0xFF); -} - -void push8(unsigned char pushval) { - write8(STP_BASE + (STP--), pushval); -} - -unsigned short pull16() { - value16 = read8(STP_BASE + (++STP)) | ((unsigned short)read8(STP_BASE + (++STP))<< 8); - return value16; -} - -unsigned char pull8() { - return read8(STP_BASE + (++STP)); -} - void run() { // Load the reset vector PC = read16(0xFFFC); @@ -171,6 +156,8 @@ void run() { break; } + + //opcodes switch(opcode) { //ADC @@ -525,4 +512,4 @@ void run() { break; } } -} +}*/ diff --git a/APPLEII/fastcpu.ino b/APPLEII/fastcpu.ino new file mode 100644 index 0000000..49ffea4 --- /dev/null +++ b/APPLEII/fastcpu.ino @@ -0,0 +1,209 @@ +// μ6502 v2.0 - Barebones 6502 Emulator By Damian Peckett +// dpeckett.com, + +//Other constants +#define SR_FIXED_BITS 0x20 +#define SR_CARRY 0x01 +#define SR_ZERO 0x02 +#define SR_INT 0x04 +#define SR_DEC 0x08 +#define SR_BRK 0x10 +#define SR_OVER 0x40 +#define SR_NEG 0x80 + +//Stack pointer base address +#define STP_BASE 0x100 + +// CPU registers +unsigned short PC; +unsigned char STP = 0xFD, A = 0x00, X = 0x00, Y = 0x00, SR = SR_FIXED_BITS; + +void run() { + // Opcode Addresses, Labels As Values + static const void* opcodes[] = { + &&BRK, &&ORA_INDX, &&UNDF, &&UNDF, &&UNDF, &&ORA_ZPG, &&ASL_ZPG, &&UNDF, &&PHP, &&ORA_IMM, &&ASL_A, &&UNDF, &&UNDF, &&ORA_ABS, &&ASL_ABS, &&UNDF, + &&BPL_REL, &&ORA_INDY, &&UNDF, &&UNDF, &&UNDF, &&ORA_ZPGX, &&ASL_ZPGX, &&UNDF, &&CLC, &&ORA_ABSY, &&UNDF, &&UNDF, &&UNDF, &&ORA_ABSX, &&ASL_ABSX, &&UNDF, + &&JSR_ABS, &&AND_INDX, &&UNDF, &&UNDF, &&BIT_ZPG, &&AND_ZPG, &&ROL_ZPG, &&UNDF, &&PLP, &&AND_IMM, &&ROL_A, &&UNDF, &&BIT_ABS, &&AND_ABS, &&ROL_ABS, &&UNDF + }; + + unsigned char value8, result8; + unsigned short value16, result16; + unsigned short ptr; + + // Load the reset vector + PC = read16(0xFFFC); + + // Begin Execution + goto *opcodes[read8(PC++)]; + + // Instruction interpreter + BRK: + push16(PC+1); + push8(SR|SR_BRK); + SR |= SR_INT; + PC = read16(0xFFFE); + goto *opcodes[read8(PC++)]; + ORA_INDX: + A |= read8(a_indx()); + flagZero(A); + flagNegative(A); + goto *opcodes[read8(PC++)]; + ORA_ZPG: + A |= read8(a_zpg()); + flagZero(A); + flagNegative(A); + goto *opcodes[read8(PC++)]; + ASL_ZPG: + ptr = a_zpg(); + value16 = read8(ptr); + result16 = value16<<1; + flagZero(result16&0x00FF); + flagNegative(result16&0x00FF); + flagCarry(result16); + write8(ptr, result16&0x00FF); + goto *opcodes[read8(PC++)]; + PHP: + push8(SR|SR_BRK); + goto *opcodes[read8(PC++)]; + ORA_IMM: + A |= read8(a_imm()); + flagZero(A); + flagNegative(A); + goto *opcodes[read8(PC++)]; + ASL_A: + value16 = A; + result16 = value16<<1; + flagZero(result16&0x00FF); + flagNegative(result16&0x00FF); + flagCarry(result16); + A = result16&0x00FF; + goto *opcodes[read8(PC++)]; + ORA_ABS: + A |= read8(a_abs()); + flagZero(A); + flagNegative(A); + goto *opcodes[read8(PC++)]; + ASL_ABS: + ptr = a_abs(); + value16 = read8(ptr); + result16 = value16<<1; + flagZero(result16&0x00FF); + flagNegative(result16&0x00FF); + flagCarry(result16); + write8(ptr, result16&0x00FF); + goto *opcodes[read8(PC++)]; + BPL_REL: + if(!(SR&SR_NEG)) PC += a_rel(); + goto *opcodes[read8(PC++)]; + ORA_INDY: + A |= read8(a_indy()); + flagZero(A); + flagNegative(A); + goto *opcodes[read8(PC++)]; + ORA_ZPGX: + A |= read8(a_zpgx()); + flagZero(A); + flagNegative(A); + goto *opcodes[read8(PC++)]; + ASL_ZPGX: + ptr = a_zpgx(); + value16 = read8(ptr); + result16 = value16<<1; + flagZero(result16&0x00FF); + flagNegative(result16&0x00FF); + flagCarry(result16); + write8(ptr, result16&0x00FF); + goto *opcodes[read8(PC++)]; + CLC: + SR &= ~SR_CARRY; + goto *opcodes[read8(PC++)]; + ORA_ABSY: + A |= read8(a_absy()); + flagZero(A); + flagNegative(A); + goto *opcodes[read8(PC++)]; + ORA_ABSX: + A |= read8(a_absx()); + flagZero(A); + flagNegative(A); + goto *opcodes[read8(PC++)]; + ASL_ABSX: + ptr = a_absx(); + value16 = read8(ptr); + result16 = value16<<1; + flagZero(result16&0x00FF); + flagNegative(result16&0x00FF); + flagCarry(result16); + write8(ptr, result16&0x00FF); + goto *opcodes[read8(PC++)]; + JSR_ABS: + push16(PC-1); + PC = a_abs(); + goto *opcodes[read8(PC++)]; + AND_INDX: + A &= read8(a_indx()); + flagZero(A); + flagNegative(A); + goto *opcodes[read8(PC++)]; + BIT_ZPG: + value8 = read8(a_zpg()); + result8 = A & value8; + flagZero(result8); + SR = (SR&0x3F) | (value8&0xC0); + goto *opcodes[read8(PC++)]; + AND_ZPG: + A &= read8(a_zpg()); + flagZero(A); + flagNegative(A); + goto *opcodes[read8(PC++)]; + ROL_ZPG: + ptr = a_zpg(); + value16 = read8(ptr); + result16 = (value16 << 1) | (SR&SR_CARRY); + flagZero(result16&0x00FF); + flagNegative(result16&0x00FF); + flagCarry(result16); + write8(ptr, result16&0x00FF); + goto *opcodes[read8(PC++)]; + PLP: + SR = pull8() | SR_FIXED_BITS; + goto *opcodes[read8(PC++)]; + AND_IMM: + A &= read8(a_imm()); + flagZero(A); + flagNegative(A); + goto *opcodes[read8(PC++)]; + ROL_A: + value16 = A; + result16 = (value16 << 1) | (SR&SR_CARRY); + flagZero(result16&0x00FF); + flagNegative(result16&0x00FF); + flagCarry(result16); + A = result16&0x00FF; + goto *opcodes[read8(PC++)]; + BIT_ABS: + value8 = read8(a_abs()); + result8 = A & value8; + flagZero(result8); + SR = (SR&0x3F) | (value8&0xC0); + goto *opcodes[read8(PC++)]; + AND_ABS: + A &= read8(a_abs()); + flagZero(A); + flagNegative(A); + goto *opcodes[read8(PC++)]; + ROL_ABS: + ptr = a_abs(); + value16 = read8(ptr); + result16 = (value16 << 1) | (SR&SR_CARRY); + flagZero(result16&0x00FF); + flagNegative(result16&0x00FF); + flagCarry(result16); + write8(ptr, result16&0x00FF); + goto *opcodes[read8(PC++)]; + + // -- Undefined Opcodes + UNDF: + // Raise an error + goto *opcodes[read8(PC++)]; +} diff --git a/APPLEII/flags.ino b/APPLEII/flags.ino new file mode 100644 index 0000000..8a18704 --- /dev/null +++ b/APPLEII/flags.ino @@ -0,0 +1,16 @@ +void inline flagZero(unsigned char value) { + if(!value) SR |= SR_ZERO; + else SR &= ~SR_ZERO; +} + +void inline flagNegative(unsigned char value) { + if(value&0x80) SR |= SR_NEG; + else SR &= ~SR_NEG; +} + +void inline flagCarry(unsigned short value) { + if(value&0xFF00) SR |= SR_CARRY; + else SR &= ~SR_CARRY; +} + + diff --git a/APPLEII/memory.ino b/APPLEII/memory.ino index e41842b..48a87b6 100644 --- a/APPLEII/memory.ino +++ b/APPLEII/memory.ino @@ -1026,52 +1026,82 @@ const unsigned char rom[] PROGMEM = { //$E000 - FFFF }; unsigned char ram[1024]; -// Free memory for storing BASIC programs -unsigned char basic[512]; -unsigned char read8(unsigned short address) { - unsigned char page = address>>8; - if(page < 0x04) { +unsigned char inline read8(unsigned short address) { + switch(address>>8) { + case 0x00: case 0x01: + case 0x02: case 0x03: return ram[address]; - } else if (page >= 0x04 && page < 0x08) { + case 0x04: case 0x05: + case 0x06: case 0x07: return screenRead(address); - } else if (page >= 0x08 && page < 0x10) { - return basic[address-0x800]; - } else if (page >= 0xE0) { + case 0xC0: + return softSwitch(address); + case 0xE0: case 0xE1: + case 0xE2: case 0xE3: + case 0xE4: case 0xE5: + case 0xE6: case 0xE7: + case 0xE8: case 0xE9: + case 0xEA: case 0xEB: + case 0xEC: case 0xED: + case 0xEE: case 0xEF: + case 0xF0: case 0xF1: + case 0xF2: case 0xF3: + case 0xF4: case 0xF5: + case 0xF6: case 0xF7: + case 0xF8: case 0xF9: + case 0xFA: case 0xFB: + case 0xFC: case 0xFD: + case 0xFE: case 0xFF: return pgm_read_byte_near(rom+address-0xE000); - } else { - // Keyboard Data - if(address == 0xC000) return keyboard_read(); - // Keyboard Strobe - if(address == 0xC010) keyboard_strobe(); - // Speaker toggle - if(address == 0xC030) speaker_toggle(); - return 0; + default: + return 0xFF; } } -unsigned short read16(unsigned short address) { +unsigned short inline read16(unsigned short address) { return (unsigned short)read8(address) | (((unsigned short)read8(address+1))<<8); } -void write8(unsigned short address, unsigned char value) { - unsigned char page = address>>8; - if(page < 0x04) { +void inline write8(unsigned short address, unsigned char value) { + switch(address>>8) { + case 0x00: case 0x01: + case 0x02: case 0x03: ram[address] = value; - } else if(page >= 0x04 && page < 0x08) { + break; + case 0x04: case 0x05: + case 0x06: case 0x07: screenWrite(address, value); - } else if (page >= 0x08 && page < 0x10) { - basic[address-0x800] = value; - } else { - // Keyboard Strobe - if(address == 0xC010) keyboard_strobe(); - // Speaker toggle - if(address == 0xC030) speaker_toggle(); + break; + case 0xC0: + softSwitch(address); + break; + default: + return; } } -void write16(unsigned short address, unsigned short value) { +void inline write16(unsigned short address, unsigned short value) { write8(address, value&0x00FF); write8(address+1, (value>>8)&0x00FF); } +// Stack functions +void inline push16(unsigned short pushval) { + write8(STP_BASE + (STP--), (pushval>>8)&0xFF); + write8(STP_BASE + (STP--), pushval&0xFF); +} + +void inline push8(unsigned char pushval) { + write8(STP_BASE + (STP--), pushval); +} + +unsigned short inline pull16() { + unsigned short value16 = read8(STP_BASE + (++STP)) | ((unsigned short)read8(STP_BASE + (++STP))<< 8); + return value16; +} + +unsigned char inline pull8() { + return read8(STP_BASE + (++STP)); +} + diff --git a/APPLEII/softswitch.ino b/APPLEII/softswitch.ino new file mode 100644 index 0000000..33a45e3 --- /dev/null +++ b/APPLEII/softswitch.ino @@ -0,0 +1,14 @@ +unsigned char softSwitch(unsigned short address) { + switch(address&0x00FF) { + case 0x00: // Keyboard Data + return keyboard_read(); + case 0x10: // Keyboard Strobe + keyboard_strobe(); + return 0xFF; + case 0x30: // Speaker toggle + speaker_toggle(); + return 0xFF; + default: + return 0xFF; + } +}