From f141b66f097f894ac9b5096925806ccd3135ae5a Mon Sep 17 00:00:00 2001 From: Butter Date: Tue, 7 Apr 2026 10:04:37 -0400 Subject: [PATCH] Fixed carry flag on addition and subtraction ops, made rom selection a command line arg --- .gitignore | 1 + 1-chip8-logo.ch8 | Bin 0 -> 260 bytes 3-corax+.ch8 | Bin 0 -> 761 bytes 4-flags.ch8 | Bin 0 -> 1041 bytes 5-quirks.ch8 | Bin 0 -> 3232 bytes 6-keypad.ch8 | Bin 0 -> 913 bytes 7-beep.ch8 | Bin 0 -> 110 bytes 8-scrolling.ch8 | Bin 0 -> 1330 bytes Cargo.lock | 1006 ++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 8 + IBM.ch8 | Bin 0 -> 132 bytes src/cpu.rs | 238 +++++++++++ src/main.rs | 59 +++ 13 files changed, 1312 insertions(+) create mode 100644 .gitignore create mode 100644 1-chip8-logo.ch8 create mode 100644 3-corax+.ch8 create mode 100644 4-flags.ch8 create mode 100644 5-quirks.ch8 create mode 100644 6-keypad.ch8 create mode 100644 7-beep.ch8 create mode 100644 8-scrolling.ch8 create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 IBM.ch8 create mode 100644 src/cpu.rs create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/1-chip8-logo.ch8 b/1-chip8-logo.ch8 new file mode 100644 index 0000000000000000000000000000000000000000..19c5cf30f469f86fce62351b46c5a68454d93429 GIT binary patch literal 260 zcmZR0kjR+8u_)kze1gED_zUt05{vRK$R{W)s=Xkeps}duf_#F(qS+VZ69p1D7OeuS z+6h*50<7vfSk*JIs;?L1h5Y!LK!AZk-oEg`(+4jW@M>vjXfQBH?AT#pVZWb2a_QcM za~T+TWMvt7W#=*;*VNQhXJGj8=iISl$Br?0dU<+SGcYhPGBYzXelVE8z|g?J!0_*Q zb93{tKhGaLc<`XmUY>!09b|>2g@uL1jvW>Z42E8n4%T;}fPrCwg~9@fbANsuxN_&n rQ3eJB7Zs7@kId}s<>JYO3=A55D^@H!*Urq$-2U$m14F`u4-EwXkfCH# literal 0 HcmV?d00001 diff --git a/3-corax+.ch8 b/3-corax+.ch8 new file mode 100644 index 0000000000000000000000000000000000000000..9fc874c917a5a6957c4affe5ac285211abb749b2 GIT binary patch literal 761 zcmY+>F^CgE6adiKn9XTYC}9y%(B+CNl4di)BHFBiNo$jSPuD`CFY0@k8D}!2~c@5Hp{WO8!#|g~rCa{wvsK7xc>~RBTCrMC)!(6(ql5233 z%V^nFSz{f(<@Q!(jdj?~WLAG8YxnB?>w{Z?274=a(RvAH4wA944%=x0-(@FG37CbH zeN7YCK2Csn4Ijl%I{97Fccqh>--tImP1)C2SH7ow%fAyp?c6B%{(pbg@um0H`x}F1 zps7;_Dmw8e@$(C(4m011z0R*fwWF-sB=#@(7v)zY(q1cM%efd4(Xh=k{gEarcRKfA zX6*oLb=4c;zCCylXeuu6p1Nq$ns;G(=DkAj{!C_Dz*_mM$vSefDS5rP`^N)jX$Edx zGB920Oc|hZ!yPIpm-{djoKh}$C`8CZM5#j^N~@nfJi2$;`uqyLv6gMx={(iGZsx0BOSQiNgC z-pXe2FBpaGAqNrc!9x#o?9p>Tcn8nRR;@Ysqw*$;L_zm3-^cFvz3=ag)JN34gKAOtE^3Rq3#fv+_fP}s-baF+sYorD9LYhG9*wX9=Mv6SV7&LJoDig(VB?VB|4z$P^CrtFI}Xs4aA z#Pdme@_uZOjd)Tt*i1KxGoH9UYu9-{wr56MB|Rxc1ut|9Td~gk!h7|KSMXzdcEov! z1|Gxww&A3;zql1I6?nFDw4C9Y?W65j_Z6=he9VuvA8bSKo7TNXve5}D_;mMc2mRCD zWk0sdBRQCmc1}{kGu??~qk&Es=!9&o;!XT7qir~6so<6FPn}TluK2Ot_%p#F>$&iU zzU^GCq4^Iqe}f-r{sYZFsk?>@STn2>{zc8d$Qzv_-m5QqML)K`jig|$?@Rv$WS&Ww zXGWNZvvKN>c~vv7@}yb@EbWeK%94|%qJ4}v6VBIi zhh?i5SHs8gvPbM54Z?YzJ1$$*-|wn4D9(|;AE|_75~Kvh7=Wn&EE6P{CMZ*Z007f8 z0VEcHPKC7)prllw1b|S&64KH`7z4{Rl~hs+fz1-j;e4qClVIUT3uiONq?DGFl1T}G mr<6EAfZlR=vW3Z&l^t?*venuljg5ur7RkJRHFy2g)Vp7@q^sHh literal 0 HcmV?d00001 diff --git a/5-quirks.ch8 b/5-quirks.ch8 new file mode 100644 index 0000000000000000000000000000000000000000..1c87f6cde015ad494756a8252f027de0f23e1ffa GIT binary patch literal 3232 zcmeHF-)|Gy6+U;aV_S~FW|FZ}7J_AOl@K8`Apx1jyB?clH_&JkQHIR}4|jqMQ6OGt z6}D-$D@`{`V9Saklxid7MH8eVPmxwgOQmR~wj;TP{;-JE_6c>Rd7wWYR?!3pijc)r zXY6FNXt#es&yntTX3o9e`Odkw#m~T803Ns3 zeKmU$s=}J57x@0-4=Q}dwHN-=H#aU{mQhR9;v>xlUnH;AalxWkB7V%!l#EyjHx@pg2ElDbftTY@WF|FXI|3({NT>S_w?llcVMNM zX2g8#{#?d*292AR9HQ-szXDPS~3Sd&OvJ5#`1DZ)6c z0?)zJKW96Xos|#^DO`m=Z?R~FpR=6*uP9BG5TlB#!e6iyUxmMDfyr{pzDkI7D%&dj zhZgIt@E@)zVO&|Kv%&x{A~WWe^UN))%ze9Vxdk!o0$W=n*!U)a_=Z4C0PLm`@^f#l0EW8y^xnanXQy7t9I7LolM2F!t!5)jF zA`vbRkfJPH9e|=d(RYS>@R@#jfasTGrr(nD`t8ZC9ElbtNzSdaXn_%h8>1&(nWo~v zn#`IN|Jat|z$4kpo(C&C2X$5jBqDq%aY9XU2{nldU+#Aa&ki&RPm8kfOd%oP{^pSH zKy%1jltVs+O!S@cJorq%G|;SHP7(dqWLM7Z)NIyIM+?RDs-rY?AVrF@$c0`_(V{H6 zLa(J8hUCcTj2^u-j_Z%%gQnjOxdK82i*>YP7K z*Ez4IIfwI_gEVv_UFY0}oN1z8O1t!r(@lCI&FPD2s^3hz^;>C=emm{ee>K^a3p(6_ z{$rf`Deq|*kDSk4m|LH6=+S;~v_Hc+i>@%|APxKQ|3u%JkTZACFUfhQf5G9~uFpmb zY#~?pO=Gem2`8MBT)5w1bcKf;q~T+Y8+>W~1}D36+oJ``7v);~9e>h|Ct3a8VoS!LM8a9Js%YF;Tj801-qs23Mx`vKWROG zT>oQ*&wIs0n_s_I;qye4+CqU1=Nita^VrYh@ zsVW}UFs$=yhAL?$!z4p)Ns=^8W16N(nr51~Y8n!#rlYgIO73Q=x`TAcEzpJWq26Qj zwLGW-u6e z_k{B!!yqF`Fg=?207mnPX&A&s%*+e|%di9_@_8>Veq4g^+%exS0CERZ)wX?~-bly2 z;!=P^1K5?EGXG)zTiepr+1UxuwzL$FCw~jy`NgjnKLPOX+)1|V{Dj=wy?b{Dz|-3O zyLa#2g~LY<5B327p_CF!yaJ#C!1H^vv$J<=|1wR}oJ#Hj@L-99@pwGGv=j&EKJp`} z?~8^3Xz_^FcE9%2_}kxq_j>@b|K-+`tJLH9Vff?}KU-^0-jh1Ms+*9sZt}a*0v`kCYQgtIwfm%r`=`U^aq(8Zl z2LQ1omc+7HcF+)wz;a-DJs*Gol%TZ!2?l(vG*Fw`0XtwPX_D5U2DP4AkAp_ds3mJj zYEWaj;emCx1NO4LYzIn#5?El-YTZ#Q_KIKF1Db8vhHcrFRkLbV;svi+HAfhpL!s+V zf#O(g6j!rr*#CNIL}Xd#bhM)GhGQS7504`EhUNyr=3X%Gi2N4AJl4S;EU=&|R>i7S zwJgyRtsbk#(T3Z949h7e!I@i++)cR78E7^Y|+9y30nx6XnF_d;${A8^Sxm T_k(i(Z{K2B2=C33@ZSFdo^~1i literal 0 HcmV?d00001 diff --git a/6-keypad.ch8 b/6-keypad.ch8 new file mode 100644 index 0000000000000000000000000000000000000000..4d1ecdccdf6968522529fff4a18492cd31032600 GIT binary patch literal 913 zcmZ9IO=uHA6vy9Af+lO#>8!OuOBih4uMc<>;yH?IY6f;flVgpg#VX1-q! zusF8wDwJpWa+M8bA5;hDY-s77)SnE$8xln|EKf`c=^JkwHBogKC3>sd(0H zHb`j4=Y|}QFAbTCuei++yyy3<^Ed=&Eh2yNz50UHZ7;x6>bw(L?1-=S^8I@JU}LxG z3filhiyK?Q?QzO&@>Fl4XZN=r0_U4aKs|8<{f`=T&q`z9s$UBRGC0k7wW!Yb;_-nAZ z}|y$QE#6^3O2rSL?@1nd!HG0g+EpH2?qr literal 0 HcmV?d00001 diff --git a/7-beep.ch8 b/7-beep.ch8 new file mode 100644 index 0000000000000000000000000000000000000000..27c205f7e1cb3a52c9314e8e0227aedd559bc24b GIT binary patch literal 110 zcmZ1!@*y>ev6&%-J4+^;XHm!}xsR!f(r<15An`#|N$1w~kD^LCMNB~kLVQ9DPZkPU zd|)?V5Yl0Im%xx{lf=#N0HpS##G{2mE+9RR<_Y--IS6yHa{N3M*Mm`6&*E=gK===mg=dU(VpWanjLF97 z^MZn|EHu$E-v3d5D|EQs-^lAhGr9IvV+w#Lc@-uBsF^_(p5jzgILvZG9bGR=*&Y_DNPkL7_TSfY$fX<+-jx z!1__J+xm4!_3fU@Ux3!1(d9W*2w0BUXZ1J@)otJNDq#?3g|L;1;OaM+vA; zg(mHzL~5~~#~@_L&=y&ENuCAF_K{(&-R%WWo`xMHesT8?4_hI98gP5T-SF7|>z`JF zeYN{K{9wOGWNjdOI2X~o@?LjzW7JJ+o+6ozH zy`b1XlI_ZQ-EMcl9W|tpn4A(j$8v3arp?iJq?aS|^sbNC@vJs{z$vDw&o~_yiig50 z`OLmDf6G0uN%^MOaWdDl=QSwb+40){ISzG9iYcR%IT$mhIE)d6QKl%&Q5Jx=6TnxV);}s6i6RJ;)0tFSq@5j}d!5MhSV$L#j8tL~_{tac6A6QW vKzTZm8j61kn$`QI(*0_)S=}m?wm5H>)~lS=_0sKX(**t-Yo|{5M!x$G{cHs6 literal 0 HcmV?d00001 diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..0989ea8 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1006 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + +[[package]] +name = "buttery_chip8" +version = "0.1.0" +dependencies = [ + "minifb", + "rand", +] + +[[package]] +name = "cc" +version = "1.2.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +dependencies = [ + "cfg-if", + "cpufeatures", + "rand_core", +] + +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + +[[package]] +name = "dlib" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a" +dependencies = [ + "libloading", +] + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "futures" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-executor" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "rand_core", + "wasip2", + "wasip3", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "indexmap" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", + "serde", + "serde_core", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "js-sys" +version = "0.3.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "libc" +version = "0.2.183" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "libredox" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" +dependencies = [ + "bitflags 2.11.0", + "libc", + "plain", + "redox_syscall", +] + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "minifb" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c470a74618b43cd182c21b3dc1e6123501249f3bad9a0085e95d1304ca2478" +dependencies = [ + "cc", + "dlib", + "futures", + "instant", + "js-sys", + "lazy_static", + "libc", + "orbclient", + "raw-window-handle", + "serde", + "serde_derive", + "tempfile", + "wasm-bindgen-futures", + "wayland-client", + "wayland-cursor", + "wayland-protocols", + "winapi", + "x11-dl", +] + +[[package]] +name = "nix" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "orbclient" +version = "0.3.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59aed3b33578edcfa1bc96a321d590d31832b6ad55a26f0313362ce687e9abd6" +dependencies = [ + "libc", + "libredox", + "sdl2", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rand" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" +dependencies = [ + "chacha20", + "getrandom", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "redox_syscall" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" +dependencies = [ + "bitflags 2.11.0", +] + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags 2.11.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "sdl2" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d42407afc6a8ab67e36f92e80b8ba34cbdc55aaeed05249efe9a2e8d0e9feef" +dependencies = [ + "bitflags 1.3.2", + "lazy_static", + "libc", + "sdl2-sys", +] + +[[package]] +name = "sdl2-sys" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff61407fc75d4b0bbc93dc7e4d6c196439965fbef8e4a4f003a36095823eac0" +dependencies = [ + "cfg-if", + "libc", + "version-compare", +] + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "version-compare" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" + +[[package]] +name = "wasip2" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9c5522b3a28661442748e09d40924dfb9ca614b21c00d3fd135720e48b67db8" +dependencies = [ + "cfg-if", + "futures-util", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.11.0", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + +[[package]] +name = "wayland-client" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715" +dependencies = [ + "bitflags 1.3.2", + "downcast-rs", + "libc", + "nix", + "scoped-tls", + "wayland-commons", + "wayland-scanner", + "wayland-sys", +] + +[[package]] +name = "wayland-commons" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8691f134d584a33a6606d9d717b95c4fa20065605f798a3f350d78dced02a902" +dependencies = [ + "nix", + "once_cell", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-cursor" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6865c6b66f13d6257bef1cd40cbfe8ef2f150fb8ebbdb1e8e873455931377661" +dependencies = [ + "nix", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6" +dependencies = [ + "bitflags 1.3.2", + "wayland-client", + "wayland-commons", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f4303d8fa22ab852f789e75a967f0a2cdc430a607751c0499bada3e451cbd53" +dependencies = [ + "proc-macro2", + "quote", + "xml-rs", +] + +[[package]] +name = "wayland-sys" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be12ce1a3c39ec7dba25594b97b42cb3195d54953ddb9d3d95a7c3902bc6e9d4" +dependencies = [ + "dlib", + "lazy_static", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.11.0", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "xcursor" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" + +[[package]] +name = "xml-rs" +version = "0.8.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..74612a4 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "buttery_chip8" +version = "0.1.0" +edition = "2024" + +[dependencies] +minifb = "0.27" +rand = "0.10" \ No newline at end of file diff --git a/IBM.ch8 b/IBM.ch8 new file mode 100644 index 0000000000000000000000000000000000000000..113338e67097e0a2ad227e5b79b3a5d1a586a660 GIT binary patch literal 132 zcmZR0ut+O`Cz0cVd;#Yo%M0?0JPJT;mPO$g*g)ZbhW{Y0 z1%o|Pf1C;*3@Q1;U!JfgI!II$z!w+T#b_RZi{S3buJ~KRKaE2*` GDhB`q?=2qy literal 0 HcmV?d00001 diff --git a/src/cpu.rs b/src/cpu.rs new file mode 100644 index 0000000..9a7cba3 --- /dev/null +++ b/src/cpu.rs @@ -0,0 +1,238 @@ +use crate::cpu; +use rand::{self, RngExt}; + +const FONT: [u8; 80] = [ + 0xF0, 0x90, 0x90, 0x90, 0xF0, // 0 + 0x20, 0x60, 0x20, 0x20, 0x70, // 1 + 0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2 + 0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3 + 0x90, 0x90, 0xF0, 0x10, 0x10, // 4 + 0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5 + 0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6 + 0xF0, 0x10, 0x20, 0x40, 0x40, // 7 + 0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8 + 0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9 + 0xF0, 0x90, 0xF0, 0x90, 0x90, // A + 0xE0, 0x90, 0xE0, 0x90, 0xE0, // B + 0xF0, 0x80, 0x80, 0x80, 0xF0, // C + 0xE0, 0x90, 0x90, 0x90, 0xE0, // D + 0xF0, 0x80, 0xF0, 0x80, 0xF0, // E + 0xF0, 0x80, 0xF0, 0x80, 0x80, // F +]; +pub struct Cpu { + reg: [u8; 16], + pub ram: [u8; 4096], + program_counter: u16, + stack: [u16; 16], + stack_pointer: u8, + index: u16, + pub display: [bool; 64 * 32], + delay_timer: u8, + sound_timer: u8, + pub keys: [bool; 16], +} + +impl Cpu { + pub fn new(rom: &[u8]) -> Cpu { + let mut cpu = Cpu { + reg: [0; 16], + ram: [0; 4096], + program_counter: 0x200, + stack: [0; 16], + stack_pointer: 0, + index: 0, + display: [false; 64 * 32], + delay_timer: 0, + sound_timer: 0, + keys: [false; 16], + }; + cpu.load_font(); + cpu.load_rom(rom); + cpu + } + pub fn load_font(&mut self) { + self.load_into_ram(&FONT, 0x050); + } + pub fn load_rom(&mut self, cart: &[u8]) { + self.load_into_ram(cart, 0x200); + } + fn stack_push(&mut self, data: u16) { + self.stack[self.stack_pointer as usize] = data; + self.stack_pointer += 1; + } + fn stack_pop(&mut self) -> u16 { + self.stack_pointer -= 1; + self.stack[self.stack_pointer as usize] + } + pub fn tick(&mut self) { + // Fetch - read two bytes from RAM at program_counter + let hi = self.ram[self.program_counter as usize] as u16; + let lo = self.ram[(self.program_counter + 1) as usize] as u16; + let mut rng = rand::rng(); + // Increment - increment the program counter by 2 + self.program_counter += 2; + // Decode - figure out what those bytes mean + let opcode = (hi << 8) | lo; + let nibble = (opcode >> 12) & 0xF; + let x = ((opcode >> 8) & 0xF) as usize; // as usize for indexing into registers + let y = ((opcode >> 4) & 0xF) as usize; + let n = (opcode & 0xF) as usize; + let nn = (opcode & 0xFF) as u8; + let nnn = opcode & 0xFFF; + // Execute - do the thing + match nibble { + 0x0 => { + match opcode { + 0x00E0 => self.display = [false; 64 * 32], //clear the screen + 0x00EE => self.program_counter = self.stack_pop(), // return from subroutine + _ => println!("opcode {:#06X} has not been implemented", opcode), + } + } + 0x1 => self.program_counter = nnn, //0x1NNN is jump to NNN + 0x2 => { + // call subroutine at nnn + self.stack_push(self.program_counter); + self.program_counter = nnn + } + 0x3 => { + if self.reg[x] == nn { + self.program_counter += 2 + } + } + 0x4 => { + if self.reg[x] != nn { + self.program_counter += 2 + } + } + 0x5 => { + if self.reg[x] == self.reg[y] { + self.program_counter += 2 + } + } + 0x6 => self.reg[x] = nn, + 0x7 => self.reg[x] = self.reg[x].wrapping_add(nn), + 0x8 => match n { + 0x0 => self.reg[x] = self.reg[y], + 0x1 => self.reg[x] |= self.reg[y], + 0x2 => self.reg[x] &= self.reg[y], + 0x3 => self.reg[x] ^= self.reg[y], + 0x4 => { + let (result, carry) = self.reg[x].overflowing_add(self.reg[y]); + self.reg[x] = result; + self.reg[0xF] = if carry { 1 } else { 0 }; + } + 0x5 => { + let result = self.reg[x].wrapping_sub(self.reg[y]); + let not_borrow = (self.reg[x] >= self.reg[y]) as u8; + self.reg[x] = result; + self.reg[0xF] = not_borrow; + } + 0x6 => { + self.reg[x] = self.reg[y]; + let lsb = self.reg[x] & 1; + self.reg[x] >>= 1; + self.reg[0xF] = lsb; + } + 0x7 => { + let result = self.reg[y].wrapping_sub(self.reg[x]); + let not_borrow = (self.reg[y] >= self.reg[x]) as u8; + self.reg[x] = result; + self.reg[0xF] = not_borrow; + } + 0xE => { + self.reg[x] = self.reg[y]; + let msb = (self.reg[x] >> 7) & 1; + self.reg[x] <<= 1; + self.reg[0xF] = msb; + } + _ => println!("opcode {:#06X} has not been implemented", opcode), + }, + 0x9 => { + if self.reg[x] != self.reg[y] { + self.program_counter += 2 + } + } + 0xA => self.index = nnn, //0xANNN set index to NNN + 0xB => self.program_counter = self.reg[0] as u16 + nnn, + 0xC => { + let random_byte: u8 = rng.random(); + self.reg[x] = nn & random_byte; + } + 0xD => { + //0xDXYN is display, and is a doozy. + // get X and Y coords from VX and VY + let x_coord: usize = self.reg[x].into(); + let y_coord: usize = self.reg[y].into(); + let mut flipped = false; + for row in 0..n { + let sprite_byte = self.ram[self.index as usize + row]; + for col in 0..8 { + let bit = (sprite_byte >> (7 - col)) & 1; + let y = y_coord + row; + let x = x_coord + col; + let idx = y * 64 + x; + if bit == 1 { + self.display[idx] ^= true; + flipped |= !self.display[idx]; + } + } + } + if flipped { + self.reg[0xF] = 1; + } else { + self.reg[0xF] = 0; + } + } + 0xE => match nn { + 0x9E => { + if self.keys[self.reg[x] as usize] { + self.program_counter += 2 + } + } + 0xA1 => { + if !self.keys[self.reg[x] as usize] { + self.program_counter += 2 + } + } + _ => println!("opcode {:#06X} has not been implemented", opcode), // unknown opcode + }, + 0xF => match nn { + 0x07 => self.reg[x] = self.delay_timer, + 0x0A => {} + 0x15 => self.delay_timer = self.reg[x], + 0x18 => self.sound_timer = self.reg[x], + 0x1E => self.index = self.index.wrapping_add(self.reg[x] as u16), + 0x29 => { + self.index = ((self.reg[x] * 5) + 0x050) as u16; + } + 0x33 => { + let vx = self.reg[x]; + let hundreds = vx / 100; + let tens = (vx / 10) % 10; + let ones = vx % 10; + self.ram[self.index as usize] = hundreds; + self.ram[(self.index + 1) as usize] = tens; + self.ram[(self.index + 2) as usize] = ones; + } + 0x55 => { + for reg in 0..=x { + self.ram[self.index as usize + reg] = self.reg[reg]; + } + } + 0x65 => { + for reg in 0..=x { + self.reg[reg] = self.ram[self.index as usize + reg]; + } + } + _ => println!("opcode {:#06X} has not been implemented", opcode), + }, + _ => println!("opcode {:#06X} has not been implemented", opcode), // unknown opcode + } + } + fn load_into_ram(&mut self, data: &[u8], offset: usize) { + data.iter().enumerate().for_each(|(i, byte)| { + //write byte to ram starting at 0x200 + self.ram[offset + i] = *byte; + }); + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..83ccdb8 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,59 @@ +mod cpu; + +use cpu::Cpu; +use minifb::{Key, Scale, Window, WindowOptions}; +use std::{env, fs}; + +const WIDTH: usize = 64; +const HEIGHT: usize = 32; +fn main() -> Result<(), Box> { + let args: Vec = env::args().collect(); + if args.len() < 2 { + eprintln!("Usage: {} ", args[0]); + std::process::exit(1); + } + let rom = fs::read(&args[1])?; + let mut chip8 = Cpu::new(&rom); + + let mut window = Window::new( + "Buttery Chip8", + WIDTH, + HEIGHT, + WindowOptions { + scale: Scale::X8, + ..WindowOptions::default() + }, + ) + .unwrap(); + let keys = [ + window.is_key_down(Key::X), // 0 + window.is_key_down(Key::Key1), // 1 + window.is_key_down(Key::Key2), // 2 + window.is_key_down(Key::Key3), // 3 + window.is_key_down(Key::Q), // 4 + window.is_key_down(Key::W), // 5 + window.is_key_down(Key::E), // 6 + window.is_key_down(Key::A), // 7 + window.is_key_down(Key::S), // 8 + window.is_key_down(Key::D), // 9 + window.is_key_down(Key::Z), // A + window.is_key_down(Key::C), // B + window.is_key_down(Key::Key4), // C + window.is_key_down(Key::R), // D + window.is_key_down(Key::F), // E + window.is_key_down(Key::V), // F + ]; + + let mut buffer: Vec = vec![0; WIDTH * HEIGHT]; + + while window.is_open() { + chip8.keys = keys; + chip8.tick(); + for (i, pixel) in chip8.display.iter().enumerate() { + buffer[i] = if *pixel { 0xFFFFFFFF } else { 0x00000000 }; + } + window.update_with_buffer(&buffer, WIDTH, HEIGHT).unwrap(); + } + + Ok(()) +}