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