1include(`z88dk.m4')
2include(`config_private.inc')
3
4; -----------------------------------------------------------------------------
5; BIFROST* ENGINE by Einar Saukas - v1.2/L
6; A Rainbow Graphics Support Engine for Animated Tiles
7;
8; Based on the ZXodus Engine by Andrew Owen
9; Most 16x16 tiles created by Dave Hughes (R-Tape)
10;
11; Adapted to z88dk by aralbrec
12; -----------------------------------------------------------------------------
13
14SECTION BIFROSTL
15org $e501
16
17; -----------------------------------------------------------------------------
18attribs:
19Z88DK_FOR(`ROWREPT', `0', `17',
20`
21        defw      race_raster + (ROWREPT * 8 * 41)
22')
23; -----------------------------------------------------------------------------
24
25PUBLIC asm_BIFROSTL_fillTileAttrL
26
27asm_BIFROSTL_fillTileAttrL:
28fill_tile_attr:
29
30; calculate multicolor attribute address
31        ld      h, attribs/256
32        ld      l, e
33        set     6, l
34        ld      a, (hl)                 ; A = delta (column offset)
35        ld      l, d
36        sla     l
37        ld      d, (hl)
38        dec     l
39        add     a, (hl)
40        ld      l, a
41        adc     a, d
42        sub     l
43        ld      h, a
44
45; replace attrib with value C
46        ld      de, 40
47        ld      b, 16
48fill_loop:
49        ld      (hl), c
50        inc     hl
51        ld      (hl), c
52        add     hl, de
53        djnz    fill_loop
54        ret
55
56; -----------------------------------------------------------------------------
57deltas:
58        defb      4, 5, 7, 8, 10, 11, 14, 15, 17, 18, 32, 33, 28, 29, 24, 25, 20, 21, 20
59; -----------------------------------------------------------------------------
60
61skip_tile:
62        ld      b, $71
63delay_skip:
64        djnz    delay_skip
65        sbc     hl, hl                  ; extra delay
66        ret
67
68; -----------------------------------------------------------------------------
69
70show_next3_delayed1:
71        nop                             ; extra delay
72show_next3_delayed2:
73        ld      bc, $8f00
74delay_show:
75        djnz    delay_show
76        call    show_next_tile
77        call    show_next_tile
78
79PUBLIC asm_BIFROSTL_showNextTile
80
81asm_BIFROSTL_showNextTile:
82show_next_tile:
83        ld      de, $0101               ; D = row, E = col (1,3,5..17)
84        ld      a, e
85        sub     __BIFROSTL_TILE_ORDER * 2
86        ld      e, a
87        sbc     a, a
88        and     18
89        add     a, e
90        ld      e, a
91        sbc     a, a
92        ld      c, a
93        add     a, a
94        add     a, d
95        ld      d, a
96        sbc     a, a
97        xor     c
98        and     18
99        add     a, d
100        ld      d, a
101        ld      (show_next_tile+1), de
102
103; -----------------------------------------------------------------------------
104
105PUBLIC asm_BIFROSTL_showTilePosL
106PUBLIC _BIFROSTL_tilemap
107
108defc _BIFROSTL_tilemap = __BIFROSTL_TILE_MAP
109
110asm_BIFROSTL_showTilePosL:
111show_tile_pos:                          ; D = row, E = col
112        ld      a, d
113        rlca
114        rlca
115        rlca
116        add     a, d
117        add     a, e
118        sub     8
119        rra
120        ld      l, a
121        ld      h, __BIFROSTL_TILE_MAP/256
122
123get_tile:
124        ld      a,(hl)
125        cp      __BIFROSTL_STATIC_MIN
126        jp      c, animate_tile
127        inc     a
128        jr      z, skip_tile
129        sub     1+__BIFROSTL_STATIC_OVERLAP
130        jr      draw_tile
131animate_tile:
132        rrca
133IF __BIFROSTL_ANIM_GROUP=4
134        rrca
135        add     a, $40
136        rlca
137ELSE
138        nop
139        add     a, $80
140        nop
141ENDIF
142        rlca
143        ld      (hl), a
144
145; -----------------------------------------------------------------------------
146
147PUBLIC asm_BIFROSTL_drawTileL
148PUBLIC _BIFROSTL_TILE_IMAGES
149
150asm_BIFROSTL_drawTileL:
151draw_tile:                              ; D = row, E = col, A = tile
152
153; calculate tile image address
154        ld      (exit_draw+1), sp
155        ld      l, 0
156        srl     a
157        rr      l
158        rra
159        rr      l
160        ld      h, a
161defc _BIFROSTL_TILE_IMAGES = ASMPC + 1
162        ld      bc, __BIFROSTL_TILE_IMAGES
163        add     hl, bc
164        ld      sp, hl
165
166; calculate screen bitmap address
167        ld      a, d                    ; DE = 000RRrrr 000ccccc
168        and     %00000111
169        rrca
170        rrca
171        rrca
172        or      e
173        ld      l, a                    ; L = rrrccccc
174        ld      a, d
175        and     %00011000
176        or      %01000000
177        ld      h, a                    ; H = 010RR000
178
179; draw first bitmap row
180Z88DK_FOR(`LOOP', `1', `7',
181`
182        pop     bc
183        ld      (hl),c
184        inc     l
185        ld      (hl),b
186        dec     l
187        inc     h
188')
189        pop     bc
190        ld      (hl),c
191        inc     l
192        ld      (hl),b
193; move to next bitmap row
194        ld      bc, 31
195        add     hl, bc
196        ld      a, h
197        and     248
198        ld      h, a
199; draw second bitmap row
200Z88DK_FOR(`LOOP', `1', `7',
201`
202        pop     bc
203        ld      (hl),c
204        inc     l
205        ld      (hl),b
206        dec     l
207        inc     h
208')
209        pop     bc
210        ld      (hl),c
211        inc     l
212        ld      (hl),b
213
214; calculate multicolor attribute address
215        ld      h, attribs/256
216        ld      l, e
217        set     6, l
218        ld      a, (hl)                 ; A = delta (column offset)
219        ld      l, d
220        sla     l
221        ld      d, (hl)
222        dec     l
223        add     a, (hl)
224        ld      l, a
225        adc     a, d
226        sub     l
227        ld      h, a
228
229; draw multicolor attribute
230        ld      de, 40
231Z88DK_FOR(`LOOP', `1', `15',
232`
233        pop     bc
234        ld      (hl), c
235        inc     hl
236        ld      (hl), b
237        add     hl, de
238')
239        pop     bc
240        ld      (hl), c
241        inc     hl
242        ld      (hl), b
243
244exit_draw:
245        ld      sp, 0
246        ret
247
248; -----------------------------------------------------------------------------
249
250PUBLIC _BIFROSTL_ISR_HOOK
251
252main_engine:
253; preserve all registers
254        push    af
255        push    bc
256        push    de
257        push    hl
258        ex      af, af'
259        exx
260        push    af
261        push    bc
262        push    de
263        push    hl
264
265tile_mapping_begin:
266; draw and animate first 3 tiles
267        call    show_next3_delayed1
268IF __BIFROSTL_ANIM_SPEED=4
269        ld      a, $c6
270ELSE
271        ld      a, $fe
272ENDIF
273        ld      (animate_tile+2), a
274; draw (and perhaps animate) another 3 tiles
275        call    show_next3_delayed2
276        ld      a, $c6
277        ld      (animate_tile+2), a
278tile_mapping_end:
279
280; synchronize with the raster beam
281        ld      bc, $3805
282        ld      a, 14
283        jr      sync_raster
284delay_128k:
285        ld      b, $3b
286
287sync_raster:
288        nop                             ; extra delay
289sync_raster_loop:
290        djnz    sync_raster_loop
291        ld      b, a
292        ld      hl, ($4000)             ; synchronize
293        dec     c
294        jr      nz, sync_raster
295
296; wait for the raster beam
297        ld      a, (bc)                 ; extra delay
298        ld      b, 4
299wait_raster:
300        djnz    wait_raster
301
302; preserve stack pointer
303        ld      (exit_raster+1), sp
304
305; race the raster beam to update attributes at the right time
306race_raster:
307Z88DK_FOR(`ROWREPT', `0', `17',
308`
309Z88DK_FOR(`LOOP', `1', `8',
310`
311        ld      sp, $5833+(32*ROWREPT)
312        ld      bc, 0                   ; columns 01 and 02
313        ld      de, 0                   ; columns 03 and 04
314        ld      hl, 0                   ; columns 05 and 06
315        exx
316        ld      de, 0                   ; columns 07 and 08
317        ld      hl, 0                   ; columns 09 and 10
318        ld      bc, 0                   ; columns 17 and 18
319        push    bc
320        ld      bc, 0                   ; columns 15 and 16
321        push    bc
322        ld      bc, 0                   ; columns 13 and 14
323        push    bc
324        ld      bc, 0                   ; columns 11 and 12
325        push    bc
326        push    hl
327        push    de
328        exx
329        push    hl
330        push    de
331        push    bc
332')
333')
334exit_raster:
335; restore stack pointer
336        ld      sp, 0
337; restore all registers
338        pop     hl
339        pop     de
340        pop     bc
341        pop     af
342        exx
343        ex      af, af'
344        pop     hl
345        pop     de
346        pop     bc
347        pop     af
348_BIFROSTL_ISR_HOOK:
349        ei
350        reti
351
352; -----------------------------------------------------------------------------
353; RAND USR 64995 to activate engine
354
355PUBLIC asm_BIFROSTL_start
356
357asm_BIFROSTL_start:
358
359        di
360        ld      a, ($004c)
361        and     2
362        ld      (delay_128k-1), a
363        ld      a, $fe
364        ld      i, a
365        im      2
366        ld      hl,main_engine
367        ld      ($fdfe),hl
368        ei
369        ret
370
371; -----------------------------------------------------------------------------
372; RAND USR 65012 to deactivate engine
373; replaced
374;
375;PUBLIC asm_BIFROSTL_stop
376;
377;asm_BIFROSTL_stop:
378;
379;        di
380;        ld      a, $3f
381;        ld      i, a
382;        im      1
383;        ei
384;        ret
385;
386
387defs $fdfd - $e501 - ASMPC
388
389; -----------------------------------------------------------------------------
390; interrupt address at $fdfd
391        jp      main_engine
392
393; -----------------------------------------------------------------------------
394; jump vector table at addresses $fe00-$ff00
395
396        defs 257, 0xfd
397
398; -----------------------------------------------------------------------------
399