Alive
News Team Current issue History Online Support Download Forum @Pouet

01 - 02 - SE - 03 - 04 - 05 - 06 - 07 - 08 - 09 - 10 - 11 - 12 - 13 - 14

Alive 10
;----------------------------------------
; Keftales Bootsector Source
;
; Turbo-Ass 1.76
;
; Code:  Cyclone / X-Troll
;
; Sound: gwEm
;
; Released at Outline 2005
;
; Please take note that this code wasn't
; optimized for speed but for small code
; size to get it into the 480 bytes of a
; bootsector. It can be done much faster
; with a bit more memory and time :).
; Please note that the boosector is 
; written to the bootsector with a TASM
; Module. So there is no generator prg 
; included.
;
;----------------------------------------
tv              EQU 1           ; Testversion 0 / Bootsector 1
;----------------------------------------
               OPT D+,P+,O+,W+
;----------------------------------------
no_of_screens   EQU 12          ; guess what :)
;----------------------------------------
              IFNE tv

              BREAKPT 'set sr=$2300:go'
                clr.b   $FFFF8260.w     ; some settings for the debugger version
                lea     varbase(PC),A6

              ELSE

                movea.l $0432.w,A6      ; get base adress from _membot

              ENDC

                lea     (A6),A0         ; clear variable space just to make sure
                bsr     cls             ; in fact this clears more than needed

                move.l  $70.w,-(SP)     ; save old_vbl

                movea.l $044E.w,A0      ; _v_bas_ad

                move.l  A0,physcr(A6)   ; set screen to current screen
                bsr     cls             ; clear screen
                movem.l pal(PC),D0-D7   ; fetch palette and write to hardware
                movem.l D0-D7,$FFFF8240.w

                pea     scrmem(A6)      ; align screen to a 256 byte border
                clr.b   3(SP)
                movea.l (SP)+,A1
                move.l  A1,logscr(A6)   ; set logical screen

                move.w  #no_of_screens-1,D1 ; screens for zoomer
                lea     scr_tab(A6),A0  ; get start of screen table
                move.l  A0,scrvecres(A6) ; resetvalue for screen pointer
                lea     4(A0),A2        ; set to next screen
                move.l  A2,scrvec(A6)   ; initial screen

                lea     scr_tab+4*2*no_of_screens(A6),A2 ; last entry

mkscrtab:       move.l  A1,(A0)+        ; zoom in
                move.l  A1,-(A2)        ; and out (in reverse order)
                lea     32000(A1),A1    ; next screen buffer
                dbra    D1,mkscrtab
;----------------------------------------
                lea     $FFFF8801.w,A0  ; initialize sound
                lea     zak(PC),A1
                bra.s   snd0
snd:            movep.w D0,0(A0)
snd0:           move.w  (A1)+,D0
                bne.s   snd

                lea     vbl(PC),A0      ;  set own vbl
                move.l  A0,$70.w
                move.w  #1,divisor(A6)  ; initialize zoom factor
;----------------------------------------
wait:
                move.w  #199,D1         ; 200 lines to render
yloop:
                moveq   #0,D3           ; set x=0 see subroutine to understand
                bsr     calc_y          ; calculate y offset & get logscr in a0
                lea     0(A0,D4.w),A0   ; calculate final address of line

                move.w  #160/4-1,D3     ; 160 bytes to clear for a line
                clr.l   (A0)+           ; this loop clears the scanline
                dbra    D3,*-4          ; before it is rendered

                move.w  #320-1,D0       ; 320 pixels to render
xloop:
                cmpi.b  #$39,$FFFFFC02.w ; check for space
                beq.s   exit            ; exit if it is pressed

                move.w  #-160,D2        ; make sure image is x-centered
                add.w   D0,D2           ; D2=x-160
                move.w  D2,D4
                move.w  divisor(A6),D6
                subq.w  #1,D6
                move.w  #-100/no_of_screens,D3 ; initial offset from y-center
                muls    D6,D3                 ; will be centered on last screen
                add.w   #-100%no_of_screens,D3
                add.w   D1,D3                 ; D3=y-y_offset 
                move.w  D3,D5

; the following is a heavy waste of cpu but its the smallest way to code it
; it might be possible to obtain a better formula but i had no time for this
; you may try different formulas here to get other patterns

                muls    D5,D2           ; D2 = Y*X ; this is the distorsion
                muls    D4,D4           ; D4 = X*X
                muls    D5,D5           ; D5 = Y*Y
                add.w   D4,D2           ; this results to:
                sub.w   D5,D2           ; D2 = X*Y + X*X - Y*Y

; Here are some example fomurlas but there are a lot more possible

; cross                  x*x - y*y
; distorted cross  x*y + x*x - y*y
; perfect circles        x*x + y*y
; distoreted oval  x*y + x*x + y*y

                move.w  divisor(A6),D4
                lsr.l   D4,D2
                and.w   #$0F,D2         ; stay within the desired range
                bne.s   *+2             ; colour cycling on colour 0 is not nice
                addq.w  #1,D2           ; so avoid it
                bsr     plot            ; render pixel to screen
                dbra    D0,xloop
                dbra    D1,yloop

                bsr.s   flip_scr        ; switch to next screen
                bsr.s   wvbl            ; wait for next vbl

init:           move.w  divisor(A6),D0    ; get divisor
                addq.w  #1,D0             ; increment
                cmp.w   #no_of_screens,D0 ; all screens calculated yet?
                bgt.s   precalc_done      ; then start zooming
                move.w  D0,divisor(A6)    ; otherwise write it back
                bra.s   wait              ; and loop
precalc_done:
zoom:
                moveq   #2,D0           ; make it run in 3 vbls :)
delay:          bsr.s   wvbl            ; this is newskool what do you expect?
                dbra    D0,delay
                bsr.s   flip_scr        ; switch to next screen
                cmpi.b  #$39,$FFFFFC02.w ; check for space
                bne.s   zoom
exit:
                move.l  $044E.w,$045E.w ; restore old screen with OS
                move.l  (SP)+,$70.w     ; restore old vbl

               IFEQ tv
                rts                     ; exit bootsector
               ELSE
                illegal                 ; debugger exit for testversion
               ENDC
cls:
                move.w  #32000/4-1,D0   ; 32000 bytes to clear
                clr.l   (A0)+           ; this routine is used for screens
                dbra    D0,*-4          ; and since memory is an issue also for
                rts                     ; the variables (a bit oversized :)
;-------------------------------------------
flip_scr:
                movea.l scrvec(A6),A1         ; get scrvec
                move.l  logscr(A6),physcr(A6) ; logscr -> physcr
flip_scr0:      move.l  (A1)+,logscr(A6)      ; newscr -> logscr
                bne.s   flip_scr1
                movea.l scrvecres(A6),A1      ; scrtab -> scrvec
                bra.s   flip_scr0
flip_scr1:      move.l  A1,scrvec(A6)         ; write back scrvec
                rts
;-------------------------------------------
wvbl:
                move.l  $0466.w,D7     ; memorize _vb_clock
                cmp.l   $0466.w,D7     ; still the same?
                beq.s   *-6            ; no then return
                rts
;-------------------------------------------
vbl:
                movem.l D0-D7,-(SP)       ; save registers

                movem.l $FFFF8242.w,D0-D6 ; rotate colours
                move.w  $FFFF825E.w,$FFFF8242.w
                movem.l D0-D6,$FFFF8244.w

                movem.l (SP)+,D0-D7       ; restore registers
vbl1:
                move.b  physcr+1(A6),$FFFF8201.w ; write screen adress
                move.b  physcr+2(A6),$FFFF8203.w

                addq.l  #1,$0466.w      ; increment _vb_clock
                rte
;-------------------------------------------
calc_xy:
                moveq   #$0F,D3         ; and.w #$FFF0,d3
                not.w   D3
                and.w   D0,D3
                lsr.w   #1,D3           ; /16*8 = /2
calc_y:
                move.w  #160,D4         ; convert y to screenaddress
                mulu    D1,D4           ; a table would have been faster ;)
                add.w   D3,D4           ; add x component
                movea.l logscr(A6),A0   ; get logical screenadress
                rts
;------------------------------------------
plot:                                   ; very small and SLOW c2p
                bsr.s   calc_xy         ; calc screen offsets from coordinates
                lea     8(A0,D4.w),A0   ; address

                move.w  D0,D4           ; determine which bit to set
                moveq   #$0F,D3
                and.w   D3,D4
                sub.w   D4,D3

                moveq   #3,D5           ; four planes
loop:
                moveq   #0,D4
                btst    D5,D2           ; n=0-3
                beq.s   no_bit
                bset    D3,D4
no_bit:         or.w    D4,-(A0)
                dbra    D5,loop
                rts
;-------------------------------------------
pal:            DC.W $0202,$0101,$0112,$0223,$0334,$0445,$0556,$0667
                DC.W $0777,$0766,$0655,$0544,$0433,$0322,$0211,$0101

zak:            DC.W $02EE,$030E,$0910,$0BEF,$0C00,$0D0C,$07FD
;-------------------------------------------
varbase:        RSRESET
divisor:        RS.W 1
adder:          RS.W 1
scrvecres:      RS.L 1
scrvec:         RS.L 1
logscr:         RS.L 1
physcr:         RS.L 1
scr_tab:        RS.L 2*no_of_screens+1

               RS.B 256
scrmem:         RS.B 0

               IFNE tv
               BSS             ; in case of debug version put screens into BSS
               REPT no_of_screens
                DS.B 32000
               ENDR
               ENDC
;-------------------------------------------
               END

Alive 10