@C9Sourcecode: Chessboard-Zoomer

@C7
We would like to thank Coyer / Daydream Software who contributed this cute fx
for the Coder`s Revenge intro. :) Until now this was the one and only source
code we ever got. :|

Yes - it`s not a new and breathtaking demo effekt. In fact it has already been
used in several demos. ;) But now you get to know how it was done - and you
will see it`s tricky and veeery simply.

I think because of the simple algorithm there`s no further explanation needed.
The source is well commented - have fun when browsing through.

                                                                      @G"^.red"
@C3
vdu=256

DIM CODE 102400
FOR PASS = 0 TO 2 STEP 2
P%=CODE
[ OPT PASS

SWI vdu+22:SWI vdu+13                   ; Screenmode 13

ADR R0,getscr_tab
ADR R1,screenbase
SWI "OS_ReadVduVariables"               ; get screenmemory startaddress

.mainloop
MOV R0,#19:SWI "OS_Byte"                ; VSync

;---TIMING...
   SWI vdu+19:SWI vdu+1:SWI vdu+24
   MOV R0,#220:SWI "OS_WriteC"
   MOV R0,#220:SWI "OS_WriteC"
   MOV R0,#000:SWI "OS_WriteC"
;------------

ADR R1,sinustables                      ; address of 1. sinustable
ADD R4,R1,#4096                         ; address of 2. sinustable
LDR R0,sinuscounter:ADD R1,R1,R0,LSL#2  ; set current offset in table 1
LDR R0,sinuscounter+4:ADD R4,R4,R0,LSL#2; set current offset in table 2

LDR R3,screenbase                       ; screenmemory startaddress
MOV R0,#256                             ; screenline counter
LDR R5,chesspos:STR R5,temp             ; preserve chessboard position

.LOOP
LDR R5,[R1],#4                          ; load value from sinustab 1
LDR R6,[R4],#4                          ; load value from sinustab 2
ADD R2,R5,R6                            ; add them to get an irregular wave...

ADR R5,checkertab-&2000:ADD R5,R5,#&2000; address of square-scaling table
LDR R6,temp                             ; load current scaling counter
LDRB R5,[R5,R2,LSR#10]                  ; load incrementor corresp. to cur. zoom
ADD R6,R6,R5                            ; - add them
STR R6,temp                             ; - and preserve for next loop

ADR R5,Sprite-&2200:ADD R5,R5,#&2200    ; address of chessboard GfX
ADD R5,R5,#56                           ; - leave out sprite header
ADD R2,R2,R5                            ; offset in gfx for current scaled line

TST R6,#%10000000000000                 ; next 'checker'-row of chessboard-gfx?
ADDEQ R2,R2,#320*128                    ; - then do it! (remove this to see how
                                        ;                it works!)

LDMIA R2!,{R5-R12}:STMIA R3!,{R5-R12}   ; copy one line (320 pixels) of chess-
LDMIA R2!,{R5-R12}:STMIA R3!,{R5-R12}   ; board gfx into screen memory
LDMIA R2!,{R5-R12}:STMIA R3!,{R5-R12}
LDMIA R2!,{R5-R12}:STMIA R3!,{R5-R12}
LDMIA R2!,{R5-R12}:STMIA R3!,{R5-R12}
LDMIA R2!,{R5-R12}:STMIA R3!,{R5-R12}
LDMIA R2!,{R5-R12}:STMIA R3!,{R5-R12}
LDMIA R2!,{R5-R12}:STMIA R3!,{R5-R12}
LDMIA R2!,{R5-R12}:STMIA R3!,{R5-R12}
LDMIA R2!,{R5-R12}:STMIA R3!,{R5-R12}
SUBS R0,R0,#1:BNE LOOP                  ; next pixelline...

;---TIMING...
   SWI vdu+19:SWI vdu+1:SWI vdu+24
   MOV R0,#000:SWI "OS_WriteC"
   MOV R0,#000:SWI "OS_WriteC"
   MOV R0,#000:SWI "OS_WriteC"
;------------

LDR R0,chesspos                         ; increase chessboard position
ADD R0,R0,#100                          ; -> whole chessboard moves up
STR R0,chesspos

LDR R0,sinuscounter                     ; increase sinuscounter 1
ADD R0,R0,#2:CMP R0,#290*2:SUBGE R0,R0,#290*2
STR R0,sinuscounter

LDR R0,sinuscounter+4                   ; increase sinuscounter 2
SUBS R0,R0,#3:ADDMI R0,R0,#260
STR R0,sinuscounter+4

SWI "OS_ReadEscapeState":BCC mainloop   ; check for ESC key...
SWI "OS_Exit"


.getscr_tab EQUD 149:EQUD -1
.screenbase EQUD 0

.temp EQUD 0
.chesspos EQUD 0

.sinuscounter EQUD 0:EQUD 0

.sinustables FN_workspace(2048*4)
.checkertab    FN_workspace(1024)
.Sprite      FN_workspace(82296)     ; - load chessboard-gfx here

]
NEXT PASS


REM calculate sinustables
FOR I=0 TO 1023
sinustables!(I*4)=320 * INT((40+SIN(I*PI/290)*39))       :REM table 1
sinustables!(I*4+1024*4)=320 * INT((23+SIN(I*PI/130)*23)):REM table 2
NEXT I

REM this table scales the height of the chessboard-squares
FOR I = 0 TO 1023
checkertab?I=(1+I/64)*120
NEXT I

REM load chessboard gfx
OSCLI "LOAD SchachP "+STR$~(Sprite)

OSCLI "SAVE RAM:c "+STR$~CODE+" "+STR$~P%
CALL CODE
END


REM reserves a block of memory (for use in inline-assembler, only)
DEF FN_workspace(number_of_bytes)
 P% = P% + number_of_bytes
 O% = O% + number_of_bytes
= 0

