PacManPlus Posted June 2, 2013 Share Posted June 2, 2013 Hi guys: I know some of you are great at reducing the time things take with tricks... I kind of need that help with this routine that runs in VBLANK. As it stands, it takes too long and crashes the game. It is the routine that runs in VBLANK and partially rebuilds the display list with the new locations of 8 sprites. It start with a display list of a character mode (the first 5 bytes) and initializes the 'last dl entry' being set there. It then adds the 8 sprites to the end of whatever display lists it occupies. Each sprite takes up three zones. I'd really like to use this as when it works there is no slow down when all 8 objects are on the screen at the same time. There are three loops: 1) initializes the 'last dl entry' flag to just after the character mode (i.e. first 5 bytes) - 2) Adds the sprites to the end of whatever current zone they occupy - and 3) terminates the display list with $00,$00,$00. Thanks, guys Bob ; UPDATE STAMP INFORMATION FOR NEXT RUN OF KERNAL LOADER LDX #$00 ;FIRST, INITIALIZE THE 'LAST DL ENTRY' TO BE JUST AFTER THE CHARACTER MODE DL LDA #$05 ;THE FIRST 5 BYTES ARE THE CHARACTER MODE DL ENTRIES LOADCLEARLOOP STA LASTDLENTRY,X INX CPX #LASTZONE BMI LOADCLEARLOOP LDX #$00 ;NOW, ADD EACH SPRITE ONLY WHERE THEY ARE ON THE SCREEN LOADSPRITELOOP LDA OTLIST,X ;SKIP SPRITE IF DISABLED (OFFSCREEN) CMP #T_DISABLED BNE LSLSTART JMP LSLNEXT LSLSTART LDA VPLIST,X ;FIRST, GET CURRENT VERTICAL POSITION AND #$0F ;MASK OFFSET STA LDRTEMP6 ;SAVE IT FOR THE OFFSET CLC LDA VZLIST,X ;NEXT PREPARE THE ZONES FOR EACH OF THE THREE SPRITE PARTS AND #$0F STA ZONTEMP0 ADC #$01 AND #$0F STA ZONTEMP1 ADC #$01 AND #$0F STA ZONTEMP2 LDA SHLIST,X ;NOW GET THE HIGH STAMP ADDRESS OFFSET FOR EACH ZONE BMI LSLSHORT ADC LDRTEMP6 ;THIS IS DONE BECAUSE THE SPRITES ABOVE #$8000 ONLY USE TWO ZONES (NOT THREE) LSLSHORT ADC #$10 STA STMTEMP0 ;TOP PART LDA SHLIST,X ADC LDRTEMP6 STA STMTEMP1 ;MIDDLE PART CLC ADC #$F0 ;BOTTOM PART STA STMTEMP2 LDA HPLIST,X ;NOW MODIFY THE HORIZONTAL POSITION TO INCLUDE THE SCROLLING CLC ADC WINDOWOBJADJ ;ADD IN THE SCROLLING ADJUSTMENT IF ANY STA HPLIST,X STA HPOSTEMP LDY ZONTEMP0 ;NOW BUILD THE DL FOR THIS ZONE (PART 1/3) LDA DLLO,Y STA LDRTEMP0 LDA DLHI,Y STA LDRTEMP1 LDA LASTDLENTRY,Y TAY LDA SLLIST,X ;LOW STAMP ADDRESS STA (LDRTEMP0),Y INY LDA #$C0 ;STAMP MODE (NOT CHAR MODE) STA (LDRTEMP0),Y INY LDA STMTEMP0 ;HIGH STAMP ADDRESS WITH OFFSET STA (LDRTEMP0),Y INY LDA LOADPALETTEWIDTH,X ;GET PALETTE AND WIDTH STA (LDRTEMP0),Y INY LDA HPOSTEMP STA (LDRTEMP0),Y INY TYA LDY ZONTEMP0 STA LASTDLENTRY,Y ;STORE THE UPDATED DL POSITION LDY ZONTEMP1 ;NOW BUILD THE DL FOR THIS ZONE (PART 2/3) LDA DLLO,Y STA LDRTEMP0 LDA DLHI,Y STA LDRTEMP1 LDA LASTDLENTRY,Y TAY LDA SLLIST,X ;LOW STAMP ADDRESS STA (LDRTEMP0),Y INY LDA #$C0 ;STAMP MODE (NOT CHAR MODE) STA (LDRTEMP0),Y INY LDA STMTEMP1 ;HIGH STAMP ADDRESS WITH OFFSET STA (LDRTEMP0),Y INY LDA LOADPALETTEWIDTH,X ;GET PALETTE AND WIDTH STA (LDRTEMP0),Y INY LDA HPOSTEMP STA (LDRTEMP0),Y INY TYA LDY ZONTEMP1 STA LASTDLENTRY,Y ;STORE THE UPDATED DL POSITION LDY ZONTEMP2 ;NOW BUILD THE DL FOR THIS ZONE (PART 3/3) LDA DLLO,Y STA LDRTEMP0 LDA DLHI,Y STA LDRTEMP1 LDA LASTDLENTRY,Y TAY LDA SLLIST,X ;LOW STAMP ADDRESS STA (LDRTEMP0),Y INY LDA #$C0 ;STAMP MODE (NOT CHAR MODE) STA (LDRTEMP0),Y INY LDA STMTEMP2 ;HIGH STAMP ADDRESS WITH OFFSET STA (LDRTEMP0),Y INY LDA LOADPALETTEWIDTH,X ;GET PALETTE AND WIDTH STA (LDRTEMP0),Y INY LDA HPOSTEMP STA (LDRTEMP0),Y INY TYA LDY ZONTEMP2 STA LASTDLENTRY,Y ;STORE THE UPDATED DL POSITION LDA HPOSTEMP SEC ;UPDATE THE COLUMN WITH THE SCROLLING SCREEN SBC #LEFTSIDE SBC WINDOWOFFSET LSR LSR LSR STA HCLIST,X LSLNEXT INX CPX #NUMOBJECT BPL LSLDONE JMP LOADSPRITELOOP LSLDONE LDX #$00 ;ADD THE TERMINATING DL ZEROS TO EACH DL LOADTERMINATELOOP LDA DLLO,X ;GET THE DISPLAY LIST ADDRESS STA LDRTEMP0 LDA DLHI,X STA LDRTEMP1 LDY LASTDLENTRY,X ;THE LAST DL ENTRY FOR THIS ZONE LDA #$00 STA (LDRTEMP0),Y ;FORCE THE THREE TERMINATING ZEROS AFTER THIS DL ENTRY INY STA (LDRTEMP0),Y INY STA (LDRTEMP0),Y INX CPX #LASTZONE BMI LOADTERMINATELOOP LDA #$00 ;ALL OF THE OBJECT HAVE BEEN ADJUSTED STA WINDOWOBJADJ ;CLEAR THE SCROLLING ADJUSTMENT VALUE RTS LOADPALETTEWIDTH .byte $1C,$1E,$1E,$1C,$1C,$1C,$1C,$1C ;THERE SHOULD BE #NUMOBJECT ENTRIES HERE Quote Link to comment Share on other sites More sharing options...
Joe Musashi Posted June 2, 2013 Share Posted June 2, 2013 I must confess I haven't wrapped my head around this code , but there are two small things I noticed: It seems loops are counting up. If they would count down instead, then CPX could be saved. (Usually this also has the advantage that depending on how you do this the index is either -1 or 0 at the end, which may have further use.) For example, in the first loop: LDA #$05 LDX #LASTZONE LOADCLEARLOOP STA LASTDLENTRY,X DEX BPL LOADCLEARLOOP In the last loop, LDA #$00 can be hoisted out of the loop body: LDA #$00 LDX #LASTZONE LOADTERMINATELOOP LDY DLLO,X STY LDRTEMP0 LDY DLHI,X STY LDRTEMP1 LDY LASTDLENTRY,X STA (LDRTEMP0),Y INY STA (LDRTEMP0),Y INY STA (LDRTEMP0),Y DEX BPL LOADTERMINATELOOP STA WINDOWOBJADJ ; A still 0 Quote Link to comment Share on other sites More sharing options...
EricBall Posted June 3, 2013 Share Posted June 3, 2013 I'll have to hunt around, but I did some sample DL builder routines - I think they're in my AA blog. But I'll try to look at your code and see if I can make any suggestions. Quote Link to comment Share on other sites More sharing options...
kenfused Posted June 3, 2013 Share Posted June 3, 2013 (edited) I will look more deeply at the code you are using tomorrow when I am home. In my initial Beef Drop DL Builder initially I did... Background DLs were all preinitialized and added to DLL Loop through each zone Skip over background stuff which was preinitialized once Loop through each sprite Add any (and the appropriate part) that should be on this zone End Loop End Loop It worked but it took a lot of cycles. (this is potentially a loop of 8 inside a loop of 24) I think eventually I rewrote it for Beef Drop (and used for b*nQ and I will describe for b*nQ since it was more complicated since sprites could go behind the background, and could be different widths and modes) I kept a table of pointers for each zone. I then needed an array of indexes Intitialize Index for each zone to 0 Loop through each object If it is a behind the playfield object, calculate and update the appropriate 2 or 3 DL entries (using table and index to know where to write) and update indexes EndLoop Loop through each zone and add the playfield entries Loop through each object If it is a foreground object, update the appropriate 2 or 3 DL entries (using table and index to know where to write) and update indexes EndLoop Add terminators. This worked much faster since the loops are not nested. For both, each list was allocated for each line to the maximum size (which I think you also do) which wastes RAM but anything that does not change you only do once and never have to update and the DLL only needs built once and doesn't have to change. For terminating the list it only important that the second byte be a zero (you don't have to waste time writing a zero in the first byte or any other bytes for that display list entry) --Ken Edited June 3, 2013 by kenfused Quote Link to comment Share on other sites More sharing options...
roland p Posted June 3, 2013 Share Posted June 3, 2013 (edited) Does LDRTEMP1 always point to the same page? Edited June 3, 2013 by roland p Quote Link to comment Share on other sites More sharing options...
PacManPlus Posted June 4, 2013 Author Share Posted June 4, 2013 Thanks, guys - I'll try these suggestions and see what happens. @roland p - I see what you're getting at, and I'll see if I can make sure LDRTEMP1 always points to the same page and only set it once. Quote Link to comment Share on other sites More sharing options...
kenfused Posted June 4, 2013 Share Posted June 4, 2013 Looks like it pretty much follows my second algorithm. One thing I would suggest is anything accessed in these loops put into zero page (even the list of last entries) if you can if you are not already doing so. There might be a CLC or two you could knock out if you know the prior add will never leave the carry set (probably not a big savings). Do the display stuff as soon as you can in your VBI if you are doing other stuff. Although as long as you get the DL entries built before the line is displayed you should be ok (although if Maria is really busy it may not leave much time for code to execute once you are on the display screen). You can throw in a background color change at the start and end of the DL building code to see where you are on the screen when it is executing. You should be able to remove these three lines that are struck through. LDY LASTDLENTRY,X ;THE LAST DL ENTRY FOR THIS ZONE LDA #$00 STA (LDRTEMP0),Y ;FORCE THE THREE TERMINATING ZEROS AFTER THIS DL ENTRY INY STA (LDRTEMP0),Y INY STA (LDRTEMP0),Y Quote Link to comment Share on other sites More sharing options...
roland p Posted June 4, 2013 Share Posted June 4, 2013 @roland p - I see what you're getting at, and I'll see if I can make sure LDRTEMP1 always points to the same page and only set it once. If so, maybe you can change the code into: LDY ZONTEMP0 ;NOW BUILD THE DL FOR THIS ZONE (PART 1/3) LDA DLLO,Y CLC ADC LASTDLENTRY,Y TAY LDA SLLIST,X ;LOW STAMP ADDRESS STA SOME_PAGE,Y LDA #$C0 ;STAMP MODE (NOT CHAR MODE) STA SOME_PAGE+1,Y LDA STMTEMP0 ;HIGH STAMP ADDRESS WITH OFFSET STA SOME_PAGE+2,Y LDA LOADPALETTEWIDTH,X ;GET PALETTE AND WIDTH STA SOME_PAGE+3,Y LDA HPOSTEMP STA SOME_PAGE+4,Y INY TYA LDY ZONTEMP0 STA LASTDLENTRY,Y ;STORE THE UPDATED DL POSITION Quote Link to comment Share on other sites More sharing options...
EricBall Posted June 4, 2013 Share Posted June 4, 2013 Any particular reason you're using 5 byte entries instead of 4? That would save you 9 cycles per zone (27 per sprite). I'd also recommend reviewing all of the code & calculations you're doing before the "Now Build the DL" code. Are you actually saving cycles/RAM/code by pre-calculating those values, or could they be done in the zone code? For instance ZONTEMP0/ZONTEMP1/ZONTEMP2 aren't required and can be calculated from VZLIST,X as required. Note: only try to eliminate CLC/SEC after you've finished optimizing everything. And always ask yourself "could C be different than I expect?" for all opcodes which change C. In http://atariage.com/forums/topic/104546-sample-7800-source-code-using-zpx/ I found a slight improvement using (ZP,X) instead of (ZP),Y to build the display lists. Although the store+increment is 12 cycles instead of 7 cycles, there's a savings on the start & end. Quote Link to comment Share on other sites More sharing options...
PacManPlus Posted June 4, 2013 Author Share Posted June 4, 2013 (edited) Thanks guys! OK, some answers: 1) LDRTEMP1 does not always point to the same page; in fact there are 3 different pages possible. 2) I am using 5 bytes headers because there is a Character (Indirect) mode being used, i.e. the first 5 bytes that I am skipping (pre-defined outside of this routine). So, I implemented the decrement mode (instead of increment), the 'only writing the second zero byte' to terminate the list, and the removal of the ZONTEMP variables and computed them on the fly. Let me see if this helps.... I'll report back! Thanks again, Bob EDIT - Actually the ZONTEMP variables are needed, as they are used more than once in the routine and to keep calculating them (instead of saving them) would take up more time. BTW - Ken the call to LOADER is the only thing in my VBI after waiting for VBlank: BOTDLI TYA PHA CLD LDA #BLACK STA BACKGRND LDA #$FF STA KNLTEMP ;SET TOP DLI TO HAPPEN NEXT INC RTLOCAL+1 ;INCREMENT CLOCK BNE DLICONT INC RTLOCAL DLICONT JSR TUNER ;DO TUNES JSR RAND ;UPDATE RANDOM NUMBER JSR SCROLLER ;SCROLL SCREEN IF NECESSARY DLLWAIT BIT MSTAT ;WAIT FOR VBLANK BPL DLLWAIT DLLOTHER JSR LOADER ;LOAD UP NEXT FRAME PLA ;UNSTACK AND LEAVE TAY DLIOUT PLA ;THIS IS WHERE MOST DLIs LEAVE TAX PLA NULLRTI RTI Edited June 5, 2013 by PacManPlus Quote Link to comment Share on other sites More sharing options...
kenfused Posted June 5, 2013 Share Posted June 5, 2013 After switching back to non-character mode, you should be able to use 4 byte headers. Are you triggering the VBI in a DLI after the last zone with stuff on it? Quote Link to comment Share on other sites More sharing options...
PacManPlus Posted June 5, 2013 Author Share Posted June 5, 2013 Really? You can mix 5-byte and 4-byte headers? Never knew that! Yes, the zone after the last displayed zone has the final interrupt. Getting back to the header thing, you can have this?: <(SCRSCOR+$00),$60,>(SCRSCOR+$00),$60+$06,#LEFTSIDE ;SCORE DLIST (WHITE) <(SPRITE1),$20+$04,>(SPRITE1),HPOS <(SPRITE2),$40+$04,>(SPRITE2),HPOS ... $00,$00,$00 Quote Link to comment Share on other sites More sharing options...
kenfused Posted June 5, 2013 Share Posted June 5, 2013 You might have to use a 5 byte header for the first sprite to turn off character mode which might make things a little more complicated. I don't remember 100% without checking but maybe someone will chime in and correct me if I'm wrong. Quote Link to comment Share on other sites More sharing options...
EricBall Posted June 5, 2013 Share Posted June 5, 2013 You need one 5 byte header per frame to set the write mode (doesn't have to be visible) and you need to use 5 byte headers for character / tile strings or 32 byte wide sprites. But for normal sprites you can use 4 byte headers. Quote Link to comment Share on other sites More sharing options...
PacManPlus Posted June 5, 2013 Author Share Posted June 5, 2013 Thanks! My Sprites are 160B (12 color) - does that make a difference? The background (character mode) is the normal 3 color 160A... I have a feeling because of this it might make things more difficult... am I correct? (it's the 'Bentley Bear's Crystal Quest' game) @ken - I'll double-check that most of the variables are in zero page - I do know that the ZONTEMP and the LDRTEMP variables are. But the SLLIST or actually any of the XXLIST variables are not due to their size Thank you all again - I really appreciate the help. Bob Quote Link to comment Share on other sites More sharing options...
kenfused Posted June 5, 2013 Share Posted June 5, 2013 Ah so maybe its writemode that keeps whatever it was last set to until the next zone. If so, and all sprites ate 12 color, you might need the first sprite to use a 5 byte header to change write mode Quote Link to comment Share on other sites More sharing options...
EricBall Posted June 5, 2013 Share Posted June 5, 2013 If you are mixing graphics modes then you will need to use 5 byte entries to change between each mode. It's probably not worth the effort to only use 5 byte entries when absolutely required. Quote Link to comment Share on other sites More sharing options...
PacManPlus Posted June 6, 2013 Author Share Posted June 6, 2013 Just tried the 4-byte header thing (made a dummy sprite 1 byte width to change the write mode). The routine got farther, but still crashed. Back to square 1 ... (BTW, I am also trying to figure this one out myself) Thanks, Bob Quote Link to comment Share on other sites More sharing options...
kenfused Posted June 6, 2013 Share Posted June 6, 2013 (edited) you said you were doing a wait for vertical blank in the vbi routine... Place the DLI that triggers it on the first blank line at the bottom and not on the last blank line (if you are not already doing so). The wait-for-vertical-blank should not be necessary.\ These assume the DLL and the blank line DL entries at the bottom do not change which I don't think you change them. --Ken Edited June 6, 2013 by kenfused Quote Link to comment Share on other sites More sharing options...
PacManPlus Posted June 6, 2013 Author Share Posted June 6, 2013 (edited) Ok, so if I have this: .byte $0F,>(NULDLST),<(NULDLST) ;16 BLANK LINES .byte $07,>(NULDLST),<(NULDLST) ;8 BLANK LINES .byte $C6,>(SCDLIST),<(SCDLIST) ;SCORE ZONE - 7 LINES - FIRST INTERRUPT .byte $07,>(INDLIST),<(INDLIST) ;INDICATOR ZONE - 8 LINES .byte $01,>(NULDLST),<(NULDLST) ;2 BLANK LINES .byte $CF,>(DLIST01),<(DLIST01) ;PF ZONE 01 - 15 LINES .byte $CF,>(DLIST02),<(DLIST02) ;PF ZONE 02 - 16 LINES .byte $CF,>(DLIST03),<(DLIST03) ;PF ZONE 03 - 16 LINES .byte $CF,>(DLIST04),<(DLIST04) ;PF ZONE 04 - 16 LINES .byte $CF,>(DLIST05),<(DLIST05) ;PF ZONE 05 - 16 LINES .byte $CF,>(DLIST06),<(DLIST06) ;PF ZONE 06 - 16 LINES .byte $CF,>(DLIST07),<(DLIST07) ;PF ZONE 07 - 16 LINES .byte $CF,>(DLIST08),<(DLIST08) ;PF ZONE 08 - 16 LINES .byte $CF,>(DLIST09),<(DLIST09) ;PF ZONE 09 - 16 LINES .byte $CF,>(DLIST10),<(DLIST10) ;PF ZONE 10 - 16 LINES .byte $CF,>(DLIST11),<(DLIST11) ;PF ZONE 11 - 16 LINES .byte $8F,>(NULDLST),<(NULDLST) ;16 BLANK LINES - FINAL INTERRUPT .byte $09,>(NULDLST),<(NULDLST) ;10 BLANK LINES I don't need the BIT MSTAT ;WAIT FOR VBLANK BPL DLLWAIT in the BOTDLI routine above? Wow - I've done this (and the 5-byte header for all objects) in all of my games... I'll give that a try... Thanks! Bob BTW, There's an interrupt on every displayed zone because I am changing colors when necessary. EDIT - I tried this, but now the music suddenly stops, and I have Display List corruption (which is what happened when I originally put the 'Loader' routine call before the wait for VBlank instead of after.) Damn. Edited June 6, 2013 by PacManPlus Quote Link to comment Share on other sites More sharing options...
kenfused Posted June 6, 2013 Share Posted June 6, 2013 Does it do the same thing if you move it down to the next blank entry but leave the wait out. Maybe also add a store to waitsync at the start of the routine Quote Link to comment Share on other sites More sharing options...
PacManPlus Posted June 6, 2013 Author Share Posted June 6, 2013 Sorry Ken - with my 'EDIT' above, I had meant that I did try it without the 'wait' for VB on the line in the DLL after DLIST11. I will try moving it down one, and put a STA WSYNC to see if it helps any. Thanks! Quote Link to comment Share on other sites More sharing options...
EricBall Posted June 6, 2013 Share Posted June 6, 2013 I usually advised against mixing STA WSYNC and DLI as STA WSYNC pauses the CPU, which may cause it to miss the DLI interrupt (or at least delay it to the start of the next line). Quote Link to comment Share on other sites More sharing options...
kenfused Posted June 6, 2013 Share Posted June 6, 2013 (edited) I usually advised against mixing STA WSYNC and DLI as STA WSYNC pauses the CPU, which may cause it to miss the DLI interrupt (or at least delay it to the start of the next line). He would be using STA WSYNC within the DLI. I don't think it would be necessary but didn't know if there would be some slight jitter to when the vbi routine starts each time. Outside the DLI I know it could be problematic. IIRC, on the Atari 400/800s the keyclick routine used it which could cause DLI issues. Edited June 6, 2013 by kenfused Quote Link to comment Share on other sites More sharing options...
PacManPlus Posted June 9, 2013 Author Share Posted June 9, 2013 Hi Guys! I think I found something that works, although it uses quite a bit of ROM space. I had to comment a lot of sound data out just to test this idea I had to see if it works. It seems to run without crashing. Please note, that the 'INSERTSPRITE2' routine is commented out because I am using the 'INSERTSPRITE3' routine to test instead: *NOTE - It sucks that the 'CODE' tags don't include tabs, which is why nothing is indented here. It is in the source code file LOADER LDX #LASTZONE - 1 ;FIRST, INITIALIZE THE 'LAST DL ENTRY' TO BE JUST AFTER THE CHARACTER MODE DL LDA #$0A ;THE FIRST 5 BYTES ARE THE CHARACTER MODE DL ENTRIES LOADCLEARLOOP STA LASTDLENTRY,X DEX BPL LOADCLEARLOOP LDX #$00 ;NOW, ADD EACH SPRITE ONLY WHERE THEY ARE ON THE SCREEN LOADSPRITELOOP LDA OTLIST,X ;SKIP SPRITE IF DISABLED (OFFSCREEN) CMP #T_DISABLED BEQ LSLNEXT LDA HPLIST,X ;NOW MODIFY THE HORIZONTAL POSITION TO INCLUDE THE SCROLLING CLC ADC WINDOWOBJADJ ;ADD IN THE SCROLLING ADJUSTMENT IF ANY STA HPLIST,X STA HPOSTEMP LDA VPLIST,X ;GET VERTICAL POSITION OFFSET AND #$0F CLC ADC SHLIST,X ;HIGH STAMP ADDRESS WITH OFFSET STA LDRTEMP1 ;'MIDDLE' PART OF STAMP (OR TOP OF 2 ZONE HIGH STAMP) ADC #$10 STA LDRTEMP0 ;'TOP' PART OF STAMP ADC #$E0 STA LDRTEMP2 ;'BOTTOM' PART OF STAMP LDA SHLIST,X BMI LSLSHORT ;GRAPHICS DATA WHICH START > $8000 ARE ONLY 2 ZONES HIGH INSTEAD OF 3 LDA VZLIST,X JSR INSERTSPRITE3 ;INSERT THE SPRITE IN THE DISPLAY LIST JMP LSLNEXT LSLSHORT LDA VZLIST,X JSR INSERTSPRITE2 LSLNEXT LDA HPOSTEMP SEC ;UPDATE THE COLUMN WITH THE SCROLLING SCREEN SBC #LEFTSIDE SBC WINDOWOFFSET LSR LSR LSR STA HCLIST,X INX CPX #NUMOBJECT BMI LOADSPRITELOOP LDA #$00 ;ADD THE TERMINATING DL ZEROS TO EACH DL LDX #LASTZONE - 1 LOADTERMINATELOOP LDA DLLO,X ;GET THE DISPLAY LIST ADDRESS STA LDRTEMP0 LDA DLHI,X STA LDRTEMP1 LDY LASTDLENTRY,X ;THE LAST DL ENTRY FOR THIS ZONE LDA #$00 INY STA (LDRTEMP0),Y ;FORCE THE THREE TERMINATING ZEROS AFTER THIS DL ENTRY (ONLY ONE ZERO IS NEEDED) DEX BPL LOADTERMINATELOOP STA WINDOWOBJADJ ;CLEAR THE SCROLLING ADJUSTMENT VALUE RTS ; INSERTSPRITE3 - JUMPS TO A ROUTINE THAT PUTS THE 3 ZONE SPRITE IN THE CORRECT DL INSERTSPRITE3 JSR JMPENGINE .word IS3ZONE01 .word IS3ZONE02 .word IS3ZONE03 .word IS3ZONE04 .word IS3ZONE05 .word IS3ZONE06 .word IS3ZONE07 .word IS3ZONE08 .word IS3ZONE09 .word IS3ZONE10 .word IS3ZONE11 .word ISRTS .word ISRTS .word ISRTS .word IS3ZONE15 .word IS3ZONE16 ; INSERTSPRITE2 - JUMPS TO A ROUTINE THAT PUTS THE 2 ZONE SPRITE IN THE CORRECT DL INSERTSPRITE2 JSR JMPENGINE .word IS2ZONE01 .word IS2ZONE02 .word IS2ZONE03 .word IS2ZONE04 .word IS2ZONE05 .word IS2ZONE06 .word IS2ZONE07 .word IS2ZONE08 .word IS2ZONE09 .word IS2ZONE10 .word ISRTS .word ISRTS .word ISRTS .word ISRTS .word IS2ZONE15 .word IS2ZONE16 ISRTS RTS ; 3-ZONE SPRITE INSERT IS3ZONE01 LDA LDRTEMP0 JSR INSERTSPRITEZONE1 ;DO TOP OF SPRITE LDA LDRTEMP1 JSR INSERTSPRITEZONE2 ;DO MIDDLE OF SPRITE LDA LDRTEMP2 JMP INSERTSPRITEZONE3 ;DO BOTTOM OF SPRITE IS3ZONE02 LDA LDRTEMP0 JSR INSERTSPRITEZONE2 ;DO TOP OF SPRITE LDA LDRTEMP1 JSR INSERTSPRITEZONE3 ;DO MIDDLE OF SPRITE LDA LDRTEMP2 JMP INSERTSPRITEZONE4 ;DO BOTTOM OF SPRITE IS3ZONE03 LDA LDRTEMP0 JSR INSERTSPRITEZONE3 ;DO TOP OF SPRITE LDA LDRTEMP1 JSR INSERTSPRITEZONE4 ;DO MIDDLE OF SPRITE LDA LDRTEMP2 JMP INSERTSPRITEZONE5 ;DO BOTTOM OF SPRITE IS3ZONE04 LDA LDRTEMP0 JSR INSERTSPRITEZONE4 ;DO TOP OF SPRITE LDA LDRTEMP1 JSR INSERTSPRITEZONE5 ;DO MIDDLE OF SPRITE LDA LDRTEMP2 JMP INSERTSPRITEZONE6 ;DO BOTTOM OF SPRITE IS3ZONE05 LDA LDRTEMP0 JSR INSERTSPRITEZONE5 ;DO TOP OF SPRITE LDA LDRTEMP1 JSR INSERTSPRITEZONE6 ;DO MIDDLE OF SPRITE LDA LDRTEMP2 JMP INSERTSPRITEZONE7 ;DO BOTTOM OF SPRITE IS3ZONE06 LDA LDRTEMP0 JSR INSERTSPRITEZONE6 ;DO TOP OF SPRITE LDA LDRTEMP1 JSR INSERTSPRITEZONE7 ;DO MIDDLE OF SPRITE LDA LDRTEMP2 JMP INSERTSPRITEZONE8 ;DO BOTTOM OF SPRITE IS3ZONE07 LDA LDRTEMP0 JSR INSERTSPRITEZONE7 ;DO TOP OF SPRITE LDA LDRTEMP1 JSR INSERTSPRITEZONE8 ;DO MIDDLE OF SPRITE LDA LDRTEMP2 JMP INSERTSPRITEZONE9 ;DO BOTTOM OF SPRITE IS3ZONE08 LDA LDRTEMP0 JSR INSERTSPRITEZONE8 ;DO TOP OF SPRITE LDA LDRTEMP1 JSR INSERTSPRITEZONE9 ;DO MIDDLE OF SPRITE LDA LDRTEMP2 JMP INSERTSPRITEZONE10 ;DO BOTTOM OF SPRITE IS3ZONE09 LDA LDRTEMP0 JSR INSERTSPRITEZONE9 ;DO TOP OF SPRITE LDA LDRTEMP1 JSR INSERTSPRITEZONE10 ;DO MIDDLE OF SPRITE LDA LDRTEMP2 JMP INSERTSPRITEZONE11 ;DO BOTTOM OF SPRITE IS3ZONE10 LDA LDRTEMP0 JSR INSERTSPRITEZONE10 ;DO TOP OF SPRITE LDA LDRTEMP1 JMP INSERTSPRITEZONE11 ;DO MIDDLE OF SPRITE IS3ZONE11 LDA LDRTEMP0 JMP INSERTSPRITEZONE11 ;DO TOP OF SPRITE IS3ZONE15 LDA LDRTEMP2 JMP INSERTSPRITEZONE1 ;DO BOTTOM OF SPRITE IS3ZONE16 LDA LDRTEMP1 JSR INSERTSPRITEZONE1 ;DO MIDDLE OF SPRITE LDA LDRTEMP2 JMP INSERTSPRITEZONE2 ;DO BOTTOM OF SPRITE ; TWO-ZONE SPRITE INSERT IS2ZONE01 LDA LDRTEMP1 JSR INSERTSPRITEZONE2 ;DO MIDDLE OF SPRITE LDA LDRTEMP2 JMP INSERTSPRITEZONE3 ;DO BOTTOM OF SPRITE IS2ZONE02 LDA LDRTEMP1 JSR INSERTSPRITEZONE3 ;DO MIDDLE OF SPRITE LDA LDRTEMP2 JMP INSERTSPRITEZONE4 ;DO BOTTOM OF SPRITE IS2ZONE03 LDA LDRTEMP1 JSR INSERTSPRITEZONE4 ;DO MIDDLE OF SPRITE LDA LDRTEMP2 JMP INSERTSPRITEZONE5 ;DO BOTTOM OF SPRITE IS2ZONE04 LDA LDRTEMP1 JSR INSERTSPRITEZONE5 ;DO MIDDLE OF SPRITE LDA LDRTEMP2 JMP INSERTSPRITEZONE6 ;DO BOTTOM OF SPRITE IS2ZONE05 LDA LDRTEMP1 JSR INSERTSPRITEZONE6 ;DO MIDDLE OF SPRITE LDA LDRTEMP2 JMP INSERTSPRITEZONE7 ;DO BOTTOM OF SPRITE IS2ZONE06 LDA LDRTEMP1 JSR INSERTSPRITEZONE7 ;DO MIDDLE OF SPRITE LDA LDRTEMP2 JMP INSERTSPRITEZONE8 ;DO BOTTOM OF SPRITE IS2ZONE07 LDA LDRTEMP1 JSR INSERTSPRITEZONE8 ;DO MIDDLE OF SPRITE LDA LDRTEMP2 JMP INSERTSPRITEZONE9 ;DO BOTTOM OF SPRITE IS2ZONE08 LDA LDRTEMP1 JSR INSERTSPRITEZONE9 ;DO MIDDLE OF SPRITE LDA LDRTEMP2 JMP INSERTSPRITEZONE10 ;DO BOTTOM OF SPRITE IS2ZONE09 LDA LDRTEMP1 JSR INSERTSPRITEZONE10 ;DO MIDDLE OF SPRITE LDA LDRTEMP2 JMP INSERTSPRITEZONE11 ;DO BOTTOM OF SPRITE IS2ZONE10 LDA LDRTEMP1 JMP INSERTSPRITEZONE11 ;DO MIDDLE OF SPRITE IS2ZONE15 LDA LDRTEMP2 JMP INSERTSPRITEZONE1 ;DO TOP OF SPRITE IS2ZONE16 LDA LDRTEMP1 JSR INSERTSPRITEZONE1 ;DO MIDDLE OF SPRITE LDA LDRTEMP2 JMP INSERTSPRITEZONE2 ;DO BOTTOM OF SPRITE INSERTSPRITEZONE1 LDY LASTDLENTRY+$00 STA DLIST01+$02,Y ;SAVE HIGH STAMP ADDRESS WITH OFFSET FIRST LDA SLLIST,X ;LOW STAMP ADDRESS STA DLIST01,Y INY LDA LOADPALETTEWIDTH,X ;GET PALETTE AND WIDTH STA DLIST01,Y INY INY LDA HPOSTEMP ;HORIZONTAL POSITION WITH SCROLL OFFSET STA DLIST01,Y INY STY LASTDLENTRY+$00 ;TERMINATOR RTS INSERTSPRITEZONE2 LDY LASTDLENTRY+$01 STA DLIST02+$02,Y ;SAVE HIGH STAMP ADDRESS WITH OFFSET FIRST LDA SLLIST,X ;LOW STAMP ADDRESS STA DLIST02,Y INY LDA LOADPALETTEWIDTH,X ;GET PALETTE AND WIDTH STA DLIST02,Y INY INY LDA HPOSTEMP ;HORIZONTAL POSITION WITH SCROLL OFFSET STA DLIST02,Y INY STY LASTDLENTRY+$01 ;TERMINATOR RTS INSERTSPRITEZONE3 LDY LASTDLENTRY+$02 STA DLIST03+$02,Y ;SAVE HIGH STAMP ADDRESS WITH OFFSET FIRST LDA SLLIST,X ;LOW STAMP ADDRESS STA DLIST03,Y INY LDA LOADPALETTEWIDTH,X ;GET PALETTE AND WIDTH STA DLIST03,Y INY INY LDA HPOSTEMP ;HORIZONTAL POSITION WITH SCROLL OFFSET STA DLIST03,Y INY STY LASTDLENTRY+$02 ;TERMINATOR RTS INSERTSPRITEZONE4 LDY LASTDLENTRY+$03 STA DLIST04+$02,Y ;SAVE HIGH STAMP ADDRESS WITH OFFSET FIRST LDA SLLIST,X ;LOW STAMP ADDRESS STA DLIST04,Y INY LDA LOADPALETTEWIDTH,X ;GET PALETTE AND WIDTH STA DLIST04,Y INY INY LDA HPOSTEMP ;HORIZONTAL POSITION WITH SCROLL OFFSET STA DLIST04,Y INY STY LASTDLENTRY+$03 ;TERMINATOR RTS INSERTSPRITEZONE5 LDY LASTDLENTRY+$04 STA DLIST05+$02,Y ;SAVE HIGH STAMP ADDRESS WITH OFFSET FIRST LDA SLLIST,X ;LOW STAMP ADDRESS STA DLIST05,Y INY LDA LOADPALETTEWIDTH,X ;GET PALETTE AND WIDTH STA DLIST05,Y INY INY LDA HPOSTEMP ;HORIZONTAL POSITION WITH SCROLL OFFSET STA DLIST05,Y INY STY LASTDLENTRY+$04 ;TERMINATOR RTS INSERTSPRITEZONE6 LDY LASTDLENTRY+$05 STA DLIST06+$02,Y ;SAVE HIGH STAMP ADDRESS WITH OFFSET FIRST LDA SLLIST,X ;LOW STAMP ADDRESS STA DLIST06,Y INY LDA LOADPALETTEWIDTH,X ;GET PALETTE AND WIDTH STA DLIST06,Y INY INY LDA HPOSTEMP ;HORIZONTAL POSITION WITH SCROLL OFFSET STA DLIST06,Y INY STY LASTDLENTRY+$05 ;TERMINATOR RTS INSERTSPRITEZONE7 LDY LASTDLENTRY+$06 STA DLIST07+$02,Y ;SAVE HIGH STAMP ADDRESS WITH OFFSET FIRST LDA SLLIST,X ;LOW STAMP ADDRESS STA DLIST07,Y INY LDA LOADPALETTEWIDTH,X ;GET PALETTE AND WIDTH STA DLIST07,Y INY INY LDA HPOSTEMP ;HORIZONTAL POSITION WITH SCROLL OFFSET STA DLIST07,Y INY STY LASTDLENTRY+$06 ;TERMINATOR RTS INSERTSPRITEZONE8 LDY LASTDLENTRY+$07 STA DLIST08+$02,Y ;SAVE HIGH STAMP ADDRESS WITH OFFSET FIRST LDA SLLIST,X ;LOW STAMP ADDRESS STA DLIST08,Y INY LDA LOADPALETTEWIDTH,X ;GET PALETTE AND WIDTH STA DLIST08,Y INY INY LDA HPOSTEMP ;HORIZONTAL POSITION WITH SCROLL OFFSET STA DLIST08,Y INY STY LASTDLENTRY+$07 ;TERMINATOR RTS INSERTSPRITEZONE9 LDY LASTDLENTRY+$08 STA DLIST09+$02,Y ;SAVE HIGH STAMP ADDRESS WITH OFFSET FIRST LDA SLLIST,X ;LOW STAMP ADDRESS STA DLIST09,Y INY LDA LOADPALETTEWIDTH,X ;GET PALETTE AND WIDTH STA DLIST09,Y INY INY LDA HPOSTEMP ;HORIZONTAL POSITION WITH SCROLL OFFSET STA DLIST09,Y INY STY LASTDLENTRY+$08 ;TERMINATOR RTS INSERTSPRITEZONE10 LDY LASTDLENTRY+$09 STA DLIST10+$02,Y ;SAVE HIGH STAMP ADDRESS WITH OFFSET FIRST LDA SLLIST,X ;LOW STAMP ADDRESS STA DLIST10,Y INY LDA LOADPALETTEWIDTH,X ;GET PALETTE AND WIDTH STA DLIST10,Y INY INY LDA HPOSTEMP ;HORIZONTAL POSITION WITH SCROLL OFFSET STA DLIST10,Y INY STY LASTDLENTRY+$09 ;TERMINATOR RTS INSERTSPRITEZONE11 LDY LASTDLENTRY+$0A STA DLIST11+$02,Y ;SAVE HIGH STAMP ADDRESS WITH OFFSET FIRST LDA SLLIST,X ;LOW STAMP ADDRESS STA DLIST11,Y INY LDA LOADPALETTEWIDTH,X ;GET PALETTE AND WIDTH STA DLIST11,Y INY INY LDA HPOSTEMP ;HORIZONTAL POSITION WITH SCROLL OFFSET STA DLIST11,Y INY STY LASTDLENTRY+$0A ;TERMINATOR RTS LOADPALETTEWIDTH .byte $1C,$1E,$1E,$1C,$1C,$1C,$1C,$1C ;THERE SHOULD BE #NUMOBJECT ENTRIES HERE ... and here is the 'JMPROUTINE' that is being referred to: ; JMPENGINE - DOES A CONDITIONAL JUMP DEPENDING ON THE VALUE OF 'A' ; ($00 = ROUTINE0, $01 = ROUTINE1, $02 = ROUTINE2...) ; INPUT: JMPLO - ADDRESS LOW TO JUMP ADDRESS, ; JMPHI - ADDRESS HIGH TO JUMP ADDRESS, ; JMPTOLO - JUMP ADDRESS LOW ; JMPTOHI - JUMP ADDRESS HIGH ; USES: A, Y ; ; ; USAGE: ; JSR JMPENGINE ; ; .word ROUTINE0 ; .word ROUTINE1 ; .word ROUTINE2 ; .word ROUTINE3 JMPENGINE ASL ;SHIFT BIT FROM CONTANTS OF A TAY PLA ;PULL SAVED RETURN ADDRESS FROM STACK STA JMPLO ;SAVE TO INDIRECT PLA STA JMPHI INY LDA (JMPLO),Y ;LOAD POINTER FROM INDIRECT STA JMPTOLO ;NOTE THAT IF AN RTS IS PERFORMED IN THE NEXT ROUTINE INY ; IT WILL RETURN TO THE EXECUTION BEFORE THE SUB LDA (JMPLO),Y ; THAT CALLED THIS ROUTINE STA JMPTOHI JMP (JMPTOLO) ;JUMP TO THE ADDRESS WE LOADED I'm going to have to put this code in each bank somehow (I'll have to use some of the space reserved for sound data) because it won't fit in the fixed bank in the ROM. Bob Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.