From 0d75e866a9805a2165db531e2d1f0171adff77c5 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Mon, 19 Oct 2020 20:44:08 +0200 Subject: [PATCH] u8 operations with wrapping to avoid overflow --- README.md | 13 ++++++++++++- chip8/src/lib.rs | 35 +++++++++++++++++------------------ screenshots/s0.png | Bin 0 -> 2848 bytes screenshots/s1.png | Bin 0 -> 2206 bytes screenshots/s2.png | Bin 0 -> 2368 bytes screenshots/s3.png | Bin 0 -> 2730 bytes src/main.rs | 21 +++++++++++---------- 7 files changed, 40 insertions(+), 29 deletions(-) create mode 100644 screenshots/s0.png create mode 100644 screenshots/s1.png create mode 100644 screenshots/s2.png create mode 100644 screenshots/s3.png diff --git a/README.md b/README.md index d0bce75..b537340 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,17 @@ # chip8-rs CHIP-8 emulator written in Rust. -(Done with the Go implementation: https://github.com/arnaucube/go-chip8) + +*(Done with the Go implementation: https://github.com/arnaucube/go-chip8)* https://en.wikipedia.org/wiki/CHIP-8 + +## Usage +``` +./chip8-rs --file roms/invaders.c8 +``` + +![](screenshots/s0.png) +![](screenshots/s1.png) +![](screenshots/s2.png) +![](screenshots/s3.png) diff --git a/chip8/src/lib.rs b/chip8/src/lib.rs index f2293d8..99b1bb8 100644 --- a/chip8/src/lib.rs +++ b/chip8/src/lib.rs @@ -15,7 +15,7 @@ pub struct Chip8 { delay_timer: u8, sound_timer: u8, stack: [u16; 16], - sp: isize, + sp: usize, pub key: [u8; 16], pub draw_flag: bool, } @@ -77,7 +77,7 @@ impl Chip8 { let y: usize = ((self.opcode & 0x00F0) >> 4) as usize; let nn: u8 = (self.opcode & 0x00FF) as u8; let nnn: u16 = (self.opcode & 0x0FFF) as u16; - // println!("{:?} {:?}", self.opcode, self.pc); + // println!("{:x} {:?}", self.opcode, self.pc); // Decode Opcode // https://en.wikipedia.org/wiki/CHIP-8#Opcode_table @@ -95,10 +95,10 @@ impl Chip8 { 0x000E => { // 00EE Returns from a subroutine self.sp -= 1; - self.pc = self.stack[self.sp as usize]; + self.pc = self.stack[self.sp]; self.pc += 2; } - _ => println!("unk {:x}", self.opcode), + _ => println!("Unknown opcode: {:x}", self.opcode), } } 0x1000 => { @@ -107,7 +107,7 @@ impl Chip8 { } 0x2000 => { // 2NNN Calls subroutine at NNN - self.stack[self.sp as usize] = self.pc; + self.stack[self.sp] = self.pc; self.sp += 1; self.pc = nnn; } @@ -143,7 +143,7 @@ impl Chip8 { } 0x7000 => { // 7XNN Adds NN to VX. (Carry flag is not changed) - self.v[x] += nn; + self.v[x] = self.v[x].wrapping_add(nn); self.pc += 2; } 0x8000 => { @@ -176,7 +176,7 @@ impl Chip8 { } else { self.v[0xF] = 0; } - self.v[x] += self.v[y]; + self.v[x] = self.v[x].wrapping_add(self.v[y]); self.pc += 2; } 0x0005 => { @@ -187,7 +187,7 @@ impl Chip8 { } else { self.v[0xF] = 0; } - self.v[x] -= self.v[y]; + self.v[x] = self.v[x].wrapping_sub(self.v[y]); self.pc += 2; } 0x0006 => { @@ -198,7 +198,7 @@ impl Chip8 { } else { self.v[0xF] = 0; } - self.v[x] = self.v[x] >> 1; + self.v[x] = self.v[x].wrapping_shr(1); self.pc += 2; } 0x0007 => { @@ -209,7 +209,7 @@ impl Chip8 { } else { self.v[0xF] = 0; } - self.v[x] = self.v[y] - self.v[x]; + self.v[x] = self.v[y].wrapping_sub(self.v[x]); self.pc += 2; } 0x000E => { @@ -220,10 +220,10 @@ impl Chip8 { } else { self.v[0xF] = 0; } - self.v[x] = self.v[x] << 1; + self.v[x] = self.v[x].wrapping_shl(1); self.pc += 2; } - _ => println!("unk {:x}", self.opcode), + _ => println!("Unknown opcode: {:x}", self.opcode), } } 0x9000 => { @@ -243,7 +243,7 @@ impl Chip8 { 0xB000 => { // BNNN Jumps to the address NNN plus V0 self.pc = nnn + self.v[0] as u16; - self.pc += 2; + // self.pc += 2; } 0xC000 => { // CXNN Sets VX to the result of a bitwise and operation on a @@ -275,9 +275,8 @@ impl Chip8 { } if self.gfx[pos] == 1 { self.v[0xF] = 1; - } else { - self.gfx[pos] ^= 1; } + self.gfx[pos] ^= 1; } } } @@ -305,7 +304,7 @@ impl Chip8 { } self.pc += 2; } - _ => println!("unk {:x}", self.opcode), + _ => println!("Unknown opcode: {:x}", self.opcode), } } 0xF000 => { @@ -378,10 +377,10 @@ impl Chip8 { } self.pc += 2; } - _ => println!("unk {:x}", self.opcode), + _ => println!("Unknown opcode: {:x}", self.opcode), } } - _ => println!("opc {:x}", self.opcode), + _ => println!("Unknown opcode: {:x}", self.opcode), } if self.delay_timer > 0 { self.delay_timer -= 1; diff --git a/screenshots/s0.png b/screenshots/s0.png new file mode 100644 index 0000000000000000000000000000000000000000..21fc911cf3a1a052645a17c8ee2ad7f335f50e5d GIT binary patch literal 2848 zcmcImc{r47AATl<2+7t$Bijs#WS3=*r7;H)Qgn)BL{9d#8CwfQ$CM(=*tbeZOoc`{ z5;bK=*=mMLGgG!0Od7`bI>$NX>Z|Mf=Xaj*_ZI%1OVbCPK^gQ^_@zqLnA*Kf~S* zv5Hv=$~;Zg+Ordbcj4n>CS!D%dC{NFHGZ-Vx)f`~TTi_^YBTo~;@0wSKY#Y2ZL~(( zuYZQ%Y0a%Y4eP0srW_{AX;Os`uP~wBC6XL@D)L0vbHj0oL|2UCS?amgHTCiniappX z0|qj3(vjZ1ZN%4-~n%b)4)SRtT;B#Uz5q{Dth}Xp) zvaFcuQG$5>Q5m1^<6Lg*?^zK45YC$hBh}J!1G8ind9{*g~ zB3Q}HuD}7%sjTc^6iZt0Mje?n6Z8dmT`eCH2@DiGFRhBBy`zzH$n&_;mjhycH-n4A zS?z65S@=C|(3a2$U9%PqvCyzO(AqTw01d^(8x~n&77k4cgktQh1crnp*2!zYNA0da zQyW69_J>*o96yfr4+R#%*u$Y%FZl@HP#<|T#?E11yr>KSf}b&#zc@$skJ4gqybP0T zo#^4vn*%PaH1|c?#9;bTLrd6b*LB%P>VNIni=>pQqdQX{W}L5fyu(UdtyWQ2tHrEJ z^_1cZF$gJ|Dm^oy$R~MbjiTT#c_Mq1u#vWvb275-1eHu^4c8wtx@g2YXH+l^zSn(tOT<{OpaoleN-$xQ{U4 zbIAdK6nCV~yjM(i&mX4mi;X{33=h1R$1@6R*vaE~T^pIFPiZw}Sk!&f6n^jmhm?Js zzAwV7ohAmK9{w`@A)5Z7ZIC6DwX1HCw z9T&u#`4N~CE^4z~!Ut}#3exK4{qm@%3B-#fHTR7?b{>5V4HopT*FWkF*Sba7>RLp1qz*Lo_ZNOyfD!tdT>u^ zb%DWKePoh?$O1R(Q9^>G)sC2vv(A3lLw!6d#C(qN!Hh}N-ldF55Q*BCKA^RgGM@Z|EuaaEZrqg;bcvP?!=9SqWFPJf8#M4`UrR*f(JoMT8zamjJ*<)n z+ddT_yeZ{7Q^=M{3Nksm8e3yIcnu?Nbd-OyOuRm>;!Qys=pCo!8b+ARrSn#3R}nKh%ZQh6sn>YFqeQ(G8oFch(?^z5%?-2Ij-y=N5)9(r=Xldr25I}JEk3&jAa6Sn@@gj z8n&-eEI(!;T6h(B@B?y7dVMF`S6RM8JP2~BUWp2^+OvP<;M!$0AG~Tx-TbON3Gj1R@}SeDb0Um=*o(M2}xrmCnAmA_5=9p|t|ra~xTtn2OJnV;Ec zd5ONB@Li>rmX?P80?*ZPjHJSwf)BR*kU{CoXh|Ykgtl*~t5|MOKP|QE@^hE5|DO^0 za(~qXDU=LkmskI59u7xGia@PHI<~<-0M7q^U{G;ze|kw8jJ}Qlceww^E;G6p3kibC zUY62Qwk)C>4P8KDBVlo4t&oX)oGw1pI|fkYOS;H5EPyahTL;0da2oni0vM~^mX+on GC;tP&4o$}Z literal 0 HcmV?d00001 diff --git a/screenshots/s1.png b/screenshots/s1.png new file mode 100644 index 0000000000000000000000000000000000000000..3161fced08f5a03f1c8a30712e78f8a6d3f2f94e GIT binary patch literal 2206 zcmdT`YgE!_82_tzG@IGZs^h#wXYM4HMrwIEg(w zeN0U(OaK5d^*wgv1OVu71^_(^V||@vnQ)Ax0|VS)-(X{7WBzo&6aW~9_#W{LPPr$Y zAZL%@^`6VwqJ-u9~`f9IMs& z!yf8io(e<^ta1#EKvu~!a%H-tsKrgf5m7X~vUE)MuVXFjw$ram^?aN>0gGA$J<9=t zy`QFLSQ82Tmq|Dnc{*F=SAkZqTOUj&5`Mo+QAGgzzv37EqO`p5;)!M5z2%Yto10~= zQf4MeL9f)^W@i>5hhhestq;=L<+*5jq;|#|1WO*g)&PdwrMH5!W@jsGWvIue@sj>% zqaQJjF#`<^_SIG9{WKXXQXQZr5hErwXXygTwJ5KJ*6B@V9?V&;yxhoao-9|~^ho7( zLC{WZ5lHp&(3uyJ4QcGj^5%4)VHuIME<{AGJYSB-w$ak#KOt}5bG-8QuWb^JA+q9 zGmIg=X%F|fpvXy64%OXBCHUMP)y&1;T7O0J4w@gM)4*B73O4a&7PSz4ez^YmCqEC( zQP5ui6wY+~HYEN@CyEiF6+EbFqn?vxm)ZALR5a+ytvl^^9XCf;he8t7p|ufO>1Sm3 zmj(6SLD^QCT%$zB!j*7Zv5I<&ku=kXrV9@BWq<@^4rPzJX+H$L54YxPYxQan5L-xL zdI~YZ(!*Jp4H{oO74}p4QL7fAP@3r!f(R=~=5--i(?5wf-0k2ZhDNy5iM`^0&jBZ<6r0%zD+088ZFcwkwgRZrKMT;9ti?M`gR z2|M;w)}C~u+xLRj*QT!`98*qdyCdo6;4G$$G;&Z@L>{^=ae<(iXO$%kk$=&?_|-oP zBgW(tk64p!@yh)B(2k2wU!WMgCOm%}L`bO(wrqq@oEExXR#%}K<=1^QtxSZ(pp?U7 z8gV~m)%)OZ91zJ#d)0Xs-(3U5X4gmid#pf9$7@aD{TQmQ)XiG~ZQ=ZGz*wiMQt7rp zDHGuiFvj$#qhu9_hjDd{bprMecD=&!pbHzpfIb!2`Gd*7fQ)7>Pi$O(8B=)z;tNP5 zzQ>KQ4cKr(55Dt%4GuXaa3vCnEU)ah!-VY^9!YMR?6eleN~$jHkS3*?NQ8l-NMOq` zL*PpAKcSU2^SEtqvDd%^DIj-weG4Oj!N@_sEApM`|DDm(uiO@%9QrqF8%6W|aBMgh z8y)(dUQIDgG8*hHq1O$T3M5K8pDm4*Bub=qEL-UHkA-djVlZ+@Y-g4KmWW|$Udfx} zr+M|&?-}y*k=~i9eBwqZhJil7UU2ab7~l{0l0J%o{*dAvD4?>csy;J)cnjuz-TshV u`}?%jcif15e3%)~?m&OLcmP0Yo@UedREi)SoOJE&+t=IwNZsL68Giw-yH6MZ literal 0 HcmV?d00001 diff --git a/screenshots/s2.png b/screenshots/s2.png new file mode 100644 index 0000000000000000000000000000000000000000..17cd8aa88814bec4dffd060207cbcb2a4171e309 GIT binary patch literal 2368 zcmds3`BRfu6#bAXP}xRpwP8tYr=uc6si2L3B(_+TAZQT?1qoCnAc#~UfW!o+RwzS( zwgQz32`$D*0|X?25(rCC!eR&_F|vNLNFWemfFvYemZsC0_NVX%^#1Z@?z{KSIrp45 z^YYIIpS0cXupIyZ+kjIiLI7af4gfIQYqiaox$V(BY&^`WcnA)U&p6%w3za)H;^YTD6vZ=Vn?Fw+m%oE#hrevfe(+L|-?ecM>s{>eaf$uC!*@5$gX9;iXnnCLt0v)y0VApSTqmU(BSRE+6@k01W$fu4h)uirzakyS%3YEqkCA@mps)Cz>n02@+I?6W}~5Fm!<|kPJm{ zl&+(*AJ5QAEaBM~`$ytwCGM4kUYGqj7Y57fkcN4>fjCzPOQ0NDdi*vmbV0kwqm{fb zl%%vwY8T@I{fptzF0aMbyUQ>%oTMku9#m?Udva|d!2(~`@uJ((IZN>xjMi+f#T9uc z&G+pP3EHl%-OrDqki)q+P$)tg!TDsYBnpXI|$O{esg=@_7(YSuzfK(70sa2#i@aMz1Es5etMUzx%7Ou z8#$|cO7*moBps@33s)*pnus35lVV37<(Qaa;Qt1yHa13+*iCe*y6LS zYzA9w(=~l*v!y0~*FLSp{ud$T-``E4EYcyD-U>h%F7F zM5+ILb`tJYOBbg-M|l!g+XtDg8Q2(bi5`@^aV;u_nDV5_aDcWl+1ga{Xzg~`9!ln_ zm`=(VefR~5J&vmU0B{@GG{8zjm?BVpJSIk3cT%EAA_%_fYN3SIgu0f7VAzpvr2~yT zr)Y){d3iE|A%y45_P@<@#$sS;Z@Q5~t@>Us(HX<+o@w%|QaS-%uehz!OQxY!ghzT` zEu;R}>>D|elnt=X_H+jMvS-WB(aD+?`;Y2F59WOjYa;jL&VOBsi8pF9ScbkjazCHT zz)iNt4{r9Lu63DJw_G7fH;bL20S-3M#Sxjp$yVBf(9yZxqG&FjFFBGNd{n>b$8&n5 zj4@o1)B=flMlr=5P^VmIy)Z-xI~XrV=r>mJ-#dA&JqpCzAyC?et8vWMwY5?%w*Y=4 zkyqq=C-~UR%2GngBx_03NsNV*(gK8f&WOEMC~;>-W%B;a#YRYHCSlL*5jhcD9PT_< z)BmokQm+LPE6J$TBqrMD;wg6avi2Sxm+=I}+w&OwVhCGo#dq2w5D&tYNRH9WVj0K7B z`35rK FzX1O4D#-u< literal 0 HcmV?d00001 diff --git a/screenshots/s3.png b/screenshots/s3.png new file mode 100644 index 0000000000000000000000000000000000000000..9a4c5642ad50e3849a092223ad93f7767ba04c27 GIT binary patch literal 2730 zcmaJ>dsLEn8ve>=Y;~<^%F4>D={R}plo^(3qGcgjjd_DqQcOoJZ=~i0ykKpUo26D` zWsbty&4kp%3nM6GRu&0lcnJ~7OuiD36j6bI#il)N+tTl!@0{ zCd@p4ILf+X2tsf5-#7A;uZffAGnk|QTC<_+b}vsm{csu8J$I2w!My54H(%~7_1d*A z?84G2$32@ZPM-3&wXfK_X78y7W@i5OO(V#M5gV^`d(t5~KhJP}uv*5Emep(A@O96| zI6La=HBaf;_>}xvMjuZuBNmerDIR!K9%2gECUsD`HZvw(O01>|e>YYT0oc*2Or`ol z8{XD=5+HoL-vVHZ098mJI%H^eRLbamY!NLym#gj^hksCKqC?Yq$|Pa}B0 z&m~}`*Ka*@KxYXkWN}MVR2(;dD^(=m#V;~kIsR&xoO7I49tkfRt?qMh)1KbHbdVCk z?hjq>^ODj?9htVuZF{S)MRcr6dv!?!^<4tPv@%9jsRG@w4vt(3tBYWpXUeu!iMWRT zOhOjTEZVW2b{Uv?=&iz}p>4jdy8!=P85@nyL=j|9tIc){2MoLCWmar~i z4}xsTTUh!6g>hq!d9*6kavQbaVxG^&{D_Iwa+;#_oV-Q+norcttR()K#1lK?%fItz z)v{KOEr*gapPu5Ij!~xz2e$(K*Y!-KQ2&I*?vOB}yCg~+Xuys;j0ID|(=e?D6dKke z5obm&a*5%TG|9sXyoT!#T;Vjh-ZWJY9BpLOq8i(4-CqcW%1RpCrRZr2$?PYH_5Xjbyo>$*Xt-Joh#w zrahg?Dq$k$T$tTQL#>w!@Wjp(uo?l@+*k$ts>WYV-FK%8j6m(ag_P($!+Ih2DAo1$ zl8PUtUse{I!22Iq609SX$}TH`^Hpp`JG>aFUiw3o!+j+Y#JEGPD^crz^| zd~Wy>cX4M*;K;!A@gAvLCSSb#ZcKO-Du&<7JHYRSJm9DNh4E#}EY(xk!swPn-F;S? z^|?Trjsmq|H4#X6SY>%~`ThP$Ed~5*r2iuN>5_(U!i{*4o<}BefAiglP&L=ET=T3x ziT6K(7`hK^<_@*s;}BZfGIp^nD;psW_v%kY8qh9AU+`EqW#IBPhC$P7A7Lg>UTl{W z{p*afnWtEF0?Fspqqv2_nvQ}a_l*iQJN5rXnsqN=NRr~Tq98{klHyF*?u>wtMotf59`L+XTFmf_ZaqqFM18yvyWQ1{gftZP6v zIazy#L}n@Yit2CV&9Vdx4}aG@vnYA6EZ<(BguT5A{T$&h6?*Ijk7~$tZ&#(C@mFU- z@&fIR`emh9)qX`G-+jYg;e-f|p{tsY{>`{n--%s9Qgd1Yz~_Q&dejayTB$5f(6WmY z$`M$?Rap|*&S>v{_U7wM8@L}Zui<|9V-o5bYkpgyaaQbuchcJ91nxnNV=Ir*;?BpMtyx}a0gQE${dhprPBzPh|C0<>PCxH*slrbQ9_;D!cxe1N zu`LCc*N~EHJVIkC#TeF9Mybj2AU*@l4jfUTfBcqx4MDD=&7K@4#Pj?GkZCj%x92KW z$r!p_bZ$WUsM;cm?&C#XZQ9rVufMx0KRA5Db5pU4y&5-(xu@d{Cid9qNo4gfS_$I4 zjVsW zB&ZIcn)_PHbWrS*cPUh`-8i_mGbJ9xh5=qb8}j=3