TGB1718 Posted September 13, 2022 Share Posted September 13, 2022 Not my best piece of code, but this is a DLI that moves all 4 players horizontally and uses a switch to decide which player to move this DLI. All new positions are calculated during the VBI and populate a lookup table. Once a DLI has been processed, it sets the flag for the next DLI to process the next player. This is only used in a demo written in MADS Assembler PDL .MACRO A B C D E F G LDX :A INC :A LDA :B,X STA WSYNC STA :C LDA :D,X STA :E LDA #:G STA :F PLA TAX PLA RTI .ENDM ; MULTI DLI'S ; DLI, ONE FOR EACH PLAYER DLI PHA TXA PHA LDA WHICHDL .IF .DEF DEBUG BMI Q3 BEQ P0 BNE Q1 .ELSE BMI P3 ; = $FF BEQ P0 ; = 0 BNE P1 ; =1 OR =2 .ENDIF .IF .DEF DEBUG Q3 LDA #0 STA WHICHDL MM PLA TAX PLA RTI Q1 CMP #2 BEQ Q2 LDA #2 STA WHICHDL JMP MM Q2 LDA #$FF STA WHICHDL JMP MM .ENDIF P0 INC MYCOL LDX DLIINDEX INC DLIINDEX LDA HP00,X STA HPOSP0 LDA PLAYCOLOR,X STA COLPM0 LDA MYCOL STA WSYNC STA COLPF2 STA COLBK LDA #1 STA WHICHDL PLA TAX PLA RTI P1 CMP #2 ; have to do check here as flag is either 1, 2, $FF or 0 BEQ P2 PDL DLIINDEX+1,HP01,HPOSP1,PLAYCOLOR1,COLPM1,WHICHDL,$02 P2 PDL DLIINDEX+2,HP02,HPOSP2,PLAYCOLOR2,COLPM2,WHICHDL,$FF P3 PDL DLIINDEX+3,HP03,HPOSP3,PLAYCOLOR3,COLPM3,WHICHDL,0 Quote Link to comment Share on other sites More sharing options...
TracMan Posted September 21, 2022 Share Posted September 21, 2022 (edited) There are shortcuts in programming DLIs, using the stack to push the registers onto and restore them at the end of the interrupt is often too slow in real world DLIs. Advanced programmers use free zero page locations to cache the registers A, X and Y (it's safe to use $80-FF out the box) because the number of cycles are less. See useful guide below for cycles used: http://www.6502.org/tutorials/6502opcodes.html Each PHA + PLA = 4 cycles each = 8 cycles, whereas STA <ZP location> and LDA <ZP location> are 6 cycles between them. As for the original question about changing the colours on every mode line, some of the terminology was a bit mixed up in the first answer, the display list you would want is pretty much just a copy of the exact same mode display list that Basic uses (without the text window), but with the interrupt bit set (bit 7 or +128) on each character line BEFORE you want the colour change (or as someone mentioned on each 8th line in a bitmap mode). For the top line, you can add the interrupt bit on the blank lines or LMS lines, beginners forget this sometimes. When an interrupt occurs, depending on the mode, the beam can be still some way off the edge of the right hand side of the screen. A bitmap mode can be way better to use than a character graphics mode in the cases when you want to do a lot (especially multiplex PMGs) because you have more CPU cycles to make the changes seamless to the user (you just lose the benefits of character graphics and the 5th colour which frustrates inexperienced programmers). In a character graphics mode like Mode 4, the Antic chip has to read the screen memory and go off indirectly to read all the values from the character set to draw, unlike just reading the memory for the bitmap mode so it actually reduces the CPU cycles available for your DLI. Note: in Antic 4, additionally the HW register CHBASE is also reread every line, so you can also easily change character sets which can be very useful for games. In an interrupt, you should actually avoid the STA WSYNC for as long as you can and in some cases, you can avoid it altogether (as when you do it the Antic chip halts the CPU via the interrupt line until the beam is at the left edge). To do many changes, you should load up the registers with 3 of the colours or other HW register changes and use the ZP locations as I mentioned above, to reduce used cycles. Example below: ; Equates SAVEA=$80 SAVEX=$81 SAVEY=$82 SOMEDLI ; Save registers. STX SAVEX STY SAVEY STA SAVEA LDX #100 ; Colour 1 LDA #48 ; Colour 2 LDY #14 ; Colour 3 STA WSYNC STA <HW REG 1> STX <HW REG 2> STY <HW REG 3> ; Restore registers. LDX SAVEX LDY SAVEY LDA SAVEA ; Exit interrupt RTI As to whether you can get more changes in, remember you are only making delta changes for each line, as sometimes one of the colours that you want was in the previous set. You don't have to do all the changes on the interrupt in one line. Try and work out how the colours will be used on the line, if near the end of the line there is only one or two colours with say two other colours not being on the screen, then you can also do the work in the initial cycles before the STA WSYNC as above where you stored the registers. No one will see them as the Antic chip has finished reading from RAM and the HW registers (DMA access) and the CPU can do it's bit ready for the following lines. Similarly, if certain colours aren't used until a bit into the left of the screen on the next change, you can change them well AFTER the STA WSYNC without any issue. You only lock up the CPU in the available time between the beam reaching the end of the previous line on it's own and the STA WSYNC. Even more advanced, if you think about it is that you can even avoid the STA WSYNC altogether as it's unnecessary when you cycle count your code and the CPU execution time is enough for the beam to have already reached the beginning of the next line. Edited September 21, 2022 by TracMan 2 Quote Link to comment Share on other sites More sharing options...
Rybags Posted September 22, 2022 Share Posted September 22, 2022 (edited) You can also do self-modifying code to save registers, e.g. near the end LDA #$FF / LDY #$FF and just store into those operands at the beginning. For absolutely critical stuff you can save more cycles by having program code in zero-page. But self-modifying code is generally not good if the routine has to be reentrant, ie potential for it to run again before the first iteration has finished. Edited September 22, 2022 by Rybags Quote Link to comment Share on other sites More sharing options...
MaPa Posted September 25, 2022 Share Posted September 25, 2022 On 9/21/2022 at 11:23 PM, TracMan said: Each PHA + PLA = 4 cycles each = 8 cycles, whereas STA <ZP location> and LDA <ZP location> are 6 cycles between them. PHA is 3 cycles but still you save 1 cycle on accumulator and more on X,Y registers due to TAX, TYA etc. 1 Quote Link to comment Share on other sites More sharing options...
xxl Posted September 25, 2022 Share Posted September 25, 2022 On 9/21/2022 at 11:23 PM, TracMan said: SOMEDLI ; Save registers. STX SAVEX STY SAVEY STA SAVEA LDX #100 ; Colour 1 LDA #48 ; Colour 2 LDY #14 ; Colour 3 STA WSYNC STA <HW REG 1> STX <HW REG 2> STY <HW REG 3> ; Restore registers. LDX SAVEX LDY SAVEY LDA SAVEA ; Exit interrupt RTI waste of space. you just need something like this and there will be some time available anyway, so you can use any other addressing mode you want: pla lda #color1 sta wsync sta hwreg1 lda #color2 sta hwreg2 lda #color3 sta hwreg3 pla rti (you won't notice the difference on the screen) Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted September 25, 2022 Share Posted September 25, 2022 (edited) Not necessarily. There are occasions when several registers are being written to and the timing between hitting WSYNC and getting those registers written and then getting back out of the NMI is critical enough that pre-loading index registers is the only reasonable way to avoid artifacts and glitches. Edited September 25, 2022 by flashjazzcat 1 Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted September 25, 2022 Share Posted September 25, 2022 42 minutes ago, xxl said: (you won't notice the difference on the screen) I think you will, PLA . . . PLA RTI looks like an imminent crash to me 1 Quote Link to comment Share on other sites More sharing options...
xxl Posted September 25, 2022 Share Posted September 25, 2022 (edited) 1 hour ago, TGB1718 said: I think you will, PLA . . . PLA RTI looks like an imminent crash to me 🙂 true 🙂 it's supposed to be PHA, I wrote it in the toilet 1 hour ago, flashjazzcat said: Not necessarily. There are occasions when several registers are being written to and the timing between hitting WSYNC and getting those registers written and then getting back out of the NMI is critical enough that pre-loading index registers is the only reasonable way to avoid artifacts and glitches. even in the $ 0F mode and for the standard screen width, there are still 4 cpu cycles of reserve. besides, it's best to check and choose the optimal method Edited September 25, 2022 by xxl Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted September 25, 2022 Share Posted September 25, 2022 11 minutes ago, xxl said: even in the $ 0F mode and for the standard screen width, there are still 4 cpu cycles of reserve. Not if you want to write to more than three registers (the 'many changes' which TracMan directly references when presenting his method). Quote Link to comment Share on other sites More sharing options...
TracMan Posted September 25, 2022 Share Posted September 25, 2022 (edited) 4 hours ago, flashjazzcat said: Not if you want to write to more than three registers (the 'many changes' which TracMan directly references when presenting his method). Yep. Explaining (for OP mainly, no doubt in my mind that the code I present is kindergarten stuff to the experts here😳😁),if you need five changes per line, three of those changes are easily done, before the start of the line. Goes without saying you should probably set the background/ border colour first 😁 Edited September 25, 2022 by TracMan 1 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.