-
Notifications
You must be signed in to change notification settings - Fork 0
/
maze.asm
263 lines (205 loc) · 4.53 KB
/
maze.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
; Maze
;
; Maze cell data; 4 bits per cell. 0 - no wall, 1 - wall
; 1 left
; 2 right
; 4 up
; 8 down
jiffies = $14
sm_ptr = $58 ; Screen memory pointer
ramtop = $6a
ch = $2f4 ; Pointer to high byte of character set
chr = $2400 ; International character set
dmactl = $22f ; DMA control
dl_ptr = $230
gfxctl = $d01d ; Graphics control
pmbase = $d407 ; PMG base pointer
p0_hpos = $d000 ; Player 0 hor pos
p1_hpos = $d001 ; Player 1 hor pos
p0_color= $2c0
p1_color= $2c1
gprior = $26f ; Graphics priority
color_reg1 = $2c5
color_reg2 = $2c6
p0_size = $d008
p0_addr = $c4
p1_addr = $c6
; Zero page variables
ORG $cb
position .word 0 ; Screen Position, word, address to screen memory
coord_x .byte 0 ; x coordinate of current cell, 0-39
coord_y .byte 0 ; y coordinate, 0-23
maze_ready .byte 0 ; is maze ready; 0 - false, otherwise true
target_jiffies .byte 0 ; keeps track of target jiffies to wait for
wall_mask .byte %00000001 ; convenience var to check walls
.MACRO SETUP_WAIT
.IFDEF SLOW_DOWN
lda jiffies ; check jiffies counters
clc
sta target_jiffies
.ENDIF
.ENDM
.MACRO DO_THE_WAIT
wait_loop
.IFDEF SLOW_DOWN
lda target_jiffies
sec
sbc jiffies
bpl wait_loop ; check if negative, as one might actually miss the
; target if checking for equality
.ENDIF
.ENDM
ORG $2000
.LOCAL display_list
:3 .byte $70
.byte $42 ; ANTIC mode 2 + sm ptr
sm .word 0
:23 .byte $02 ; ANTIC mode 2
.byte $41, a(display_list) ; Jump to address and wait for VBL
.ENDL
.DEF ALG_HUNT_AND_KILL ; maze_alg points to Hunt-and-Kill
.DEF SLOW_DOWN ; slow down the maze generation
ICL "definitions"
; Maze carving
ICL "sparse_maze"
; Maze algorithms
ICL "hunt_and_kill"
; Control schemes
ICL "player_control"
; General utility macros and procs
ICL "general_utils"
; Coordinate mapping utilities
ICL "coord_utils"
the_guy_height = 7
the_guy
.byte %00000000
.byte %00111000
.byte %01010100
.byte %01111100
.byte %01000100
.byte %00111000
.byte %00000000
; Player grid coordinates
p0_x .byte 1
p0_y .byte 1
p1_x .byte 20
p1_y .byte 12
.PROC init
lda #$30 ; set PMG 2k memory are from $3000-$37ff
sta pmbase
sta position + 1
clc
adc #4 ; p0 data starts at pmbase + 1k
sta p0_addr + 1
adc #1 ; p1 data starts at p1_addr + $100
sta p1_addr + 1
lda #0 ; reset lo-bytes of addresses
sta p0_addr
sta p1_addr
sta position
setup_display_list
lda #0 ; set black background color
sta color_reg2
lda #$f ; max luminance for foreground
sta color_reg1
mva #>chr ch ; set character set
init_and_enable_pmg
setup_players
clear_screen_memory
maze_alg.init
jmp main
.ENDP
.PROC setup_display_list
lda #0 ; disable ANTIC for display list update
sta dmactl
mwa sm_ptr display_list.sm
mwa #display_list dl_ptr ; set display list address
lda #$22 ; enable ANTIC again
sta dmactl
rts
.ENDP
.PROC init_and_enable_pmg
enable_pmg
; PMG / http://www.hintermueller.de/dereatari-chapter-4
lda #[46 + 16] ; single line resolution
sta dmactl
; clear pmg memory
ldy #0
lda #0
clr_loop_pmg
sta (p0_addr), y
iny
bne clr_loop_pmg
ldy #0
; p0 lo byte sets y coordinate (includes borders)
lda p0_y
sta p0_addr
p0_loop ; Copy... The Guy
lda the_guy,y
sta (p0_addr),y
iny
cpy #the_guy_height
bne p0_loop
lda #1 ; set priority to players, playfield then background
sta gprior
lda #2 ; enable players
sta gfxctl
lda #$BF
sta p0_color
p1_init
; set p1
ldy #0
lda p1_y
sta p1_addr
p1_loop
lda the_guy,y
sta (p1_addr),y
iny
cpy #the_guy_height
bne p1_loop
lda #$48
sta p1_color
rts
.ENDP
.PROC setup_players
.ENDP
.PROC clear_screen_memory
; Clear screen memory, 40*24 bytes = 3 pages and change
mwa sm_ptr position
mwa sm_ptr position+2 ; use zero page locations without worries at this point
inc position+3 ; as they are uninitialized anyway. I setup pointers
mwa position+2 position+4 ; to 3 consecutive pages for simpler clearing loop
inc position+5
lda #walled_in
ldy #0 ; Offset
clr_loop
sta (position),y
sta (position+2),y
sta (position+4),y
iny
bne clr_loop
; Still 192 bytes to go on the fourth page
ldy #192
inc position+5 ; increase hi byte for next page
clr_loop2
dey
sta (position+4),y
bne clr_loop2
rts
.ENDP
.PROC main
maze_loop
maze_alg.step ; run one step of algorithm
lda #0
cmp maze_ready ; is maze ready
beq maze_loop
main_loop
SETUP_WAIT
player_control.read_controls
DO_THE_WAIT
jmp main_loop
.ENDP
; Custom character set
ORG chr
INS "maze.chr"
RUN init