-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathReadMe.txt
More file actions
153 lines (119 loc) · 7.55 KB
/
ReadMe.txt
File metadata and controls
153 lines (119 loc) · 7.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
Source in folder: Tests/Sprites/ScanlineDelay/
Test will draw some kind of "ruler" in the ULA screen, with the largest
ruler line representing the +0 scanline, the active target of copper code.
The left side of ruler is on odd lines (-3,-1,+1,+3,+5,+7) with +0 and +4
having extra parts left of the odd-marks. The right side of the ruler
shows even lines (-2,+0,+2,+4,+6) with +0 and +4 being longest+longer ones.
Between the rulers the left half is occupied by static sprite (for
comparison purposes and to verify that sprites are actually rendered),
the right half should contain only single line from the sprite (same
graphics pattern is used for the right sprite, but only single line is
rendered (visibility = ON/OFF)).
Depending on the position of the single line, one can read the sprite
renderer delay.
There is extra change of ULA paper to light cyan for the whole scanline,
where the sprite is set to "visible", this one should align to the
+0 ruler.
If the ULA line is misaligned, it signals the copper commands are affecting
wrong scanlines (common in emulators to affect previous scanline instead
of target one, in such case the sprite delay counts against the cyan paper).
## New technical info for core 3.0.7+
The sprite engine is now swapping the buffers at sprite coordinate X=-1,
just before the first sprite pixel is sent to the display. This shifts
the description in following paragraph by roughly 1/4 of scanline T-states
to right, so now changes done to sprite attributes during H-blank period
will be only one scanline delayed (or may affect the current buffer which
will be displayed at following scanline, if the renderer is still rendering
the sprites you are modifying).
In other words, if you want to turn sprite from invisible to visible at
pixel [10,52] (sprite coordinates) (scanline 20, left border scanline 19
in copper coordinates), the sprite engine should pick the change of flag
if it is written ahead of copper WAIT(line=18, horizontal=~50).
Somewhere around copper coordinates line=18,H=50 (scanline 19 (in PAPER))
the buffers are swapped, buffer with new drawing is shown at scanline 19,
and sprite engine is drawing with the modified flag new buffer for scanline
20 (in PAPER).
## Older core 3.0.5 technical details
On older core 3.0.5 the sprite engine is using double-buffering (per
scanline), so the result is visible with one scanline delay. But be aware
the rendering of buffer for scanline "y" starts right after the last
sprite pixel of line y-2 is displayed (copper H=36, sprite X=320), and will
continue with rendering until the same spot is reached on line y-1.
This means you need to adjust sprite attributes quite early if you want the
change to be visible with only one line delay, like toward end of paper
area or within the sprite area - of course then you risk some of the changes
may get rendered in the current process, if you are exhausting pixel
bandwidth a lot, and you modify the last sprites in list too early
(the sprite engine always render sprites from sprite 0 to sprite 127, even
when top-to-bottom priority is flipped, and there's about 1600+ pixels per
line available, so if you have on single line 50 visible sprites with scale
1x (16 pixels per sprite), the sprite engine will finish the rendering
roughly around first third of "paper" area, then changing sprite attributes
after half of screen (sprite X=32+128) shouldn't affect anything as the
buffer is already finished.
## How the test works:
The copper will WAIT for scanline-1, horizontal=35 = just around sprite
X=312 coordinate, ahead of the target scanline (the target scanline is
eighth pixel line from top).
Then the copper commands will modify the ULA paper color to light cyan
and make the right sprite visible.
Another copper WAIT is issued for "scanline" (with horizontal=35 too),
i.e. just single scanline below the first wait.
And the following commands will restore the ULA paper color, and make
the right sprite invisible again.
This copper code is auto-restarted every frame (the copper mode %11).
## Added four further variants of the initial test described above:
The second test "RotMir / Xpos" does test two distinct things with single
sprite. At the target scanline the ULA paper is changed to light yellow
and sprite attributes are modified to have ROTATE+MIRROR_X, and move
sprite by 9 pixels to right. The rotate+mirror will demonstrate itself
as single line with color dots (instead of single-color line), the X-offset
will demonstrate by the line of sprite being on the right side. These two
effects will very likely happen at the same line (with most of the sprite
renderers), but they are two distinct tests and maybe some renderer may
trigger each feature on different line.
The third test "Transp. index" doesn't modify the sprite attributes, but
only changes the global Sprite transparency index from $1F to $01 at the
active line (ULA paper light violet). On that line the sprite transparent
area with $1F cyan color will be suddenly visible, for single scanline.
The fourth test "Palette color" will turn off sprite transparency (set to $01)
for whole rectangle area to make the $1F area visible, and the copper will
modify the Sprite palette item $1F to "orange" color, at the active scanline
(ULA paper cyan). This should uncover if the palette values are used at the
moment of rendering, or rendering is done with index-colors and 9b RGB is
fetched from palette later, when buffer is applied to display output.
(the core 3.0.5 does render sprites in index mode into buffer, and does
fetch final 9b color from palette when the buffer is mixed into display
output, so the changes applied to palette item are without delay)
## How is it even useful if you want to code for Next:
There is old art of "sprite multiplexing" technique, allowing you to
display more sprites on screen than the original HW claims to support,
if you modify the HW sprites attributes racing the display-beam drawing
the scanlines one by one to the display. So the same HW sprite may be
used to draw one sprite in top area, and another sprite in bottom area
(as long as the areas don't share the same scanline, which would require
two HW sprites to get them rendered both).
With Next and it's 128 HW sprites it is actually not that likely you
would need multiplexing technique, but if you do, the info from this
test is important for you to time the multiplexing changes (or even
non-multiplexing-but-very-late changes) correctly to get the desired
display output. With current core 3.0.5 you need to modify sprite
coordinates, visibility and pattern "one scanlines ahead", but the decisive
edge is at the sprite position X=320, i.e. it's more like "two scanlines"
ahead.
The point where the buffer flips may be adjusted in future cores, if it
will be adjusted, I will hopefully update this text with new info.
## Test extension to verify 4-byte/5-byte attribute sprites
Sprites are set up through Next registers $34-$39,$75-$79 (not through port).
From left to right:
1) 4 byte type + explicit zero written to fifth
2) 4 byte type converted from 5 byte type (scaleY) (fifth byte non-zero ahead)
3) 4 byte type + explicit non-zero (scaleY) written to fifth after fourth
4) 5 byte type +scaleY
The first three sprites should look the same, ignoring the fifth byte either
way because of the extended bit.
Next rows contain sprites set through I/O port $57, left sprite is 4-byte type
looking as the one above from NextReg setup, right sprite is 5-byte type with
2x scaleY (same as the fourth sprite above).
The left 4-byte sprite attributes are first tainted by 5-byte type + 2xY, then
the final state is set through I/O port (to verify the fifth gets cleared).