Jump to content

What is meant by the ABBUC advice....

Recommended Posts

ABBUC software contest


rules state "Before changing the display list (DLISTL/H) a vertical blank should take place (wait for it). "


What does that mean?

I'm pretty sure a vertical blank takes place 50 or 60 times per second, you can automatically assume one has already taken place.

So they must mean something else...I do not know what they mean.


What do they want? And second, if its a bog standard thing, could someone share some assembler?



Link to comment
Share on other sites

Probably just advice to waiting for vertical blank before you change DLIST pointer, so the VBL will not happen in between writing low and high byte of the pointer (in that case the DLIST will point to some "random" place and it would produce glitches for one frame or it can even crash AFAIK if DLIs are enabled).

  • Like 1
Link to comment
Share on other sites

Not sure why they'd word it as such. It is possible though highly unlikely in assembler that if you change the display list pointers you can get a half-baked value if a VBlank takes place between stores.

If doing a disk load and you want a title screen it's highly advisable to change the DList pointer then have a 1 frame wait so it gets enstated. The problem with doing disk operations is that Stage 2 VBlank will be disabled for a good deal of the time so screen relevant changes like DLists and colours can have an unwanted delay.

Link to comment
Share on other sites

My above post is worded poorly. First, my atari is in the shop, so I am talking about an emulated atari.

Second the whole atari doesn't crash, but I get massive corruption on the screen.

; turn off antic
lda #0
sta $022F

; poke dlist into os
ldy #<DL1
sty $0230
ldy #>DL1
sty $0231

; poke screen memory into os
ldy #$00
sty $58
ldy #$40
sty $59

; wait 1 to make sure dlist is picked up - adding these lines causes the first screen to become garbage characters
lda #1
jsr _delay_asm

; turn on antic
lda #$22 sta $022F

Link to comment
Share on other sites

I assume you mean my screen memory is in the banked area, my display list isn't revealed in that code just referenced as DL1.


I put the DL in page 6.


On putting screen memory in $4000 - for now that is still hard coded. That's from early in the programming effort where I hadn't gotten used to labels yet, so some of my maze drawing routines have some hard coded, expecting memory to start at $4000 values.


I had things spread out everywhere at first. Laughably creating a 32k executable out of minimal amount of code, lol. now most everything is handled by the linker, and the org=$2000.... but I have some screen memory stuff that is still hard coded. I do have plans to change it.


Imho, you really have only a small slice of memory in the atari that you can safely use - regrettably the early documentation let me down a little bit. My current goal is to start at $2000 and have everything run in the range $2000 - $4000, with some small page 6 use, and some small page zero use - and to be frank, right now I'm vastly overusing page 0, and have plans to reduce that, to make it safe for basic, so users don't have to unplug their cart, if they have it in.


I don't have the code with me, but the delay routine is to read the jiffy register and loop until it changes. It's more complicated than that, because it accepts a parameter for the number of jiffies in the A register. And it has to account for the jiffy register possibly having cycled back to zero. So it does some branching logic back and forth, but the end result it waits the specified number of jiffies, by rereading the jiffy register until it changes, enough. this delay routine is called by the music playing and the game loop - and works everywhere else.


When I get home I can share the code. I could put in a far simpler delay loop and try that....I just can't imagine what's causing this.


Although, to be frank, I don't need to know. I don't have any need to use my delay loop here, I just did, as a convenience. so I should just remove it and everything goes back to working. I just need to figure out what ABBUC wants...


any ideas? How do you all meet this requirement?

Link to comment
Share on other sites

Of course you're quite correct about the DL - I meant the frame buffer. :)

A simple way to wait for vertical sync is this:

	.proc WaitForSync
	lda VCount
	lda VCount

It has the advantage of working even with all interrupts disabled.


Really it's only the screen RAM position you need to worry about regarding the banked region, and then only if you're running alongside DOS or planning to bank memory yourself. To be DOS and cart safe, you can put Antic data at $2000-$3FFF or $8000-$9FFF. As long as code doesn't directly manipulate PORTB, it can safely be placed in the banking window, although it's sometimes prudent to keep interrupt service routines out of that area too.

  • Like 1
Link to comment
Share on other sites

Thanks. So at first I am thinking, those aren't 6502 instructions. However, I get it, they are mads macro for repeat not equal and repeat equal.... And you are branching on vcount which is vertical line counter at d40b



I am just talking aloud for anyone else learning assembly. Other than making it work in my ca65 environment, I will deinately try this tonight. I suspect it won't be a fix for whatever nonsense I have going on but will improve my delay routine to use vcount. Although the game loop won't use any delay on upcoming revision... Still might need it for this

Link to comment
Share on other sites

They mean this:

    lda 20
lp  cmp 20
    beq lp
    lda #<xx
    sta $0230
    lda #>yy
    sta $0231

As said above, one has to guarantee (this way or another) that no VBL occurs between setting the low byte of a vector and setting its high byte.

Edited by drac030
Link to comment
Share on other sites

So at first I am thinking, those aren't 6502 instructions. However, I get it, they are mads macro for repeat not equal and repeat equal.... And you are branching on vcount which is vertical line counter at d40b.

Yes - my apologies: I just pasted this straight out of existing source code. RNE is equivalent to BNE LABEL where LABEL points to the previous instruction, and REQ is the same but using BEQ. VCOUNT is indeed the vertical line counter at $D40B.

Link to comment
Share on other sites

Isn't it sufficient, to just check that the line counter isn't near the bottom of the screen? Like in

      ; wait until we aren't at the bottom of the screen
wait: lda $d40b   ; VCOUNT
      cmp #120
      bcs wait

      ; set new display list address
      lda #<new_displist
      sta $230
      lda #>new_displist
      sta $231

Link to comment
Share on other sites

Actually, for just the DList pointer none of that is necessary. Just use the same method the OS does with it's SETVBV routine.



  ldx #<new_dlist
  ldy #>new_dlist
  sta wsync
  stx sdslstl
  sty sdslsth


Since NMIs will only occur at cycle 7 (?) of a scanline the write to WSync ensures both parts of the pointer will be written before an NMI can start. I assume this should still work fine in the worst case DMA situation (wide screen, 40 character mode badline, 3 byte DList instruction, PMG DMA enabled)

  • Like 1
Link to comment
Share on other sites

Well I'm home now and quickly discovered the silly reason for my screen corruption.


I have my code organized into 'transition' screens and part of the code uses Absolute,X addressing to load in the screen. It starts at 0. But it never really set the X register to 0 - it was just coincidentally starting at 0.


Up until that time I added code that touched the X register, as my original delay routine did.


Anyway, this is good, I added STA WSYNC, and thus now guarantee that a vblank won't occur between the setting of the upper and lower byte of the dl.

I kind of hoped in the far reaches of my imagination that this might also be a fix for why Altirra won't display my program correctly, but it's not. Oh well.

  • Like 1
Link to comment
Share on other sites

Actually there is the chance a VBlank could occur with that method I mentioned. If an IRQ occurred after the STX then the VBlank during servicing of that. But it wouldn't matter as Stage 2 would be skipped anyway.


I'm pretty sure it's possible for the NMI to fire immediately after the IRQ exits with RTI. Unlike CLI, RTI doesn't hold off IRQs for an additional instruction.


There's also the problem that the 6502 often begins executing the next instruction before it is suspended by WSYNC. That means that if the WSYNC wait runs across the VBI, the VBI can't fire before STX because that instruction has already begun executing, and is delayed until before STY -- boom. SETVBV is a challenging function to write, especially since it is not allowed to touch NMIEN.


Fortunately, for SDLSTL/SDLSTH, it's simpler and faster just to change them with IRQs disabled by wrapping the write with SEI/CLI. If you want to know when stage 2 VBI has run to actually push the new values to the hardware and swap in the new screen, overwrite one of the input shadows with an invalid value -- e.g. PTRIG7=$FF -- and wait for it to change back to a legal value again ($00/$01). Polling RTCLOK ($14) is not reliable as it updates in stage 1 VBI.


It's good that ABBUC has this rule, because it's a common failure mode for programs to crash because they have a dirty screen swap on startup. That's inconvenient for people creating compilation disks because whether the crash happens can vary based on the loader that's used to load the program. You can't think "the timing windows too small, it won't happen" -- it will.

  • Like 5
Link to comment
Share on other sites

You could get it even more compact.



repeat  bit ptrig7
  bmi repeat


Also, it's often the case your DList will be somewhere fairly high in memory. If it's fixed location above $8000 just put the high byte in PTRIG.


Alternate to my method - two STA WSYNC instructions in a row should guarantee that VBlank doesn't occur between the DList stores.

  • Like 1
Link to comment
Share on other sites

Something like this then?

More like this:


; poke dlist into os
        ldy #<DL2
        ldx #>DL2
        sty sdlstl
        stx sdlsth

; wait for change to actually take effect
        LDA #$FF
        STA PTRIG7
        CMP #$02
(As Rybags points out, you can also use BMI for >=$80 instead CMP #$02 to check for when the display change occurs.)
  • 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.

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.

  • Recently Browsing   0 members

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