cleanup and vbl a0 corruption fix
[megadrive.git] / hexed / hexed.s
1 ##################################################
2 #                                                #
3 # Assemble with gas                              #
4 #   --register-prefix-optional --bitwise-or      #
5 #                                                #
6 ##################################################
7
8 .text
9 .globl main
10
11 ##################################################
12 #                                                #
13 #        Register and bitmask definitions        #
14 #                                                #
15 ##################################################
16
17 .equ GFXDATA,           0xc00000
18 .equ GFXCNTL,           0xc00004
19
20 .equ VDP0_E_HBI,        0x10
21 .equ VDP0_E_DISPLAY,    0x02 
22 .equ VDP0_PLTT_FULL,    0x04 
23
24 .equ VDP1_SMS_MODE,     0x80
25 .equ VDP1_E_DISPLAY,    0x40
26 .equ VDP1_E_VBI,        0x20
27 .equ VDP1_E_DMA,        0x10
28 .equ VDP1_NTSC,         0x00
29 .equ VDP1_PAL,          0x08
30 .equ VDP1_RESERVED,     0x04
31
32 .equ VDP12_SPR_SHADOWS, 0x08
33 .equ VDP12_SCREEN_V224, 0x00
34 .equ VDP12_SCREEN_V448, 0x04
35 .equ VDP12_PROGRESSIVE, 0x00
36 .equ VDP12_INTERLACED,  0x02
37 .equ VDP12_SCREEN_H256, 0x00
38 .equ VDP12_SCREEN_H320, 0x81
39
40 .equ VDP16_MAP_V32,     0x00
41 .equ VDP16_MAP_V64,     0x10
42 .equ VDP16_MAP_V128,    0x30
43 .equ VDP16_MAP_H32,     0x00
44 .equ VDP16_MAP_H64,     0x01
45 .equ VDP16_MAP_H128,    0x03
46
47
48
49 ##################################################
50 #                                                #
51 #                   MACROS                       #
52 #                                                #
53 ##################################################
54
55
56 /* Write val to VDP register reg */
57 .macro write_vdp_reg reg val
58         move.w #((\reg << 8) + 0x8000 + \val),(a3)
59 .endm
60
61
62 /* For immediate addresses */
63 .macro VRAM_ADDR reg adr
64         move.l #(((0x4000 + (\adr & 0x3fff)) << 16) + (\adr >> 14)),\reg
65 .endm
66
67
68 .macro CRAM_ADDR reg adr
69         move.l  #(((0xc000 + (\adr & 0x3fff)) << 16) + (\adr >> 14)),\reg
70 .endm
71
72
73 # make VDP word from address adr and store in d0
74 .macro XRAM_ADDR_var adr
75         move.l \adr,d0
76         lsl.l #8,d0
77         lsl.l #8,d0
78         rol.l #2,d0
79         lsl.b #2,d0
80         lsr.l #2,d0
81 .endm
82
83
84 .macro VRAM_ADDR_var adr
85         XRAM_ADDR_var \adr
86         or.l #0x40000000,d0
87 .endm
88
89
90 .macro CRAM_ADDR_var adr
91         XRAM_ADDR_var \adr
92         or.l #0xc0000000,d0
93 .endm
94
95
96 .macro VSCROLL_ADDR reg adr
97         move.l  #(((0x4000 + (\adr & 0x3fff)) << 16) + ((\adr >> 14) | 0x10)),\reg
98 .endm
99
100
101 .macro HSCROLL_ADDR reg adr
102         move.l #(((0x4000 + (\adr & 0x3fff)) << 16) + (\adr >> 14)),\reg
103 .endm
104
105
106 #################################################
107 #                                               #
108 #                    DATA                       #
109 #                                               #
110 #################################################
111
112 colors:
113         dc.w 0x0000,0x0eee
114 colors_end:
115
116 # pattern:
117
118
119 sprite_data:
120         /*         Y        size     link          attr        X */
121         dc.w       0;  dc.b 0x05;  dc.b 0;  dc.w 0x6002;  dc.w 0
122 sprite_data_end:
123
124 hello:
125         .ascii  "hello world"
126
127 ##################################################
128 #                                                #
129 #               MAIN PROGRAM                     #
130 #                                                #
131 ##################################################
132  
133 .align 2
134
135 main:
136         /* Initialize VDP */
137         jsr             init_gfx
138
139         /* Load color data */
140         movea.l         #0,a0
141         movea.l         #colors,a1
142         moveq.l         #(colors_end-colors)/2,d0
143         jsr             load_colors
144
145         /* load patterns */
146         movea.l         #0,a0
147         movea.l         #font,a1
148         move.l          #128,d0
149         jsr             load_tiles
150
151         /* generate A layer map */
152         movea.l         #0xe000,a6
153         move.l          #28-1,d4
154 lmaploop0:
155         movea.l         a6,a0
156         jsr             load_prepare
157
158         move.l          #64/2-1,d3
159 0:      move.l          #0x00000000,(a0)
160         dbra            d3,0b
161
162         add.l           #64*2,a6
163         dbra            d4,lmaploop0
164
165         /* generate B layer map */
166         movea.l         #0xc000,a0
167         jsr             load_prepare
168
169         move.l          #64*28/2-1,d3
170 0:      move.l          #0x00000000,(a0)
171         dbra            d3,0b
172
173         /* upload sprite data */
174         movea.l         #0xfc00,a0
175         jsr             load_prepare
176         movea.l         #sprite_data,a1
177
178         move.l          #(sprite_data_end-sprite_data)/2-1,d3
179 0:      move.l          (a1)+,(a0)
180         dbra            d3,0b
181
182         jsr             wait_vsync
183
184         movea.l         #hello,a0
185         moveq.l         #1,d0
186         moveq.l         #1,d1
187         jsr             print
188
189 ##################################################
190 #                                                #
191 #                 MAIN LOOP                      #
192 #                                                #
193 ##################################################
194
195 forever:
196
197
198         jsr             wait_vsync
199         bra             forever
200         
201
202
203 #################################################
204 #                                               #
205 #         Initialize VDP registers              #
206 #                                               #
207 #################################################
208
209 init_gfx:
210         move.l          #GFXCNTL,a3
211         write_vdp_reg   0,(VDP0_E_DISPLAY | VDP0_PLTT_FULL)
212         write_vdp_reg   1,(VDP1_E_VBI | VDP1_E_DISPLAY | VDP1_E_DMA | VDP1_RESERVED)
213         write_vdp_reg   2,(0xe000 >> 10)        /* Screen map a adress */
214         write_vdp_reg   3,(0xe000 >> 10)        /* Window address */
215         write_vdp_reg   4,(0xc000 >> 13)        /* Screen map b address */
216         write_vdp_reg   5,(0xfc00 >>  9)        /* Sprite address */
217         write_vdp_reg   6,0     
218         write_vdp_reg   7,0                     /* Backdrop color */
219         write_vdp_reg   10,1                    /* Lines per hblank interrupt */
220         write_vdp_reg   11,0                    /* 2-cell vertical scrolling */
221         write_vdp_reg   12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320)
222         write_vdp_reg   13,(0x8000 >> 10)       /* Horizontal scroll address */
223         write_vdp_reg   15,2
224         write_vdp_reg   16,(VDP16_MAP_V32 | VDP16_MAP_H64)      /* layer size */
225         write_vdp_reg   17,0
226         write_vdp_reg   18,0xff
227         rts
228
229
230 # Load tile data from ROM
231 #  a0: VRAM base
232 #  a1: pattern address
233 #  d0: number of tiles to load
234 #  destroys d1
235
236 load_tiles:
237         move.l          d0,d1
238         VRAM_ADDR_var   a0
239         move.l          d0,(GFXCNTL).l
240         
241         move.l          #GFXDATA,a0
242         lsl.w           #3,d1
243         subq.l          #1,d1
244 0:
245         move.l          (a1)+,(a0)
246         dbra            d1,0b
247
248         rts
249
250
251 # Prepare to write to VDP RAM @a3
252 # sets a0 to VDP data port for convenience
253 #  a0: VRAM base
254 #  destroys d0
255
256 load_prepare:
257         VRAM_ADDR_var   a0
258         move.l          d0,(GFXCNTL).l
259         move.l          #GFXDATA,a0
260         rts
261
262
263 # Load color data from ROM
264 #  a0: CRAM base
265 #  a1: color list address
266 #  d0: number of colors to load
267 #  destroys d1
268
269 load_colors:
270         move.l          d0,d1
271         CRAM_ADDR_var   a0
272         move.l          d0,(GFXCNTL).l
273
274         move.l          #GFXDATA,a0
275         subq.w          #1,d1
276 0:
277         move.w          (a1)+,(a0)
278         dbra            d1,0b
279
280         rts
281
282
283 # print
284 #  a0 - string
285 #  d0 - x
286 #  d1 - y 
287 #  destroys a1
288
289 print:
290         move.l          a0,a1
291         lsl.w           #6,d1
292         add.w           d1,d0
293         lsl.w           #1,d0
294         movea.l         #0xe000,a0
295         add.w           d0,a0
296         jsr             load_prepare
297         moveq.l         #0,d0
298
299 _print_loop:
300         move.b          (a1)+,d0
301         beq             _print_end
302
303         move.w          d0,(a0)
304         jmp             _print_loop
305
306 _print_end:
307         rts
308
309
310 #################################################
311 #                                               #
312 #       Wait for next VBlank interrupt          #
313 #                                               #
314 #################################################
315
316 wait_vsync:
317         movea.l         #vtimer,a0
318         move.l          (a0),a1
319 _wait_change:
320         stop            #0x2000
321         cmp.l           (a0),a1
322         beq             _wait_change
323         rts
324
325
326 #################################################
327 #                                               #
328 #                 RAM DATA                      #
329 #                                               #
330 #################################################
331
332 .bss
333
334 # used by sega_gcc.s
335 .globl htimer
336 .globl vtimer
337 .globl rand_num
338 htimer:         .long 0
339 vtimer:         .long 0
340 rand_num:       .long 0
341
342 #
343
344 .end
345
346 # vim:filetype=asmM68k