12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092 |
- /*
- this is the sprite/oam routine file.
- direct sprite features:
- -setup sprite variables
- -create and upload spritelist-buffer to oam-ram
- -upload sprite palettes
- object manager features:
- -create and process object list
- -create objects, each with own memory space
- -delete objects
- -routines for:
- -cycling through animations
- -moving objects along preset paths
-
- areas needed:
- OAMBuffer ds 200
- oam memory format:
- Byte 1 xxxxxxxx x: X coordinate
- Byte 2 yyyyyyyy y: Y coordinate
- Byte 3 cccccccc c: starting character (tile) number p: palette number
- Byte 4 vhoopppc v: vertical flip h: horizontal flip o: priority bits
- Note: the 'c' in byte 4 is the MOST significant bit in the 9-bit char #.
- 00110000
- OAMPriorityBuffer ds 20
- oam priority format:
- 2bits per sprite, 4 sprites per byte
- bit0 = size toggle
- bit1 = x coordinate msb
- ObjectList ds $400
- Maximum number of objects: 64
- Object Format: 32bytes per object
- .db %11101010 ;0 object type designation
- ;bit0=X position sign of sprite(usually 0)
- ;bit1=Object size flag
- ;bit2=collidable
- ;bit3=subroutine? if set, this object has its own subroutine that must be executed every frame
- ;bit4=animate? if set, this object is animated(a special table for each object specifies the exact animation with commands for tileloading, waiting, animation loop etc)
- ;bit5=bg-bound? if set, this object must move in accordance with background layer 0
- ;bit6=object active? if set, this object is active and needs to be drawn. if clear, this sprite doesnt need to be drawn, but must be processed, anyway
- ;bit7=object present? if set, this slot has an object. if clear, its considered empty and can be overwritten
- .db %00000000 ;1 object type designation 2
- ;bit7=pseudo 3d sprite that needs to be moved according to z-value when background moves
- ;bit6=don't upload tiles for this sprite. useful for stuff like particles and such where lots of sprites share the same tiles.
- .db 6 ;2 number of subroutine. executed if bit6 of object type is set
- .db 14 ;3 tileset to use
- .db 9 ;4 current "frame" of tileset to display
- .db $cc ;5 starting tile in vram
- .db %00111101 ;6 palette and config. vhoopppN; oo=priority. ppp=palette. N=nametable vh=flip
- .dw $0 ;7 x position
- .dw 201 ;9 y position
- .db 0 ;11 current frame in animation list
- .db 0 ;12 object command list to use
- .db 0 ;13 object offset in object list.
- .db 9 ;14 palette number to upload for this sprite
- .dw OamTypeTextbox ;15 object number
- .db 0 ;17 x-displacement
- .db 0 ;18 y-displacement
- .db 4 ;19 z-displacement
- .db 0 ;20 z-value for pseudo-3d scenes
- .db 0 ;21 collision subroutine
- .db 0 ;22 animation repeat counter for nop, must not be set up
- ;23-25 left void for future expansion
- ;custom variables differing between sprites:
- .db 0 ;26 spare variable
- .db $80 ;27 target x-pos /npc walking distance
- .db 32 ;28 target y-pos
- .db 0 ;29 current x-pos, must not be set up
- .db 8 ;30 current y-pos, must not be set up
- .db 0 ;void
- .db 0 ;void
- .db 0 ;void
- .db 0 ;void
- .db 0 ;void
- .db 0 ;void
- .db 0 ;void
- object command list format:
- an entry is always 2 bytes long, mostly consisting of a command byte and a parameter
- normally, one command from the list is executed per frame.
- ".." means no parameter.
- if bit7 of command byte is set, execute the next command immediately.
- this is used to execute multiple commands per frame.
- control code: function:
- -00NN create another object in object list. NN is the number of the object to create. searches for the next free slot in object list
- -01.. deletes object from list(can only delete itself. if an object wants to delete another one, it has to do this via the subroutine)
- -02XY adds signed xy-vector to objects position.
- -03TF increment current tileset frame. TF=number of frames to advance
- -04TF set tileset frame. TF=tileset frame to set
- -05PC set palette and config PC=palette and config ;IMPORTANT!! if this is executed, the tile positions of an object bigger than 8x8 must be swapped!!
- -06AF goto frame in animation list. can be used to create infinite looping objects. AF=frame in animation list
- -07CL goto command list. always starts at position 0 in that command list and discards current command list. CL=command list to go to.
- -08.b0 set/unset object screen-bound (with bit0 of parameter)
- -09.b0 set/unset object subroutine enable (with bit0 of parameter)
- -0aSS set object subroutine. SS=subroutine number
- -0bTS set tileset. TS:number of tileset to use
- -0cSE play soundeffect
- -0dFN nop and wait for next frame(s). used for delays. FN specifies number of frames to wait. 0=wait one frame, 5=wait 6 frames etc
- -0e.. inifite loop. object stays active
- -0f.. terminate. used to end object list processing. marks object as inactive.
- -10VS set target speed vector. bits0-5: speed (0-2subpixel precision) bits 6,7: accel type (0=direct, 1=linear slow, 2=linear fast, 3=smooth). speed 0 disables vector speed calculation
- -11VD set target vector direction/angle. bits0-5: target direction ($00=up $10=right $20=down $30=left) bits 6,7: direction change type (0=direct, 1=linear slow, 2=linear fast, 3=smooth). clockwise/counterclockwise direction is determined by distance between current and target direction(alsways uses fastest/smallest angle)
- -12NN create object and put it to the coordinates of the calling object. NN=number of object to create
- sprite palettes start at cgram entry 128
- oam registers:
- $2101 - global sprite size select
- sprite tile location select: 0,4000,8000,c000
- $2102 - oam adress
- $2103 - oam table and priority rotation select
- $2104 - oam data. this is a doublewrite/read register.
- free space for sprites:
- $4000 bytes at $c000
- $20 bytes per 8x8 sprite = 512 tiles for sprites
- first sprite tile must always be blank
- size: amount possible in terms of vram space:
- 8x8 512
- 16x16 128
- 32x32 32
- for sprites bigger than 8x8, the vram tile data is seperated into horizontal rows, each 16 tiles (=512 bytes) apart.
- they are always 16 tiles apart, no matter if the sprites are 16,32 or 64 pixels in size
- heres a table what to upload where for different sized sprites:
- xsize: ysize: number of lines to upload: number of bytes to transfer per line:
- 8 8 1 32
- 16 16 2 64
- 32 32 4 128
- 64 64 8 256
- 16 32 4 64
- 32 64 8 128
- initial setting for register $2101 gets loaded with
- graphics config file loader "SetBGMode" and put into variable "ObjSel", updated every vblank
- variables:
- ObjectListPointer dw ;pointer to current object in object list, used to set direct register
- CurrentObjectNumber db ;number of currently selected object in list
- OamBufferPointer dw ;pointer to current sprite in oam buffer
- fixed variables:
- .define ObjectFileSize 16 ;size of one object file
- routines in detail:
- InitOam:
- -clears oam table buffer
- -clears object memory
- CreateObject:
- -upload object file to first free slot in object list
- -upload current frame of tileset to vram
- -calculate transfer size by object size
- -calculate transfer source by object size*frame number
- -calculate transfer target by starting tile in vram
- -upload palette to vram according to palette number config
- -set object offset in object list variable
- ObjectProcessor:
- -check object list for active object
- -write sprite(s) to oambuffer according to object file
- -process animation list if enabled
- -execute subroutine if enabled
- */
- ObjectProcessSubroutine:
- rep #$31
- phx
- ldx.b ObjectListPointerCurrent
- lda.w ObjEntrySubRout,x
- and.w #$ff ;max number of routines: 256
- asl a
- tax
- php
- phd
- jsr (AniSubroutineJumpLUT,x)
- pld
- plp
- plx
- rts
- ObjectProcessAniList:
- php
- ObjectProcessAniListYes:
- rep #$31
- ;load pointer to current animation list:
- lda.w ObjEntryAniList,x ;get number of list to use
- and.w #$ff
- asl a
- phx
- tax
- ; sta.b TempBuffer
- lda.l (ObjectAnimationLUT+BaseAdress),x ;get relative pointer to object
- plx
- clc
- adc.w #ObjectAnimationLUT ;calculate real pointer
- sta.b ThreeBytePointerLo
-
- sep #$20
- lda.b #(:ObjectAnimationLUT+BaseAdress>>16)
- sta.b ThreeBytePointerBank
- ;get pointer to currently active frame:
- rep #$31
- lda.w ObjEntryAniFrame,x
- and.w #$ff
- asl a
- tay
- ;get command
- phx
- lda.b [ThreeBytePointerLo],y ;get current command
- sta.b OamAniListStraightRepeatFlag ;store for immediate repeat checking
- pha
- and.w #$1f ;mask off repeat flag, maximum number of commands: 32
- asl a
- tax
- pla
- phy
- php
- phd
- /*
- rep #$31
- pha
- lda.b ObjectListPointerCurrent
- clc
- adc.w #ObjectList & $ffff
- tcd
-
- pla
- */
-
- sep #$20
- lda.b #0 ;clear high byte
- xba ;and put parameter into a
- ;parameter is in a,8bit
- ;direct register points to current object
- ;bank is $7e
- jsr (AniListJumpLUT,x)
-
- pld
- plp
- ply
- plx
- sep #$20
- lda.b OamAniListStraightRepeatFlag
- bmi ObjectProcessAniListYes ;if bit7 is set, next command is executed immediately
-
- plp
- rts
- AniListJumpLUT:
- .dw AniListCreateObj ;0
- .dw AniListDelete
- .dw AniListMove
- .dw AniListTileFrameInc
- .dw AniListTileFrameSet
- .dw AniListPalConfSet
- .dw AniListGotoAniFrame
- .dw AniListGotoAniList
- .dw AniListMakeBGBound
- .dw AniListSubroutineEnable
- .dw AniListSetSubroutine ;10
- .dw AniListTileSetSet
- .dw AniListPlaySoundEffect
- .dw AniListVoid
- .dw AniListInfiniteLoop
- .dw AniListEnd ;15
- .dw AniListSetVectorSpeed
- .dw AniListSetVectorDir
- .dw AniListCreateObjPosition
- ;does nothing, doesn't proceed to next animation command
- AniListInfiniteLoop:
- rts
-
- AniListVoid:
- ldx.b ObjectListPointerCurrent
- sta.w TempBuffer
- lda.w TempBuffer
- beq AniListVoidProceed ;if argument is 0, proceed to next frame directly
- lda.w ObjEntryAniCmdRepeat,x ;if argument is not zero, but command list repeat is, we just encountered this void command. load new wait value.
- bne AniListVoidDecrease ;if argument is not zero, we're on a repeated loop here. don't load new value, just decrease old one.
-
- lda.w TempBuffer
- sta.w ObjEntryAniCmdRepeat,x
- rts
-
- ;argument was already loaded, decrease
- AniListVoidDecrease:
- dec a
- sta.w ObjEntryAniCmdRepeat,x
- beq AniListVoidProceed ;if repeat value just turned 0, we're done here, go to next command
- rts
- AniListVoidProceed:
- ; ldx.b ObjectListPointerCurrent
- ; stz.w ObjEntryAniCmdRepeat,x ;not needed, but do it anyway just to be safe
- inc.w ObjEntryAniFrame,x
- rts
-
- AniListCreateObj:
- ldx.b ObjectListPointerCurrent
- inc.w ObjEntryAniFrame,x
- jsr CreateObject
- rts
- AniListCreateObjPosition:
- rep #$31
- tay ;save number of object to load
- ldx.b ObjectListPointerCurrent ;get position of calling object
- lda.w ObjEntryXPos,x ;save to stack
- adc.w #8*16 ;move one tile to the left
- pha
- lda.w ObjEntryYPos,x
- clc
- adc.w #8*16 ;move one tile to the bottom
- pha
- inc.w ObjEntryAniFrame,x
- tya
- jsr CreateObject
- ldx.b ObjectListPointerCurrent ;get position of newly-created object
- pla
- sta.w ObjEntryYPos,x ;update position
- pla
- sta.w ObjEntryXPos,x
-
- rts
- AniListGotoAniFrame:
- ldx.b ObjectListPointerCurrent
- sta.w ObjEntryAniFrame,x ;store new animation frame
- rts
- AniListDelete:
- ldx.b ObjectListPointerCurrent
- sta.w ObjEntryType,x ;clear object type info and present flag
- rts
- AniListMove:
- ldx.b ObjectListPointerCurrent
- inc.w ObjEntryAniFrame,x
- pha
- and.b #$f0 ;get x-add
- clc
- lsr a
- lsr a
- lsr a
- lsr a
- bit.b #$08 ;check if negative
- beq AniListMoveXNotNeg
-
- and.b #$07
- eor.b #$ff ;xor to substract value
- inc a
- AniListMoveXNotNeg:
- rep #$31
- asl a ;subpixel precision
- asl a
- asl a
- asl a
- adc.w ObjEntryXPos,x
- sta.w ObjEntryXPos,x
- sep #$20
- pla
- and.b #$0f ;get x-add
- bit.b #$08 ;check if negative
- beq AniListMoveYNotNeg
-
- and.b #$07
- eor.b #$ff ;xor to substract value
- inc a
- AniListMoveYNotNeg:
- rep #$31
- and.w #$ff ;mask off high byte from x-position calculation
- asl a ;subpixel precision
- asl a
- asl a
- asl a
-
- adc.w ObjEntryYPos,x
- sta.w ObjEntryYPos,x
- sep #$20
- rts
- AniListTileFrameInc:
- ldx.b ObjectListPointerCurrent
- inc.w ObjEntryAniFrame,x ;increment animation frame
- clc
- adc.w ObjEntryTilesetFrame,x ;add increment number to tileset frame
- sta.w ObjEntryTilesetFrame,x ;store new tileset frame
- lda.w ObjEntryType,x
- bit.b #%01000000 ;check if active. if inactive/offscreen, dont waste time uploading a new frame
- beq AniListTileFrameIncOffscreen
- jsr CreateObjUploadSpriteFrame
- AniListTileFrameIncOffscreen:
- rts
- AniListTileSetSet:
- ldx.b ObjectListPointerCurrent
- sta.w ObjEntryTileset,x ;set tileset frame
- inc.w ObjEntryAniFrame,x ;increment animation frame
-
- jsr CreateObjUploadSpriteFrame
- rts
- AniListTileFrameSet:
- ldx.b ObjectListPointerCurrent
- inc.w ObjEntryAniFrame,x ;increment animation frame
- sta.w ObjEntryTilesetFrame,x ;set tileset frame
- jsr CreateObjUploadSpriteFrame
- rts
- AniListPalConfSet:
- ldx.b ObjectListPointerCurrent
- inc.w ObjEntryAniFrame,x ;increment animation frame
- sta.w ObjEntryPalConf,x ;set palette and priority config
- rts
- AniListGotoAniList:
- ldx.b ObjectListPointerCurrent
- sta.w ObjEntryAniList,x ;set animation list
- stz.w ObjEntryAniFrame,x ;reset animation frame
- stz.b TempBuffer+10 ;clear animation-command repeat flag
- rts
- AniListMakeBGBound:
- ldx.b ObjectListPointerCurrent
- inc.w ObjEntryAniFrame,x ;increment animation frame
- and.b #1 ;get bit 0
- clc
- asl a ;move to correct location
- asl a
- asl a
- asl a
- asl a
- sta.b TempBuffer
- lda.w ObjEntryType,x ;get object type byte
- and.b #$DF ;mask off bg bound flag
- ora.b TempBuffer ;set flag according to command parameter
- sta.w ObjEntryType,x ;get object type byte
- rts
- AniListSubroutineEnable:
- ldx.b ObjectListPointerCurrent
- inc.w ObjEntryAniFrame,x ;increment animation frame
- and.b #1 ;get bit 0
- clc
- asl a ;move to correct location
- asl a
- asl a
- sta.b TempBuffer
- lda.w ObjEntryType,x ;get object type byte
- and.b #$F7 ;mask off bg bound flag
- ora.b TempBuffer ;set flag according to command parameter
- sta.w ObjEntryType,x ;get object type byte
- rts
- AniListSetSubroutine:
- ldx.b ObjectListPointerCurrent
- inc.w ObjEntryAniFrame,x ;increment animation frame
- sta.w ObjEntrySubRout,x ;set new subroutine
- rts
-
- AniListPlaySoundEffect:
- rep #$31
- ldx.b ObjectListPointerCurrent
- inc.w ObjEntryAniFrame,x ;increment animation frame
- and.w #$ff
- jsr SpcPlaySoundEffectSimple
- rts
- AniListEnd:
- ldx.b ObjectListPointerCurrent
- inc.w ObjEntryAniFrame,x ;increment animation frame
- lda.w ObjEntryType,x ;
- and.b #$ef ;mask off animate flag
- sta.w ObjEntryType,x ;
- rts
- AniListSetVectorSpeed:
- ldx.b ObjectListPointerCurrent
- inc.w ObjEntryAniFrame,x ;increment animation frame
- sta.w ObjEntryVectorTarSpeed,x
- and.b #%111111
- cmp.b #$3f
- bne AniListSetVectorSpeedNoOver
- dec.w ObjEntryVectorTarSpeed,x
- AniListSetVectorSpeedNoOver:
- lda.w ObjEntryVectorSpeed,x
- and.b #%1111111 ;clear "target met" flag
- sta.w ObjEntryVectorSpeed,x
- rts
- AniListSetVectorDir:
- ldx.b ObjectListPointerCurrent
- inc.w ObjEntryAniFrame,x ;increment animation frame
- sta.w ObjEntryVectorTarDir,x
- and.b #%111111
- sta.b TempBuffer
- lda.w ObjEntryVectorDir,x
- and.b #%111111
- sta.b TempBuffer+1 ;34
- cmp.b TempBuffer ;28
- beq AniListSetVectorDirEqual
- bcs AniListSetVectorDirCurrBigger
- lda.b TempBuffer
- sec
- sbc.b TempBuffer+1
- cmp.b #32 ;check if that distance is bigger than 180 degrees
- bcs AniListSetVectorDirTargetCounterClock
- bra AniListSetVectorDirTargetClockwise
- AniListSetVectorDirCurrBigger:
- sec ;substract current from target to get distance between them
- sbc.b TempBuffer ;c
- cmp.b #32 ;check if that distance is bigger than 180 degrees
- bcc AniListSetVectorDirTargetCounterClock
- AniListSetVectorDirTargetClockwise:
- lda.w ObjEntryVectorDir,x
- and.b #%00111111 ;clear "target met"
- ora.b #%01000000 ;set "clockwise"-flag
- sta.w ObjEntryVectorDir,x
- rts
- AniListSetVectorDirTargetCounterClock:
- lda.w ObjEntryVectorDir,x
- and.b #%00111111 ;clear "target met" and turn direction flag(counter clockwise)
- sta.w ObjEntryVectorDir,x
- rts
- AniListSetVectorDirEqual:
- lda.w ObjEntryVectorDir,x
- ora.b #$80
- sta.w ObjEntryVectorDir,x
- rts
- ;in: x,16bit:relative object pointer
- ;out: x,16bit:relative pointer of next active object
- ;if carry is set on return, all objects have been processed
- CheckActiveObject:
- ; rep #$31
- CheckActiveObjectLoop:
- lda.l (ObjEntryType + $7e0000-1),x ;get object type byte (get -1 so that the bmi check still works in 16bit mode)
- ; xba
- ; nop
- bmi CheckActiveObjectDone ;if a not-present object is found, end list processing
- txa
- clc
- adc.w #ObjectFileSize ;increment slot pointer
- tax
- cpx.w #ObjectFileSize*63 ;check if maximum number of objects reached, then step out(maybe spit out an error if needed)
- bne CheckActiveObjectLoop
- CheckActiveObjectListDone:
- ; sep #$20
- sec
- rts
- ; bra CheckActiveObjectListDone ;this is to prevent a lockup if the list is full
- ; beq CheckActiveObjectListDone ;this is to prevent a lockup if the list is full
-
- ; bra CheckActiveObjectLoop
-
- CheckActiveObjectDone:
- ; rep #$31
- stx.b ObjectListPointerCurrent ;store currently found object so that routines can check this back later
- ; sep #$20
- clc
- rts
- ObjectProcessor:
- php
- sep #$20
- phb
- lda.b #$7e
- pha
- plb
- lda.b NMIOamUploadFlag ;don't process list if last frame wasn't uploaded first. needed to prevent sprite flicker due to dma'ing incomplete oam list(irq firing during oam processor)
- bne ObjectProcessorExit
- rep #$31
- stz.w ColObjListPointer ;clear pointer in collision object list
- ; sep #$20
- ;check for active objects
- jsr ClearOamBufferPart ;only clear the part of the buffer that was actually written to last frame
- jsr ClearOamPriorityBuffer
- ; jsr ClearPriorityZBuffer
- ; jsr ClearColObjList
- ldx.w #0 ;start at object 0
- ObjectProcessorLoop:
- jsr CheckActiveObject ;check for active object
- bcc ObjectProcessorNoExit ;if carry is set, all objects were processed
-
- jsr ZSortToOamBuffer
- ; rep #$31
- stz.b ObjectListPointerCurrent
- inc.b NMIOamUploadFlag ;initiate oam buffer upload
- ObjectProcessorExit:
- plb
- plp
- rts
- ObjectProcessorNoExit:
- ;check if sprite needs to be drawn on screen:
- lda.w ObjEntryType,x ;get object type byte
- ; bit.b #%01000000
- ; beq ObjProcInactive ;skip the oam write if bit isnt set
-
- bit.w #%00100000 ;check if sprite is screenbound. if it is, dont check if the sprite is offscreen.
- bne ObjProcDontCheckOnscreen
- ObjectProcessorCheckOnscreen:
- ; rep #$31
- lda.w ObjEntryXPos,x ;remove precision
- lsr a
- lsr a
- lsr a
- lsr a
- sta.w TempBufferTest
- lda.w ObjEntryYPos,x ;remove precision
- lsr a
- lsr a
- lsr a
- lsr a
- sta.w TempBufferTest+2
-
- lda.w ObjEntryXDisplacement,x
- and.w #$ff
- eor.w #$ffff
- ; adc.w ObjEntryXPos,x ;check if sprite is left of screen
- clc
- adc.w TempBufferTest
- clc
- adc.w #32
- cmp.b ScreenPixelPositionX
- bcc ObjProcInactive
-
- lda.w ObjEntryXDisplacement,x
- and.w #$ff
- clc
- adc.b ScreenPixelPositionX
-
- clc
- adc.w #(TileBufferSizeX+1)*8 ;check if sprite is right of screen
- ; cmp.w ObjEntryXPos,x
- cmp.w TempBufferTest
- bcc ObjProcInactive
- lda.w ObjEntryYDisplacement,x
- and.w #$ff
- eor.w #$ffff
- clc
- ; adc.w ObjEntryYPos,x ;check if sprite is on top of screen
- adc.w TempBufferTest+2
- clc
- adc.w #32
- cmp.b ScreenPixelPositionY
- bcc ObjProcInactive
- lda.w ObjEntryYDisplacement,x
- and.w #$ff
- clc
- adc.b ScreenPixelPositionY
- clc
- adc.w #TileBufferSizeX*8 ;check if sprite is below screen
- ; cmp.w ObjEntryYPos,x
- cmp.w TempBufferTest+2
- bcc ObjProcInactive
- ObjProcDontCheckOnscreen:
- jsr ObjectSingleSpriteToOam
- ; sep #$20
- lda.w ObjEntryType,x ;get object type byte
- ora.w #%01000000
- sta.w ObjEntryType,x ;set active flag
- bra ObjProcActive
- ObjProcInactive:
- ; sep #$20
- lda.w ObjEntryType,x ;get object type byte
- and.w #%10111111
- sta.w ObjEntryType,x ;clear active flag
- ObjProcActive:
- ; sep #$20
- lda.w ObjEntryType,x ;get object type byte
- phx
- bit.w #%00010000
- beq ObjProcNoAnim ;skip the oam write if bit isnt set
-
- jsr ObjectProcessAniList
- ObjProcNoAnim:
- plx
- stx.b ObjectListPointerCurrent ;must be saved cause ani list routines that create new sprites might rewrite it
- phx
- ; sep #$20
- lda.w ObjEntryType,x ;get object type byte
- bit.w #%00001000
- beq ObjProcNoSub ;skip the oam write if bit isnt set
-
- jsr ObjectProcessSubroutine
- ObjProcNoSub:
- ; sep #$20
- plx
- stx.b ObjectListPointerCurrent ;must be saved cause ani list routines that create new sprites might rewrite it
- phx
- lda.w ObjEntryType,x ;get object type byte
- bit.w #%00000100
- beq ObjProcNoColl ;skip the oam write if bit isnt set
-
- jsr CreateColListEntry
- ObjProcNoColl:
- plx
- stx.b ObjectListPointerCurrent ;must be saved cause ani list routines that create new sprites might rewrite it
- /*
- lda.w ObjEntryVectorTarSpeed,x ;get vector target speed
- and.w #%111111 ;mask off target bit
- beq ObjProcNoVectorMove ;skip vector move if vector speed is 0
- jsr ObjVectorMoveHandler
- ObjProcNoVectorMove:
- */
- ;check if object is of gravity decaying type
- lda.w ObjEntryType2,x ;get object type byte
-
- bit.w #%10000 ;check if sprite is screenbound. if it is, dont check if the sprite is offscreen.
- beq ObjProcNoGravity
- jsr ObjProcUpdateGravity
- ObjProcNoGravity:
- ; rep #$31
- txa
- clc
- adc.w #ObjectFileSize
- tax
- stx.b ObjectListPointerCurrent ;relative pointer to current object in objectlist
- jmp ObjectProcessorLoop
-
- plp
- rts
- ;upload collidable object information to a special list
- CreateColListEntry:
- php
- txy
- ldx ColObjListPointer ;get pointer to currently active slot in col obj list
- sep #$20
- ; lda.b #$80 ;load col-obj present flag
- lda.w ObjEntryColliSub,y ;get subroutine number and
- ora.b #$80 ;set enable flag
- xba
- lda.w ObjEntryListOffset,y ;load obj number in object list
- rep #$31
- sta.l ColObjList,x ;store in obj col list
- lda.w ObjEntryXPos,y ;get x pos of obj and divide by 16
-
- lsr a ;remove subpixel precision
- lsr a
- lsr a
- lsr a
-
- inx
- inx
- sta.l ColObjList,x ;store in obj col list
- lda.w ObjEntryYPos,y ;get y pos of obj and divide by 16
- lsr a ;remove subpixel precision
- lsr a
- lsr a
- lsr a
- inx
- inx
- sta.l ColObjList,x ;store in obj col list
- inx
- inx
- stx ColObjListPointer ;update pointer to next entry in collision list
- tyx
- plp
- rts
- ;in: a, 8bit: number of object to load
- ; x, 16bit: target low: x, high:y-position/8
- ;in y, 8bit: target z-position
- ;uses TempBuffer0,1. maybe convert to use own temp area for better flexibility?
- CreateObjectPosition:
- php
-
- rep #$31
- stx.b CollisionPixelX
- sty.b CollisionPixelY
- ; sty.b CollisionPixelY
- and.w #$ff ;2byte pointer
- asl a
- tax ;put into x
- phd
- lda.w #0
- tcd
- sep #$20
- phb
- lda.b #$7e
- pha
- plb
- rep #$31
- lda.l (ObjectLUT+BaseAdress),x ;get relative pointer to object
- clc
- adc.w #ObjectLUT ;calculate real pointer
- sta.b ThreeBytePointerLo
-
- sep #$20
- lda.b #(:ObjectLUT+BaseAdress>>16)
- sta.b ThreeBytePointerBank
- ;check for free object space in object list:
- ; rep #$31
- ldx.w #0
- CreateObjectPositionCheckFreeSpaceLoop:
- lda.w ObjEntryType,x ;get object type byte
- bpl CreateObjectPositionCheckFreeSpaceDone ;if free, step out
- rep #$31
- txa
- adc.w #ObjectFileSize ;increment slot pointer
- tax
- sep #$20
- cpx.w #ObjectFileSize*63 ;check if maximum number of objects reached, then step out(maybe spit out an error if needed)
- beq CreateObjectPositionCheckFreeSpaceDone ;this is to prevent a lockup if the list is full
-
- bra CreateObjectPositionCheckFreeSpaceLoop
-
- CreateObjectPositionCheckFreeSpaceDone:
- rep #$31
- stx.b ObjectListPointerCurrent ;relative pointer to current object in objectlist
- txa
- clc
- lsr a
- lsr a
- lsr a
- lsr a ;divide objectlist pointer by 16 to get current object number
- sep #$20
- sta.b CurrentObjectNumber
- rep #$31
- ldy.w #0
-
- CreateObjectPositionUploadLoop:
- lda.b [ThreeBytePointerLo],y ;get first byte of object file in rom
- sta.w ObjEntryType,x
-
- inx
- inx
- iny
- iny
- cpy.w #(ObjectFileSize&$fffe) ;check if object file was uploaded, word-aligned
- bne CreateObjectPositionUploadLoop
- ldx.b ObjectListPointerCurrent
- lda.w ObjEntryType,x ;get object type byte
- bit.w #%100000 ;check if screenbound
- beq CreateObjectPositionNotScreenBound
- lda.w ObjEntryType2-1,x ;pseudo-3d object?
- bpl CreateObjectPositionNot3D
- lda.b CollisionPixelX ;plot directly to loaded xy position if screenbound
- and.w #$ff
- clc
- asl a ;multiply with 16, 3d high-precision value
- asl a
- asl a
- asl a
- ; asl a
- ; asl a
-
- asl a
- asl a
- asl a
- sta.w ObjEntryXPos,x
- lda.b CollisionPixelX
- and.w #$ff00
- xba
- clc
- asl a ;multiply with 16, 3d high-precision value
- asl a
- asl a
- asl a
- ; asl a
- ; asl a
- asl a
- asl a
- asl a
- sta.w ObjEntryYPos,x
- lda.b CollisionPixelY ;store z-value
- sep #$20
- sta.w ObjEntryZDisplacement,x
- rep #$31
- bra CreateObjectPositionNotScreenBoundSkip
- CreateObjectPositionNot3D:
- lda.b CollisionPixelX ;plot directly to loaded xy position if screenbound
- and.w #$ff
- clc
- asl a ;multiply by 8
- asl a
- asl a
-
- asl a ;add subpixel precision
- asl a
- asl a
- asl a
-
- sta.w ObjEntryXPos,x
- lda.b CollisionPixelX
- xba
- and.w #$ff
- clc
- asl a ;multiply by 8
- asl a
- asl a
- asl a ;add subpixel precision
- asl a
- asl a
- asl a
- sta.w ObjEntryYPos,x
- bra CreateObjectPositionNotScreenBoundSkip
- CreateObjectPositionNotScreenBound:
- clc
- lda.b CollisionPixelX
- and.w #$ff
- asl a ;multiply by 8
- asl a
- asl a
- asl a ;add subpixel precision
- asl a
- asl a
- asl a
-
- sta.w ObjEntryXPos,x
- clc
- lda.b CollisionPixelX
- and.w #$ff00
- xba
- asl a ;multiply by 8
- asl a
- asl a
- asl a ;add subpixel precision
- asl a
- asl a
- asl a
- sta.w ObjEntryYPos,x
- CreateObjectPositionNotScreenBoundSkip:
- ;upload object number:
- ; ldx.b ObjectListPointer
- ; clc
- ; adc.w #(ObjectList & $ffff)
- ; clc
- ; adc.w #13
- ; tax
- lda.w #0
- tay
- ; tax
- ; inx
- sep #$20
- lda.b CurrentObjectNumber
- sta.w ObjEntryListOffset,x ;store in the object number offset in an object file
- jsr CreateObjUploadSpriteFrame
- jsr CreateObjUploadPalette
- ;the animation list has to be executed at once in case objects create additional objects
- ldx.b ObjectListPointerCurrent
- ; stx.b ObjectListPointerCurrent
- phx
- lda.w ObjEntryType,x ;get object type byte
- bit.b #%00010000
- beq ObjLoaderPositionNoAnim ;skip the oam write if bit isnt set
-
- jsr ObjectProcessAniList
- ObjLoaderPositionNoAnim:
- lda.w ObjEntryType2,x ;increase max obj number if gravity particle present
- bit.b #%10000
- beq ObjLoaderPositionNoGravObj ;skip the oam write if bit isnt set
-
- jsr ObjectProcessGravObjInc
- ObjLoaderPositionNoGravObj:
- plx
- stx.b ObjectListPointerCurrent ;must be saved cause ani list routines that create new sprites might rewrite it
- sep #$20
- lda.w ObjEntryType,x ;get object type byte
- bit.b #%00001000
- beq ObjLoaderPositionNoSub ;skip the oam write if bit isnt set
-
- jsr ObjectProcessSubroutine
- ObjLoaderPositionNoSub:
- plb
- pld
- plp
- rts
- ;upload palette:
- CreateObjUploadPalette:
- lda.w ObjEntryType2,x
- bit.b #%00100000 ;don't upload palette if corresponding flag is set
- bne CreateObjUploadPaletteCancel
-
- rep #$31
- lda.w ObjEntryPalConf,x ;get palette config
- sta.b TempBuffer
- lda.w ObjEntryPalNumber,x ;get palette number
- and.w #$ff ;2byte pointer
- asl a ;2byte length
- asl a
- tax ;put into x
- lda.l (SpritePaletteLUT+BaseAdress),x ;get relative pointer to object
- clc
- adc.w #SpritePaletteLUT ;calculate real pointer
- sta.b ThreeBytePointerLo
-
- lda.l (SpritePaletteLUT+BaseAdress+2),x ;get length
- and.w #$fe ;mask off bit0. palettes always have word entries. prevents uploader from crashing if invalid palette is being loaded
- cmp.w #$20
- bcs UploadObjPalNoOverflow
- lda.w #$20 ;never load palettes bigger than 32 bytes
- UploadObjPalNoOverflow:
- sta.b TempBuffer+1
-
- lda.w #0
- sep #$20
- lda.b #(:SpritePaletteLUT+BaseAdress>>16)
- sta.b ThreeBytePointerBank
- rep #$31
- lda.b TempBuffer
- and.w #$E ;only get three palette bits
- clc
- lsr a ;rotate right to get palette number
- clc
- adc.w #8 ;add sprite palette offset
-
- asl a ;multiply with 16 to get real start adress in palette buffer
- asl a
- asl a
- asl a
- asl a
-
- tax
-
- ldy.w #0
- CreateObjectPositionUploadPaletteLoop:
- lda.b [ThreeBytePointerLo],y ;get first byte of object file in rom
- sta.w PaletteBuffer & $ffff,x
-
- inx
- inx
- iny
- iny
- cpy.b TempBuffer+1 ;check if object file was uploaded, word-aligned
- bne CreateObjectPositionUploadPaletteLoop
- sep #$20
- inc.b NMIPaletteUploadFlag
- CreateObjUploadPaletteCancel:
- rts
- ;in: a, 8bit: number of object to load
- CreateObject:
- php
-
- rep #$31
- and.w #$ff ;2byte pointer
- sta.b TempBuffer
- asl a
- tax ;put into x
- phd
- lda.w #0
- tcd
-
- sep #$20
- phb
- lda.b #$7e
- pha
- plb
- rep #$31
- lda.l (ObjectLUT+BaseAdress),x ;get relative pointer to object
- clc
- adc.w #ObjectLUT ;calculate real pointer
- sta.b ThreeBytePointerLo
-
- sep #$20
- lda.b #(:ObjectLUT+BaseAdress>>16)
- sta.b ThreeBytePointerBank
- ;check for free object space in object list:
- ; rep #$31
- ldx.w #0
- CreateObjectCheckFreeSpaceLoop:
- lda.w ObjEntryType,x ;get object type byte
- bpl CreateObjectCheckFreeSpaceDone ;if free, step out
- rep #$31
- txa
- adc.w #ObjectFileSize ;increment slot pointer
- tax
- sep #$20
- cpx.w #ObjectFileSize*63 ;check if maximum number of objects reached, then step out(maybe spit out an error if needed)
- beq CreateObjectCheckFreeSpaceDone ;this is to prevent a lockup if the list is full
-
- bra CreateObjectCheckFreeSpaceLoop
-
- CreateObjectCheckFreeSpaceDone:
- rep #$31
- stx.b ObjectListPointerCurrent ;relative pointer to current object in objectlist
- txa
- clc
- lsr a
- lsr a
- lsr a
- lsr a ;divide objectlist pointer by 16 to get current object number
- sep #$20
- sta.b CurrentObjectNumber
- rep #$31
- ldy.w #0
- CreateObjectUploadLoop:
- lda.b [ThreeBytePointerLo],y ;get first byte of object file in rom
- sta.w ObjEntryType,x
-
- inx
- inx
- iny
- iny
- cpy.w #(ObjectFileSize&$fffe) ;check if object file was uploaded, word-aligned
- bne CreateObjectUploadLoop
-
- ;upload object number:
- ldx.b ObjectListPointerCurrent
- ; clc
- ; adc.w #(ObjectList & $ffff)
- ; clc
- ; adc.w #13
- ; tax
- lda.w #0
- tay
- ; tax
- ; inx
- ; lda.b TempBuffer ;store number of object so other routines can clearly identify it.
- ; sta.w ObjEntryObjectNumber,x
- sep #$20
- lda.b CurrentObjectNumber
- sta.w ObjEntryListOffset,x ;store in the object number offset in an object file
- jsr CreateObjUploadSpriteFrame
- /*
- ;upload palette:
- rep #$31
- lda.w ObjEntryPalConf,x ;get palette config
- sta.b TempBuffer
- lda.w ObjEntryPalNumber,x ;get palette number
- and.w #$ff ;2byte pointer
- asl a ;2byte length
- asl a
- tax ;put into x
- lda.l (SpritePaletteLUT+BaseAdress),x ;get relative pointer to object
- clc
- adc.w #SpritePaletteLUT ;calculate real pointer
- sta.b ThreeBytePointerLo
-
- lda.l (SpritePaletteLUT+BaseAdress+2),x ;get length
- and.w #$fe ;word-align, no longer than 256 bytes
- sta.b TempBuffer+1
-
- lda.w #0
- sep #$20
- lda.b #(:SpritePaletteLUT+BaseAdress>>16)
- sta.b ThreeBytePointerBank
- rep #$31
- lda.b TempBuffer
- and.w #$E ;only get three palette bits
- clc
- lsr a ;rotate right to get palette number
- clc
- adc.w #8 ;add sprite palette offset
-
- asl a ;multiply with 16 to get real start adress in palette buffer
- asl a
- asl a
- asl a
- asl a
-
- tax
-
- ldy.w #0
- CreateObjectUploadPaletteLoop:
- lda.b [ThreeBytePointerLo],y ;get first byte of object file in rom
- sta.w PaletteBuffer & $ffff,x
-
- inx
- inx
- iny
- iny
- cpy.b TempBuffer+1 ;check if object file was uploaded, word-aligned
- bne CreateObjectUploadPaletteLoop
- sep #$20
- inc.b NMIPaletteUploadFlag
- */
- jsr CreateObjUploadPalette
-
- ldx.b ObjectListPointerCurrent
- ; stx.b ObjectListPointerCurrent
- ; sep #$20
- lda.w ObjEntryType,x ;get object type byte
- bit.b #%00010000
- beq ObjLoaderNoAnim ;skip the oam write if bit isnt set
-
- jsr ObjectProcessAniList
- ObjLoaderNoAnim:
- lda.w ObjEntryType2,x ;increase max obj number if gravity particle present
- bit.b #%10000
- beq ObjLoaderPositionNoGravObj2 ;skip the oam write if bit isnt set
-
- jsr ObjectProcessGravObjInc
- ObjLoaderPositionNoGravObj2:
- sep #$20
- lda.w ObjEntryType,x ;get object type byte
- bit.b #%00001000
- beq ObjLoaderNoSub ;skip the oam write if bit isnt set
-
- jsr ObjectProcessSubroutine
- ObjLoaderNoSub:
- rep #$30
- ; stz.b ObjectListPointerCurrent
- plb
- pld
- plp
- rts
- ;upload current frame to vram
- ;get sprite config and lookup transfer type
- CreateObjUploadSpriteFrame:
- php
- sep #$20
- lda.w ObjEntryType2,x
- bit.b #%01000000
- beq CreateObjUploadSpriteFrameDontCancel
- ;don't upload any sprite tiles if bit6 of object type 2 is set. this is used for the music notes and stuff like that where many sprites share the same tiles in order to minimize dma overhead.
- plp
- rts
- CreateObjUploadSpriteFrameDontCancel:
- rep #$31
- lda.w ObjEntryType,x ;get sprite size bit
- and.w #%10
- clc
- asl a ;put into bit3
- asl a
- sta.b TempBuffer
-
-
- lda.b ObjSel
- and.w #%11100000
- clc
- lsr a
- lsr a
- lsr a
- lsr a
- lsr a
- ora.b TempBuffer ;add sprite size bit
- sta.b TempBuffer
- asl a ;multiply by 3 to get pointer
- clc
- adc.b TempBuffer
- phx
- tax ;put into x
- lda.l (ObjSizeLUT+BaseAdress),x ;get transfer length and number of bytes to transfer for this sprite
- sta.b TempBuffer+8 ;+8 is length, +9 is transfer number
- lda.l (ObjSizeLUT+BaseAdress+2),x ;get transfer type
- sta.b TempBuffer+14 ;+14 is type
-
- plx
- ; rep #$31
- ; lda.w #80
- ; sta.b TempBuffer ;this is the number of tiles of one frame
- ; stz.b TempBuffer+1
- ; sep #$20
- clc
- lda.b TempBuffer+8 ; length of one transfer and divide by 32 to get number of h-tiles
- and.w #$ff
- inc a ;increment once to get real length
- lsr a
- lsr a
- lsr a
- lsr a
- lsr a
- sta.b TempBuffer
- lda.b TempBuffer+9 ; transfer number 16bit
- and.w #$ff
- sta.b TempBuffer+2
- lda.w #0
- tay
- CreateObjCalcSizeLoop3:
- cpy.b TempBuffer+2
- beq CreateObjCalcSizeDone3
- iny
- adc.b TempBuffer
- bra CreateObjCalcSizeLoop3
- CreateObjCalcSizeDone3:
- sta.b TempBuffer ;store total number of tiles
- lda.w ObjEntryTilesetFrame,x ;get current tileset frame
- and.w #$ff
- sta.b TempBuffer+2
- lda.w #0
- tay
- CreateObjCalcSizeLoop2:
- cpy.b TempBuffer+2
- beq CreateObjCalcSizeDone2
- iny
- adc.b TempBuffer
- bra CreateObjCalcSizeLoop2
- CreateObjCalcSizeDone2:
- sta.b TempBuffer+2 ;this is the first tile to be uploaded
- lda.w ObjEntryTileset,x ;get tileset number
- and.w #$ff
- sta.b TempBuffer+4 ;multiply with 3
- asl a
- clc
- adc.b TempBuffer+4
-
- txy
- tax
- lda.l (SpriteTilesetLUT+BaseAdress),x
- sta.b TempBuffer+4
- lda.l (SpriteTilesetLUT+1+BaseAdress),x
- tyx
- ; and.w #$ff
- sta.b TempBuffer+5
-
- lda.b TempBuffer+2 ;get first tile and multiply with 32 to get actual byte offset
- clc
- asl a
- asl a
- asl a
- asl a
- asl a
- clc
- adc.b TempBuffer+4
- bcc CreateObjCalcSourceNoWrap
-
- inc.b TempBuffer+6 ;increment bank
- CreateObjCalcSourceNoWrap:
- sta.b TempBuffer+4 ;store transfer source offset
- sep #$20
- lda.w ObjEntryPalConf,x ;get nametable bit(msb of sprites first tile)
- and.b #1
- xba
- lda.w ObjEntryVramTile,x ;get target tile number
- ; and.w #$ff
- rep #$31
- ; clc
- asl a ;multiply by 16(bytesize is 32, but vram is word-aligned)
- asl a
- asl a
- asl a
- clc
- adc.b SpriteTileOffsetVram ;add initial sprite offset
- sta.b TempBuffer+10 ;this is the vram target
- phx ;push object list pointer
- ldx.b DmaFifoPointer
- lda.b TempBuffer+8 ;get transfer length and increase by 1 to get real length 16bit
- and.w #$ff
- inc a
- sta.b TempBuffer+12
- CreateObjUploadTilesLoop:
- rep #$31
- lda.b TempBuffer+14 ;transfer type
- sta.l DmaFifoEntryType,x
- ;store transfer target
- lda.b TempBuffer+10
- sta.l DmaFifoEntryTarget,x ;vram target 2116
- ;store transfer source
- lda.b TempBuffer+4
- sta.l DmaFifoEntrySrcLo,x ;source 4202
- lda.b TempBuffer+5
- sta.l DmaFifoEntrySrcHi,x ;source 4203
- ;store transfer length
- lda.b TempBuffer+12 ;get transfer length. not used except for 8x8 sprites, where it is 32 bytes
- sta.l DmaFifoEntryCount,x ;length 4205
- /*
- ;update vram target pointer:
- lda.b TempBuffer+10
- clc
- adc.w #32*16/2 ;add one 16tile-line to vram target
- sta.b TempBuffer+10
- */
- ;update fifo buffer target:
- txa ;update fifo entry pointer
- clc
- adc.w #DmaFifoEntryLength
- /*
- tax
-
- ;update source pointer
- lda.b TempBuffer+4
- clc
- adc.b TempBuffer+12
- sta.b TempBuffer+4
- sep #$20
- dec.b TempBuffer+9 ;decrement number of transfers
- bne CreateObjUploadTilesLoop
-
- ;sprite tile transfer done
- rep #$31
- txa ;update fifo entry pointer
- ; clc
- ; adc.w #DmaFifoEntryLength
- */
- sta.b DmaFifoPointer
- plx
- plp ;fetch object list pointer
- rts
- /*
- ;old version which created multiple transfers in fifo buffer
- CreateObjUploadSpriteFrame:
- CreateObjLookupSpriteSize:
- php
- rep #$31
- lda.w ObjEntryType,x ;get sprite size bit
- and.w #%10
- clc
- asl a ;put into bit3
- asl a
- sta.b TempBuffer
-
-
- lda.b ObjSel
- and.w #%11100000
- clc
- lsr a
- lsr a
- lsr a
- lsr a
- lsr a
- ora.b TempBuffer ;add sprite size bit
- asl a ;multiply by 2 to get pointer
- phx
- tax ;put into x
- lda.l (ObjSizeLUT+BaseAdress),x ;get transfer length and number of bytes to transfer for this sprite
- plx
- sta.b TempBuffer+8 ;+8 is length, +9 is transfer number
- ; rep #$31
- ; lda.w #80
- ; sta.b TempBuffer ;this is the number of tiles of one frame
- ; stz.b TempBuffer+1
- ; sep #$20
- clc
- lda.b TempBuffer+8 ; length of one transfer and divide by 32 to get number of h-tiles
- and.w #$ff
- inc a ;increment once to get real length
- lsr a
- lsr a
- lsr a
- lsr a
- lsr a
- sta.b TempBuffer
- lda.b TempBuffer+9 ; transfer number 16bit
- and.w #$ff
- sta.b TempBuffer+2
- lda.w #0
- tay
- CreateObjCalcSizeLoop3:
- cpy.b TempBuffer+2
- beq CreateObjCalcSizeDone3
- iny
- adc.b TempBuffer
- bra CreateObjCalcSizeLoop3
- CreateObjCalcSizeDone3:
- sta.b TempBuffer ;store total number of tiles
- lda.w ObjEntryTilesetFrame,x ;get current tileset frame
- and.w #$ff
- sta.b TempBuffer+2
- lda.w #0
- tay
- ;this must be reprogrammed, too:
- CreateObjCalcSizeLoop2:
- cpy.b TempBuffer+2
- beq CreateObjCalcSizeDone2
- iny
- adc.b TempBuffer
- bra CreateObjCalcSizeLoop2
- CreateObjCalcSizeDone2:
- sta.b TempBuffer+2 ;this is the first tile to be uploaded
- lda.w ObjEntryTileset,x ;get tileset number
- and.w #$ff
- sta.b TempBuffer+4 ;multiply with 3
- asl a
- clc
- adc.b TempBuffer+4
-
- txy
- tax
- lda.l (SpriteTilesetLUT+BaseAdress),x
- sta.b TempBuffer+4
- lda.l (SpriteTilesetLUT+1+BaseAdress),x
- tyx
- ; and.w #$ff
- sta.b TempBuffer+5
-
- lda.b TempBuffer+2 ;get first tile and multiply with 32 to get actual byte offset
- clc
- asl a
- asl a
- asl a
- asl a
- asl a
- clc
- adc.b TempBuffer+4
- bcc CreateObjCalcSourceNoWrap
-
- inc.b TempBuffer+6 ;increment bank
- CreateObjCalcSourceNoWrap:
- sta.b TempBuffer+4 ;store transfer source offset
- sep #$20
- lda.w ObjEntryPalConf,x ;get nametable bit(msb of sprites first tile)
- and.b #1
- xba
- lda.w ObjEntryVramTile,x ;get target tile number
- ; and.w #$ff
- rep #$31
- ; clc
- asl a ;multiply by 16(bytesize is 32, but vram is word-aligned)
- asl a
- asl a
- asl a
- clc
- adc.b SpriteTileOffsetVram ;add initial sprite offset
- sta.b TempBuffer+10 ;this is the vram target
- phx ;push object list pointer
- ldx.b DmaFifoPointer
- lda.b TempBuffer+8 ;get transfer length and increase by 1 to get real length 16bit
- and.w #$ff
- inc a
- sta.b TempBuffer+12
- CreateObjUploadTilesLoop:
- rep #$31
- lda #1 ;transfer type normal dma
- sta.l DmaFifoEntryType,x
- ;store transfer target
- lda.b TempBuffer+10
- sta.l DmaFifoEntryTarget,x ;vram target 2116
- ;store transfer source
- lda.b TempBuffer+4
- sta.l DmaFifoEntrySrcLo,x ;source 4202
- lda.b TempBuffer+5
- sta.l DmaFifoEntrySrcHi,x ;source 4203
- ;store transfer length
- lda.b TempBuffer+12 ;get transfer length
- sta.l DmaFifoEntryCount,x ;length 4205
- ;update vram target pointer:
- lda.b TempBuffer+10
- clc
- adc.w #32*16/2 ;add one 16tile-line to vram target
- sta.b TempBuffer+10
- ;update fifo buffer target:
- txa ;update fifo entry pointer
- clc
- adc.w #DmaFifoEntryLength
- tax
-
- ;update source pointer
- lda.b TempBuffer+4
- clc
- adc.b TempBuffer+12
- sta.b TempBuffer+4
- sep #$20
- dec.b TempBuffer+9 ;decrement number of transfers
- bne CreateObjUploadTilesLoop
-
- ;sprite tile transfer done
- rep #$31
- txa ;update fifo entry pointer
- ; clc
- ; adc.w #DmaFifoEntryLength
- sta.b DmaFifoPointer
- plx
- plp ;fetch object list pointer
- rts
- */
- ;first writes a sorted list of object priorities, then transfers these to oam
- ZSortToOamBuffer:
- php
- rep #$31
- sep #$20
- ldx.w #0 ;reset pointer to priority list
- lda.b OamZsortSpriteNumber ;exit immediatly if there are no priority sprites on the current screen. else, it keeps on going on forever
- bne ZSortToOamBufferNoExit
-
- plp
- rts
-
- ZSortToOamBufferNoExit:
- sta.b TempBuffer+2 ;counter for inner loop
- sta.b TempBuffer+3 ;counter for outer loop
- stz.b TempBuffer ;clear "highest priority" variable
-
- ; ldx.w #0 ;reset pointer to priority list
- txy ;reset pointer to zsort list
-
- ZsortSortingInnerLoop:
- lda.w OamZSortBuffer & $FFFF+4,y ;entry present?
- bpl ZsortNotPresent
- ;sprite present
- lda.w OamZSortBuffer & $FFFF+5,y ;get priority
- cmp.b TempBuffer ;check if bigger than last highest sprite
- bcc ZsortNotBiggest
-
- sta.b TempBuffer ;new highest priority
- rep #$31
- tya ;get pointer in sprite list, save to sort listing
- sta.w OamZSortObjList & $FFFF,x
- ZsortNotBiggest:
- ZsortNotPresent:
- rep #$31
- tya
- adc.w #OamZSortBufferSize ;get next entry
- tay
- sep #$20
- dec.b TempBuffer+2 ;decrease inner counter
- bne ZsortSortingInnerLoop
- ;sorted through all once
- lda.b OamZsortSpriteNumber
- sta.b TempBuffer+2 ;set counter for inner loop
- stz.b TempBuffer ;clear highest
- ;clear "present"-bit of highest in this round
- phy
- lda.w OamZSortObjList & $FFFF,x ;get pointer to highest
- tay
- lda.w OamZSortBuffer & $FFFF+4,y ;clear "present"-bit
- and.b #$7f
- sta.w OamZSortBuffer & $FFFF+4,y
-
- ply
-
- inx ;figure out next one
- inx
- ldy.w #0 ;reset source buffer pointer
-
- dec.b TempBuffer+3 ;decrease counter
- bne ZsortSortingInnerLoop
- ZSortToOamBufferDoneSorting:
- ; lda.b OamZsortSpriteNumber
- stz.b TempBuffer+2 ;clear pointer in priority list, counter
- ldx.b OamBufferPointer ;get oam pointer, write after priorityless sprites
- ; ldy.w #0
- ZSortWriteToOamLoop:
- rep #$31 ;get pointer to current priority list entry
- lda.b TempBuffer+2
- and.w #$ff
- tay
- lda.w OamZSortObjList & $FFFF,y ;get first pointer
- tay
- ;copy data from zbuffer to oam buffer
- lda.w OamZSortBuffer & $FFFF,y
- sta.w OamBuffer & $ffff,x ;store in oam buffer
- lda.w OamZSortBuffer & $FFFF+2,y
- sta.w OamBuffer & $ffff+2,x ;store in oam buffer
- phx
- phy
- txa
- and.w #$01f0 ;get byte target of size buffer
- ; and.w #$0100 ;get byte target of size buffer
- ; xba ;divide by 16
- lsr a ;divide by 16
- lsr a
- lsr a
- lsr a
- sta.b TempBuffer ;this is the 16bit pointer to the current byte in size buffer
- ;calculate bit offset in spritesize buffer:
- txa
- clc
- and.w #$c ;get target bits of size buffer
- lsr a ;shift right twice to get correct jump offset
- tax
- lda.w OamZSortBuffer & $FFFF+4,y
- ldy.b TempBuffer
- and.w #%11
- jmp (PrioObjectProcessorSizeTableJTbl,x)
-
- PrioObjectProcessorSizeTableJTbl:
- .dw PrioObjProcSizeJtblBit0
- .dw PrioObjProcSizeJtblBit1
- .dw PrioObjProcSizeJtblBit2
- .dw PrioObjProcSizeJtblBit3
- PrioObjProcSizeJtblBit3:
- asl a
- asl a
- PrioObjProcSizeJtblBit2:
- asl a
- asl a
- PrioObjProcSizeJtblBit1:
- asl a
- asl a
- PrioObjProcSizeJtblBit0:
- ora.w OamPriorityBuffer & $ffff,y ;store in corresponding bits/bytes
- sta.w OamPriorityBuffer & $ffff,y ;store in corresponding bits/bytes
- ply
- plx
- lda.w #0
- ; sta.w OamZSortBuffer & $FFFF,y ;clear zsort buffer entries right after use so we dont have to clear the whole list each frame
- ; sta.w OamZSortBuffer & $FFFF+2,y
- ; sta.w OamZSortBuffer & $FFFF+3,y
- inx
- inx
- inx
- inx
- sep #$20
- lda.b TempBuffer+2 ;process next entry
- inc a
- inc a
- sta.b TempBuffer+2 ;process next entry
- lsr a
- cmp.b OamZsortSpriteNumber ;done copying?
- bne ZSortWriteToOamLoop
-
- stx.b OamBufferPointer
-
- plp
- rts
- ;in: a,16bit: desired scanline to draw sprite to.
- ;out: y,16bit: relative pointer to correct entry in zsort buffer
- ObjectZSortGetFreeSlot:
- ; php
- ; rep #$31
- ; tya
- sta.b TempBuffer ;get desired scanline
- asl a ;multiply by 5 to get pointer into zsort buffer
- asl a
- clc
- adc.b TempBuffer
- tay
- ObjectZSortGetFreeSlotLoop:
- lda.w OamZSortBuffer & $FFFF,y
- beq ObjectZSortGetFreeSlotDone
-
- tya
- sec ;increase scanline by one if theres a sprite here already
- sbc.w #OamZSortBufferSize
- bcc ObjZSortGetSlotUnderrun
- tay
- bra ObjectZSortGetFreeSlotLoop
- ObjZSortGetSlotUnderrun:
- ldy.w #210*OamZSortBufferSize ;select max entry
- bra ObjectZSortGetFreeSlotLoop
- ObjectZSortGetFreeSlotDone:
- ; tya
- ; clc
- ; adc.w #OamZSortBuffer ;make this a direct pointer
- ; tay
- ; plp
- rts
- ObjProcScreenBound:
- sep #$20
- lda.w ObjEntryZDisplacement,x ;calculate priority?
- ; and.w #$ff ;only get z-priority
- beq ObjProcScreenBoundNoPriorityCalc
- ;****************************************************
- ;write sprite to oam zsort buffer instead
- ldy.b OamZsortBufferPointer ;get buffer pointer
- ; rep #$31
- lda.w ObjEntryType2,x ;pseudo-3d sprite?
- bmi ObjProc3dSprite
- lda.w ObjEntryZDisplacement,x ;store z
- sta.w OamZSortBuffer & $ffff+5,y
- rep #$31
- lda.w ObjEntryXPos,x ;get xy-coordinates
- lsr a ;remove subpixel precision
- lsr a
- lsr a
- lsr a
- ; sep #$20
- sta.w OamZSortBuffer & $ffff,y ;store x coordinate
- ; rep #$31
- lda.w ObjEntryYPos,x ;get xy-coordinates
- lsr a ;remove subpixel precision
- lsr a
- lsr a
- lsr a
- sep #$20
- sta.w OamZSortBuffer & $ffff+1,y ;store x coordinate
- jmp ObjProcZsortWriteExit
- ObjProc3dSprite:
- lda.w ObjEntryZDisplacement,x
- eor.b #$ff ;invert priority for 3d sprites
- sta.w OamZSortBuffer & $ffff+5,y
- rep #$31
- lda.w ObjEntryXPos,x ;get xy-coordinates
- lsr a ;divide by 16, high precision position
- lsr a
- lsr a
- lsr a
- ; lsr a
- ; lsr a
- sep #$20
- sta.w OamZSortBuffer & $ffff,y ;store x coordinate
- rep #$31
- lda.w ObjEntryYPos,x ;get xy-coordinates
- lsr a ;divide by 16, high precision position
- lsr a
- lsr a
- lsr a
- ; lsr a
- ; lsr a
- sep #$20
- sta.w OamZSortBuffer & $ffff+1,y ;store x coordinate
- jmp ObjProcZsortWriteExit
- ObjProcScreenBoundNoPriorityCalc:
- rep #$31
- lda.w ObjEntryXPos,x ;get xy-coordinates
- lsr a ;remove subpixel precision
- lsr a
- lsr a
- lsr a
- sta.w OamBuffer & $ffff,y ;store x coordinate
- lda.w ObjEntryYPos,x ;get xy-coordinates
- lsr a ;remove subpixel precision
- lsr a
- lsr a
- lsr a
- sep #$20
- sta.w OamBuffer & $ffff+1,y ;store y coordinate
-
- jmp ObjProcDrawConfig
- ObjectSingleSpriteToOam:
- ;dont upload directly to sprite buffer, but put sprite in a seperate 256entry-list according to y+ydisplacement value so the sprites get z-sorted. ;upload sprite to oam buffer:
- ; rep #$31
- ldy.b OamBufferPointer ;get pointer to current oam buffer entry
- lda.w ObjEntryType,x
- bit.w #%00100000 ;check if screenbound
- bne ObjProcScreenBound
- lda.w ObjEntryZDisplacement,x
- and.w #$ff
- beq ObjProcNoPriorityCalc
- ObjProcPriorityCalc:
- ;****************************************************
- ;write sprite to oam zsort buffer instead
- ldy.b OamZsortBufferPointer ;get buffer pointer
- lda.w ObjEntryYPos,x ;get xy-coordinates
- lsr a ;remove subpixel precision
- lsr a
- lsr a
- lsr a
- sta.b TempBuffer
-
- lda.w ObjEntryZDisplacement,x
- and.w #$ff
- clc
- ; adc.w ObjEntryYPos,x ;get xy-coordinates
- adc.b TempBuffer
- sec
- sbc.b ScreenPixelPositionY ;substract screen position to get sprite position on screen. before doing this, we made sure the sprite is actually onscreen.
- sep #$20
- sta.w OamZSortBuffer & $ffff+5,y
- rep #$31
- lda.w ObjEntryXPos,x ;get xy-coordinates
- ; clc
- lsr a ;remove subpixel precision
- lsr a
- lsr a
- lsr a
- ; adc.w #16 ;add 16 because of left border
- sec
- sbc.w ObjEntryXDisplacement,x
- sec
- sbc.b ScreenPixelPositionX ;substract screen position to get sprite position on screen. before doing this, we made sure the sprite is actually onscreen.
- sta.w OamZSortBuffer & $ffff,y ;store x coordinate
- bcs ObjProcPriorSprNoWrap1 ;if sprite wraps around left screen edge, carry is clear
- lda.w ObjEntryType,x ;set x-position sign bit if sprite wraps around the edge
- ora.w #%1
- sta.w ObjEntryType,x
- bra ObjProcPriorSprWrapDone
- ObjProcPriorSprNoWrap1:
- lda.w ObjEntryType,x ;clear x-position sign bit if sprite wraps around the edge
- and.w #$fffe
- sta.w ObjEntryType,x
-
- ObjProcPriorSprWrapDone:
- lda.w ObjEntryYPos,x ;get xy-coordinates
- lsr a ;remove subpixel precision
- lsr a
- lsr a
- lsr a
- sec
- sbc.b ScreenPixelPositionY ;substract screen position to get sprite position on screen. before doing this, we made sure the sprite is actually onscreen.
- sec
- sbc.w ObjEntryYDisplacement,x
- sep #$20
- sta.w OamZSortBuffer & $ffff+1,y ;store x coordinate
- ObjProcZsortWriteExit:
- lda.w ObjEntryType,x ;get size/x-sign bits
- and.b #%11
- ora.b #$80 ;set "present" bit
- sta.w OamZSortBuffer & $ffff+4,y
- inc.b OamZsortSpriteNumber ;increment number of sortable sprites
- rep #$31
- lda.w ObjEntryVramTile,x ;starting tile and config
- sta.w OamZSortBuffer & $ffff+2,y ;store tile and config
-
- tya ;calc new value for buffer
- adc.w #OamZSortBufferSize
- sta.b OamZsortBufferPointer
-
- rts
- ;****************************************************
- ObjProcNoPriorityCalc:
- lda.w ObjEntryXPos,x ;get xy-coordinates
- lsr a ;remove subpixel precision
- lsr a
- lsr a
- lsr a
- clc
- ; adc.w #16 ;add 16 because of left border
- sec
- sbc.w ObjEntryXDisplacement,x
- sec
- sbc.b ScreenPixelPositionX ;substract screen position to get sprite position on screen. before doing this, we made sure the sprite is actually onscreen.
- sta.w OamBuffer & $ffff,y ;store x coordinate
- bcs ObjProcSprNoWrap1 ;if sprite wraps around left screen edge, carry is clear
- lda.w ObjEntryType,x ;set x-position sign bit if sprite wraps around the edge
- ora.w #%1
- sta.w ObjEntryType,x
- bra ObjProcSprWrapDone
- ObjProcSprNoWrap1:
- lda.w ObjEntryType,x ;clear x-position sign bit if sprite wraps around the edge
- and.w #$fffe
- sta.w ObjEntryType,x
-
- ObjProcSprWrapDone:
- lda.w ObjEntryYPos,x ;get xy-coordinates
- lsr a ;remove subpixel precision
- lsr a
- lsr a
- lsr a
- sec
- sbc.b ScreenPixelPositionY ;substract screen position to get sprite position on screen. before doing this, we made sure the sprite is actually onscreen.
- sec
- sbc.w ObjEntryYDisplacement,x
- sep #$20
- sta.w OamBuffer & $ffff+1,y ;store x coordinate
- ObjProcDrawConfig:
- ;calculate byte offset in spritesize buffer:
- rep #$31
- ; ldy.b OamBufferPointer ;get pointer to current oam buffer entry
- phx
- phy
- tya
- and.w #$1f0 ;get byte target of size buffer
- lsr a
- lsr a
- lsr a
- lsr a
- sta.b TempBuffer ;this is the 16bit pointer to the current byte in size buffer
- ;calculate bit offset in spritesize buffer:
- tya
- clc
- and.w #$c ;get target bits of size buffer
- lsr a ;shift right twice to get correct jump offset
- tay
- lda.w ObjEntryType,x ;get size/x-sign bits
- tyx
- ldy.b TempBuffer
- and.w #%11
- jmp (ObjectProcessorSizeTableJTbl,x)
-
- ObjectProcessorSizeTableJTbl:
- .dw ObjProcSizeJtblBit0
- .dw ObjProcSizeJtblBit1
- .dw ObjProcSizeJtblBit2
- .dw ObjProcSizeJtblBit3
- ObjProcSizeJtblBit3:
- asl a
- asl a
- ObjProcSizeJtblBit2:
- asl a
- asl a
- ObjProcSizeJtblBit1:
- asl a
- asl a
- ObjProcSizeJtblBit0:
- ora.w OamPriorityBuffer & $ffff,y ;store in corresponding bits/bytes
- sta.w OamPriorityBuffer & $ffff,y ;store in corresponding bits/bytes
-
- ply
- plx
- ; sep #$20
- rep #$31
- lda.w ObjEntryVramTile,x ;starting tile and config
- sta.w OamBuffer & $ffff+2,y ;store tile and config
- iny ;move pointer to next tile
- iny
- iny
- iny
- sty.b OamBufferPointer ;store new buffer to next oam object
-
- rts
- InitOam:
- php
- jsr ClearOamBuffer
- jsr ClearOamPriorityBuffer
- jsr ClearObjectList
-
- sep #$20
- stz.w GravObjectCounter ;reset amount of gravity objects
- stz.b NMIOamUploadFlag ;clear this flag so that oam processor is executed at least once (in case irq oam uploader fucks up)
- .IF DEBUG == 1
- lda.b #1 ;create cpu-usage object in every scene if debug is enabled
- jsr CreateObject
- .endif
- plp
- rts
-
- ClearOamPriorityBuffer:
- php
- rep #$31
- sep #$20
- lda.b #0 ;clear word: $0000
- ldy.w #$20
- ldx.w #OamPriorityBuffer&$ffff
- jsr ClearWRAM
-
- plp
- rts
- /*
- ClearOamPriorityBuffer:
- php
- rep #$31
- lda.w #$0000 ;clear with y-position at line 255
- ldx.w #$0020
- ClearOamPriorityBufferLoop:
- sta.l (OamPriorityBuffer &$ffff + $7e0000-2),x
- dex
- dex
- bne ClearOamPriorityBufferLoop
- plp
- rts
- */
- ClearOamBufferPart:
- /*
- php
- rep #$31
- lda.w #$c900 ;clear with y-position at line 201
- ldx.b OamBufferPointer
- bra ClearOamBufferLoop
- */
- php
- rep #$31
- sep #$20
- lda.b #3 ;clear word: $0000
- ldy.b OamBufferPointer
- beq ClearOamBufferPartNoTrans ;need to do this, else $ffff long transfer occurs
-
- ldx.w #OamBuffer&$ffff
- jsr ClearWRAM
- ClearOamBufferPartNoTrans:
- rep #$31
- stz.b OamBufferPointer
- stz.b OamZsortBufferPointer
- stz.b OamZsortSpriteNumber
- plp
- rts
-
- ClearOamBuffer:
- /*
- php
- rep #$31
- lda.w #$c900 ;clear with y-position at line 201
- ldx.w #$0200
- ClearOamBufferLoop:
- sta.l (OamBuffer &$ffff + $7e0000-2),x
- dex
- dex
- sta.l (OamBuffer &$ffff + $7e0000-2),x
- dex
- dex
- sta.l (OamBuffer &$ffff + $7e0000-2),x
- dex
- dex
- sta.l (OamBuffer &$ffff + $7e0000-2),x
- dex
- dex
- sta.l (OamBuffer &$ffff + $7e0000-2),x
- dex
- dex
- sta.l (OamBuffer &$ffff + $7e0000-2),x
- dex
- dex
- sta.l (OamBuffer &$ffff + $7e0000-2),x
- dex
- dex
- sta.l (OamBuffer &$ffff + $7e0000-2),x
- dex
- dex
- sta.l (OamBuffer &$ffff + $7e0000-2),x
- dex
- dex
- sta.l (OamBuffer &$ffff + $7e0000-2),x
- dex
- dex
- sta.l (OamBuffer &$ffff + $7e0000-2),x
- dex
- dex
- sta.l (OamBuffer &$ffff + $7e0000-2),x
- dex
- dex
- sta.l (OamBuffer &$ffff + $7e0000-2),x
- dex
- dex
- sta.l (OamBuffer &$ffff + $7e0000-2),x
- dex
- dex
- sta.l (OamBuffer &$ffff + $7e0000-2),x
- dex
- dex
- sta.l (OamBuffer &$ffff + $7e0000-2),x
- dex
- dex
- bpl ClearOamBufferLoop
- */
- php
- rep #$31
- sep #$20
- lda.b #3 ;clear word: $0000
- ldy.w #$200
- ldx.w #OamBuffer&$ffff
- jsr ClearWRAM
-
- rep #$31
- stz.b OamBufferPointer
- stz.b OamZsortBufferPointer
- stz.b OamZsortSpriteNumber
- plp
- rts
- ClearColObjList:
- php
- rep #$31
- sep #$20
- lda.b #0 ;clear word: $0000
- ldy.w #ColObjFileSize*32 ;old one was: ldx.w #ColObjFileSize*32-2, maybe -2 needed?
- ldx.w #ColObjList&$ffff
- jsr ClearWRAM
- plp
- rts
- /*
- php
- rep #$31
- lda.w #0 ;clear with y-position at line 201
- ldx.w #ColObjFileSize*32-2
- ClearColObjListLoop:
- sta.l (ColObjList &$ffff + $7e0000-2),x
- dex
- dex
- bne ClearColObjListLoop
- stz.w ColObjListPointer
- plp
- rts
- */
- ClearZBuffer:
- php
- rep #$31
- sep #$20
- lda.b #0 ;clear word: $0000
- ldy.w #OamZSortBufferSize*256
- ldx.w #OamZSortBuffer&$ffff
- jsr ClearWRAM
- plp
- rts
-
- /*
- php
- rep #$31
- lda.w #0 ;clear with y-position at line 201
- ldx.w #OamZSortBufferSize*256
- ClearZBufferLoop:
- sta.l (OamZSortBuffer & $ffff + $7e0000-2),x
- dex
- dex
- bne ClearZBufferLoop
- ; stz.w ColObjListPointer
- plp
- rts
- */
- ClearObjectList:
- php
- rep #$31
- sep #$20
- lda.b #0 ;clear word: $0000
- ldy.w #ObjectFileSize*64
- ldx.w #ObjectList&$ffff
- jsr ClearWRAM
- plp
- rts
- /*
- php
- rep #$31
- lda.w #$0000
- ldx.w #ObjectFileSize*64
- ClearObjectListLoop:
- sta.l (ObjectList &$ffff + $7e0000-2),x
- dex
- dex
- bne ClearObjectListLoop
- plp
- rts
- */
- ;in: a,16bit: type of objects to delete
- ;uses TempBuffer
- ;takes around 11 scanlines
- SeekDeleteObjects:
- php
- rep #$31
- sta.b TempBuffer ;store 16bit compare number
- ldx.w #0
- SeekDeleteObjectsLoop:
- lda.l ObjEntryObjectNumber+$7e0000,x ;get object number
- cmp.b TempBuffer
- bne SeekDeleteObjectsNoMatch
-
- lda.w #0
- sta.l ObjEntryType+$7e0000,x ;delete object if number matches.
- SeekDeleteObjectsNoMatch:
- txa
- clc
- adc.w #ObjectFileSize ;goto next entry
- tax
- cpx.w #ObjectFileSize*64 ;check all 64 entries.
- bne SeekDeleteObjectsLoop
-
- plp
- rts
- ;in: a,16bit: type of object to seek
- ;uses TempBuffer
- ;takes around 11 scanlines max.
- ;searches for first object of selected type.
- ;returns relative pointer to object in x
- ;if object was not found, carry is set
- SeekObject:
- php
- rep #$31
- sta.b TempBuffer ;store 16bit compare number
- ldx.w #0
- SeekObjectLoop:
- lda.l ObjEntryObjectNumber+$7e0000,x ;get object number
- cmp.b TempBuffer
- bne SeekObjectNoMatch
- ;match found:
- plp
- clc
- rts
- SeekObjectNoMatch:
- txa
- clc
- adc.w #ObjectFileSize ;goto next entry
- tax
- cpx.w #ObjectFileSize*64 ;check all 64 entries.
- bne SeekObjectLoop
-
- plp
- sec
- rts
-
- ;same as above, but don't reset pointer into obj list. useful for finding multiple objects of the same type
- SeekObjectContinue:
- php
- rep #$31
- sta.b TempBuffer
- bra SeekObjectLoop
-
-
-
- ObjVectorMoveHandler:
- php
- rep #$31
- sep #$20
- ldx.b ObjectListPointerCurrent
- lda.w ObjEntryVectorSpeed,x
- bmi ObjVectorSpeedMet
- and.b #%111111
- sta.b TempBuffer
- lda.w ObjEntryVectorTarSpeed,x
- pha
- and.b #%111111
- sta.b TempBuffer+1
- pla ;get speed change mode (upper 2 bits) and use it as pointer to jump LUT
- rol a
- rol a
- rol a
- asl a
- rep #$31
- and.w #%110
- phx
- tax
- sep #$20
- jsr (ObjVectorSpeedChangeModeLUT,x)
-
- plx
- sta.b TempBuffer+2 ;store inc/dec value
- ;speed inc/dec
- lda.b TempBuffer+1
- cmp.b TempBuffer ;check if target speed is bigger than actual speed
- bcs ObjVectorTarSpeedBiggerLinear
- ;target speed is lower than actual speed
- lda.b TempBuffer
- sec
- sbc.b TempBuffer+2 ;#%1000 ;decrease speed by one full unit
- cmp.b TempBuffer+1 ;has actual speed become => target?
- bmi ObjVectorTarSpeedMetLin ;has speed wrapped around to $ff? if yes, target has also been reached(only needed if target is smaller than 1.0)
- bcs ObjVectorTarSpeedNotMetLinInc
- ;target speed met:
- bra ObjVectorTarSpeedMetLin
- ;target speed is bigger than actual speed
- ObjVectorTarSpeedBiggerLinear:
- lda.b TempBuffer
- clc
- adc.b TempBuffer+2 ;#%1000 ;increase speed by one full unit
- cmp.b TempBuffer+1 ;has actual speed become => target?
- bcc ObjVectorTarSpeedNotMetLinInc
- ObjVectorTarSpeedMetLin:
- lda.b TempBuffer+1 ;if target speed has been met or exceeded, write target speed into current and set "speed met"-flag.
- and.b #%111111
- ora.b #$80
- ObjVectorTarSpeedNotMetLinInc:
- sta.w ObjEntryVectorSpeed,x
- ObjVectorSpeedMet:
- rep #$31
- ldx.b ObjectListPointerCurrent
- lda.w ObjEntryVectorDir-1,x
- bmi ObjVectorTargetDirMet
- asl a
- asl a
- and.w #%1111110000000000 ;put into high byte
- sta.b TempBuffer
- lda.w ObjEntryVectorTurnSpeed,x ;get subpixel precision, 5bits starting at bit3
- asl a ;put into bits 5-9
- asl a
- and.w #%0000001111100000 ;mask off unwanted stuff
- ora.b TempBuffer
- sta.b TempBuffer
- lda.w ObjEntryVectorTarDir,x
-
- pha
- xba
- asl a
- asl a
- and.w #%1111110000000000 ;put into high byte
- sta.b TempBuffer+2
-
- pla
- lsr a
- lsr a ;get speed change mode (upper 2 bits) and use it as pointer to jump LUT
- lsr a
- lsr a
- lsr a
-
- and.w #%110
- phx
- tax
- jsr (ObjVectorDirChangeModeLUT,x)
- plx
- sta.b TempBuffer+4 ;store inc/dec value
- ; lda.b TempBuffer+1
- ; cmp.b TempBuffer ;check if target speed is bigger than actual speed
- lda.w ObjEntryVectorDir,x
- bit.w #%01000000
- bne ObjVectorRotateClockwise ;bcs ObjVectorTarSpeedBiggerLinear
- ;rotate anti-clockwise to meet target dir
- lda.b TempBuffer ;get current angle
- cmp.b TempBuffer+2 ;is target angle smaller? (=must 0 be crossed to reach target?)
- bcs AntiClockwiseNoZeroCross
- ;must cross 0 to reach target
- sec
- sbc.b TempBuffer+4 ;substract speed value
- bcs AntiClockwiseTargetNotMet ;if 0 wasn't passed, target value couldn't have possibly been reached
- cmp.b TempBuffer+2 ;compare target to new angle
- bcc AntiClockwiseTargetMet ;target met if new angle is smaller than old
- bra AntiClockwiseTargetNotMet
- ObjVectorTargetDirMet:
- jmp ObjVectorTargetDirMetLong
- AntiClockwiseNoZeroCross:
- sec
- sbc.b TempBuffer+4 ;substract speed value
- bcc AntiClockwiseTargetMet ;target met if angle wraps around through 0.
- cmp.b TempBuffer+2 ;compare target to new angle
- bcc AntiClockwiseTargetMet ;target met if new angle is smaller than old
- bra AntiClockwiseTargetNotMet
-
- ObjVectorRotateClockwise:
- ;rotate clockwise to meet target dir
- lda.b TempBuffer ;get current angle
- cmp.b TempBuffer+2 ;is target angle smaller? (=must 0 be crossed to reach target?)
- bcc ClockwiseNoZeroCross
- ;must cross 0 to reach target
- clc
- adc.b TempBuffer+4 ;add speed value
- bcc AntiClockwiseTargetNotMet ;if 0 wasn't passed, target value couldn't have possibly been reached
- cmp.b TempBuffer+2 ;compare target to new angle
- bcs AntiClockwiseTargetMet ;target met if new angle is bigger than old
- bra AntiClockwiseTargetNotMet
-
- ClockwiseNoZeroCross:
- clc
- adc.b TempBuffer+4 ;add speed value
- bcs AntiClockwiseTargetMet ;target met if angle wraps around through 0.
- cmp.b TempBuffer+2 ;compare target to new angle
- bcs AntiClockwiseTargetMet ;target met if new angle is bigger than old
- bra AntiClockwiseTargetNotMet
- AntiClockwiseTargetMet:
- lda.b TempBuffer+2 ;target met, set target without subpixel as new angle
- and.w #%1111110000000000
- lsr a
- lsr a
- ora.w #$8000 ;set "target met" flag
- bra AntiClockwiseTargetWrite
-
- AntiClockwiseTargetNotMet:
- and.w #%1111111111100000 ;angle with subpixel precision
- lsr a
- lsr a
- AntiClockwiseTargetWrite:
- sta.b TempBuffer ;save new angle
- sep #$20
- lda.w ObjEntryVectorDir,x
- and.b #%01000000
- ora.b TempBuffer+1 ;save back new direction
- sta.w ObjEntryVectorDir,x
-
- lda.w ObjEntryVectorTurnSpeed,x
- and.b #%111
- ora.b TempBuffer
- sta.w ObjEntryVectorTurnSpeed,x
- ObjVectorTargetDirMetLong:
- rep #$31 ;get current position in vector angle, 16 max
- lda.w ObjEntryType2,x
- and.w #$f
- sta.b TempBuffer
- lda.w ObjEntryVectorTurnSpeed,x ;get subpixel precision for later usage
- and.w #%111
- sta.b TempBuffer+2
- lda.w ObjEntryVectorSpeed,x
- and.w #%111111
- pha
- lda.w ObjEntryVectorDir,x ;get direction, multiply with 32, add current position in angle
- and.w #%111111
- asl a
- asl a
- asl a
- asl a
- asl a
- adc.b TempBuffer
- clc
- adc.w #VectorAngleCodeLUT
- tax ;source offset
- ldy.w #VectorAngleSMCode&$ffff ;target offset
-
- pla ;get vector speed
- clc
- adc.b TempBuffer+2 ;add sub-pixel buffer
- pha
- and.w #%111
- sta.b TempBuffer+2 ;save back for next frame
-
- pla
- lsr a ;remove sub-pixel precision
- lsr a
- lsr a
- and.w #%111
- pha
- beq VectorAngleNoSpeed ;triggers when vector move distance is lower than 1 and prevents ram thrashing.
-
- dec a ;decrease length by one for mvn
- .db $54 ;MVN
- .db $7e ;destination bank
- .db :VectorAngleCodeLUT+$c0 ;target bank
- lda.w #$6b ;rtl opcode
- sta.w $0,y ;store after sm-code. y conveniently points to the byte after the last one transferred by MVN.
-
- ldx.b ObjectListPointerCurrent
- lda.w ObjEntryYPos,x
- lsr a ;remove subpixel precision
- lsr a
- lsr a
- lsr a
-
- tay
- lda.w ObjEntryXPos,x
- lsr a ;remove subpixel precision
- lsr a
- lsr a
- lsr a
- phx
- tax
- jsl VectorAngleSMCode
-
- txa
- plx
- asl a ;add subpixel precision
- asl a
- asl a
- asl a
- sta.w ObjEntryXPos,x
- tya
- asl a ;add subpixel precision
- asl a
- asl a
- asl a
- sta.w ObjEntryYPos,x
- VectorAngleNoSpeed:
- pla ;update vector angle position
- clc
- adc.b TempBuffer
- and.w #$f
- sta.b TempBuffer
-
- sep #$20
-
- ldx.b ObjectListPointerCurrent
- lda.w ObjEntryType2,x ;update vector angle position
- and.b #%11110000
- ora.b TempBuffer
- sta.w ObjEntryType2,x
-
- lda.w ObjEntryVectorTurnSpeed,x ;update vector speed sub-pixel position
- and.b #%11111000
- ora.b TempBuffer+2
- sta.w ObjEntryVectorTurnSpeed,x
- plp
- rts
- ObjVectorSpeedChangeModeLUT:
- .dw ObjVectorSpeedChangeDirect
- .dw ObjVectorSpeedChangeLinearSlow
- .dw ObjVectorSpeedChangeLinearFast
- .dw ObjVectorSpeedChangeLinearSmooth
-
- ObjVectorSpeedChangeDirect:
- lda.b #$40
- rts
-
- ObjVectorSpeedChangeLinearSlow:
- lda.b #1 ;smallest possible unit, takes 64 frames max to reach target speed
- rts
-
- ObjVectorSpeedChangeLinearFast:
- lda.b #8 ;one full unit, takes 8 frames max to reach target speed
- rts
- ;smooth: divide the difference between target and current speed by two and use that to alter the current speed
- ObjVectorSpeedChangeLinearSmooth:
- lda.b TempBuffer+1
- sec
- sbc.b TempBuffer ;check if target speed is bigger than actual speed
- bcc ObjVectorTarSpeedBiggerSmooth
-
- bra ObjVectorTarSpeedSmooth
- ObjVectorTarSpeedBiggerSmooth:
- lda.b TempBuffer
- sec
- sbc.b TempBuffer+1
- ObjVectorTarSpeedSmooth:
- lsr a
- bne ObjVectorTarSpeedMinOKSmooth
-
- lda.b #1 ;minimum speed: 1
- rts
-
- ObjVectorTarSpeedMinOKSmooth:
- cmp.b #8
- bcc ObjVectorTarSpeedMaxOKSmooth
-
- lda.b #8 ;maximum speed: 8
- ObjVectorTarSpeedMaxOKSmooth:
- rts
-
-
- ObjVectorDirChangeModeLUT:
- .dw ObjVectorDirChangeDirect
- .dw ObjVectorDirChangeLinearSlow
- .dw ObjVectorDirChangeLinearFast
- .dw ObjVectorDirChangeLinearSmooth
-
- ObjVectorDirChangeDirect:
- lda.w #$fc00
- rts
-
- ObjVectorDirChangeLinearSlow:
- lda.w #$20 ;smallest possible unit, takes 64 frames max to reach target speed
- rts
-
- ObjVectorDirChangeLinearFast:
- lda.w #$400 ;one full unit, takes 8 frames max to reach target speed
- rts
- ;smooth: divide the difference between target and current speed by two and use that to alter the current speed
- ObjVectorDirChangeLinearSmooth:
- lda.b TempBuffer+2
- sec
- sbc.b TempBuffer ;check if target speed is bigger than actual speed
- bcc ObjVectorDirTarSpeedBiggerSmooth
-
- bra ObjVectorDirTarSpeedSmooth
- ObjVectorDirTarSpeedBiggerSmooth:
- lda.b TempBuffer
- sec
- sbc.b TempBuffer+2
- ObjVectorDirTarSpeedSmooth:
- lsr a
- cmp.w #$20 ;smaller than minimum speed?
- bcs ObjVectorDirTarSpeedMinOKSmooth
-
- lda.w #$20 ;minimum speed: 1
- rts
-
- ObjVectorDirTarSpeedMinOKSmooth:
- cmp.w #$400
- bcc ObjVectorDirTarSpeedMaxOKSmooth
-
- lda.w #$400 ;maximum speed: 8
- ObjVectorDirTarSpeedMaxOKSmooth:
- rts
-
- OamSubCreateParticles:
- ;create a couple of particles, position and palette same as victim:
- ;input: x=pointer to object that is emitting the particles
- ; a=number to add to the random number(0-3) of particles to generate. (valid ranges:0-3)
- ;modifies:paltemp
- ;calls: createobject (uses TempBuffers), updates random a couple of times
- php
- rep #$31
- phx
- sep #$20
- pha
- lda.b R4
- and.b #%11
- sta.b PalTemp
- pla
- and.b #%11
- clc
- adc.b PalTemp
- beq ParticleCreateExit
- sta.b PalTemp
-
- CreateParticleLoop:
- rep #$31
- lda.w ObjEntryYPos,x
- lsr a ;remove subpixel precision
- lsr a
- lsr a
- lsr a
- lsr a
- lsr a
- lsr a
- and.w #$ff
- xba
- sta.b TempBuffer
-
- lda.w ObjEntryXDisplacement,x
- and.w #$ff
- sta.b TempBuffer+2
- lda.w ObjEntryXPos,x
- lsr a ;remove subpixel precision
- lsr a
- lsr a
- lsr a
- sec
- sbc.w #10
-
- lsr a
- lsr a
- lsr a
- inc a
- and.w #$ff
- ora.b TempBuffer
- tax
- lda.w #54
- jsr CreateObjectPosition
- sep #$20
- plx
- lda.w ObjEntryPalConf,x
- and.b #%1110
- sta.b TempBuffer
- phx
- ldx.b ObjectListPointerCurrent
- lda.w ObjEntryPalConf,x
- and.b #%11110001
- ora.b TempBuffer ;store palette of player for this particle
- sta.w ObjEntryPalConf,x
- jsr Random ;update random numbers so that all particles look different
- jsr Random ;update random numbers so that all particles look different
- dec.b PalTemp
- bne CreateParticleLoop
- ParticleCreateExit:
- plx
- plp
- rts
-
- ObjProcUpdateGravity:
- lda.w ObjEntryLifeCounter,x
- and.w #$ff
- beq ObjProcGravityKill
- dec.w ObjEntryLifeCounter,x ;decrease life counter
- lda.w ObjEntryXSpeed,x ;add speed x-dir
- and.w #$ff
- clc
- adc.w #$ff80 ;align in middle so that x-speed can be both positive and negative
- clc
- adc.w ObjEntryXPos,x
- sta.w ObjEntryXPos,x
-
- lda.w ObjEntryGravity,x
- and.w #$ff
- clc
- adc.w ObjEntryYSpeed,x
- sta.w ObjEntryYSpeed,x
- clc
- adc.w ObjEntryYPos,x
- sta.w ObjEntryYPos,x
- lsr a ;remove subpixel prec.
- lsr a
- lsr a
- lsr a
- cmp.w GravityCutOffYPos ;check if object is too low and should be deleted
- bcs ObjProcGravityKill
- rts
-
- ObjProcGravityKill:
- dec.w GravObjectCounter
- stz.w ObjEntryType,x ;kill object if life is up
- rts
-
-
- ObjectProcessGravObjInc:
- php
- sep #$20
- lda.w GravObjectCounter
- cmp.w MaxGravObjCount ;number bigger than max count?
- bcc ObjectProcessGravObjNoDel
- stz.w ObjEntryType,x ;delete object if count is too high
- stz.w ObjEntryType2,x
- plp
- rts
- ObjectProcessGravObjNoDel:
- inc.w GravObjectCounter
- plp
- rts
-
|