From 99d41cd790dcf324c149e9558573489677281798 Mon Sep 17 00:00:00 2001 From: Andrew Kesterson Date: Sat, 3 Nov 2012 08:41:02 -0400 Subject: [PATCH] Milestone 2 --- mario.chr | Bin 0 -> 8192 bytes nesgame.S | 104 +++++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 95 insertions(+), 9 deletions(-) create mode 100644 mario.chr diff --git a/mario.chr b/mario.chr new file mode 100644 index 0000000000000000000000000000000000000000..d150cccdfb35f2cf6ee6124dc9839cb43f35fdf8 GIT binary patch literal 8192 zcmZWue{d94o_{?(Nsq}eJ^T;`7^XW3f^KasL$S()4AXs-PTgO9+`+6EX!TAuDtSYJ<<@?=#`r^Mw5m# z{qFO9Jrj}pPO4wO{=V<`eSf|0`@R=h)wJaD6+0L}GYr$NTAo#9I@1fx@qE8fOem^m zn5L;IEM=HpnK9dOUC(o?Z*{F&Ynq%ZimI9w4_}?)W&ht?_u>p+d(#%iBw5o8&b?wW z6Inj$xM(@&nwU$|M2kV7j?JTQjH&qM*i}DYKqsDNu0MZGIuVA9kWEt}ix#nXCC6CR z=G^x^JAcH$cY?Jm+hhqujsr0O?_nZdWDz`lr)tr6hg!&8DwQggc)?=SGC42+NQD7d z%>b-sfE|T&0{X)MhQ=1ITBQpE*p3fI)q0w;oaVEuwyG** z9$Av5Ftx5@JI5^BMq8v-Hq6D>Tyy;vmM)r{PfxnG?X5^#ah8ZP*Y$ZWWn|K6wr)%% zBdAI#W%-o~tnPcm&x~`PHSp1B(J^&Qfgq$WEK}sB5vx{hTRnUluc;Wb-tno`tCmHo z+Vl_*7$A7p3>N+bwmrBnMn;u6U$LT4N~k6$3uvsur51m0Ba|1@oY}IIpMDDZX&U;T zd#nJNo#W*H>(hxm{I3E5RMm=qK5E;rEqVscr2?q^hJUY_PyS8YupEepqYa&f=8G0V zLjbw=IQ;wmKq8Vy-vGm@;r%S_I2WjOYztq%1`#-dgOMwjVElmIIaZ^`2Y~BTZO`YX z%%HWA%VrV?zl>;QMQLh|5<|F8m6`47dOS;gEDz6xcQq~7f*@X+h^Jd5C@K8@bI-+) zs;#K81q%}lI+OpDY}L)@^%ASX1FnZ@jToYoODC!jhUPn#S=|nc zZmndonq%sH0|yNAR<4|z3oD8|O+GbDgO>lMoXOAKohjzsix+>zxy?S^ zE&Z7cm%#amx)tFDSxTqVE5a})v13@AcnZ8`sL2HI@pLqqfPD}JWErQFh>(7oN_a)h zm23Ds;R}TVo{X8C&rk$(PdZ;ZPO)HA%H?d<^9V;R@>8UqpPH9;^ul(!rf6Kz)JFP7K=B0;_Aqu@ zG11pue)6&pqq3~$+l=Mye15}*O}C*na=CN{Ljb}Ah|)x6P z|4EK`RTav6b#P`tnu~^6v!hMR<75OGJ);TtJVqL1Gx?V5v%u4Dy&q-)W3ZWt2$eV{GZSMdfdjjTxfNbD&A+}22>~WQ{vs*n zmW?g#9lyEg`K)d8rp+r)wp5|4$SCPzky_u|ro#00d^P1Df7*}aL64MjV!*1BO(jW| z6*xI)`_?xqMs{(pX*7n@ZH*5Wn1OA~FqB3l7^bJgjqnSZU9Ou7i}uJ_$cQDF2P;}8 zNV!;JHA~tUKox~ey9LZ80pGr6ttriku$#UeDImOHXjLNaEHVdFvV2=tPY>kT*wxc3 ze0|`MNVfam`}oal#pIfjPDa-#%4o(&Mk|@AKaFIHg+r&_c{c493ox-@K#CCq^ce#K zJS}3-BN!B&l3-vuPQW0W4HzK)nwBI}%@G!du_0K}FxI1zVe*>xb+pT2DcyP3UAOLv zXR?p(*;DDGB5>1I(`0OJ(|5mhk8XCoeC(q$AHQREbrv(Z@^RvFTd~-FPgD4RA2W;X zpMGjr<3+prKqj89rG9Q4i$vaVURqmF^2unLabo_zNZJEH$btHTw zxGBU*d;t%p=iAnR&NPcz zBxe>l}$zEHKoFLK8CXFvPl~On~AK`DYNDugE{EMp}?m01yN~E#)6blxjo%NuqU1 z=ihnn#EBfU66x<^&t?(~0p@UcxUo@zT~HrkcT)}1bxlJpl`HW7(rb`ZnklfTvQ*46 zlQkHM$y_?S`?2-wwIHB@gXBwZN}ER8N`!=F8c09K6CZta+_tQ|jl3s?!r@3H9uM{z zt}%7~oH_HOx)zVloA+&KyBxnTV{31^>86DX=Y`Y_>;St3)h+g?sXgnKWXitZfjq}p z2BRo1^qPEz`Ye;j_29ths_B~(l&tV4ieZDItj#urS zjnPPg_y_omEbx#ASwP4mwPSpyJcSx~tP{5ZEmC_+C%AF^Rfrq@D%r}UZSOErEU^ah zA*WpLld-W0zs%BlOG{g0+2=Ue*-*gHSx#qW(6>BJ+ zYoX~{Ix8CNK?YF*gQT#yPmw~{79=P%Jb^=?H{QkCRz#VucNK~R7#}BK#_$A+i3#w- z@EdMu=^P%zv8vXG#XE)li67Y?{GcBcgna1BIlVx5K2cdO@NMDsz)x_R4|oOhmAp^N zIWl;91Hy7$C~#&Xr+-sBdb>z_90TP$v)&R{^vYaMkD8It%gyCa*(?!brE z1(5}& zk`(G#788e}<@2tIVDn&nFj<}Cl_blL8qxmk$w71dzEimN$y;whtCLxX;QMZYK_u3A zsKCG%pjRl6teSlowk!cP@p)vy^0(#uODk9;k?{t9_+RuL zW6k~=)W=cy6PT8D=!K_YdeiLc!Z5rZ)_kd9=IsJfJ=X~zlI5#5N>W*-h!nXBgjbA=H`y(ndauEaQN*nzYK>P z2I3li@qwb_AQYUUQ5rk_zyo&=RG&&5!`3lz%sV$UwC`YL*T%o1a|HKg^(V!GzFOuN z9yvXN#b7LJ@110Y;JB= z1d@X;AQvn^guWmbEQq}35AY!G`8YM<{u2B}90ZC7tO7zo9DKkw0tkoeXv;eK;Zf1~ z@aTt-Se9Si{3^v6-~8%kS@zleNACxk@uT-2g_l_P&;NM~1kUo;How~3JlTe1Zv^fO zIO4jpbY&m)vPkRo`6#Ha#N)lL4ZY$zE&$QN1KWuR@jCt4iZfdLdTI3yN}K@?#n)F3b> zEv^6}2Y&LwefM=6LID57?;)WYUAlBBVX0uirb$=s(6NwCA3AghsHIC`1F^o5#el-q zvtt8w=ukRcxG;AviOf}89sz809O~OaUo{6uCTM4)eVFv2cbc2tkrRX%^iKPE{rmLH zB$*9*iT!6v1zx-w{62l(7(?g85ta;@pNJ!8PG;ihvabv z7Z((0)2K5-m`^}`ntH$P7qGw)QB@$lo=&O?35NreLqQ$QI1bqY=2pdhUbLZ!>;-c> zaXLPvkKElq^zzF;!`{v|w6>yNVx!YTfa%fE1$2^HFk1H~EC4dwuKN>aGHBzg`%?tl zBzZdUCs2nEBSY9Vfmu)-lsN zGc)N<;zVu~JIDSg&gR+DUJ9n@+voquMQ-KtD*u0FYt;{x29r8p;^jHc$-)>m6%4fZBSW?bEId9#_{_ zv-I$%;CO|}_P5rLcxBuixQRh`~ACc+pkZ}nnT`GO{zn0ALw4)6E8SZMIXzxVbk zlb7Rq>#sjKTdhLBt{=QOI0$iZJ*z5Yd$>;6ifk-wkA(#vkvg;T*X}51`z#V~U4F~$ z5&U;x@%%L_yTo8TcJ1m}+mWnYETV6_$?>Ua{C}hd*xshbldfIwqg6Ge>UtlqTJ4`2 z^-r};s@`Re`_1v_eS@AZiCH>R3J&cNaVf#hPn|jAPyNRoZ2R}WzvSNh9ml;XAAc{f s2kyP~fqREvnC8P%{_xaZ)_ZekFa9!bQbp!(VTpSIw{DqLycQt;2Z|&#bpQYW literal 0 HcmV?d00001 diff --git a/nesgame.S b/nesgame.S index 4f88763..87babc3 100644 --- a/nesgame.S +++ b/nesgame.S @@ -56,12 +56,15 @@ _START_clearmem: STA $0500, x ;; *(0x0100 + x) = 0; STA $0600, x ;; .... STA $0700, x ;; the INX and BNE at the bottom are the "; x++)" - ;; This clears the zero page, the stack, and - ;; the entirety of main RAM + ;; This clears the zero page (0000-00FF, the + ;; stack (0100-01FF), the entirety of main RAM + ;; (0200-07FF) - LDA #$FE ;; It's also not clear at all what these two - STA $0300, x ;; are setting; maybe it's object attribute - ;; memory (OAM)? + LDA #$FE ;; These two are clearing all of the sprite + STA $0200, x ;; OAM; previous tutorial had this at 0300, + ;; which may have been wrong. I wonder why + ;; NES engineers put the OAM inside of main + ;; RAM? we lose FF bytes this way. INX ;; X is already 0 so this should do X=1, ;; and the Zero and Sign flags should both go 0 @@ -75,7 +78,74 @@ _START_vblankwait2: MAIN: ;; horray, here is main() - ;; all we do is set the PPU mask to intensify blues, and loop forever + ;; Let's hit milestone 2 and draw a sprite + +_MAIN_LoadPalettes: + LDA $2002 ; The PPU Memory address at $2006 expects + ; the high byte of the palette address first, + ; then the low byte, but we can't know + ; which one it's expecting right now, so we + ; read the PPU status at $2002 to reset the + ; high/low latch on $2006. + LDA #$3F ; we're populating the second palette, at $3F10 + STA $2006 + LDA #$00 + STA $2006 + LDX #$00 +_MAIN_LoadPaletteLoop: + LDA palette, x ; Loop over each index of the byte array at + STA $2007 ; 'palette', store each one into the accumulator + INX ; and then store the accumulator into the PPU + CPX #$20 ; .. compare X to 20 (size of 'palette'), and + BNE _MAIN_LoadPaletteLoop ; loop as long as the Zero flag isn't set (NE) + +_MAIN_PlaceSprites: + ;; All sprites live between 0200-02FF; there are a max of 64 sprites + ;; on screen, and each one has a 4 byte struct describing it. + ;; *(sprite + 0) = y position + ;; *(sprite + 1) = tile index (0-FF) in the pattern table for pixels + ;; *(sprite + 2) = attributes. Color palette, priority, and mirroring. + ;; 76543210 + ;; ||| || + ;; ||| ++- Color Palette of sprite. Choose which set of 4 from + ;; ||| the 16 colors to use. You can select sprite colors only + ;; ||| in groups of 4 on 4 byte boundaries; so you can select + ;; ||| colors 0-3, 4-7, 8-11, and 12-15, but not 2-5, for + ;; ||| example. Palette construction and use is an art in + ;; ||| itself! + ;; ||| + ;; ||+------ Priority (0: in front of background; 1: behind background) + ;; |+------- Flip sprite horizontally + ;; +-------- Flip sprite vertically + ;; *(sprite + 3) = x position + + LDA #$80 + STA $0200 ; sprite 0 (0200 + 0) is at center ($80) x + STA $0203 ; sprite 0 (0200 + 0) is at center ($80) y + LDA #$00 + STA $0201 ; sprite 0 is tile number 0 + STA $0202 ; use colors 0-3, no mirroring + + ;; $2000 is the PPU Control register, controlled by various bitflags. + ;; + ;; 7654 3210 + ;; |||| |||| + ;; |||| ||++- Base nametable address + ;; |||| || (0 = $2000; 1 = $2400; 2 = $2800; 3 = $2C00) + ;; |||| |+--- VRAM address increment per CPU read/write of PPUDATA + ;; |||| | (0: increment by 1, going across; + ;; |||| | 1: increment by 32, going down) + ;; |||| +---- Sprite pattern table address for 8x8 sprites + ;; |||| (0: $0000; 1: $1000; ignored in 8x16 mode) + ;; |||+------ Background pattern table address (0: $0000; 1: $1000) + ;; ||+------- Sprite size (0: 8x8; 1: 8x16) + ;; |+-------- PPU master/slave select (has no effect on the NES) + ;; +--------- Generate an NMI at the start of the + ;; vertical blanking interval (0: off; 1: on) + + LDA #%10000000 ; enable NMI (so we get a function call every + ; vblank), and draw sprites from table 0 + STA $2000 ;; The PPU mask is set at $2001, the 2nd PPU Control register, and it ;; sets one config option for every bit of the byte @@ -93,12 +163,24 @@ MAIN: ;; |+------- Intensify greens (and darken other colors) ;; +-------- Intensify blues (and darken other colors) - LDA #%10000000 ;; blue background! + LDA #%00010000 ;; turn on sprites, no more background color STA $2001 ;; Write to PPU Control Register 2 _MAIN_loop: JMP _MAIN_loop ;; Loop forever and do nothing NMI: + ;; We need to copy all our OAM data to put sprites on screen during + ;; vblank. $2003 is the PPU OAM address, so we're going to tell it + ;; to pull OAM from $0200, and do a DMA transfer. + LDA #$00 + STA $2003 + LDA #$02 + STA $4014 ; 4014 is the OAM_DMA operation, which will + ; do a DMA from the (LDA|$2003) address, + ; for FF bytes (in our case $0200-$02FF), + ; which takes ~513 cycles. An unrolled + ; loop to do the same thing would take + ; 3-4 times as long. RTI ; just return .bank 1 ;; NESASM sees our 16kB code banks as pairs of @@ -107,8 +189,11 @@ NMI: ;; between them. ;; .. How to know when we have written enough ;; code? .. - - ;; insert the rest of the bank 1 code here + +palette: + .db $0F,$31,$32,$33,$0F,$35,$36,$37,$0F,$39,$3A,$3B,$0F,$3D,$3E,$0F + .db $0F,$1C,$15,$14,$0F,$02,$38,$3C,$0F,$1C,$15,$14,$0F,$02,$38,$3C + .bank 1 .org $FFFA @@ -122,3 +207,4 @@ NMI: .bank 2 ;; CHR bank 0 starts here for tile/sprite data .org $0000 ;; CHR data is below PRG data in the memory + .incbin "mario.chr" ; include 8kB of graphics from SMB1 \ No newline at end of file