home *** CD-ROM | disk | FTP | other *** search
- ; \|/
- ; O O
- ; --------------------------------oOO--U--OOo--------------------------------
- ; | |
- ; | Library for CakeHead 2. |
- ; | By Alain BROBECKER. (as Baah) |
- ; | September 1995 |
- ; ---------------------------------------------------------------------------
- ; This library contains a lot of usefull routines, most of them won' t
- ; be called often in a sourcecode. (The worst case I think is once per
- ; VBl, for wait_and_swap, clear_mode9...)
- ; You must note that some of these routs need to be together, because I
- ; considered that some variables (fixed_time, videoram_adress, ...) will
- ; be accessed through PC. So, better not to change the order of this
- ; library if you are not familiar with this.
- ; Also, when I indicate ??? on the KILL line, this means that a swi
- ; is used, and since I have no decent docs, there may be extra registers
- ; modified, so beware!
-
-
- ;****************************************************************************
- ; MAKE INVERSES
- ;****************************************************************************
- ; This routine calculates and store all the numbers between (r1/1) and
- ; (r1/r2). You guessed it, I use this to make an inverses table, where
- ; r1 is the premultiplication factor.
- ; IN ---- r0=adress where to create the inverses table.
- ; r1=dividend.
- ; r2=last divisor.
- ; OUT --- nothing.
- ; KILL -- r0 to r8.
-
- .make_inverses
- mov r3,#1 ; Used by the division routine.
- mov r4,#1 ; r4 is the current divisor.
- ._make_one_inverse
- mov r5,r4 ; r5=divisor.
- mov r6,r1 ; r6=premul factor=dividend.
- mov r7,#0 ; r7 will contain the quotient of r1/r4.
- mov r8,#15 ; Shift for the division.
- ._divide_one_step
- cmp r6,r5,lsl r8 ; dividend bigger than divisor<<r8?
- subGE r6,r6,r5,lsl r8 ; Yes, then dividend-=divisor<<r8,
- addGE r7,r7,r3,lsl r8 ; and add 1<<r8 to the quotient.
- subS r8,r8,#1 ; Next shift.
- bPL _divide_one_step
- cmp r5,r6,lsl #1 ; Flags=divisor-2*rest.
- addLE r7,r7,#1 ; Round to nearest integer.
- str r7,[r0],#4 ; Save r1/r4.
- add r4,r4,#1 ; r4 is the next divisor.
- cmp r4,r2 ; It was the last one?
- bLE _make_one_inverse
- mov pc,r14 ; Finished.
-
-
- ;****************************************************************************
- ; MAKE SIN COS
- ;****************************************************************************
- ; This routine calculates the sinus table, for angles between 0 and 5*pi/2.
- ; (So the cos table is between pi/2 and 5*pi/2) I take in account the fact
- ; that all sinus and cosinus values between 0 and pi/4 are positive.
- ; When I write sinN, it is in fact sin(N*A).
- ; IN ---- r0=adress where to create the table.
- ; OUT --- nothing.
- ; KILL -- r0 to r12.
-
- #set sin_shift=16 ; Shift for saved values. Must be =<28.
- #set sin_nb=64 ; Nb of angles between [0;pi/4[.
-
- .sinA dcd 3294116 ; sin((pi/4)/sin_nb)*2^28.
- .cosA dcd 268415243 ; cos((pi/4)/sin_nb)*2^28.
-
- .make_sinus
- ldr r1,sinA ; r1=sinA*2^28.
- ldr r2,cosA ; r2=cosA*2^28.
- mov r3,#0 ; r3=sin0*2^28.
- mov r4,#1<<28 ; r4=cos0*2^28.
- mov r5,#sin_nb+1
- .make_one_sinus
- mov r6,r4,lsr #28-sin_shift ; r6=cosN*2^shift.
- str r6,[r0,#sin_nb*2*4] ; Save sin(N+pi/2)=cosN.
- mov r6,r3,lsr #28-sin_shift ; r6=sinN*2^shift.
- str r6,[r0],#4 ; Save sinN.
- umul64 r6,r7,r1,r3,r8,r9,r10 ; [r6|r7]=sinN*sinA.
- umul64 r8,r9,r2,r4,r10,r11,r12 ; [r8|r9]=cosN*cosA.
- sub64 r6,r7,r8,r9,r6,r7 ; [r6|r7]=cos(N+1)=cosN*sin1-sinN*sin1.
- umul64 r3,r8,r3,r2,r9,r10,r11 ; [r3|r8]=sinN*cosA.
- umul64 r4,r9,r4,r1,r10,r11,r12 ; [r4|r9]=cosN*sinA.
- add64 r3,r8,r3,r8,r4,r9 ; [r3|r8]=sin(N+1)=sinN*cos1+cosN*sin1.
- adjust64 r3,r3,r8,28 ; r1=sin(N+1)=sinN*cos1+cosN*sin1.
- adjust64 r4,r6,r7,28 ; r2=cos(N+1)=cosN*sin1-sinN*sin1.
- subS r5,r5,#1 ; One sinus processed.
- bNE make_one_sinus
-
- sub r0,r0,#4 ; Complete the table by stupid copy.
- mov r1,r0 ; Point on the position which are like
- add r2,r0,#sin_nb*8 ; (pi/4+k*(pi/2)) 0<=k<=4
- mov r3,r2
- add r4,r2,#sin_nb*8
- mov r5,r4
- add r6,r4,#sin_nb*8
- mov r7,r6
- add r8,r6,#sin_nb*8
- mov r9,r8
- mov r10,#sin_nb+1 ; Copy sin_nb+1 values.
- ._make_sinus_copy
- ldr r11,[r0],#-4
- str r11,[r3],#4 ; sin(pi-X)=sinX.
- str r11,[r8],#-4 ; sin(2*pi+X)=sinX.
- rsb r11,r11,#0
- str r11,[r4],#-4 ; sin(pi+X)=-sinX.
- str r11,[r7],#4 ; sin(2*pi-X)=-sinX.
- ldr r11,[r2],#-4
- str r11,[r1],#4 ; cos(-X)=cosX.
- subS r10,r10,#1 ; One value copied.
- strNE r11,[r9],#4 ; cos(2*pi+X)=cosX. No copy if r10=0.
- rsb r11,r11,#0
- str r11,[r5],#4 ; cos(pi-X)=-cosX.
- str r11,[r6],#-4 ; cos(pi+X)=-cosX.
- bNE _make_sinus_copy
- mov pc,r14
-
-
- ;****************************************************************************
- ; FIX TIME
- ;****************************************************************************
- ; This function sets the current time as new time base.
- ; IN ---- nothing.
- ; OUT --- r0=nb of cent-seconds since last hard reset.
- ; KILL -- r0 and ???.
- .fix_time
- swi OS_ReadMonotonicTime
- str r0,fixed_time
- mov pc,r14
- .fixed_time
- dcd 0
-
-
- ;****************************************************************************
- ; READ TIME
- ;****************************************************************************
- ; This function sets the current time as new time base.
- ; IN ---- nothing.
- ; OUT --- r0=nb of cent-seconds since last time fix.
- ; KILL -- r0,r1 and ???.
- .read_time
- swi OS_ReadMonotonicTime
- ldr r1,fixed_time
- sub r0,r0,r1
- mov pc,r14
-
-
- ; ###########################################################################
- ; ###########################################################################
- ; ###########################################################################
- ; ###########################################################################
- ; ###########################################################################
- ; | |
- ; | SCREEN ROUTS |
- ; | |
- ; ###########################################################################
-
-
- .videoram_adress
- dcd 148,-1
- .screen_offset
- dcd &02000000,0
-
- ;****************************************************************************
- ; SCREEN INIT
- ;****************************************************************************
- ; This function sets the screen to mode9, remove cursors, and read the
- ; physical screen base of screen.
- ; IN ---- nothing.
- ; OUT --- nothing.
- ; KILL -- r0,r1,???
- .screen_init
- swi 256+22 ; Vdu 22, set screenmode.
- swi 256+9 ; Mode 9.
- swi OS_RemoveCursors ; Fuck the cursor.
- adr r0,videoram_adress
- mov r1,r0
- swi OS_ReadVduVariables ; Get videoram adress.
- mov pc,r14
-
-
- ;****************************************************************************
- ; GET SHOWSCREEN
- ;****************************************************************************
- ; This function will return the adress of the showscreen.
- ; IN ---- nothing.
- ; OUT --- r0=showscreen adress.
- ; KILL -- r0,r1.
- .get_showscreen
- ldr r0,videoram_adress
- ldr r1,screen_offset+4
- add r0,r0,r1 ; r0=adress of showscreen.
- mov pc,r14
-
-
- ;****************************************************************************
- ; GET WORKSCREEN
- ;****************************************************************************
- ; This function will return the adress of the workscreen.
- ; IN ---- nothing.
- ; OUT --- r0=workscreen adress.
- ; KILL -- r0,r1.
- .get_workscreen
- ldr r0,videoram_adress
- ldr r1,screen_offset+4
- eor r1,r1,#160*256
- add r0,r0,r1 ; r0=adress of workscreen.
- mov pc,r14
-
- ;****************************************************************************
- ; WAIT AND SWAP
- ;****************************************************************************
- ; This routine waits for vertical sync, and then it swaps between workscreen
- ; and showscreen, and returns adress of workscreen.
- ; IN ---- nothing.
- ; OUT --- r0=adress of workscreen.
- ; KILL -- r0,r1 and ???.
-
- .wait_and_swap
- mov r0,#&13 ; Wait for Vsync.
- swi OS_Byte
- ldr r1,screen_offset+4 ; Swap show and work screen.
- eor r1,r1,#160*256
- str r1,screen_offset+4
- adr r1,screen_offset+3
- mov r0,#22
- swi OS_Word
- ldr r0,videoram_adress ; Calculate adress of workscreen.
- ldr r1,screen_offset+4
- eor r1,r1,#160*256
- add r0,r0,r1
- mov pc,r14
-
-
- ;****************************************************************************
- ; DISAPPEAR
- ;****************************************************************************
- ; This routine will make the current showed screen scroll up or down to
- ; let another, uniformly colored, screen appear. After this rout, the
- ; whole videoram is filled with the color given as a parameter.
- ; IN ---- r1=color to fill with. (0-255)
- ; OUT --- r0=adress of workscreen.
- ; KILL -- r0 and nothing else, but uses r13.
-
- .disappear
- stmfd r13!,{r1-r12,r14}
- str r1,_fill_pattern
- mov r11,#160 ; r11=inc1.
- ldr r10,screen_offset+4 ; r10=screen_offset.
- cmp r10,#0 ; First screen? (r10=0)
- rsbNE r11,r11,#0 ; If r10<>0, inc1=-160.
- mov r12,r11 ; r12=inc2=inc1.
- eor r2,r10,#160*256 ; r2=offset to workscreen.
- ldr r0,videoram_adress
- add r0,r0,r2 ; r0 points on workscreen.
- bl clear_mode9 ; Clear workscreen.
- ._one_frame
- mov r0,#&13 ; Wait for Vsync.
- swi OS_Byte
- addS r10,r10,r11 ; Screen offset+=inc1.
- add r11,r11,r12 ; inc1+=inc2.
- movLE r10,#0 ; offset=<0, then offset=0 and we
- movLE r12,#0 ; indicate we have reached the end.
- cmp r10,#160*256
- movGE r10,#160*256 ; offset>=160*256, then offset=160*256
- movGE r12,#0 ; and indicate it' s the end.
- str r10,screen_offset+4 ; Set screen adress.
- adr r1,screen_offset+3
- mov r0,#22
- swi OS_Word
- cmp r12,#0 ; We have reached the end?
- bNE _one_frame
- ldr r1,_fill_pattern ; Clear the new workscreen.
- eor r2,r10,#160*256
- ldr r0,videoram_adress
- add r0,r0,r2 ; r0 points on workscreen.
- bl clear_mode9
- ldmfd r13!,{r1-r12,pc}
- ._fill_pattern
- dcd 0
-
-
- ;****************************************************************************
- ; SET PALETTE
- ;****************************************************************************
- ; Not much to say, so....
- ; IN ---- r2 points on the 16*3 bytes color palette.
- ; OUT --- nothing.
- ; KILL -- r0 to r4 and ???.
- .set_palette
- adr r0,_setpal_string
- mov r3,#0 ; Counter for the colors.
- ._setpal_loop
- strB r3,[r0,#1] ; Put color number into string.
- ldrB r4,[r2],#1 ; Copy red compound into the string.
- strB r4,[r0,#3]
- ldrB r4,[r2],#1 ; Same for green...
- strB r4,[r0,#4]
- ldrB r4,[r2],#1 ; ..and blue...
- strB r4,[r0,#5]
- mov r1,#6 ; Use a 'write 6 bytes' to change color.
- swi OS_WriteN
- addS r3,r3,#1
- cmp r3,#16 ; 16 colors changed?
- bNE _setpal_loop
- mov pc,r14 ; Finished.
- ._setpal_string
- dcb 19,0,16,0,0,0
-
- ALIGN
-
-
- ;****************************************************************************
- ; CLEAR MODE9
- ;****************************************************************************
- ; Again a stupid routine, no comment... (22*32*14+27*14+6)=40*256
- ; IN ---- r0 points on the Mode9 screen.
- ; r1=pattern to fill with. (In the lower byte)
- ; OUT --- nothing.
- ; KILL -- nothing, but uses r13 as a stack.
-
- .clear_mode9
- stmfd r13!,{r2-r12,r14}
- str r13,_old_stack
- add r1,r1,r1,lsl #8
- add r1,r1,r1,lsl #16
- mov r2,r1:mov r3,r2:mov r4,r3:mov r5,r4:mov r6,r5:mov r7,r6:mov r8,r7
- mov r9,r8:mov r10,r9:mov r11,r10:mov r12,r11:mov r13,r12
- mov r14,#22
- ._clear_many
- str r14,_counter
- mov r14,r13 ; Here, r1-r14=fill pattern.
- stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}
- stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}
- stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}
- stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}
- stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}
- stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}
- stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}
- stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}
- ldr r14,_counter
- subS r14,r14,#1
- bNE _clear_many
- mov r14,r13
- stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}
- stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}
- stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}
- stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}
- stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}
- stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}
- stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r14}:stmia r0!,{r1-r6}
- sub r0,r0,#160*256 ; Restore r0.
- ldr r13,_old_stack
- ldmfd r13!,{r2-r12,pc}
- ._old_stack
- dcd 0
- ._counter
- dcd 0
-