1include(`z88dk.m4')
2include(`config_private.inc')
3
4; -----------------------------------------------------------------------------
5; BIFROST* ENGINE by Einar Saukas - v1.2/H
6; A Rainbow Graphics Support Engine for Animated Tiles
7;
8; Most 16x16 tiles created by Dave Hughes (R-Tape)
9; Adapted to z88dk by aralbrec
10; -----------------------------------------------------------------------------
11
12SECTION BIFROSTH
13org $ded7
14
15PUBLIC _BIFROSTH_tilemap
16defc _BIFROSTH_tilemap = __BIFROSTH_TILE_MAP
17
18; -----------------------------------------------------------------------------
19
20PUBLIC asm_BIFROSTH_drawBackTilesH
21
22asm_BIFROSTH_drawBackTilesH:
23draw_back_tiles:
24        bit     0, e
25        jr      nz, draw_updown_tiles
26        push    de
27        push    bc
28        dec     e
29        call    draw_updown_tiles
30        pop     bc
31        pop     de
32        inc     e
33draw_updown_tiles:
34        ld      a, e
35        cp      19
36        ret     nc
37        ld      a, d
38        and     $0f
39        jr      z, draw_tile_pos
40        xor     d
41        ld      d, a
42        push    de
43        push    bc
44        call    nz, draw_tile_pos
45        pop     bc
46        pop     de
47        ld      a, d
48        add     a, 16
49        ld      d, a
50
51PUBLIC asm_BIFROSTH_drawTilePosH
52
53asm_BIFROSTH_drawTilePosH:
54draw_tile_pos:
55        ld      a, d
56        cp      160
57        ret     nc
58        rrca
59        rrca
60        rrca
61        add     a, d
62        add     a, e
63        sub     17
64        rra
65        ld      l, a
66        ld      h, __BIFROSTH_TILE_MAP/256
67        ld      a,(hl)
68        ld      hl, get_tile+2
69        cp      (hl)
70        jp      c, draw_tile
71        inc     a
72        jp      nz, get_tile+9
73
74; -----------------------------------------------------------------------------
75
76PUBLIC asm_BIFROSTH_fillTileAttrH
77
78asm_BIFROSTH_fillTileAttrH:
79fill_tile_attr:
80        ld      (exit_draw+1), sp
81
82; calculate multicolor attribute address
83        ld      a, c
84        ld      h, attribs/512
85        ld      l, d
86        add     hl, hl
87        ld      bc, attribs-((attribs/512)*512)
88        add     hl, bc
89        ld      sp, hl
90        ld      h, deltas/256
91        ld      l, e
92        ld      c, (hl)                 ; BC = delta (column offset)
93        dec     b
94        inc     l
95        ld      l, (hl)                 ; HL = second delta (column offset)
96        ld      h, b
97        sbc     hl, bc
98        ex      de, hl
99
100; replace attrib with value
101Z88DK_FOR(`LOOP', `1', `16',
102`
103        pop     hl
104        add     hl, bc
105        ld      (hl), a
106        add     hl, de
107        ld      (hl), a
108')
109        jp      exit_draw
110
111; -----------------------------------------------------------------------------
112draw_at_last_col:
113; draw multicolor attributes of a tile starting at the last column in the multicolor area
114Z88DK_FOR(`LOOP', `1', `15',
115`
116        pop     hl
117        ld      c, a
118        add     hl, bc
119        ex      de, hl
120        ldi
121        inc     hl
122        ex      de, hl
123')
124        pop     hl
125        ld      c, a
126        add     hl, bc
127        ex      de, hl
128        jp      ldi_exit_draw
129
130; -----------------------------------------------------------------------------
131bitmaps:
132; lookup table with screen coordinates
133Z88DK_FOR(`LOOP', `1', `16',
134`
135        defw      0
136')
137Z88DK_FOR(`ROWREPT', `0', `17',
138`
139Z88DK_FOR(`LINREPT', `0', `7',
140`
141        defw      16384 + (((ROWREPT+1)/8)*2048) + (LINREPT*256) + (((ROWREPT+1)%8)*32) + __BIFROSTH_SHIFT_COLUMNS
142')
143')
144Z88DK_FOR(`LOOP', `1', `16',
145`
146        defw      0
147')
148; -----------------------------------------------------------------------------
149attribs:
150; lookup table with multicolor attribute coordinates
151Z88DK_FOR(`LOOP', `1', `16',
152`
153        defw      0
154')
155Z88DK_FOR(`RACEREPT', `0', `143',
156`
157        defw      race_raster + (RACEREPT * 41)
158')
159Z88DK_FOR(`LOOP', `1', `16',
160`
161        defw      0
162')
163; -----------------------------------------------------------------------------
164        defb      0
165show_next3_delayed:
166        nop                             ; extra delay
167        nop                             ; extra delay
168        jp      show_next3
169
170; -----------------------------------------------------------------------------
171draw_sprites:
172        ld      de, 0                   ; first sprite: D = lin, E = col
173        ld      bc, 0                   ; first sprite: C = tile
174        call    draw_sprite
175        ld      de, 0                   ; second sprite: D = lin, E = col
176        ld      c, 0                    ; second sprite: C = tile
177draw_sprite:
178; execute draw_tile with different delays depending on column
179        ld      b, 81                   ; delay for draw_at_odd_col
180        ld      a, e
181        rrca
182        dec     a
183        jr      c, sprite_loop1
184        ld      b, 44                   ; delay for draw_at_even_col_inc
185        cp      5
186        jr      c, sprite_loop2
187        ld      b, 40                   ; delay for draw_at_even_col_dec
188        cp      8
189        jr      nz, sprite_loop
190        ld      b, 86                   ; delay for draw_at_last_col
191sprite_loop2:
192        sbc     hl, hl                  ; extra delay
193sprite_loop1:
194        inc     hl                      ; extra delay
195sprite_loop:
196        dec     b
197        jr      nz, sprite_loop
198skip_sprite_loop:
199        ld      a, c
200        jp      draw_tile
201
202; -----------------------------------------------------------------------------
203draw_at_even_col_dec:
204; draw multicolor attributes of a tile starting at even column with non-increasing delta
205        cp      21
206        jp      z, draw_at_last_col
207        ld      c, a
208        inc     l
209        sub     (hl)                    ; (HL) = second delta (column offset)
210        jp      c, draw_at_even_col_inc
211        inc     a
212        ex      af, af'
213        ld      a, c
214Z88DK_FOR(`LOOP', `1', `15',
215`
216        pop     hl
217        ld      c, a
218        add     hl, bc
219        ex      de, hl
220        ldi
221        ex      de, hl
222        ex      af, af
223        ld      c, a
224        sbc     hl, bc
225        ex      de, hl
226        ldi
227        ex      de, hl
228        ex      af, af
229')
230        pop     hl
231        ld      c, a
232        add     hl, bc
233        ex      de, hl
234        ldi
235        ex      de, hl
236        ex      af, af'
237        ld      c, a
238        sbc     hl, bc
239        ex      de, hl
240        jp      ldi_exit_draw
241
242; -----------------------------------------------------------------------------
243deltas:
244; lookup table with deltas (column offsets)
245IF __BIFROSTH_SHIFT_COLUMNS=0
246        defb      4, 4, 5, 7, 8, 10, 11, 14, 15, 17, 18, 32, 33, 28, 29, 24, 25, 20, 21, 21
247ELSE
248        defb      4, 4, 5, 7, 8, 10, 11, 14, 15, 33, 34, 29, 30, 24, 25, 20, 21, 17, 18, 18
249ENDIF
250
251; -----------------------------------------------------------------------------
252draw_at_even_col_inc:
253; draw multicolor attributes of a tile starting at even column with increasing delta
254        cpl
255        ex      af, af'
256        ld      a, c
257Z88DK_FOR(`LOOP', `1', `15',
258`
259        pop     hl
260
261        ld      c, a
262        add     hl, bc
263        ex      de, hl
264        ldi
265        ex      de, hl
266        ex      af, af
267
268        ld      c, a
269        add     hl, bc
270        ex      de, hl
271        ldi
272        ex      de, hl
273        ex      af, af
274')
275        pop     hl
276        ld      c, a
277        add     hl, bc
278        ex      de, hl
279        ldi
280        ex      de, hl
281        ex      af, af'
282        ld      c, a
283        add     hl, bc
284        ex      de, hl
285        jp      ldi_exit_draw
286
287; -----------------------------------------------------------------------------
288skip_tile:
289        ld      b, $84
290delay_tile:
291        dec     b
292        jr      nz, delay_tile
293        ret
294
295; -----------------------------------------------------------------------------
296show_next3:
297        call    show_next_tile
298        call    show_next_tile
299
300PUBLIC asm_BIFROSTH_showNextTile
301
302asm_BIFROSTH_showNextTile:
303show_next_tile:
304        ld      de, $1001               ; D = lin (16,32,48..144), E = col (1,3,5..17)
305        ld      a, e
306        sub     +(9-__BIFROSTH_TILE_ORDER)*2
307        ld      e, a
308        jr      nc, prev_lin
309        add     a, 18
310        ld      e, a
311        xor     a
312        jr      reset_lin
313prev_lin:
314        ld      a, d
315        sub     16
316        ld      d, a
317        cp      16
318reset_lin:
319        sbc     a, a
320        and     144
321        add     a, d
322        ld      d, a
323        ld      (show_next_tile+1), de
324
325; -----------------------------------------------------------------------------
326
327PUBLIC asm_BIFROSTH_showTilePosH
328
329asm_BIFROSTH_showTilePosH:
330show_tile_pos:                          ; D = lin (0..160), E = col (0..18)
331        ld      a, d
332        rrca
333        rrca
334        rrca
335        add     a, d
336        add     a, e
337        sub     17
338        rra
339        ld      l, a
340        ld      h, __BIFROSTH_TILE_MAP/256
341
342get_tile:
343        ld      a,(hl)
344        cp      __BIFROSTH_STATIC_MIN
345        jp      c, animate_tile
346        inc     a
347        jr      z, skip_tile
348        sub     1+__BIFROSTH_STATIC_OVERLAP
349        jr      draw_tile
350animate_tile:
351        rrca
352IF __BIFROSTH_ANIM_GROUP=4
353        rrca
354        add     a, $40
355        rlca
356ELSE
357        nop
358        add     a, $80
359        nop
360ENDIF
361        rlca
362        ld      (hl), a
363
364; -----------------------------------------------------------------------------
365
366PUBLIC asm_BIFROSTH_drawTileH
367PUBLIC _BIFROSTH_TILE_IMAGES
368
369asm_BIFROSTH_drawTileH:
370draw_tile:                              ; D = lin, E = col, A = tile
371; calculate screen bitmap lookup address
372        ld      (exit_draw+1), sp
373        ld      h, bitmaps/512
374        ld      l, d
375        add     hl, hl
376        ld      sp, hl
377
378; preserve values
379        ld      b, e
380        ld      c, h
381
382; calculate tile image address
383        ld      l, 0
384        srl     a
385        rr      l
386        rra
387        rr      l
388        ld      h, a
389defc _BIFROSTH_TILE_IMAGES = ASMPC + 1
390        ld      de, __BIFROSTH_TILE_IMAGES
391        add     hl, de
392
393; draw bitmap lines
394Z88DK_FOR(`LOOP', `1', `16',
395`
396        pop     de
397        ld      a, e
398        add     a, b
399        ld      e, a
400        ldi
401        ldi
402')
403; calculate multicolor attribute address
404        ex      de, hl
405        ld      hl, attribs-bitmaps-32
406        add     hl, sp
407        ld      sp, hl
408        ld      h, deltas/256
409        ld      l, b
410        ld      a, (hl)                 ; A = delta (column offset)
411
412; distinguish between even/odd column
413        ld      b, 0
414        bit     0, l
415        jp      z, draw_at_even_col_dec
416
417draw_at_odd_col:
418; draw multicolor attributes starting at odd column
419Z88DK_FOR(`LOOP', `1', `15',
420`
421        pop     hl
422        ld      c, a
423        add     hl, bc
424        ex      de, hl
425        ldi
426        ldi
427        ex      de, hl
428')
429        pop     hl
430        ld      c, a
431        add     hl, bc
432        ex      de, hl
433        ldi
434ldi_exit_draw:
435        ldi
436
437exit_draw:
438        ld      sp, 0
439        ret
440
441; -----------------------------------------------------------------------------
442
443PUBLIC _BIFROSTH_ISR_HOOK
444
445main_engine:
446; preserve all registers
447        push    af
448        push    bc
449        push    de
450        push    hl
451        ex      af, af'
452        exx
453        push    af
454        push    bc
455        push    de
456        push    hl
457
458tile_mapping_begin:
459; draw and animate first 3 tiles
460        call    show_next3_delayed
461IF __BIFROSTH_ANIM_SPEED=4
462        ld      a, $c6
463ELSE
464        ld      a, $fe
465ENDIF
466        ld      (animate_tile+2), a
467IF __BIFROSTH_SPRITE_MODE=0
468; draw (and perhaps animate) another 3 tiles
469        call    show_next3
470ELSE
471; draw both sprite tiles
472        call    draw_sprites
473ENDIF
474        ld      a, $c6
475        ld      (animate_tile+2), a
476tile_mapping_end:
477
478; synchronize with the raster beam
479        ld      bc, $3805
480        ld      a, 14
481        jr      sync_raster
482delay_128k:
483        ld      b, $3b
484
485sync_raster:
486        nop                             ; extra delay
487sync_raster_loop:
488        djnz    sync_raster_loop
489        ld      b, a
490        ld      hl, ($4000)             ; synchronize
491        dec     c
492        jr      nz, sync_raster
493
494; wait for the raster beam
495IF __BIFROSTH_SHIFT_COLUMNS=0
496        ld      a, (bc)                 ; extra delay
497        ld      b, 4
498ELSE
499        add     hl, hl                  ; extra delay
500        ld      b, 5
501ENDIF
502wait_raster:
503        djnz    wait_raster
504
505; preserve stack pointer
506        ld      (exit_raster+1), sp
507
508; race the raster beam to update attributes at the right time
509race_raster:
510Z88DK_FOR(`ROWREPT', `0', `17',
511`
512Z88DK_FOR(`LOOP', `1', `8',
513`
514IF __BIFROSTH_SHIFT_COLUMNS=0
515        ld      sp, $5833+(32*ROWREPT)
516        ld      bc, 0                   ; columns 01 and 02
517        ld      de, 0                   ; columns 03 and 04
518        ld      hl, 0                   ; columns 05 and 06
519        exx
520        ld      de, 0                   ; columns 07 and 08
521        ld      hl, 0                   ; columns 09 and 10
522        ld      bc, 0                   ; columns 17 and 18
523        push    bc
524        ld      bc, 0                   ; columns 15 and 16
525        push    bc
526        ld      bc, 0                   ; columns 13 and 14
527        push    bc
528        ld      bc, 0                   ; columns 11 and 12
529        push    bc
530        push    hl
531        push    de
532        exx
533        push    hl
534        push    de
535        push    bc
536ELSE
537        ld      sp, $5837+(32*ROWREPT)
538        ld      hl, 0                   ; columns 05 and 06
539        ld      de, 0                   ; columns 07 and 08
540        ld      bc, 0                   ; columns 09 and 10
541        exx
542        ld      hl, 0                   ; columns 11 and 12
543        ld      de, 0                   ; columns 21 and 22
544        ld      bc, 0                   ; columns 19 and 20
545        push    de
546        ld      de, 0                   ; columns 17 and 18
547        push    bc
548        push    de
549        ld      de, 0                   ; columns 15 and 16
550        push    de
551        ld      de, 0                   ; columns 13 and 14
552        push    de
553        push    hl
554        exx
555        push    bc
556        push    de
557        push    hl
558ENDIF
559')
560')
561exit_raster:
562; restore stack pointer
563        ld      sp, 0
564; restore all registers
565        pop     hl
566        pop     de
567        pop     bc
568        pop     af
569        exx
570        ex      af, af'
571        pop     hl
572        pop     de
573        pop     bc
574        pop     af
575
576_BIFROSTH_ISR_HOOK:
577
578        ei
579        reti
580
581; -----------------------------------------------------------------------------
582; RAND USR 64995 to activate engine
583
584PUBLIC asm_BIFROSTH_start
585
586asm_BIFROSTH_start:
587
588        di
589        ld      a, ($004c)
590        and     2
591        ld      (delay_128k-1), a
592        ld      a, $fe
593        ld      i, a
594        im      2
595        ld      hl,main_engine
596        ld      ($fdfe),hl
597        ei
598        ret
599
600; -----------------------------------------------------------------------------
601; RAND USR 65012 to deactivate engine
602; replaced
603;
604;PUBLIC asm_BIFROSTH_stop
605;
606;asm_BIFROSTH_stop:
607;
608;        di
609;        ld      a, $3f
610;        ld      i, a
611;        im      1
612;        ei
613;        ret
614
615defs $fdfd - $ded7 - ASMPC
616
617; -----------------------------------------------------------------------------
618; interrupt address at $fdfd
619        jp      main_engine
620
621; -----------------------------------------------------------------------------
622; jump vector table at addresses $fe00-$ff00
623        defs 257, 0xfd
624; -----------------------------------------------------------------------------
625