From db560436c5f04ae3120ddbecdcc38e66b421af4e Mon Sep 17 00:00:00 2001 From: mothcompute Date: Wed, 2 Feb 2022 12:49:45 -0800 Subject: [PATCH] initial commit --- README.md | 27 +++++ layla/bin/howmany | Bin 0 -> 20184 bytes layla/bin/laylatest | Bin 0 -> 20184 bytes layla/buildcheck | 1 + layla/howmany.c | 8 ++ layla/layla.c | 168 +++++++++++++++++++++++++++ layla/layla.h | 69 +++++++++++ layla/main.c | 9 ++ spencer/main.c | 30 +++++ spencer/mcbs | 3 + spencer/opcodes | 275 ++++++++++++++++++++++++++++++++++++++++++++ spencer/spctest | Bin 0 -> 17952 bytes spencer/spencer.c | 152 ++++++++++++++++++++++++ spencer/spencer.h | 64 +++++++++++ 14 files changed, 806 insertions(+) create mode 100644 README.md create mode 100755 layla/bin/howmany create mode 100755 layla/bin/laylatest create mode 100755 layla/buildcheck create mode 100644 layla/howmany.c create mode 100644 layla/layla.c create mode 100644 layla/layla.h create mode 100644 layla/main.c create mode 100644 spencer/main.c create mode 100644 spencer/mcbs create mode 100644 spencer/opcodes create mode 100755 spencer/spctest create mode 100644 spencer/spencer.c create mode 100644 spencer/spencer.h diff --git a/README.md b/README.md new file mode 100644 index 0000000..bc43285 --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# Snezzy + +SNES emulator for awful people + +## What? + +you know how zsnes 0.150 is all kinds of awful? i want an emulator that is accurate enough to run most games, but is completely crippled in sound and video. i want to scream. i want to scream, and i want to be able to say it's my own damn fault + +## What's wrong with you? + +wish i knew + +## How do I play games in it? + +i ask myself this too! + +short answer: thats the neat thing. you dont + +long answer: build layla and create an instruction decode loop, write a memory remapper, and implement 96% of the opcodes in the 65816 emulator. next, create an emulator for the ricoh 5a22 extensions, the spc700, and the s-ppu. finally, send me your code because you just made an entire emulator! congratulations! you can play any game without expansion chips! + +## What's the name mean? + +snezzy: [see this twitter post](https://twitter.com/Lynntendo64/status/1479021585646473216) + +layla: i was listening to [this song](https://www.youtube.com/watch?v=TngViNw2pOo) on loop when i started writing it + +spencer: SPenCer. SPC diff --git a/layla/bin/howmany b/layla/bin/howmany new file mode 100755 index 0000000000000000000000000000000000000000..1cdd32f8e449db65f3ec008c2cb244cf73c7c86a GIT binary patch literal 20184 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 TBZrC>t!}b3Zg3blvg-c;;+nlv literal 0 HcmV?d00001 diff --git a/layla/bin/laylatest b/layla/bin/laylatest new file mode 100755 index 0000000000000000000000000000000000000000..af63dab98c14c4494ba96e1fdca8c3e54902585e GIT binary patch literal 20184 zcmeHP3vgW3c|NO`Wg+c~hlv0YF9c@{V=WfOjsPp{N?LgpR<>eGJSK+gm3C!qW~Ej3 zQDo|3GXlmt#)*eyrX}@sXlFWUJ842DsZ1M^NHHV8p%X*e)D3h{JV_C;OP$yTh1lMH z|GEFax_em}8H3|-_h{~Z_k923ob#XiI9KPMyUibLFL5}Oq*C=+MY&D2CgWwny=!;} z;8jhk2EU(F*QyHS%QR=oy(U0vrh_H?G$bqt#%Zf=?2qox;Y<5oM!$n7{!jlMRqf6H^X*< zQ&b@&L5U~DgtjJ*ryaeJQS$0vrR;ViY-h(d))%BQC~f$4D*R!}>tee$w|1lKc-*9w zpp^G{*il^Oo1~l9b9r<1LmeNVf*f9Tb1d4s>eicM;f7drC_U0J(zL2!)vcan+;fYr z0@Z6dHtO~@YkO45b~R3%*gKRXFJHoWsOUtxS74*ClYRTrKXv_geQnR155E!%zH!-2 zwQWCrjC80SmZ-BHf|h82Q*d7$0IEhN)Umkt$fC z{|ISA|Em?)ljAUbb#x)|d^#(+9>{svbt(B!>L@D+ub2;bwK#X)O5W|y=TEbKla2ob z2i@JCum1@1O*a1P%n#f6W9;9}_XDZtDe+_Due{tW&mG7wcMJ1PHvUP`rvns8{GVWc zsf~9pGWDLe@rRjz#>S6bY3jQ_XQKFj zV7{OFtIT|pjSnz?@J>@s=OvvxlBO)Y^?ERE;py5W>8OQYAS7_c!b>bjT<4`%H>?4U9` z)$dx|HfvAy+uqy*Ta{kX6BuniR ziyx(GsD1sj`xGDY_ts|U_P|FV^Jg=Go&K3Xru^jXO6@GKfcfZ)C7JS5I{PkuM`tS1 zRWFoJW0!)s`~H14%l%sQWm0{yEK|NuXMaFh)AC!`wOMA;$DgIj&H4h9InbZ+AGP?m z>{2CNV_l`AhfeS4Diy)#ky>eiYfOz!IUXHPHJhs5n$?b!`-e+V2)gR~H59TJbeYq? zIhD<3UYI@xV7Fz2JG!b5*J@&KmnQl%UDdl^%4@Bz!hVOP3LHS!-mYr0g^jj#?e$jo zPfWW|r@+phnTe?dnF-feOX=v;wuLY5Xel+zfzD&&uCM)=a-)YFyQ(iU+jwf>{sKkl z=KrC9V79(h?6+zjWmlbT+55{1maWUQw7YB`WtW{**B>m`{ zA}9NKZ;Fl~dZl7My;3osUXiAlp7(ky=Fuw^XVoio3I0)m>%f@(B-MxXj;@csjdGp+ zc-#1Hp*D7v^I2Bbs4q4TzdoqzST^iV-MApcsK- z1kPIo9Qf~kuw$*?y(H=OuU}uK+Wf5@oxY&EXKhDkSJ2<-U)$|(Q%Ovz#rxf{7)^$y z(#hN1OVU+p$?{w7t-{miHKlhPMUAh;_WJ*3vp3+jRDU#^tp+aoZ8jSOt^>w^8Q>GZ zzXX00_-)|Jz<&WA0sahFjsG4r|1O(d2D}>>1pYHH27DFx1aRds*aO!BUj}{$cm%lh zIP6PN58yK3H*m`e0u#99#emK4!X9`x@SDKvW?&Dz9e4zI5Lk@~m9pQ%9{43-5cnK0 z23+=DHv2sw&D~ORJhWapMrs|`R4=I9jrtQ$?<`az4*2JRQf&+L6yOcmy%pOtZ)dY! zpmNr>JL^8@y5zyi?dr~}@3?8j4c8M*wi~fcz#b3wxF^o=epM(5O$aNb;zHV0jI{T+N-(30av+|RmCtpoaX5hEcvGJI3px2}$o~%Vx$HMWz5&PiT=K1upFV?p59EK3^I@*| zJ_q^VKt7lM*CFr3`7@XONyytF|Es+AJ(X);JHM?GH*2vzepf?&0P;bryksC} zzY+3lao*mQCpQnkHgH=Z4?rFvdAqarDet^0>uavBT$UM z#Sj5`zfj&M#1K}e6^zx4^1>o!^mH1z+C)7T#IC%zc#TQt-p^yT-200(&Zi{rl$|)8 zjZ=OcV=hWE=6V*-Qk3MKu_>10u~MfmGhV`2$H=euan5{?R%g5>g(0d=0Y-UVlXu_v zwLVqH6%>AiD<<`RnjK+^S|=(04_UK4Ahqgg&fm-Sm;u)9l{n*ZLFe09j>k!zmwK@K z^A7S}xxL_3{Nidmic+^%5D)ALf9 z`fb)mD|$Y4K(dDiDQ;Gv zHU-VRJm(pjzasY>Y)X}S96MBQ?m3(VPip{?}Rj9Me0O=GO5FUx9!)6rOIq!kFmAAhCpc(-!A? z=wF8T4D&w{_%T^6V_vR1dd>>28o|5sUF+OCny*t{Z@#dT{m6Ju{-3d)dAZJu|9hC1 zah{&bgv*W0%l$y~Lz>SolX3~xm+QFbKM1~7)#Z*KvHUdYm$;Pt-$nR`+0Vc7`b%DJ zsdg~`2J`ZNj;}KRRp#|vGMqilyj<5L4u7k8DQy;?1%D}y^I<;D<^LiR>_^52;%Ab1 z86WhqtDk5;XfI9RQDR3w*ZL-9{XGtz;$!be2aX@NRgw2=!CzWZr|kcSxR!W2*w~2w z-K3U*r{hiTZ&Lq8=H>dT=QvTuD&`d*pAjy%op~82il4ifALkC)#QI&#-)HNWS0S%O zoVRnFSzT>peHm{`Jm1rCbLPI&a5Ec(piliZVC%0a`;qa39EU^Tsa&~^Nx2WP{y%Yp z?qb01tR92p}O+N`2O z(G-ZjL@Jp|V`WI6nq66Lqy~*XT3eokK{#$~j>UUJF(aIcCz3`eJ)-*JgTt{%DiX#` zvY-YnZjTzFL?X1shzz9?TU37{G#D|$>A}G*FtOwes!5(IErHi{ZC~%}^c()QZ3b4f z=j(-)(RSZjUuQ>azC7d+$6}35(7KI&8hdH4S1;}NS{LfaVxcBwM8cs|2pUEr5(+o2qP+(b z(Nx6T#o~N33qIV$Uk0#w$tiq>iu()|XT*p5;$ht}wvPtn*`iZWxcNB%G&29&07f_& zHwHpOVft=B$2w?*qeDhI8406+UMecmYmE$b5XhCf;oPFlx>dyLT2T{`2_bk!Z!*aR zo8K~s8GT#&VyJQ~HWVMm?+S9%-=x2bV5>F0X(0VgA3G@c1p_#sGW)5H*6%3fxk9A$ zab>;(rj#eSWiS=$1*Q@v4#*xp$q-2lD~~=!HV>se!-@ECB$3);p?cF%d|x9PX3E#n z(Lg7Whtvl`$pPgFZy7=nCZ-amvc6r|%%nO3St5Ty|-G z1($e?mCRJf<6c3TUtzJmuhn zZ1ys47j(0pfZhHc2=K~YT-q=5MuO6QnK!c6KLmTa2Z_DRD+wOtf~k!ZXR(+0ohUeJ zve?T!m7vT^K}9F>VNG8`hUS38UgmuSW&9@f7d^p;VNY{Pl9zcUK{pp>uRqgj7j`J7 zVlVSrf={zR%D1=w&)L3(9m+hJV1RkD$0+}O@%w9V6ch1JLol5fW&V&^U02yB+=I<( z?`AteFDY4)&As{tWLEo4tRT3k%3_RNu^09qZT2!A7nJ!?(YGJJ-(`D=zjCuCV=HF` z?DpS>fa)*yZEjOj@VJ@H{o3tcg2Zaybe*Xxc#zL$aUlIK`JZ9OiA~hxxlg{MWY?Fx z;2W@YS?uMzHb)ykB8i@vo6QS<7y>$Wqp*-$Q1#S6)_LZXyGdv*n9@35>1wUbgqLp}RU~s(0M^Syc&R@+I|`aqp(p zrsDhbZT2->zP+AeFV`P2qq +#include "layla.c" + +int main() { + int c = 0; + for(int i = 0; i < 256; i++) c+=(!!(long)ll_opcodes[i]); + printf("%i opcodes complete (%f%% to native mode success!)\n", c, 0.390625 * c); +} diff --git a/layla/layla.c b/layla/layla.c new file mode 100644 index 0000000..762a79d --- /dev/null +++ b/layla/layla.c @@ -0,0 +1,168 @@ +#include "layla.h" + +uint8_t (*ll_read)(ll_cpu* c, uint32_t addr) = NULL; +void (*ll_write)(ll_cpu* c, uint32_t addr, uint8_t b) = NULL; + +int ll_init_status = 0; + +void ll_reg_read(uint8_t(*rdp)(ll_cpu* c, uint32_t addr)) { + ll_read = rdp; + ll_init_status |= 2; + if(ll_init_status == 6) ll_init_status = 1; +} + +void ll_reg_write(void(*wrp)(ll_cpu* c, uint32_t addr, uint8_t b)) { + ll_write = wrp; + ll_init_status |= 4; + if(ll_init_status == 6) ll_init_status = 1; +} + +uint16_t ll_read16(ll_cpu* c, uint32_t addr) { + // TODO + return 0; +} + +void ll_write16(ll_cpu* c, uint32_t addr, uint16_t w) { + // TODO +} + +uint16_t llnop(ll_cpu* c) {} + +uint16_t ll18(ll_cpu* c) { + c->P.f.C = 0; +} + +uint16_t ll1b(ll_cpu* c) { + if(c->e) { + if(c->SP.D.H != 1) exit(printf("LINE %s ERR\n", __LINE__)); + c->SP.D.L = c->A.D.L; + } + else c->SP.F = c->A.F; +} + +uint16_t ll38(ll_cpu* c) { + c->P.f.C = 1; +} + +uint16_t ll3b(ll_cpu* c) { + c->A.F = c->SP.F; + ll_setnz16(SP); +} + +uint16_t ll58(ll_cpu* c) { + c->P.f.I = 0; +} + +uint16_t ll5b(ll_cpu* c) { + c->D.F = c->A.F; + ll_setnz16(D); +} + +uint16_t ll78(ll_cpu* c) { + c->P.f.I = 1; +} + +uint16_t ll7b(ll_cpu* c) { + c->A.F = c->D.F; + ll_setnz16(A); +} + +uint16_t ll98(ll_cpu* c) { + ll_trans(Y, A); +} + +uint16_t ll9a(ll_cpu* c) { + // ll_trans sans status + if(c->P.f.XB) c->SP.D.L = c->X.D.L; + // TODO needed? + if(!c->e && c->P.f.XB) c->SP.D.H = 0; + else c->SP.F = c->X.F; +} + +uint16_t ll9b(ll_cpu* c) { + ll_trans(X, Y); +} + +uint16_t lla8(ll_cpu* c) { + ll_trans(A, Y); +} + +// `llaa, you got me on my knees` +uint16_t llaa(ll_cpu* c) { + ll_trans(A, X); +} + +uint16_t llb8(ll_cpu* c) { + c->P.f.V = 0; +} + +uint16_t llba(ll_cpu* c) { + ll_trans(SP, X); +} + +uint16_t lld8(ll_cpu* c) { + c->P.f.D = 0; +} + +uint16_t lleb(ll_cpu* c) { + ll_swap(c->A.D.H, c->A.D.L); + ll_setnz8(A); +} + +uint16_t llf8(ll_cpu* c) { + c->P.f.D = 1; + printf("DECIMAL UNIMPLEMENTED\n"); +} + +uint16_t llfb(ll_cpu* c) { + c->e = c->P.f.C; + if(c->e) { + c->P.f.M = 1; + c->P.f.XB = 1; + c->X.D.H = 0; + c->Y.D.H = 0; + c->SP.D.H = 1; + } +} + +#define LL_E 0 +// if negative, called opcode will return the number of cycles. else, use this +int ll_cycles[256] = { +//(YX) 0 1 2 3 4 5 6 7 8 9 a b c d e f + LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, // 0 + LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, // 1 + LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, // 2 + LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, 2, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, // 3 + LL_E, LL_E, 2, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, // 4 + LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, // 5 + LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, // 6 + LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, 2, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, // 7 + LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, // 8 + LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, 2, 2, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, // 9 + LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, 2, LL_E, 2, LL_E, LL_E, LL_E, LL_E, LL_E, // a + LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, 2, LL_E, LL_E, LL_E, LL_E, LL_E, // b + LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, // c + LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, // d + LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, 2, 3, LL_E, LL_E, LL_E, LL_E, // e + LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, LL_E, 2, LL_E, LL_E, 2, LL_E, LL_E, LL_E, LL_E // f +}; + +ll_opcode ll_opcodes[256] = { +//(YX) 0 1 2 3 4 5 6 7 8 9 a b c d e f + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &ll18, NULL, NULL, &ll1b, NULL, NULL, NULL, NULL, // 1 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 2 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &ll38, NULL, NULL, &ll3b, NULL, NULL, NULL, NULL, // 3 + NULL, NULL, &llnop, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 4 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &ll58, NULL, NULL, &ll5b, NULL, NULL, NULL, NULL, // 5 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 6 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &ll78, NULL, NULL, &ll7b, NULL, NULL, NULL, NULL, // 7 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 8 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &ll98, &ll9b, NULL, NULL, NULL, NULL, NULL, NULL, // 9 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &lla8, NULL, &llaa, NULL, NULL, NULL, NULL, NULL, // a + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &llb8, NULL, &llba, NULL, NULL, NULL, NULL, NULL, // b + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // c + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &lld8, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // d + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &llnop, &lleb, NULL, NULL, NULL, NULL, // e + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &llf8, NULL, NULL, &llfb, NULL, NULL, NULL, NULL // f +}; diff --git a/layla/layla.h b/layla/layla.h new file mode 100644 index 0000000..53fd786 --- /dev/null +++ b/layla/layla.h @@ -0,0 +1,69 @@ +#ifndef LAYLA_H +#define LAYLA_H + +#include + +#define PACK_STRUCT __attribute__((packed)) +#define ll_swap(X, Y) X ^= Y ^= X ^= Y + +typedef struct { + uint8_t C : 1; + uint8_t Z : 1; + uint8_t I : 1; + uint8_t D : 1; + uint8_t XB : 1; + uint8_t M : 1; + uint8_t V : 1; + uint8_t N : 1; +} PACK_STRUCT ll_status_internal; + +typedef union { + uint8_t byte; + ll_status_internal f; +} ll_status; + +typedef struct { + uint8_t L; + uint8_t H; +} ll_reg_HL; + +typedef union { + uint16_t F; + ll_reg_HL D; +} ll_reg; + +typedef struct { + // bools? whats that, a bowl spoon? + uint8_t e : 1; + uint8_t DB; + uint8_t PB; + ll_status P; + ll_reg A; + ll_reg X; + ll_reg Y; + ll_reg D; + ll_reg SP; + ll_reg PC; + void* data; +} ll_cpu; + +typedef uint16_t(*ll_opcode)(ll_cpu*); + +#define ll_setnz16(DEST) \ + c->P.f.N = c->DEST.F >> 15; \ + c->P.f.Z = (c->DEST.F == 0) + +#define ll_setnz8(DEST) \ + c->P.f.N = c->DEST.D.L >> 7; \ + c->P.f.Z = (c->DEST.D.L == 0) + +#define ll_trans(SRC, DEST) \ + if(c->P.f.XB) { \ + c->DEST.D.L = c->SRC.D.L; \ + ll_setnz8(DEST); \ + } else { \ + c->DEST.F = c->SRC.F; \ + ll_setnz16(DEST); \ + } + +#endif diff --git a/layla/main.c b/layla/main.c new file mode 100644 index 0000000..beffa11 --- /dev/null +++ b/layla/main.c @@ -0,0 +1,9 @@ +#include +#include +#include "layla.c" +int main() { + printf("sizeof ll_status: %u\n", sizeof(ll_status)); + ll_reg b; + b.F = 0xFFEE; + printf("%02X\n", b.D.H); +} diff --git a/spencer/main.c b/spencer/main.c new file mode 100644 index 0000000..e08c9bb --- /dev/null +++ b/spencer/main.c @@ -0,0 +1,30 @@ +#include + +uint8_t mmr(uint8_t reg, uint8_t d, uint8_t rw) { + +} + +int main(int argc, char** argv) { + spc_cpu s; + spc_init(&s, malloc(0x10000), &mmr); + // TODO copy in new spc data + while(1) { + printf( "WAIT: %u\n" + "\tPC: 0x%04X\n" + "\tSP: 0x%02X\n" + "\tA: 0x%02X\n" + "\tX: 0x%02X\n" + "\tY: 0x%02X\n" + , + s.wait, + s.PC, + s.SP, + s.A, + s.X, + s.Y + ); + int r = spc_loop(&s); + if(r) exit(printf("error\n")); + } + return printf("stub\n"); +} diff --git a/spencer/mcbs b/spencer/mcbs new file mode 100644 index 0000000..1101da0 --- /dev/null +++ b/spencer/mcbs @@ -0,0 +1,3 @@ +SOURCES=main.c +OUTPUT=spctest +FLAGS=-I. diff --git a/spencer/opcodes b/spencer/opcodes new file mode 100644 index 0000000..1ce02cd --- /dev/null +++ b/spencer/opcodes @@ -0,0 +1,275 @@ +Mnemonic Code Bytes Cyc Operation NVPBHIZC + + NOP 00 1 2 do nothing ........ + + CLRP 20 1 2 P = 0 ..0..... + + INC X 3D 1 2 X++ N.....Z. + + SETP 40 1 2 P = 1 ..1..... + + MOV X, A 5D 1 2 X = A N.....Z. + + CLRC 60 1 2 C = 0 .......0 + + SETC 80 1 2 C = 1 .......1 + + EI A0 1 3 I = 1 .....1.. + + INC A BC 1 2 A++ N.....Z. + + DI C0 1 3 I = 0 .....0.. + + CLRV E0 1 2 V = 0, H = 0 .0..0... + + INC Y FC 1 2 Y++ N.....Z. + + + + + TCALL 0 01 1 8 CALL [$FFDE] ........ + SET1 d.0 02 2 4 d.0 = 1 ........ + BBS d.0, r 03 3 5/7 PC+=r if d.0 == 1 ........ + OR A, d 04 2 3 A = A | (d) N.....Z. + OR A, !a 05 3 4 A = A | (a) N.....Z. + OR A, (X) 06 1 3 A = A | (X) N.....Z. + OR A, [d+X] 07 2 6 A = A | ([d+X]) N.....Z. + OR A, #i 08 2 2 A = A | i N.....Z. + OR dd, ds 09 3 6 (dd) = (dd) | (ds) N.....Z. + OR1 C, m.b 0A 3 5 C = C | (m.b) .......C + ASL d 0B 2 4 Left shift (d) as above N.....ZC + ASL !a 0C 3 5 Left shift (a) as above N.....ZC + PUSH PSW 0D 1 4 (SP--) = Flags ........ + TSET1 !a 0E 3 6 (a) = (a)|A, ZN as for A-(a) N.....Z. + BRK 0F 1 8 Push PC and Flags, PC = [$FFDE] ...1.0.. + BPL r 10 2 2/4 PC+=r if N == 0 ........ + TCALL 1 11 1 8 CALL [$FFDC] ........ + CLR1 d.0 12 2 4 d.0 = 0 ........ + BBC d.0, r 13 3 5/7 PC+=r if d.0 == 0 ........ + OR A, d+X 14 2 4 A = A | (d+X) N.....Z. + OR A, !a+X 15 3 5 A = A | (a+X) N.....Z. + OR A, !a+Y 16 3 5 A = A | (a+Y) N.....Z. + OR A, [d]+Y 17 2 6 A = A | ([d]+Y) N.....Z. + OR d, #i 18 3 5 (d) = (d) | i N.....Z. + OR (X), (Y) 19 1 5 (X) = (X) | (Y) N.....Z. + DECW d 1A 2 6 Word (d)-- N.....Z. + ASL d+X 1B 2 5 Left shift (d+X) as above N.....ZC + ASL A 1C 1 2 Left shift A: high->C, 0->low N.....ZC + DEC X 1D 1 2 X-- N.....Z. + CMP X, !a 1E 3 4 X - (a) N.....ZC + JMP [!a+X] 1F 3 6 PC = [a+X] ........ + TCALL 2 21 1 8 CALL [$FFDA] ........ + SET1 d.1 22 2 4 d.1 = 1 ........ + BBS d.1, r 23 3 5/7 PC+=r if d.1 == 1 ........ + AND A, d 24 2 3 A = A & (d) N.....Z. + AND A, !a 25 3 4 A = A & (a) N.....Z. + AND A, (X) 26 1 3 A = A & (X) N.....Z. + AND A, [d+X] 27 2 6 A = A & ([d+X]) N.....Z. + AND A, #i 28 2 2 A = A & i N.....Z. + AND dd, ds 29 3 6 (dd) = (dd) & (ds) N.....Z. + OR1 C, /m.b 2A 3 5 C = C | ~(m.b) .......C + ROL d 2B 2 4 Left shift (d) as above N.....ZC + ROL !a 2C 3 5 Left shift (a) as above N.....ZC + PUSH A 2D 1 4 (SP--) = A ........ + CBNE d, r 2E 3 5/7 CMP A, (d) then BNE ........ + BRA r 2F 2 4 PC+=r ........ + BMI r 30 2 2/4 PC+=r if N == 1 ........ + TCALL 3 31 1 8 CALL [$FFD8] ........ + CLR1 d.1 32 2 4 d.1 = 0 ........ + BBC d.1, r 33 3 5/7 PC+=r if d.1 == 0 ........ + AND A, d+X 34 2 4 A = A & (d+X) N.....Z. + AND A, !a+X 35 3 5 A = A & (a+X) N.....Z. + AND A, !a+Y 36 3 5 A = A & (a+Y) N.....Z. + AND A, [d]+Y 37 2 6 A = A & ([d]+Y) N.....Z. + AND d, #i 38 3 5 (d) = (d) & i N.....Z. + AND (X), (Y) 39 1 5 (X) = (X) & (Y) N.....Z. + INCW d 3A 2 6 Word (d)++ N.....Z. + ROL d+X 3B 2 5 Left shift (d+X) as above N.....ZC + ROL A 3C 1 2 Left shift A: low=C, C=high N.....ZC + CMP X, d 3E 2 3 X - (d) N.....ZC + CALL !a 3F 3 8 (SP--)=PCh, (SP--)=PCl, PC=a ........ + TCALL 4 41 1 8 CALL [$FFD6] ........ + SET1 d.2 42 2 4 d.2 = 1 ........ + BBS d.2, r 43 3 5/7 PC+=r if d.2 == 1 ........ + EOR A, d 44 2 3 A = A EOR (d) N.....Z. + EOR A, !a 45 3 4 A = A EOR (a) N.....Z. + EOR A, (X) 46 1 3 A = A EOR (X) N.....Z. + EOR A, [d+X] 47 2 6 A = A EOR ([d+X]) N.....Z. + EOR A, #i 48 2 2 A = A EOR i N.....Z. + EOR dd, ds 49 3 6 (dd) = (dd) EOR (ds) N.....Z. + AND1 C, m.b 4A 3 4 C = C & (m.b) .......C + LSR d 4B 2 4 Right shift (d) as above N.....ZC + LSR !a 4C 3 5 Right shift (a) as above N.....ZC + PUSH X 4D 1 4 (SP--) = X ........ + TCLR1 !a 4E 3 6 (a) = (a)&~A, ZN as for A-(a) N.....Z. + PCALL u 4F 2 6 CALL $FF00+u ........ + BVC r 50 2 2/4 PC+=r if V == 0 ........ + TCALL 5 51 1 8 CALL [$FFD4] ........ + CLR1 d.2 52 2 4 d.2 = 0 ........ + BBC d.2, r 53 3 5/7 PC+=r if d.2 == 0 ........ + EOR A, d+X 54 2 4 A = A EOR (d+X) N.....Z. + EOR A, !a+X 55 3 5 A = A EOR (a+X) N.....Z. + EOR A, !a+Y 56 3 5 A = A EOR (a+Y) N.....Z. + EOR A, [d]+Y 57 2 6 A = A EOR ([d]+Y) N.....Z. + EOR d, #i 58 3 5 (d) = (d) EOR i N.....Z. + EOR (X), (Y) 59 1 5 (X) = (X) EOR (Y) N.....Z. + CMPW YA, d 5A 2 4 YA - (d) N.....ZC + LSR d+X 5B 2 5 Right shift (d+X) as above N.....ZC + LSR A 5C 1 2 Right shift A: 0->high, low->C N.....ZC + CMP Y, !a 5E 3 4 Y - (a) N.....ZC + JMP !a 5F 3 3 PC = a ........ + TCALL 6 61 1 8 CALL [$FFD2] ........ + SET1 d.3 62 2 4 d.3 = 1 ........ + BBS d.3, r 63 3 5/7 PC+=r if d.3 == 1 ........ + CMP A, d 64 2 3 A - (d) N.....ZC + CMP A, !a 65 3 4 A - (a) N.....ZC + CMP A, (X) 66 1 3 A - (X) N.....ZC + CMP A, [d+X] 67 2 6 A - ([d+X]) N.....ZC + CMP A, #i 68 2 2 A - i N.....ZC + CMP dd, ds 69 3 6 (dd) - (ds) N.....ZC + AND1 C, /m.b 6A 3 4 C = C & ~(m.b) .......C + ROR d 6B 2 4 Right shift (d) as above N.....ZC + ROR !a 6C 3 5 Right shift (a) as above N.....ZC + PUSH Y 6D 1 4 (SP--) = Y ........ + DBNZ d, r 6E 3 5/7 (d)-- then JNZ ........ + RET 6F 1 5 Pop PC ........ + BVS r 70 2 2/4 PC+=r if V == 1 ........ + TCALL 7 71 1 8 CALL [$FFD0] ........ + CLR1 d.3 72 2 4 d.3 = 0 ........ + BBC d.3, r 73 3 5/7 PC+=r if d.3 == 0 ........ + CMP A, d+X 74 2 4 A - (d+X) N.....ZC + CMP A, !a+X 75 3 5 A - (a+X) N.....ZC + CMP A, !a+Y 76 3 5 A - (a+Y) N.....ZC + CMP A, [d]+Y 77 2 6 A - ([d]+Y) N.....ZC + CMP d, #i 78 3 5 (d) - i N.....ZC + CMP (X), (Y) 79 1 5 (X) - (Y) N.....ZC + ADDW YA, d 7A 2 5 YA = YA + (d), H on high byte NV..H.ZC + ROR d+X 7B 2 5 Right shift (d+X) as above N.....ZC + ROR A 7C 1 2 Right shift A: high=C, C=low N.....ZC + MOV A, X 7D 1 2 A = X N.....Z. + CMP Y, d 7E 2 3 Y - (d) N.....ZC + RET1 7F 1 6 Pop Flags, PC NVPBHIZC + TCALL 8 81 1 8 CALL [$FFCE] ........ + SET1 d.4 82 2 4 d.4 = 1 ........ + BBS d.4, r 83 3 5/7 PC+=r if d.4 == 1 ........ + ADC A, d 84 2 3 A = A+(d)+C NV..H.ZC + ADC A, !a 85 3 4 A = A+(a)+C NV..H.ZC + ADC A, (X) 86 1 3 A = A+(X)+C NV..H.ZC + ADC A, [d+X] 87 2 6 A = A+([d+X])+C NV..H.ZC + ADC A, #i 88 2 2 A = A+i+C NV..H.ZC + ADC dd, ds 89 3 6 (dd) = (dd)+(d)+C NV..H.ZC + EOR1 C, m.b 8A 3 5 C = C EOR (m.b) .......C + DEC d 8B 2 4 (d)-- N.....Z. + DEC !a 8C 3 5 (a)-- N.....Z. + MOV Y, #i 8D 2 2 Y = i N.....Z. + POP PSW 8E 1 4 Flags = (++SP) NVPBHIZC + MOV d, #i 8F 3 5 (d) = i (read) ........ + BCC r 90 2 2/4 PC+=r if C == 0 ........ + TCALL 9 91 1 8 CALL [$FFCC] ........ + CLR1 d.4 92 2 4 d.4 = 0 ........ + BBC d.4, r 93 3 5/7 PC+=r if d.4 == 0 ........ + ADC A, d+X 94 2 4 A = A+(d+X)+C NV..H.ZC + ADC A, !a+X 95 3 5 A = A+(a+X)+C NV..H.ZC + ADC A, !a+Y 96 3 5 A = A+(a+Y)+C NV..H.ZC + ADC A, [d]+Y 97 2 6 A = A+([d]+Y)+C NV..H.ZC + ADC d, #i 98 3 5 (d) = (d)+i+C NV..H.ZC + ADC (X), (Y) 99 1 5 (X) = (X)+(Y)+C NV..H.ZC + SUBW YA, d 9A 2 5 YA = YA - (d), H on high byte NV..H.ZC + DEC d+X 9B 2 5 (d+X)-- N.....Z. + DEC A 9C 1 2 A-- N.....Z. + MOV X, SP 9D 1 2 X = SP N.....Z. + DIV YA, X 9E 1 12 A=YA/X, Y=mod(YA,X) NV..H.Z. + XCN A 9F 1 5 A = (A>>4) | (A<<4) N.....Z. + + + TCALL 10 A1 1 8 CALL [$FFCA] ........ + SET1 d.5 A2 2 4 d.5 = 1 ........ + BBS d.5, r A3 3 5/7 PC+=r if d.5 == 1 ........ + SBC A, d A4 2 3 A = A-(d)-!C NV..H.ZC + SBC A, !a A5 3 4 A = A-(a)-!C NV..H.ZC + SBC A, (X) A6 1 3 A = A-(X)-!C NV..H.ZC + SBC A, [d+X] A7 2 6 A = A-([d+X])-!C NV..H.ZC + SBC A, #i A8 2 2 A = A-i-!C NV..H.ZC + SBC dd, ds A9 3 6 (dd) = (dd)-(ds)-!C NV..H.ZC + MOV1 C, m.b AA 3 4 C = (m.b) .......C + INC d AB 2 4 (d)++ N.....Z. + INC !a AC 3 5 (a)++ N.....Z. + CMP Y, #i AD 2 2 Y - i N.....ZC + POP A AE 1 4 A = (++SP) ........ + MOV (X)+, A AF 1 4 (X++) = A (no read) ........ + BCS r B0 2 2/4 PC+=r if C == 1 ........ + TCALL 11 B1 1 8 CALL [$FFC8] ........ + CLR1 d.5 B2 2 4 d.5 = 0 ........ + BBC d.5, r B3 3 5/7 PC+=r if d.5 == 0 ........ + SBC A, d+X B4 2 4 A = A-(d+X)-!C NV..H.ZC + SBC A, !a+X B5 3 5 A = A-(a+X)-!C NV..H.ZC + SBC A, !a+Y B6 3 5 A = A-(a+Y)-!C NV..H.ZC + SBC A, [d]+Y B7 2 6 A = A-([d]+Y)-!C NV..H.ZC + SBC d, #i B8 3 5 (d) = (d)-i-!C NV..H.ZC + SBC (X), (Y) B9 1 5 (X) = (X)-(Y)-!C NV..H.ZC + MOVW YA, d BA 2 5 YA = word (d) N.....Z. + INC d+X BB 2 5 (d+X)++ N.....Z. + MOV SP, X BD 1 2 SP = X ........ + DAS A BE 1 3 decimal adjust for subtraction N.....ZC + MOV A, (X)+ BF 1 4 A = (X++) N.....Z. + TCALL 12 C1 1 8 CALL [$FFC6] ........ + SET1 d.6 C2 2 4 d.6 = 1 ........ + BBS d.6, r C3 3 5/7 PC+=r if d.6 == 1 ........ + MOV d, A C4 2 4 (d) = A (read) ........ + MOV !a, A C5 3 5 (a) = A (read) ........ + MOV (X), A C6 1 4 (X) = A (read) ........ + MOV [d+X], A C7 2 7 ([d+X]) = A (read) ........ + CMP X, #i C8 2 2 X - i N.....ZC + MOV !a, X C9 3 5 (a) = X (read) ........ + MOV1 m.b, C CA 3 6 (m.b) = C ........ + MOV d, Y CB 2 4 (d) = Y (read) ........ + MOV !a, Y CC 3 5 (a) = Y (read) ........ + MOV X, #i CD 2 2 X = i N.....Z. + POP X CE 1 4 X = (++SP) ........ + MUL YA CF 1 9 YA = Y * A, NZ on Y only N.....Z. + BNE r D0 2 2/4 PC+=r if Z == 0 ........ + TCALL 13 D1 1 8 CALL [$FFC4] ........ + CLR1 d.6 D2 2 4 d.6 = 0 ........ + BBC d.6, r D3 3 5/7 PC+=r if d.6 == 0 ........ + MOV d+X, A D4 2 5 (d+X) = A (read) ........ + MOV !a+X, A D5 3 6 (a+X) = A (read) ........ + MOV !a+Y, A D6 3 6 (a+Y) = A (read) ........ + MOV [d]+Y, A D7 2 7 ([d]+Y) = A (read) ........ + MOV d, X D8 2 4 (d) = X (read) ........ + MOV d+Y, X D9 2 5 (d+Y) = X (read) ........ + MOVW d, YA DA 2 5 word (d) = YA (read low only) ........ + MOV d+X, Y DB 2 5 (d+X) = Y (read) ........ + DEC Y DC 1 2 Y-- N.....Z. + MOV A, Y DD 1 2 A = Y N.....Z. + CBNE d+X, r DE 3 6/8 CMP A, (d+X) then BNE ........ + DAA A DF 1 3 decimal adjust for addition N.....ZC + TCALL 14 E1 1 8 CALL [$FFC2] ........ + SET1 d.7 E2 2 4 d.7 = 1 ........ + BBS d.7, r E3 3 5/7 PC+=r if d.7 == 1 ........ + MOV A, d E4 2 3 A = (d) N.....Z. + MOV A, !a E5 3 4 A = (a) N.....Z. + MOV A, (X) E6 1 3 A = (X) N.....Z. + MOV A, [d+X] E7 2 6 A = ([d+X]) N.....Z. + MOV A, #i E8 2 2 A = i N.....Z. + MOV X, !a E9 3 4 X = (a) N.....Z. + NOT1 m.b EA 3 5 m.b = ~m.b ........ + MOV Y, d EB 2 3 Y = (d) N.....Z. + MOV Y, !a EC 3 4 Y = (a) N.....Z. + NOTC ED 1 3 C = !C .......C + POP Y EE 1 4 Y = (++SP) ........ + SLEEP EF 1 ? Halts the processor ........ + BEQ r F0 2 2/4 PC+=r if Z == 1 ........ + TCALL 15 F1 1 8 CALL [$FFC0] ........ + CLR1 d.7 F2 2 4 d.7 = 0 ........ + BBC d.7, r F3 3 5/7 PC+=r if d.7 == 0 ........ + MOV A, d+X F4 2 4 A = (d+X) N.....Z. + MOV A, !a+X F5 3 5 A = (a+X) N.....Z. + MOV A, !a+Y F6 3 5 A = (a+Y) N.....Z. + MOV A, [d]+Y F7 2 6 A = ([d]+Y) N.....Z. + MOV X, d F8 2 3 X = (d) N.....Z. + MOV X, d+Y F9 2 4 X = (d+Y) N.....Z. + MOV dd, ds FA 3 5 (dd) = (ds) (no read) ........ + MOV Y, d+X FB 2 4 Y = (d+X) N.....Z. + MOV Y, A FD 1 2 Y = A N.....Z. + DBNZ Y, r FE 2 4/6 Y-- then JNZ ........ + STOP FF 1 ? Halts the processor ........ diff --git a/spencer/spctest b/spencer/spctest new file mode 100755 index 0000000000000000000000000000000000000000..75a71ce9d760d3b4e8dbed5af43565875387513f GIT binary patch literal 17952 zcmeHP4{#LMd4G3EAh5YRuyAA>n=Lkp>{^F}ffA>R_k<2st-x21Y)FllLw7kua%tFGNj5jApsgtNh1 zzwf>Gt@bu2oF=i8$=uWIeeeCgfA4+!_U+rZ`}7%q>jtO8!6?mPA7@w^^$0|jj6)xn z86YZK#}>lxP3%TC7s?eJ6MR(=;EHs{Sxl=WJ_ji3)nKLsT`FKklxm0+^=3bjL#srUbGM;v-0uPhQe;Kpu^+`QDZI<#x(FdljuO~ylj=zA^%PZUrv(u1( z8By~07odl6`Bf90<}K3SZ0Dgyo^a7If}|oSq2fFP_`Nl3_I$-)VH|unx>VPk9od2b@PI) z4>cTC6DWi2K$|Fo2{AkS@J9ew;IO9#0G8W9EQk9dN!FW6CYY`#lEIEo>K$F5)H{QbDC>;R7YP>?~L>WqmfUCp$HwN12yAGy*n7`VOYj~vX*UZZE0Gsukx-o zbE~{-nBLO1Ne_kN;oXr$G8}K)v_2Z^3AY7zMbX;s?pTksrVG)Mg1jY8=siyU$IM>` zpd5j61j-Tky^p|K?wj7x(r2r*p~|1EWK7$i zNjeKzE&Wv0NnZEDnpXiXtauH6-OE(SVYv%=lj8+QD_+7fPWdLYy!M;pOjR z8K+>A-{Ivav5Zr%$wRz+49hs>njD2P)~DfrT8!uJ*Nj)S^lQ_Bw$|awufx`!6K~w5oygD89H+GBE+?zOz`siaRfX|R_p;_0eXL)9qaSox>W+3T-FO%znP$A6 zT&N8-UJG?9EI92)s~z-q9QoilliC)%6b4YKWE15SjZ8T;~@ zk($x-&+icHmNDJ(N<-(TcaUb#L(ix9?EOQJ`EB9@jE<882 zxih^lcYMzpA*gz0*vH=l!9sQ*v$qDd>oNtX?m=yM$rJGK;U25-Of42lfhy!{j;wo( zm8zqW9rRDnQqkLGMQ=e67GQ?K$jNTk&i%cZXD<6Afh}wvIx-( zN4F!&vm+NV`#49x3BMvc@;ai2I9hFHM}CCaevZBlkr&yK?*W?5?{p6w1q?GI-{8m& z_khZg9qy4Ya71+vEa8ai9!Ybg(LL}bu$Rs^x<@_*$o`CbKxixO{W}5R4Ifi0(&Mif zPhw#(P%(MHWU%3YgQM8dCfr=`GeQtfV0yfNe%4f*k$BgX7|5jN9R+J_s`4oOGK=`6 zVtP>>{!dIV80X6~?r*X(o_5SI zDvKBuGmNtkL$f907iSnR6fusQj2YnzCN}x?8DXaxdFPC%d4^Tzdq>`Rg~(6c#f{o8 ztl&j{VHu}j)czSfJj2Dtd&k7_xB2Kcewr^KOgTnNsxKGnVtj#RQukQ3=$=Qkx$dzi zhpTy)?KA>&hy0h!OTHd1`7gu8P9I}i+&D4US_Gy`yRTvK7 zeStF<{Sq|f2czxzkoL#by!FY-iDsyuh>h{4ku}~KY`q9V!bl4v3eG(4@f#<6MxOTu7vA8hH+=U3m`p$A;U2*59WWjn{%6zso@L1|L#P|9 z!UG@-GLHhW-eCFt)pu{}aO1^W81voJV!Y^UZ!ymM+I+^Pc5S%sEWle^Z+#bQGI8z~ z;PJ$}bCSy%ek$h+t;YYh8gDck|LrSOzoMm2I<$|zoccM=kN$Fp?>^rS-~B$_dQZpu zInJDr@_CgxlfrXdPUQ%cBT$Y&IRfPf{C-3L-xpme{p-0WCfKPPvzJD`l^c2NeBZOV z?8TMWP35we9?WI0dhPrVazAF5vTuFc;W_tU&NFrF7ca46xuJMX(;hL+rEttPGKqas<--iXVI)7VHX}h(=!tr=44lkA* zH_Z812pW#>l4{Qt3I~B61lkYu@23le4AB1oIu3OIn}q_-NG||Yfd2e^p`Zet3zLnV zKyL!t4|D?PA)wn}W;6j5Q?($>@#!th(dTj8aP_>ZQQ#rI6b=vgghd0!n&T0T%HkUi>u~ybNnu4 zxWezM{kzI$SN(yxnrmHp-bR<&<67r))%#qvO)jO$Rnz41G{JNdgE|0qy1pd5j61pZJXK;QMzcYHWy$AsSsV!B!o^TR=SZ^zTN>jag= z{9f<|$%jV`p01aaz8l2n15Cs}f4LCDat5CzAenP{W~JW`Ewd(`LhJj zB@!nh)!>0aAoNr_Dh22{jJ`Geki;|6G2u*>soohW2g~|Ak$+g2=j{QIi^AG8FK1DJ8EMptjZ)OS z%@YKdu>+7nzcf!F{PSG?8gt%3IKG7c|Fr8Ux3ie#mXn1UTFTBT&c5cC>iJ`CX9=_4 zH^-$s?Wf>H_<4(G7Mc5;2%if9aWI&LsDudmUw}JtHfD=6u9Yr^_ypucOim-%?SL!A zCV1(2j@PiAYB5vec8W19Z3o-~vnx7ZB=KRCce)wP0}0Z z@I}rVW}nAYImLN-6)!YMd@UU4BET^YWUPX7p(y3|$#%sh{$Yua%L!&!;%hlB3l{P` z=nA{|MmAOW^nw8Ly8jnH13Au1H-^EE)FV)+{LK z$>44l>4_u(=!hp1$rOBX*}-NuTxkhS zD|lT6gK$+i!Z21EI zRzF(hd(%1+DPH3%?mWXCa4KzB0QB|5bT^o^U+wW7aDmtXon&_ zdMXhPar^=DiIKn)BKPvy9Pdgbq+h;|k6R4)u@TcFYn>Ids5!sc&s-ZPwurqyHXL@rWy%J z$k)_Thu44?#k+!uF6IsG?Ex2pCgXy$Cmc^iVm(C#9eD9@G>8f^*BebTFOQiw8SaBT z_I=>Rc<=CryJTE z;W`BlT`+v`R3qm{L}{HuvT2y3BD)!KxHdrg>!dzW)sz$&S~nngEo7|veNvz3EhH!@ z4Qm9q*z{?BM^qs}N$vXg0uHY}V^n`ye<4ckm&+dJdJUNkLI&TFlRmA_5LM)T0o#aK zYCqiMq)+QZL^D#5{M+0AMXBE;Z>e_ue*_F;LiTY=!IPx44kuAw zSIQ%O7!IqxBK3&&T7@BRGta(Z)2Dd_(SM-|OFN`bW*@cb(>#(WtuvCmz5o7`)Hma= zNJ&XA$RZI5Q;|IeIcz`a=cNGAkSQrLcK^=+Y}McSM?#M1L1bEzEgb9x;JM(Cm%aHM zL;sJ!E>C5muYj)GqEF9F({%tsA~{i-DHA>g4D37PpPpOj|4WR^`eXmcM0#`{bAX`; z>C-;%Gjd{Ci%OP6`b6Ibo>iZzQn+4FO%{oe9#JPKTlIIULUO0nSLi`V8c-x9QU%Ir zi|SAF(Ec?-g8Yy?`m&~l(!X?PvPfS}<4v6Ot(5wnDFm5=(toY2KaRur2toCsaShj< isqT<9Q|3;QJ!vyeen}7?Z%XN>@xdL^wKfG?k^LXS6hbBd literal 0 HcmV?d00001 diff --git a/spencer/spencer.c b/spencer/spencer.c new file mode 100644 index 0000000..2f97462 --- /dev/null +++ b/spencer/spencer.c @@ -0,0 +1,152 @@ +#include + +// needs memset +#include + +// needs printf +#include + +void spc_init(spc_cpu* s, void* mem, uint8_t(*mmr)(uint8_t, uint8_t, uint8_t)) { + memset(s, 0, sizeof(spc_cpu)); + s->mmr = mmr; + s->mem = mem; + s->initialized = 0x59C700; +} + +const uint8_t spc_ipl[0x40] = { + 0xCD, 0xEF, 0xBD, 0xE8, 0x00, 0xC6, 0x1D, 0xD0, 0xFC, 0x8F, 0xAA, 0xF4, 0x8F, 0xBB, 0xF5, 0x78, + 0xCC, 0xF4, 0xD0, 0xFB, 0x2F, 0x19, 0xEB, 0xF4, 0xD0, 0xFC, 0x7E, 0xF4, 0xD0, 0x0B, 0xE4, 0xF5, + 0xCB, 0xF4, 0xD7, 0x00, 0xFC, 0xD0, 0xF3, 0xAB, 0x01, 0x10, 0xEF, 0x7E, 0xF4, 0x10, 0xEB, 0xBA, + 0xF6, 0xDA, 0x00, 0xBA, 0xF4, 0xC4, 0xF4, 0xDD, 0x5D, 0xD0, 0xDB, 0x1F, 0x00, 0x00, 0xC0, 0xFF +}; + +uint8_t spc_r(spc_cpu* s, uint16_t p) { + if((p >= 0xF0 && p <= 0xF7) || (p >= 0xFA && p <= 0xFF)) return s->mmr(p - 0xF0, 0, S_R); + if(p >= 0xFFC0 && s->mmr(0xF1, 0, S_R) >> 7) return spc_ipl[p - 0xFFC0]; + return s->mem[p]; +} + +void spc_w(spc_cpu* s, uint16_t p, uint8_t d) { + if((p >= 0xF0 && p <= 0xF7) || (p >= 0xFA && p <= 0xFF)) { + s->mmr(p - 0xF0, d, S_W); + return; + } + s->mem[p] = d; +} + +// this is bad +#define spc_im8(C, O) (spc_r(C, C->PC + 1 + O)) + +// this is not okay +#define spc_im16(C) ((((uint16_t)spc_im8(C, 1)) << 8) | spc_im8(C, 0)) + +// with code like this all these opcodes are illegal opcodes +#define spc_dp(C, O) ((((uint16_t)spc_getp(C)) << 8) | (uint8_t)O) + +#define spc_sp(C, O) (0x100 | (uint8_t)O) + +#define spc_push(C, O) spc_w(C, 0x100 + ((uint8_t)C->SP--), O) + +#define spc_pull(C) spc_r(C, C->SP++) + +#define NUL 0 +int spc_cycles[256] = { // -1: length returned by spc_eval +// 0 1 2 3 4 5 6 7 8 9 a b c d e f + 2, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 0 + NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 1 + 2, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 2 + NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, 2, NUL, NUL, // 3 + 2, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 4 + NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, 2, NUL, NUL, // 5 + 2, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 6 + NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 7 + 2, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 8 + NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 9 + 3, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // a + NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, 2, NUL, NUL, NUL, // b + 3, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // c + NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // d + 2, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // e + NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, 2, NUL, NUL, NUL // f +}; + +uint8_t spc_len[256] = { +// 0 1 2 3 4 5 6 7 8 9 a b c d e f + 1, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 0 + NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 1 + 1, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 2 + NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, 1, NUL, NUL, // 3 + 1, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 4 + NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, 1, NUL, NUL, // 5 + 1, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 6 + NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 7 + 1, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 8 + NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // 9 + 1, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // a + NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, 1, NUL, NUL, NUL, // b + 1, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // c + NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // d + 1, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, // e + NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, 1, NUL, NUL, NUL // f +}; + +int spc_eval(spc_cpu* s, int* err) { + int cycles = 0; + switch(spc_r(s, s->PC)) { + case 0x00: + break; + case 0x20: + spc_unsetp(s); + break; + case 0xBC: + spc_inc(s, s->A); + break; + case 0x3D: + spc_inc(s, s->X); + break; + case 0x40: + spc_setp(s); + break; + case 0x5D: + spc_trans(s, s->X, s->A); + break; + case 0x60: + spc_unsetc(s); + break; + case 0x80: + spc_setc(s); + break; + case 0xA0: + spc_seti(s); + break; + case 0xC0: + spc_unseti(s); + break; + case 0xE0: + spc_unsetv(s); + spc_unseth(s); + break; + case 0xFC: + spc_inc(s, s->Y); + break; + default: + printf("unimplemented opcode: 0x%02X\n", spc_r(s, s->PC)); + *err = 1; + break; + } + s->PC += spc_len[spc_r(s, s->PC)]; + return cycles; +} + +int spc_loop(spc_cpu* s) { + if(s->initialized != 0x59C700) return !printf("SPENCER UNINITIALIZED\n") - 1; + int err = 0; + if(s->wait == 0) { + printf("-- EVAL --\n"); + int w = spc_cycles[spc_r(s, s->PC)], c = spc_eval(s, &err); + if(w == -1) s->wait = c; + else s->wait = w; + s->wait--; + } else s->wait--; + return err; +} diff --git a/spencer/spencer.h b/spencer/spencer.h new file mode 100644 index 0000000..7af743a --- /dev/null +++ b/spencer/spencer.h @@ -0,0 +1,64 @@ +#ifndef SPENCER_H +#define SPENCER_H + +#include +#include + +// mmr flags +#define S_R 1 // read +#define S_W 0 // write +#define S_I 2 // internal (for internal emulator function) + +typedef struct { + uint8_t A, X, Y, SP, P; // 1 byte registers + uint16_t PC; // 2 byte registers + uint8_t* mem; // 0x10000 bytes + + /* MMR arguments: + * + * width description + * ------------------------- + * u8 | register number (0-15) + * u8 | data to write (if reading anything is fine) + * u8 | S_R to read, S_W to write + */ + uint8_t(*mmr)(uint8_t, uint8_t, uint8_t); + unsigned int wait; + unsigned int initialized; + uint8_t sleeping; +} spc_cpu; + +#define spc_getn(CPU) (CPU->P >> 7) +#define spc_getv(CPU) ((CPU->P >> 6) & 1) +#define spc_getp(CPU) ((CPU->P >> 5) & 1) +#define spc_getb(CPU) ((CPU->P >> 4) & 1) +#define spc_geth(CPU) ((CPU->P >> 3) & 1) +#define spc_geti(CPU) ((CPU->P >> 2) & 1) +#define spc_getz(CPU) ((CPU->P >> 1) & 1) +#define spc_getc(CPU) (CPU->P & 1) + +#define spc_setn(CPU) CPU->P |= 0x80 +#define spc_setv(CPU) CPU->P |= 0x40 +#define spc_setp(CPU) CPU->P |= 0x20 +#define spc_setb(CPU) CPU->P |= 0x10 +#define spc_seth(CPU) CPU->P |= 0x08 +#define spc_seti(CPU) CPU->P |= 0x04 +#define spc_setz(CPU) CPU->P |= 0x02 +#define spc_setc(CPU) CPU->P |= 0x01 + +#define spc_unsetn(CPU) CPU->P &= ~0x80 +#define spc_unsetv(CPU) CPU->P &= ~0x40 +#define spc_unsetp(CPU) CPU->P &= ~0x20 +#define spc_unsetb(CPU) CPU->P &= ~0x10 +#define spc_unseth(CPU) CPU->P &= ~0x08 +#define spc_unseti(CPU) CPU->P &= ~0x04 +#define spc_unsetz(CPU) CPU->P &= ~0x02 +#define spc_unsetc(CPU) CPU->P &= ~0x01 + +#define spc_sbn(c, d) c->P = (c->P & 0x7F) | (d & 0x80) +#define spc_sbz(c, d) c->P = (c->P & 0xFD) | (!d << 1) + +#define spc_inc(c, d) d++; spc_sbn(c, d); spc_sbz(c, d) +#define spc_trans(c, a, b) a = b; spc_sbn(c, a); spc_sbz(c, a) + +#endif