-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathputTile.bas
More file actions
267 lines (210 loc) · 6.38 KB
/
putTile.bas
File metadata and controls
267 lines (210 loc) · 6.38 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
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
' Routine to place a 16 pixel by 16 pixel "Tile" onto the screen at character position x,y from adddress given.
' Data must be in the format of 16 bit rows, followed by attribute data.
' (c) 2010 Britlion, donated to the ZX BASIC project.
' Thanks to Boriel, LCD and Na_than for inspiration behind this.
' This routine could be used as the basis for a fast sprite system, provided all sprites can be in 4 character blocks.
' It can also be used to clean up dirty background (erase sprites), or put backgrounds from tiled blocks onto a screen.
' Note the comments about Self Modifying code should be ignored. This has been updated with IX+n methods, which overall are faster than accessing and changing the code.
' (They would have to be accessed to change the memory anyway - may as well just access them directly.)
SUB putTile(x as uByte, y as uByte, graphicsAddr as uInteger)
ASM
JP pt_start
ptstackSave:
defb 0,0
pt_start:
ld a,i
push af ; Save interrupt status.
; Routine to save the background to the buffer
DI ; we really, really, REALLY can NOT be having interrupts while the stack and IX and IY are pointed elsewhere.
PUSH IX
PUSH IY
;ld HL, 65535 ; Self modifying code should load this with the graphics address.
LD D,(IX+9)
LD E,(IX+8)
EX DE,HL
;; Print sprites routine
LD (ptstackSave), SP ; Save Stack Pointer
LD SP,HL ; now SP points at the start of the graphics.
; This function returns the address into HL of the screen address
ld a,(IX+5) ; Load in x - note the Self Modifying value
ld IYH, a ; save it
ld l,a
ld a,(IX+7) ; Load in y - note the Self Modifying value
ld IYL, a ; save it
ld d,a
and 24
add a,64
ld h,a
ld a,d
and 7
rrca
rrca
rrca
or l
add a,2 ; Need to be to the right so backwards writing pushes land properly.
ld l,a
; SO now, HL -> Screen address, and SP -> Graphics. Time to start loading.
POP BC ; Row 0
POP DE ; row 1
EX AF,AF'
POP AF ; row 2
EX AF,AF'
EXX
POP BC ; row 3
POP DE ; row 4
POP HL ; row 5
EXX
; All right. We're loaded. Time to dump!
LD IX,0
ADD IX,SP ; Save our stack pointer into IX
LD SP,HL ; point at the screen.
PUSH BC ; row 0
INC H
LD SP,HL
PUSH DE ; row 1
INC H
LD SP,HL
EX AF,AF'
PUSH AF ; row 2
INC H
LD SP,HL
EXX
PUSH BC ; row 3
EXX
INC H
LD SP,HL
EXX
PUSH DE ; row 4
EXX
INC H
LD SP,HL
EXX
PUSH HL ; ROW 5
EXX
; We're empty. Time to load up again.
LD SP,IX
POP BC ; ROW 6
POP DE ; ROW 7
EX AF,AF'
POP AF ; ROW 8
EX AF,AF'
EXX
POP BC ; ROW 9
POP DE ; ROW 10
POP HL ; ROW 11
EXX
; and we're loaded up again! Time to dump this graphic on the screen.
LD IX,0
ADD IX,SP ; save SP in IX
INC H
LD SP,HL
PUSH BC ; ROW 6
INC H
LD SP,HL
PUSH DE ; ROW 7
DEC HL
DEC HL
; Aha. Snag. We're at the bottom of a character. What's the next address down?
ld a,l
and 224
cp 224
jp z,ptSameThird3
ptNextThird3:
ld de,1760
and a
sbc hl,de
jp ptAddrDone3
ptSameThird3:
ld de,32
and a
adc hl,de
ptAddrDone3:
INC HL
INC HL
LD SP,HL
EX AF,AF'
PUSH AF ; ROW 8
INC H
LD SP,HL
EXX
PUSH BC ; ROW 9
EXX
INC H
LD SP,HL
EXX
PUSH DE ; ROW 10
EXX
INC H
LD SP,HL
EXX
PUSH HL ; ROW 11
EXX
; Okay. Registers empty. Reload time!
LD SP,IX
POP BC ; ROW 12
POP DE ; ROW 13
EXX
POP BC ; ROW 14
POP DE ; ROW 15
POP HL ; Top Attrs
EXX
EX AF,AF'
POP AF ; Bottom Attrs
EX AF,AF'
; and the last dump to screen
INC H
LD SP,HL
PUSH BC
INC H
LD SP,HL
PUSH DE
INC H
LD SP,HL
EXX
PUSH BC
EXX
INC H
LD SP,HL
EXX
PUSH DE
EXX
; Pixels done. Just need to do the attributes.
; So set HL to the attr address:
ld a,IYL ;ypos
rrca
rrca
rrca ; Multiply by 32
ld l,a ; Pass to L
and 3 ; Mask with 00000011
add a,88 ; 88 * 256 = 22528 - start of attributes.
ld h,a ; Put it in the High Byte
ld a,l ; We get y value *32
and 224 ; Mask with 11100000
ld l,a ; Put it in L
ld a,IYH ; xpos
adc a,l ; Add it to the Low byte
ld l,a ; Put it back in L, and we're done. HL=Address.
INC HL ; we need to be to the right of the ATTR point as pushes write backwards.
INC HL
; attr
LD SP,HL
EXX
PUSH HL ; top row
EXX
LD HL,34 ; we need to move down to the next row. We already backed up 2, so we add 34.
ADD HL,SP
LD SP,HL
EX AF,AF' ; bottom row
PUSH AF
ptNextSprite2:
; done. Cleanup.
LD SP,(ptstackSave) ; put our stack back together.
; done all 4 final clean up
POP IY
POP IX
POP AF ; recover interrupt status
JP PO, pt_nointerrupts
EI ; Okay. We put everything back. If you need interrupts, you can go with em.
pt_nointerrupts:
END ASM
END SUB