Jump to content
IGNORED

Sprite Positioning: Timing Confusion


DigitalAnthony

Recommended Posts

Hello, Atari VCS programmers.  Not sure if this is the right place, but I am confused with regards to the exercise for Chapter 9 on 8bitworkshop.com.  I've been following along with the companion book, "Making Games for the Atari 2600" and I'm finding discrepancies between the Javatari and Stella debugger.  Using both debuggers, I set a breakpoint at the blue highlighted line (included at end of post).  When I step past the first sta WSYNC instruction, the Javatari debugger shows 62 lines of the horizontal blank remaining, while Stella shows 68.  The Stella one made sense to me since my understanding is that the instruction pauses the 6507's execution until the start of the next scanline, and then you have a fresh 68 color clocks of horizontal blank to work with.  Is this incorrect?  Are the 3 cycles required for the instruction consumed on the previous scanline or the next scanline?  Both emulators display the same image, however, when the programs are executed.  

 

Also, when using the HMxx register, I have noticed some sources show a table like so:

image.png.ed989972f51dd030e11a6462f42f0805.png

 

while other sources (Stella programmer's guide) say it goes from -8 to +7 and the values are reversed.  Which one is it?  Using the table shown above and assuming there are only 62 lines left in the horizontal blank, the sprite position makes sense for the Javatari program, but the 62 doesn't make sense.  I appreciate any help you guys can provide to clear this confusion. 

 

 

; Instead of representing the horizontal position in CPU clocks,
; we're going to use TIA clocks.

    lda counter    ; load the counter as horizontal position
    and #$7f    ; force range to (0-127)
    
; We're going to divide the horizontal position by 15.
; The easy way on the 6502 is to subtract in a loop.
; Note that this also conveniently adds 5 CPU cycles
; (15 TIA clocks) per iteration.
    sta WSYNC    ; 35th line
    sta HMCLR    ; reset the old horizontal position
DivideLoop
    sbc #15        ; subtract 15
    bcs DivideLoop    ; branch until negative
; A now contains (the remainder - 15).
; We'll convert that into a fine adjustment, which has
; the range -8 to +7.
    eor #7
    asl        ; HMOVE only uses the top 4 bits, so shift by 4
    asl
    asl
    asl
; The fine offset goes into HMP0
    sta HMP0
; Now let's fix the coarse position of the player, which as you
; remember is solely based on timing. If you rearrange any of the
; previous instructions, position 0 won't be exactly on the left side.
    sta RESP0
; Finally we'll do a WSYNC followed by HMOVE to apply the fine offset.
    sta WSYNC    ; 36th line
    sta HMOVE    ; apply offset

Edited by DigitalAnthony
Whoops, just saw there was a programming sub-forum. Not sure how to move this topic over there though. Sorry about that.
Link to comment
Share on other sites

Welcome to AtariAge!

 

When in doubt, follow Stella emulator and the Stella Programmer's Guide. The may not be 100% correct in all cases, but usually they are. 

 

The HMOVE table you provided is correct. The confusion results from the signs used, which is a matter of perspective. In your case a negative value means movement to the left, in other cases it is vice versa. But the HMxx values are correct in both cases.

 

A 2600 scanline has 76 cycles, not 68. But only 160/3 cycles are executed during the visible part of it. The other 68/3 cycles happen outside the visible area, while the beam is moving back to the left. You can use all 76 cycles, but then you have to make sure that your always code produces the correct number of them. If not, you can use WSYNC, which takes 3 cycles like any other TIA register read or write. So that reduces your available cycles/scanline down to 73.

 

The example code you provided is incomplete (we do not know the states of 'counter' and of the carry flag), so I cannot check which one is correct. You can also attach a binary (zipped), if that helps.

 

If you want to get this topic moved, ask a moderator. They can do it for you.

  • Like 1
Link to comment
Share on other sites

Thank you very much for the help.  I realized now that I accidentally typed "68 lines".  What I meant by that was the number of TIA Clock Counts you have in the horizontal blank area (-68 pixel position).  I've attached the zipped binary file to this response.  When I run it on Stella, the debugger shows that the "sta RESP0" instruction happens on machine cycle 20 (color clock 60/pixel position -8).  This seems weird to me that the code would strobe the RESP0 register when the TIA is still in the horizontal blank.  Does this cause player0 to be positioned 6 pixels into the display, and then that explains why the HMP0 is set to $60 to offset this and start the pixel at the far left?  

 

https://atariage.com/forums/topic/208473-resp0-while-pixel-position-is-negativelow/

timing2.a.rom.zip

Edited by DigitalAnthony
Added a link that clears up my confusion
Link to comment
Share on other sites

Yes, too early RESxx position to a very left position. Generally you should avoid them, because with the current code you cannot move the sprites smoothly. They will stuck at the left before they start moving. Start at 23, then you can get the full range up to 73, which is just early enough for the following WSYNC.

  • Like 1
Link to comment
Share on other sites

DigitalAnthony,

 

We were actually just having a rollicking discussion of horizontal position just the other week. You might want to check it out:  

 

 

But to answer your question, yes, you can strobe RESP0 when the TIA is still in horizontal blank because the counter that controls horizontal positioning for P0 is a different one from the "main" horizontal counter. What's interesting is that the P0 counter isn't (normally) counting during horizontal blank. The clock that feeds it is only (normally) connected during the visible part of the horizontal line. The counter is designed to have 160 "ticks" before cycling around*, so it will hit zero at the same time on every scanline unless you mess with it.

 

And RESP0 is one way to mess with it. All it does is reset the P0 counter to zero at the time you strobe it. It doesn't store the current horizontal position or anything like that. It doesn't have too, because player drawing isn't triggered by referencing an actual stored position. It's only triggered by that cycling counter hitting zero.

 

Anyway, if you do the reset during HBLANK, that's no big deal. It's like setting a clock to midnight while it's unplugged. Once the counter starts up again, the beam will be at the left of the screen and (since the counter is now zero) the drawing of player 0 will be instantly triggered.

 

There is a five-cycle delay** between the triggering of the draw and actual drawing, so you can't actually get to the extreme left using RESP0 alone.

 

 - Jeff

 

* Okay, technically it only counts 40 times in a cycle, but the counter (when it's running!) only ticks every four color clocks. So it winds up being a 160-clock cycle anyway. Not really an important distinction from the programmer's perspective.

 

** Only four cycles for missile and ball objects

Edited by JeffJetton
  • Like 1
Link to comment
Share on other sites

Thanks for the detailed explanation Jeff!  I finally got a chance to read through the discussion you linked and it definitely covers some very "to the metal" concepts involving digital design that I would love to one day gain a deep understanding of.  One thing that still confuses me, however, is that you say there is a five-cycle delay when drawing player objects caused not by the RESP0 instruction, but rather within the TIA itself.  This leads me to believe that the closest to the extreme left you would be able to start a player pixel (without HMxx) would be at pixel position 5 (color clock 73).  But in practice, I'm finding that the earliest position is actually pixel position 3 (color clock 70).  This coincides with my understanding of the programming techniques, but contradicts my understanding I came to after reading the technical details of the hardware you explained.  Am I missing something here?

Link to comment
Share on other sites

Following the link you posted to the discussion earlier, I experimented with your resptest.asm file.  Originally in the file, you had:

sta WSYNC
SLEEP 20
sta RESP0

This positioned P0 at position #6, which makes sense and coincides with the explanation you provided in the comments.  However, when I changed 20 to 19, as it has been done in the attached file, and loaded up the debugger and selected the TIA tab, it states that the position of P0 is #3.  It would seem somehow the delay is starting 2 cycles deep into the blank section.  

 

The file I attached is titled playfield.asm but it is the same as your file except for that one change I mentioned.  This is a real stumper... ?

 

 

playfield.asm

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...