From 70c90cd77add00c3e42a46d3c263bf47a2f15527 Mon Sep 17 00:00:00 2001 From: Jaidyn Ann Date: Mon, 12 Oct 2020 20:30:37 -0500 Subject: [PATCH] Proper map-system, pallete/attr/tile-loading; misc abstraction and refactoring --- sbp.mfk | 271 +++++++++++++++++++++++++++++++------------------------- sbp.nes | Bin 40976 -> 40976 bytes 2 files changed, 151 insertions(+), 120 deletions(-) diff --git a/sbp.mfk b/sbp.mfk index 9184792..000439d 100644 --- a/sbp.mfk +++ b/sbp.mfk @@ -18,21 +18,6 @@ struct Sprite { } // abstraction for 16x16 animated monstrosities -struct Entity { - Sprite top0, // left side, for the record - Sprite bottom0, - Sprite top1, // right side, please kill me - Sprite bottom1, - - // all this can be crammed into a byte (if merge dircount w frame) `o` - // note to self: do that - byte movement, // 0-3; idle, walk, jump/fall - byte jump, // 0/1 - byte direction, // 0/1 - byte dircount, // counter for time-limited movement; i.e., jumping - byte frame, // internal count used for animation; max 5 - byte walkspeed -} // ============================================================================ @@ -49,26 +34,13 @@ volatile Gamestate gamestate // the current Gamestate // ============================================================================ // CONSTANTS // ============================================================================ -const array pallete = [ - $22,$29,$1A,$0F, - // construction-blocks - $00,$06,$07,$16, - // construction-bricks - $16,$06,$07,$00, - $22,$27,$17,$0F, +const array fg_pallete = [ $22,$1C,$15,$14, $0F,$18,$28,$0F, // sam $0F,$28,$29,$0F, // enemies $03,$07,$05,$03 // angry owo ] -// palette selections for the 16x16 ppu tiles -// %DownRight DownLeft TopRight TopLeft -const array attribute = [ - %01010101, %00000101, %00000101, %00000101, %00000101, %00000101, %00000101, %00000101, - %00000101, %00000101, %00000101, %00000101, %00000101, %00000101, %00000101, %00000101, - %00000101, %00000101, %00000101, %00000101, %00000101, %00000101, %00000101, %00000101 -] enum Gamestate { STATETITLE, @@ -149,11 +121,11 @@ const array BABY_WALK = [ $00, $C0, $00, $00, $00, $C4, $00, $00, $00, $C5, $00, $00 ] + // ============================================================================ // CORE // ============================================================================ // quite important uwu - void main() { sam.dircount = 0 gamestate = STATETITLE @@ -192,18 +164,7 @@ inline void main_game_logic() { // uwu owo uwu owo uwu owo inline void init_graphics() { init_sprites() - load_palletes() -} - -// loads palletes onto the ppu -macro void load_palletes() { - byte i - read_ppu_status() // read PPU status to reset the high/low latch - ppu_set_addr( ppu_pallete_ram ) - - for i,0,until,$20 { - ppu_write_data( pallete[i] ) - } + load_fg_pallete( fg_pallete ) } // cleans up oam (object attribute memory) @@ -240,8 +201,6 @@ void title_init() { //write a full screen of background data - load_sky_background() - //write the title screen message read_ppu_status() // read PPU status to reset the high/low latch ppu_set_addr(ppu_nametable_ram+$018B) // point the PPU to the message's start @@ -310,12 +269,9 @@ void ingame_init() { ppu_mask = 0 //write a full screen of data - load_sky_background() - draw_score_text_background() - init_map() + init_map1_c() +// draw_score_text_background() - load_ingame_attr_table() - ppu_set_scroll(0,0) ppu_wait_vblank() //wait for next vblank before re-enabling NMI //so that we don't get messed up scroll registers @@ -332,7 +288,7 @@ void ingame_init() { } void ingame_logic() { - draw_score() +// draw_score() //update scroll last because writes to vram also //overwrite the scroll register ppu_set_scroll(0,0) // tell the ppu there is no background scrolling @@ -383,15 +339,6 @@ void update_ingame_sprites ( ) update_entity( pointer.Entity( baby.addr ), BABY_WALK, BABY_WALK ) } -macro void load_ingame_attr_table() { - byte i - read_ppu_status() // read PPU status to reset the high/low latch - ppu_set_addr(ppu_nametable_0_attr_ram) // point the PPU to nametable 0's attribute table - for i,0,until,$37 { - ppu_write_data(attribute[0]) - } -} - // ============================================================================ // GAME-OVER @@ -437,67 +384,60 @@ void draw_gameover() { } + // ============================================================================ // MISC GRAPHICS // ============================================================================ // ------------------------------------- // BACKGROUND // ------------------------------------- -inline void load_sky_background() { +inline void blank_bg() { word xx read_ppu_status() // read PPU status to reset the high/low latch ppu_set_addr(ppu_nametable_ram) // point the PPU to palette ram for xx,0,until,$0300 { - ppu_write_data($00) // $00 = sky + ppu_write_data($00) } } - -const array(byte) bg_pallete = [ $2C, - $29,$1A,$0F, $00, - // construction-blocks - $06,$07,$16, $16, - // construction-bricks - $06,$07,$00, $22, - $27,$17,$0F ] - -const array(word) locations = [ $280 ] -const array(byte) location_tiles = [ $80 ] - -const array(word) ranges = [ $2C0,$380 ] -const array(byte) range_tiles = [ $83 ] - -void init_map () { +// ------------------------------------- +// PALLETE MANAGEMENT +// ------------------------------------- +// loads colours into the section of memory dedicated to background (sprite) colours. +// useful resource: https://wiki.nesdev.com/w/index.php/PPU_palettes +// (edits $3F00 to $3F0F) +void load_bg_pallete ( pointer pallete ) { byte i - word j - word last_range - last_range = 0 - read_ppu_status() // read PPU status to reset the high/low latch - ppu_set_addr( ppu_pallete_ram ) for i,0,until,$F { - ppu_write_data( bg_pallete[i] ) - } - - read_ppu_status() // read PPU status to reset the high/low latch - for i,0,until,$1 { - ppu_set_addr(ppu_nametable_ram + locations[i]) // point the PPU to the top boundary's start - ppu_write_data(location_tiles[i]) //write the top boundary tile - } - - for i,0,until,$2 { - if last_range != $0 { - ppu_set_addr(ppu_nametable_ram + ranges[i-1]) // point the PPU to the top boundary's start - for j,ranges[i-1],until,ranges[1] { - ppu_write_data(range_tiles[0]) //write the top boundary tile - } - last_range = 0 - } else { - last_range = 1 - } + ppu_write_data( pallete[i] ) } } +// loads colours into the section of memory dedicated to foreground (sprite) colours. +// unrelated, but heck do I feel like I'm spelling pallete wrong. doesn't it have 'double-t' vibes? +// like palette? or maybe pallette? hmm. +// (edits $3F10 to $3F1F) +void load_fg_pallete ( pointer pallete ) { + byte i + ppu_set_addr( ppu_pallete_ram + $10 ) + for i,0,until,$F { + ppu_write_data( pallete[i] ) + } +} + +// load pallete selection for bg tiles to ppu +// useful resource: https://wiki.nesdev.com/w/index.php/PPU_palettes +macro void load_attr_table( pointer attributes ) { + byte i + read_ppu_status() // read PPU status to reset the high/low latch + ppu_set_addr(ppu_nametable_0_attr_ram) // point the PPU to nametable 0's attribute table + for i,0,until,$37 { + ppu_write_data(attributes[0]) // !!!! provisional value + } +} + + macro void draw_score_text_background() { byte i read_ppu_status() // read PPU status to reset the high/low latch @@ -507,10 +447,43 @@ macro void draw_score_text_background() { } } +inline void draw_score() { + byte digit01 + byte digit10 + read_ppu_status() // read PPU status to reset the high/low latch + + //display player1's score + digit01 = score1 %% 10 //get the ones digit + digit10 = score1 / 10 //get the tens digit + digit10 %%= 10 + + ppu_set_addr(ppu_nametable_ram+$29) // point the PPU to player1's score number + if digit10 > 0 { + ppu_write_data(digit10 + '0') + } + ppu_write_data(digit01 + '0') +} + + +// ============================================================================ +// ENTITIES +// ============================================================================ +struct Entity { + Sprite top0, // left side, for the record + Sprite bottom0, + Sprite top1, // right side, please kill me + Sprite bottom1, + + // all this can be crammed into a byte (if merge dircount w frame) `o` + // note to self: do that + byte movement, // 0-3; idle, walk, jump/fall + byte jump, // 0/1 + byte direction, // 0/1 + byte dircount, // counter for time-limited movement; i.e., jumping + byte frame, // internal count used for animation; max 5 + byte walkspeed +} -// ------------------------------------- -// SPRITES -// ------------------------------------- void update_entity ( pointer.Entity ent, pointer idle, pointer walk ) { entity_physics( ent ) if ( ent[0].bottom0.tile > $39 ) { @@ -597,6 +570,7 @@ void entity_sprite ( pointer.Entity ent, byte xx, byte yy, pointer idle, pointer ent[0].frame += 1 } + // ------------------------------------- // "PHYSICS" // ------------------------------------- @@ -619,6 +593,9 @@ void entity_physics ( pointer.Entity ent ) { } } +// frankly, this is just terrible. reeeee !!!! +// please replace this, please replace this, please replace this +// oh gods almightly please please please void entity_jump_physics ( pointer.Entity ent ) { if ( ent[0].bottom0.y < BOTTOMWALL - 10 && ent[0].jump == 1 && ent[0].dircount == 0 ) { // if not on ground, don't start jumping @@ -658,26 +635,80 @@ void entity_destiny ( pointer.Entity ent ) { ent[0].movement = 1 } -// ------------------------------------- -// ETC -// ------------------------------------- -inline void draw_score() { - byte digit01 - byte digit10 + +// ============================================================================ +// MAPS +// ============================================================================ +// load a map onto the ppu +void init_map ( pointer.word locations, pointer location_tiles, + pointer.word ranges, pointer range_tiles, + pointer pallete, pointer attrs ) { + byte i + word j + word last_range + last_range = 0 read_ppu_status() // read PPU status to reset the high/low latch - - //display player1's score - digit01 = score1 %% 10 //get the ones digit - digit10 = score1 / 10 //get the tens digit - digit10 %%= 10 - - ppu_set_addr(ppu_nametable_ram+$29) // point the PPU to player1's score number - if digit10 > 0 { - ppu_write_data(digit10 + '0') + + load_bg_pallete( pallete ) + load_attr_table( attrs ) + + blank_bg() + + read_ppu_status() + i = 0 + while ( locations[i] != nullchar ) { + ppu_set_addr(ppu_nametable_ram + locations[i]) + ppu_write_data(location_tiles[i]) + i += 1 + } + + i = 0 + while ( ranges[i] != nullchar ) { + if last_range != 0 { + ppu_set_addr(ppu_nametable_ram + ranges[i-1]) + for j,ranges[i-1],until,ranges[i] { + ppu_write_data(range_tiles[i/2]) // only writes first tile, oh no !!!! + } + last_range = 0 + } else { + last_range = 1 + } + i += 1 } - ppu_write_data(digit01 + '0') } +void init_map1_c () { + init_map( pointer.word( MAP1_C_LOCATIONS ), MAP1_C_LOCATION_TILES, + pointer.word( MAP1_C_RANGES ), MAP1_C_RANGE_TILES, + MAP1_C_PALLETE, MAP1_C_ATTRS ) +} + +// ------------------------------------- +// MAP DATA +// ------------------------------------- +// map1: construction site +const array(word) MAP1_C_LOCATIONS = [ $280, $20, nullchar ] +const array(byte) MAP1_C_LOCATION_TILES = [ $80, $80 ] + +const array(word) MAP1_C_RANGES = [ $2C0, $380, $200, $220, nullchar ] +const array(byte) MAP1_C_RANGE_TILES = [ $83, $81 ] + +const array(byte) MAP1_C_PALLETE = [ $22, + $29,$1A,$0F, $00, + // construction-blocks + $06,$07,$16, $16, + // construction-bricks + $06,$07,$00, $22, + $27,$17,$0F ] + +// palette selections for the ppu tiles +// also not the most efficient way to store this data. !!!! +// %DownRight DownLeft TopRight TopLeft +const array(byte) MAP1_C_ATTRS = [ + %01010101, %00000101, %00000101, %00000101, %00000101, %00000101, %00000101, %00000101, + %00000101, %00000101, %00000101, %00000101, %00000101, %00000101, %00000101, %00000101, + %00000101, %00000101, %00000101, %00000101, %00000101, %00000101, %00000101, %00000101 ] + // ============================================================================ // UTIL diff --git a/sbp.nes b/sbp.nes index b91dde2a917b5eabb75317c26f139b1b02452602..fe928a2c40253804afeecce9426373964f395b0e 100644 GIT binary patch delta 2404 zcmah}O>7%Q6rTOF*X#ep*{qW`nfx@hlQs$zXy~OW;>U`N2(9P=fmjX^j*2Rgh64iO zP1A9Hs#G=>5uoB`U&CE13h@3lhgxfTh5pE(k7w%A2*f`Jn>K^X7Z= zz4vC{n>SP35R33P_Vyrb&1J)u$&j%Rao_`?Yg;e}N$~2xF)j=zxf0f3hOqp$m2Z^Od7`#sUj{RjhiLE3H`DC%zfe9)tX?R2;i%9z@*L8R%FX!z`6+lnE(mEA9?jbwOu zV@j}FORD*454v%BDRblKQpSY#d~i*aLY}=xRJKF{c%s02>ikMiqw%^{yRN^r#EacU zyQ)E_&ROiWWfv1X3Om1X%JMpUC&gsg%x%_(yS~D??uT=5a{qk;NeWE%!AQW^17k0Y z0n^=%Aet`MrL?~r);PxUP=(^-GNdrk^oB*ALxG8Nn$X^ z*+~+CIf`#uCY6as6%xdM7i^^>SC15fu%yCL0O$WG01g2T+fqd)!_av$IY3*$rIiG! z5A6J4mt5daOfT(COOD3wuJ&F;Viv=L<)Ru8&JS)8{N7>qt@d4i+C9uZ+E;C99Ofr3 zYqFU4kmdVV`ztCx*M8dHc*$gVd_XG#z)gbdAuh3bz zzZ%@%INVds2||H1V@igbquDVa1n02b0)!6r(=v8jMI$IT`V+FHl9tWQa}I1;Ig#Ne zz#5almg}mXUn%5>lp|t}2st1w=hkv#CLOAxV$ku?!D_uIz4_PuW*1!5$I?PwtR+0K z#{+vkFwg|I_IWEFxRvr&Qf6i;^HJt|iZbOZJ}qCI|Mxe*SBIPls6_~B(P@k9SSe)t zT&cM-!e#d51)!dCDK0e^N4TWJqnoN7^gtAhKU>%qPjH>M%)>Fj6yY+v#si8j$ED`t z2$yu&m}&;(00PosC^46QkO$yAKypfURn=2Nr4V%PK|2At$m@QNvqu+QRRvYfZ|Nb> z)h#s!YG_MMfEsJ6@Nzez#v!WU^zo*!c^U%D3d|zR0hr;y?Jy+v-6Av#H$6lT8dKcKjVqltSi)Xh}%KB0`pk z5kf*-Y>`^!gwp2I{q3r8GLY0d&;~GHpfAx^FnCPH(wz3Gl9^7(b$=SRK!+oL^? z^gh~msQp6T3KaZcm@OuHD1aSPN@{0kzTOro`#PsBu vGx)^J>(ev6d)g9FBNdIN(oxB;NZ0NJPQUG&nvaoR=gW5j`n3V;=k9+1Jn=+o delta 2221 zcmaJ?YiJx*6u$G=*_qkL>?X61JnG(Tnr&8VX{|M}MNNcal@)`fDk3<=7Isl6wDtFH zlgu_tN!fJ;(O=V$D;-Hnmj0;wqa{9C9QtR_O3|OGu0(%yp@@h=J$D{yQpIKOx#yhk zJnp&o+&lGEwhsSvIgRkzbRkmF@a-8BEg<~oEWV}V4|Reqr5-Wa`7|=`&Ieh1xuTh9 z9$_F1#_N@37MpkhinLuAMrv+sGC zcCwAJUFD6Kw`cIXIt0tY7~U|!vA@hZwRr^cYUc$!FJO(vMt*V$>_u1>#21NZ|K5>^ zWO4SoX7DZE`gA2_#9?M^#prGEwq(Rj)Zh#3w5u+6Im!cMaVt>+wfOOM!Jrm@oN=|b zr)4*5d0)H5R`Mfon{B0f(uoxEQDzfbwjyq*bZJY1sOO}*P7k4pdf4bS?>Bh28X7)b zVvODfuU$%`s~^=4U46ZFNP{EOc^CnA!=7^wBfc1KKjxfPoWzrsVs{-_2T8uzzEb<< z+Lc=KD3i>tRlriFmJlOO_&}ihHi?g~GhlWA%nmqa<+aLIr7l*b!spZGjB_M5+mV)^ zsa<-uc3rf8`$@8Y@fTJ2VcKNe^>rY(#oFg!!5jVXqP}I-gNuXhkhAJRGH7AwF}DfN zl^2HGx)O_t_L5_fAPFnvmbKBN36r7gp%Aw3(a;sYJGVk64@+=Ud+ogyr%=XkK7bBx z3JazEU;6@_fiVCh2BQZ?FN|%_(9Q4o-AuB1i{B*^q^CfONUHfGpHHUDypxTjx*|!X zOS>T-NjCcehs$%b_}UEAm7I792L856wsj?t;acyjXq_zV{jj!^#q$AtK7chM=pqT~ z63$hPKufUp*F&JHpfE7JJ!r&PJ&w;bFr}{`=p0nk$ zd3UkzW5gDY!M%034j}d&=Y9tLW9eV)Z-3$(OF!widfa1Ka!}3Wb-`ryp!udAHEX(J z&gfy7Bbd|8DGxf~K_@mK4c;Yn0(0eQ?ViYVi91HEbN5J7Njc4bi=!4x=*f( z#OQOdoM3ILOt4^_Vl^XXGH`!jXGClNN{EP1x&%9;oPmc#goh*!FNSD`U}wa1iHAEp zAsR727<J7|*;)$&cfsB=Y~E$U1W z94{6>D^6%+*h2M?Es(6$t#j}FecwCG<>W-3>9U=e&-D0Aug`4rm>UDW#%FG1d`(7! zRmt`g6kC>|+5v+#CmXUMI8=6Ml+wamX90TNfhd(7K1wOcjjxMF$Y&HVzIGM@`tcaY ziBi~QpixQ-OEezqK$Oa6nNCrvBDr+Q3rHCVNOG`;lm>xrhaCq>A>I*1Uko>7Xvz^o zh1~o~kn)AeIY$&h#48(HyfvkcY^F;VcxKZN}m9dBEr@^3gFfa#TW?`0K z=3tIMWw+;`8>s1CGLkN#i!G6wQ=XwbxKN&@Jh)Mwqx_`n>-jh-JRc{G=i{XEe4KQ& zI{M_R4ViY)v3B*}T~x{D`xPVvlSv_nvO7{rb}*qT=}|=)%`03m!0mhpUu7%Yk-&fd zzK^w=jI6#fgH{njU!X71S1^AK<2ph^d$Laq@7@07$iCcDJH|%G^G`pzf3{M60Z-zW z@j(o~SMY1VygGIA_^DI)@adx`PgmHfJ^1iDCr%!JoEludAeY{6uE;lq52|yscjlTG L