;----------------------------------------
; 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
|