-
Notifications
You must be signed in to change notification settings - Fork 2
/
tutorial_2_scrolling.asm
353 lines (290 loc) · 6.21 KB
/
tutorial_2_scrolling.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
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
// ------------------------------------------------------------
//
// Tutorial 2 - 4 way scrolling by changing screen ptr location.
//
// Shows how to scroll the screen in both directions by modifying the TextXPos
// and TextYPos and then calculating the address of the screen to set into
// ScreenPtr and ColorPtr
//
.cpu _45gs02
// ------------------------------------------------------------
// Defines to describe the screen size
//
// If you use H320 then SCREEN_WIDTH much be <= 360, otherwise <= 720
#define H320
.const SCREEN_WIDTH = 320
// If you use V200 then SCREEN_HEIGHT much be <= 240, otherwise <= 480
#define V200
.const SCREEN_HEIGHT = 240
// Choose IS_NTSC if you are running in NTSC 60hz mode
//#define IS_NTSC
// ------------------------------------------------------------
#import "mega65macros.asm"
// Figure out how many characters wide and high the visible area is
//
.const CHARS_WIDE = (SCREEN_WIDTH / 8)
.const CHARS_HIGH = (SCREEN_HEIGHT / 8)
// We have a screen size that is larger than the visible area so we can freely
// scroll around it.
//
.const NUM_SCREENS_WIDE = 2
.const NUM_SCREENS_HIGH = 2
// LOGICAL_ROW_SIZE is the number of bytes the VIC-IV advances each row
//
.const LOGICAL_ROW_SIZE = CHARS_WIDE * NUM_SCREENS_WIDE
.const LOGICAL_NUM_ROWS = CHARS_HIGH * NUM_SCREENS_HIGH
// Color RAM is at a fixed base address
//
.const COLOR_RAM = $ff80000
// ------------------------------------------------------------
//
* = $02 "Basepage" virtual
ChrPtr: .word $0000
ColPtr: .dword $00000000
XPos: .word $0000
YPos: .word $0000
FrameCount: .byte $00
XCourse: .word $0000
YCourse: .word $0000
// ------------------------------------------------------------
//
BasicUpstart65(Entry)
* = $2016 "Basic Entry"
Entry: {
sei
lda #$35
sta $01
enable40Mhz()
enableVIC4Registers()
disableCIAInterrupts()
disableC65ROM()
//Disable IRQ raster interrupts
//because C65 uses raster interrupts in the ROM
lda #$00
sta $d01a
//Change VIC2 stuff here to save having to disable hot registers
lda #%00000111 // Reset XSCL (horizontal fine scroll)
trb $d016
cli
// Setup H640 / H320 mode
//
lda #$80
#if H320
trb $d031 //Clear bit7=H320
#else
tsb $d031 //Set bit7=H640
#endif
// Setup V400 / V200 mode
lda #$08
#if V200
trb $d031 //Clear bit3=V200
#else
tsb $d031 //Set bit3=V400
#endif
// SDBDRWDLSB,SDBDRWDMSB - Side Border size
lda #LEFT_BORDER
sta $d05c
lda #%00111111
trb $d05d
lda #(>LEFT_BORDER) & %00111111
tsb $d05d
// TBDRPOS - Top Border position
lda #<TOP_BORDER
sta $d048
lda #%00001111
trb $d049
lda #(>TOP_BORDER) & %00001111
tsb $d049
// BBDRPOS - Bottom Border position
lda #<BOTTOM_BORDER
sta $d04a
lda #%00001111
trb $d04b
lda #(>BOTTOM_BORDER) & %00001111
tsb $d04b
VIC4_SetNumCharacters(CHARS_WIDE+1)
VIC4_SetNumRows(CHARS_HIGH+1)
VIC4_SetRowWidth(LOGICAL_ROW_SIZE)
VIC4_SetScreenPtr(SCREEN_BASE)
jsr InitScreenColorRAM
// Set background red so we can see where the screen ends
// and the borders start
lda #$02
sta $d021
// Main loop
mainloop:
// Wait for (H400) rasterline BOT_BORDER
!: lda $d053
and #$07
cmp #>(BOTTOM_BORDER)
bne !-
lda #<(BOTTOM_BORDER)
cmp $d052
bne !-
!: cmp $d052
beq !-
inc $d020
inc FrameCount
ldx FrameCount
lda sintable,x
sta XPos+0
lda costable,x
sta YPos+0
// inc XPos+0
// inc YPos+0
// lda #$00
// sta XPos+0
// sta YPos+0
// Set the fine X scroll by moving TextXPos left
//
lda XPos+0
and #$07
#if H320
asl // When in H320 mode, move 2x the number of pixels
#endif
sta shiftLeft
sec
lda #<LEFT_BORDER //#$50
sbc shiftLeft:#$00
sta $d04c
lda #>LEFT_BORDER
sbc #$00
sta $d04d
// Set the fine Y scroll by moving TextYPos up
//
lda YPos+0
and #$07
#if V200
asl // When in H200 mode, move 2x the number of pixels
#endif
sta shiftUp
sec
lda #<TOP_BORDER
sbc shiftUp:#$00
sta $d04e
lda #>TOP_BORDER
sbc #$00
sta $d04f
// Now calculate the Y course scroll
lda YPos+0
sta YCourse+0
lda YPos+1
sta YCourse+1
// Shift right 3 times to divide by 8
lsr YCourse+1
ror YCourse+0
lsr YCourse+1
ror YCourse+0
lsr YCourse+1
ror YCourse+0
// Now calculate the X course scroll
lda XPos+0
sta XCourse+0
lda XPos+1
sta XCourse+1
// Shift right 3 times to divide by 8
lsr XCourse+1
ror XCourse+0
lsr XCourse+1
ror XCourse+0
lsr XCourse+1
ror XCourse+0
// We have a lookup table for the byte offset of each row,
// put Y course into X to access that table
ldx YCourse+0
// Using X as the row value, add the X course value to get the
// offset into both the screen and color RAM
//
clc
lda RowOffsetsLo,x
adc XCourse+0
sta screenOffsLo
sta colorOffsLo
lda RowOffsetsHi,x
adc XCourse+1
sta screenOffsHi
sta colorOffsHi
// Set the lower 16bits of screen ptr,
// !!! avoid having your screen buffer cross a 64k boundary) !!!
//
clc
lda #<SCREEN_BASE
adc screenOffsLo:#$00
sta $d060
lda #>SCREEN_BASE
adc screenOffsHi:#$00
sta $d061
// Set the lower 16bits of color ptr,
// !!! avoid having your color buffer cross a 64k boundary) !!!
//
clc
lda #<COLOR_RAM
adc colorOffsLo:#$00
sta $d064
lda #>COLOR_RAM
adc colorOffsHi:#$00
sta $d065
dec $d020
jmp mainloop
}
// ------------------------------------------------------------
// Routine to initialize the screen and color RAM with data
//
InitScreenColorRAM: {
//
lda #<SCREEN_BASE
sta ChrPtr+0
lda #>SCREEN_BASE
sta ChrPtr+1
lda #<COLOR_RAM
sta ColPtr+0
lda #>COLOR_RAM
sta ColPtr+1
lda #[COLOR_RAM >>16]
sta ColPtr+2
lda #[COLOR_RAM >> 24]
sta ColPtr+3
ldx #$00
!oloop:
txa
tay
ldz #$00
!iloop:
tya
sta (ChrPtr),z
and #$07
sta ((ColPtr)),z
iny
inz
cpz #LOGICAL_ROW_SIZE
bne !iloop-
clc
lda ChrPtr+0
adc #LOGICAL_ROW_SIZE
sta ChrPtr+0
lda ChrPtr+1
adc #0
sta ChrPtr+1
clc
lda ColPtr+0
adc #LOGICAL_ROW_SIZE
sta ColPtr+0
lda ColPtr+1
adc #0
sta ColPtr+1
inx
cpx #LOGICAL_NUM_ROWS
bne !oloop-
rts
}
RowOffsetsLo:
.fill LOGICAL_NUM_ROWS, <(i * LOGICAL_ROW_SIZE)
RowOffsetsHi:
.fill LOGICAL_NUM_ROWS, >(i * LOGICAL_ROW_SIZE)
sintable:
.fill 256, 84 + (sin((i/256) * PI * 2) * 84)
costable:
.fill 256, 84 + (cos((i/256) * PI * 2) * 84)
* = $4000 "ScreenBase" virtual
SCREEN_BASE:
.fill (LOGICAL_ROW_SIZE * LOGICAL_NUM_ROWS), $00