-
Notifications
You must be signed in to change notification settings - Fork 0
/
elite-teletext-sixels.asm
271 lines (208 loc) · 7.93 KB
/
elite-teletext-sixels.asm
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
\ ******************************************************************************
\
\ TELETEXT ELITE SIXEL ROUTINES
\
\ Elite was written by Ian Bell and David Braben and is copyright Acornsoft 1984
\
\ The code on this site has been reconstructed from a disassembly of the version
\ released on Ian Bell's personal website at http://www.elitehomepage.org/
\
\ The commentary is copyright Mark Moxon, and any misunderstandings or mistakes
\ in the documentation are entirely my fault
\
\ The terminology and notations used in this commentary are explained at
\ https://elite.bbcelite.com/terminology
\
\ The deep dive articles referred to in this commentary can be found at
\ https://elite.bbcelite.com/deep_dives
\
\ ------------------------------------------------------------------------------
\
\ The code in this section is mostly taken from the Bitshifters' sixel-plotting
\ routines here:
\
\ https://github.com/bitshifters/teletextr/blob/master/lib/mode7_plot_pixel.asm
\
\ It has been reformatted and has been tweaked to work with Teletext Elite (to
\ support EOR plotting, screen indents and so on), but the core routines are
\ mostly unchanged from the original.
\
\ ******************************************************************************
MODE7_VRAM = &7C00 \ The start of video RAM for mode 7
MODE7_INDENT = 3 \ Width of the left indent in characters to apply to the
\ entire space view (so it gets centred)
MODE7_LOW_X = 2 \ The first sixel x-coordinate we can draw sixels in
MODE7_HIGH_X = 2*40-2 \ The last sixel x-coordinate we can draw sixels in + 1,
\ less 2 to compensate for the first character on each
\ row being a graphics control code
MODE7_LOW_Y = 3 \ The first sixel y-coordinate we can draw sixels in (so
\ we not draw on the first character row)
MODE7_HIGH_Y = 3*25 \ The last sixel y-coordinate we can draw sixels in + 1
MESSAGE_ROW = 17 \ The character row containing the in-flight message bar
\ ******************************************************************************
\
\ Name: ySixelLo
\ Type: Variable
\ Category: Teletext Elite
\ Summary: Lookup table to convert a sixel y-coordinate into a mode 7 screen
\ address (low byte)
\
\ ******************************************************************************
.ySixelLo
FOR i, 0, MODE7_HIGH_Y-1
y = (i DIV 3) * 40 + 1 + MODE7_INDENT \ Add 1 to skip the graphics character
\ in column 0, and then add the screen
\ indent
EQUB LO(y-i) \ Adjust for (ZP),Y style addressing, where Y will be
\ the y-coordinate
NEXT
\ ******************************************************************************
\
\ Name: ySixelHi
\ Type: Variable
\ Category: Teletext Elite
\ Summary: Lookup table to convert a sixel y-coordinate into a mode 7 screen
\ address (high byte)
\
\ ******************************************************************************
.ySixelHi
FOR i, 0, MODE7_HIGH_Y-1
y = (i DIV 3) * 40 + 1 + MODE7_INDENT \ Add 1 to skip the graphics character
\ in column 0, and then add the screen
\ indent
EQUB HI(y-i) \ Adjust for (ZP),Y style addressing, where Y will be
\ the y-coordinate
NEXT
\ ******************************************************************************
\
\ Name: xSixel
\ Type: Variable
\ Category: Teletext Elite
\ Summary: Lookup table to convert a sixel x-coordinate into a mode 7 screen
\ address, as a row offset
\
\ ******************************************************************************
.xSixel
FOR i, 0, MODE7_HIGH_X-1
y = i>>1
EQUB LO(y)
NEXT
\ ******************************************************************************
\
\ Name: xSixelChar
\ Type: Variable
\ Category: Teletext Elite
\ Summary: Lookup table to return a sixel character containing the relevant
\ three-sixel column containing that x-coordinate, pre-filled with
\ all three sixels populated
\
\ ******************************************************************************
.xSixelChar
FOR n, 0, MODE7_HIGH_X-1
IF (n AND 1) == 0
EQUB 32+1+4+16 \ Left column mask (i.e. all three left sixels set)
ELSE
EQUB 32+2+8+64 \ Right column mask (i.e. all three rights sixel set)
ENDIF
NEXT
\ ******************************************************************************
\
\ Name: ySixelChar
\ Type: Variable
\ Category: Teletext Elite
\ Summary: Lookup table to return a sixel character containing the relevant
\ two-sixel row containing that y-coordinate, pre-filled with both
\ sixels populated
\
\ ******************************************************************************
.ySixelChar
FOR n, 0, MODE7_HIGH_Y-1
IF (n MOD 3) == 0
EQUB 32+1+2 \ Top row mask (i.e. both top sixels set)
ELIF (n MOD 3) == 1
EQUB 32+4+8 \ Middle row mask (i.e. both middle sixels set)
ELSE
EQUB 32+16+64 \ Bottom row mask (i.e. both bottom sixels set)
ENDIF
NEXT
\ ******************************************************************************
\
\ Name: charRowAddress
\ Type: Variable
\ Category: Teletext Elite
\ Summary: Lookup table to return the screen address of the start of a mode 7
\ character row, for printing text
\
\ ******************************************************************************
.charRowAddress
FOR n, 0, 25
EQUW MODE7_VRAM + MODE7_INDENT + (n*&28)
NEXT
\ ******************************************************************************
\
\ Name: PlotSixelClipped
\ Type: Subroutine
\ Category: Teletext Elite
\ Summary: Plot a mode 7 sixel
\
\ ------------------------------------------------------------------------------
\
\ Arguments:
\
\ X Sixel x-coordinate
\
\ Y Sixel y-coordinate
\
\ ******************************************************************************
.PlotSixelClipped
IF NOT(_DOCKED) AND NOT(_LOADER)
CPY #MESSAGE_ROW*3 \ In flight, do not draw on the message row
BEQ clip1
CPY #MESSAGE_ROW*3+1
BEQ clip1
CPY #MESSAGE_ROW*3+2
BEQ clip1
ENDIF
CPX #MODE7_LOW_X \ If the sixel is off-screen, jump to clip1 to return
BCC clip1 \ from the subroutine
CPY #MODE7_LOW_Y
BCC clip1
CPX #MODE7_HIGH_X
BCS clip1
CPY #MODE7_HIGH_Y
BCS clip1
IF _LOADER
CLC \ Set ZP(1 0) to the screen address of the character
LDA xSixel,X \ block, starting with the low byte
ADC ySixelLo,Y
STA ZP
LDA ySixelHi,Y \ And then the high byte
ADC #HI(MODE7_VRAM)
STA ZP+1
ELSE
CLC \ Set SC(1 0) to the screen address of the character
LDA xSixel,X \ block, starting with the low byte
ADC ySixelLo,Y
STA SC
LDA ySixelHi,Y \ And then the high byte
ADC #HI(MODE7_VRAM)
STA SCH
ENDIF
LDA ySixelChar,Y \ Get the sixel character with the relevant row
\ pre-filled for the y-coordinate in Y
AND xSixelChar,X \ Apply the sixel character with the relevant column
\ pre-filled for the x-coordinate in X, so the result
\ is a sixel character with the sixel at (x, y) filled
.sixelLogic
\ This label enables us to modify the logic used to draw
\ the sixel, for use in the charts
IF _LOADER
ORA (ZP),Y \ OR the sixel into the screen, overwriting whatever is
STA (ZP),Y \ already there
ELSE
EOR (SC),Y \ EOR the sixel into the screen, flipping whatever is
ORA #%00100000 \ already there
STA (SC),Y
ENDIF
.clip1
RTS \ Return from the subroutine