Jump to content
IGNORED

how many graphics modes can you have in a display list?


xxx

Recommended Posts

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

Link to comment
Share on other sites

  • 2 weeks later...

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 by TracMan
  • Like 2
Link to comment
Share on other sites

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 by Rybags
Link to comment
Share on other sites

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.

  • Thanks 1
Link to comment
Share on other sites

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)

 

 

 

Link to comment
Share on other sites

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 by flashjazzcat
  • Like 1
Link to comment
Share on other sites

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

 

:D

Edited by xxl
Link to comment
Share on other sites

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 by TracMan
  • Like 1
Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...