Jump to content
IGNORED

Horizontal Placement, Multiple Sprites


Recommended Posts

I'm starting to grasp how the TIA works on a more complex level. I understand that updating the registers on different lines can allow for multiple instances of GRP0 and GRP1.

 

I've attached a screenshot of Dragonfire as a good example of this technique.

 

Now, how exactly do you "place" these objects in certain positions horizontally? Is this a matter of using HMOVE during the drawing of the frame?

 

Obviously I need a solution that is very brief in cycles. I want enough time to have multi-colored sprites just like this example.

 

I've read over the Dragonfire source code, but it's a bit dense to find the portion that I am referring to.

post-36643-0-25320900-1394231902_thumb.png

Link to comment
Share on other sites

The five RESxx ("reset") registers have only one function-- to reset a sprite's horizontal position on the scan line-- so they have no other use per se. However, they can be used to trigger extra copies of the sprites beyond the normal three-copy limit.

 

There are a few things you should know about the RESxx registers.

 

First, writing to ("strobing") a RESxx register lets you position the corresponding sprite at intervals of 3 color clocks (CCs), since 1 machine cycle (MC) equals 3 CCs. The new screen position is equal to 3 times the MC immediately following the completion of the write instruction, minus 68 CCs to get the pixel position on the visible portion of the scan line, plus an extra number of CCs to compensate for the START signal. For the players you need to add 5 CCs, but for the missiles and ball you need to add only 4 CCs, so in theory the possible positions are as follows:

 

 

MC CC  M+4 -68 P+5 -68
-- --- --- --- --- ---
00 000 004 -64 005 -63
01 003 007 -61 008 -60
02 006 010 -58 011 -57
03 009 013 -55 014 -54
04 012 016 -52 017 -51
05 015 019 -49 020 -48
06 018 022 -46 023 -45
07 021 025 -43 026 -42
08 024 028 -40 029 -39
09 027 031 -37 032 -36
10 030 034 -34 035 -33
11 033 037 -31 038 -30
12 036 040 -28 041 -27
13 039 043 -25 044 -24
14 042 046 -22 047 -21
15 045 049 -19 050 -18
16 048 052 -16 053 -15
17 051 055 -13 056 -12
18 054 058 -10 059 -09
19 057 061 -07 062 -06
20 060 064 -04 065 -03
21 063 067 -01 068 000
22 066 070 002 071 003
23 069 073 005 074 006
24 072 076 008 077 009
25 075 079 011 080 012
26 078 082 014 083 015
27 081 085 017 086 018
28 084 088 020 089 021
29 087 091 023 092 024
30 090 094 026 095 027
31 093 097 029 098 030
32 096 100 032 101 033
33 099 103 035 104 036
34 102 106 038 107 039
35 105 109 041 110 042
36 108 112 044 113 045
37 111 115 047 116 048
38 114 118 050 119 051
39 117 121 053 122 054
40 120 124 056 125 057
41 123 127 059 128 060
42 126 130 062 131 063
43 129 133 065 134 066
44 132 136 068 137 069
45 135 139 071 140 072
46 138 142 074 143 075
47 141 145 077 146 078
48 144 148 080 149 081
49 147 151 083 152 084
50 150 154 086 155 087
51 153 157 089 158 090
52 156 160 092 161 093
53 159 163 095 164 096
54 162 166 098 167 099
55 165 169 101 170 102
56 168 172 104 173 105
57 171 175 107 176 108
58 174 178 110 179 111
59 177 181 113 182 114
60 180 184 116 185 117
61 183 187 119 188 120
62 186 190 122 191 123
63 189 193 125 194 126
64 192 196 128 197 129
65 195 199 131 200 132
66 198 202 134 203 135
67 201 205 137 206 138
68 204 208 140 209 141
69 207 211 143 212 144
70 210 214 146 215 147
71 213 217 149 218 150
72 216 220 152 221 153
73 219 223 155 224 156
74 222 226 158 227 159
75 225 229 161 230 162

 

However, the first 68 CCs correspond to the horizontal blanking period, and due to the way the TIA draws the sprites they can't be positioned "offscreen" inside the HBLANK area-- i.e., you can strobe the RESxx registers during HBLANK, but the sprites won't be positioned within the HBLANK region; instead, they be positioned as though you'd strobed their RESxx registers at cycle 22 (i.e., where cycle 22 is the first cycle following the completion of the write instruction). If you look at the list above, it looks like the players should be able to be positioned at pixel 000 by strobing their RESxx registers at cycle 21, but it doesn't work that way. I'll explain this more in a moment.

 

Second, since you can position a sprite only at intervals of 3 CCs, you'll need to also use the HMxx ("horizontal motion") registers and the HMOVE register to position them at the other pixel positions.

 

Third, when you reset a sprite's position, it may not appear on that scan line-- it depends on whether the sprite has already been drawn on that scan line (at the old position) and whether you're displaying any copies of the sprite, but it can also depend on whether you strobe the RESxx register more than once. To understand why, you need to know how the TIA draws the sprites.

 

When you reset a sprite's position by strobing its RESxx register, the TIA sets the sprite's START signal at that position. The START signal lasts for 4 CCs, but the TIA doesn't actually begin to draw the sprite until after the START signal is turned off again. So, for example, if you were to strobe the RESP0 register at cycle 25 (meaning the write instruction is executed during cycles 22, 23, and 24, with cycle 25 being the first cycle after the write instruction has completed), then player0's START signal would be automatically turned on at CC 075 (or pixel position 007) of each scan line (until you reset the sprite's position to a different location), and automatically turned off again at CC 079 (or pixel position 011). Thus, the sprite won't actually be drawn until CC 079. However, for the players it's as if the players were 9 bits wide but with the first pixel always being blank-- i.e., the drawing of the players is delayed by an extra CC, as follows:

 

 

MC 22 = CCs 066, 067, and 068 -- begin STA RESxx instruction
MC 23 = CCs 069, 070, and 071 -- STA RESxx continues executing
MC 24 = CCs 072, 073, and 074 -- STA RESxx completes executing
MC 25 = CC 075 -- sprite's START signal begins
CC 076 -- START signal continues
CC 077 -- START signal continues
CC 078 -- START signal continues
CC 079 -- drawing begins here for the missiles and the ball
CC 080 -- drawing begins here for the players

 

If we use SSSS to represent the 4-CC START signal, then for a player it would look like the following:

 

SSSSx76543210

 

where "x" represents the extra blank CC and "76543210" represents bits 7 through 0 of the player's GRPx register.

 

However, the TIA doesn't actually generate a START signal after the RESxx register has been strobed-- it doesn't begin generating the START signal until 228 CCs later. So if you're displaying just 1 copy (i.e., the main copy) of player0, and player0 hasn't already been drawn on the scan line where you've strobed RESP0, then player0 won't appear on that scan line at all. But if player0 had already been drawn on that scan line before you strobed RESP0, then player0 will appear at the old position on that scan line, and at the new position on the subsequent scan lines.

 

(Note: I think the ball may be an exception to this rule-- i.e., its START signal may begin immediately rather than being delayed by 228 CCs, as I've seen references in the 2600 literature that say you can trigger the ball multiple times on a scan line-- but I haven't tried it to see whether or not it works.)

 

On the other hand, if you're displaying additional copies of the sprite, the TIA will generate START signals for the additional copies, so they *will* appear on the scan line where you strobe the RESxx register. These additional START signals will occur 16, 32, or 64 CCs after the beginning of the first START signal, as follows:

 

ssssx76543210xxxSSSSx76543210xxxSSSSx76543210xxxxxxxxxxxxxxxxxxxSSSSx76543210xxx

 

In the line above, ssss represents the START signal that's delayed by 228 CCs (1 scan line), which triggers the main copy of the sprite. The other START signals (SSSS) are for the close copy, medium copy, and far copy of the sprite, which *won't* be delayed by 1 scan line-- but they'll occur only if those copies are turned on.

 

The trick that lets you draw more than 3 copies of a sprite on a scan line works because the extra START signals do occur right away-- i.e., you won't get copy 1 (the main copy) on that scan line, but you will get copy 2 and copy 3. So if you strobe RESxx multiple times-- with a suitable delay between the multiple strobes-- you can draw copy 2 and copy 3 multiple times.

 

Now, there's an interesting fact that lets you get all 3 copies if you time things just right. If you strobe RESxx such that the ssss signal for the main copy would occur sometime during one of the SSSS signals, that SSSS signal will act like the new ssss signal, although it will be "repositioned" to be aligned with the sprite's new position. For example, if you have the NUSIZ0 register set to draw 3 close copies of player0, you can draw all 3 copies on the scan line by doing the following:

 

 

STA RESP0
sleep 3
STA RESP0

 

This is because the first STA RESP0 sets the main copy's ssss signal (which doesn't actually get triggered until 228 CCs later) at the new position, and the first SSSS signal (for copy 2) occurs 16 CCs later. But the second STA RESP0 is timed so that the ssss signal for the second STA RESP0 occurs 18 CCs later, or 2 CCs into the SSSS signal for copy 2, therefore you end up getting a START signal that's 6 CCs long. This is useful if you want to display more than 3 copies of the sprite, but in most cases you'll want to just strobe RESxx once and then use HMOVE to fine-position the sprite. In that case you'll need to strobe RESxx once, store the desired fine-positioning motion value in the HMxx register, and then use HMOVE (typically right after WSYNC), so you can basically count on needing 1 scan line to position the sprite, such that there will always be at least 1 blank scan line between one version of the sprite (at the old position) and the next version of the sprite (at the new position). The only exception would be if the old position were far enough to the left of the new position, in which case you could theoretically draw the two versions of the sprite with no blank line between them-- although in practice a positioning loop is typically used, so you will get at least one blank line on which you'll call the subroutine that executes the positioning loop.

 

I hope the above explanation wasn't too confusing. You don't need to worry about the intricate details unless you're planning to use the multi-reset trick-- and you probably shouldn't attempt that until after you've understood the basics of sprite positioning.

  • Like 1
Link to comment
Share on other sites

[lots of stuff]

 

Wow, thank you for the copious amount of details on that subject. I will probably have to revisit this as a reference until I dedicate this stuff to memory.

 

 

There's a lot of comments in the source I posted for this demo of mid-screen sprite repositioning.

 

http://atariage.com/forums/topic/169471-early-hmove-demo/

 

Great resource as well.

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