********************************************************************
*
*       Voxelspace_Calc
*
*       calculation routines for Voxelspace (PPC version)
*
*       assemble with:
*       powerasm Voxelspace_Calc_P.s to Voxelspace_Calc_P.o smallcode
*
*       link with smalldata and smallcode enabled
*
*       Note: this is extremely heavily optimized. Don't try to
*       understand everything (or anything? :). Documentation is
*       unsufficient.
*
*       © 1997 HAAGE&PARTNER Computer GmbH
*
********************************************************************


                include graphics/gfx.i
                include powerpc/powerpc.i
                include powerpc/memoryppc.i
                include Voxelspace.i

                include powerpc_lib.i

;// XREF / XDEF
                xref    _PowerPCBase
                xref    ChunkyBuffer
                xref    TempBuffer
                xref    HiddenBitmap
                xref    ViewCircle
                xref    ViewAngle
                xref    Perspective
                xref    HeightData
                xref    MapFile
                xref    ActualHeight
                xref    StartHeight
                xref    ViewDistance
                xref    MinRange
                xref    MaxRange
                xref    PixCount
                xref    Pix_Count
                xref    PixelCount
                xref    Ray_Count
                xref    Direction
                xref    RayCount
                xref    Angle
                xref    PosXDet
                xref    PosYDet
                xref    Pic_Mask2
                xref    ColumnCount
                xref    HRotActual
                xref    BitmapWidth
                xref    AreaHeight
                xref    DispHeight
                xref    SkyPos
                xref    SkyScroll
                xref    SkyBuffer
                xref    SkyData
                xref    SkyHeight
                xref    SkyWidth
                xref    SkyWidth2
                xref    BATNumber
                xref    _CITF_0
                xref    _CITF_TEMP

                xdef    GetPPCMem_PPC
                xdef    FreePPCMem_PPC
                xdef    Calculation_PPC_T
                xdef    Calculation_PPC_T_A
                xdef    Calculation2_PPC_T
                xdef    Calculation2_PPC_T_A
                xdef    Calculation4_PPC
                xdef    Calculation4_PPC_A
                xdef    ChunkyToPlanar_PPC
;;/
;// Macros
****  citf: Convert Integer to Floating Signed (Double Precision)
*
*       parameters:
*       1: destination FP-Register
*       2: intermediate FP-Register (MUST hold the value $4330000080000000)
*       3: source GP-Register

citf            macro
                xoris   trash,\3,$8000
                sw      trash,_CITF_TEMP+4
                lf      \1,_CITF_TEMP
                fsub    \1,\1,\2
                endm
;;/

                section "Voxelspace_Calc",code

                cpu     POWERPC
                smalldata
                smallcode
                setlocal        256,r13
                vea

;// GetPPCMem_PPC (allocates memory with respect to MMU configuration)
******************************************************************************
*
*       _d0 = GetPPCMem_PPC (_d0,_d1)
*
*       allocates memory with respect to MMU configuration
*
*       In:  _d0 = memsize
*            _d1 = memflags
*
*       Out: _d0 -> memory
******************************************************************************
GetPPCMem_PPC
                prolog  256
                mr      r5,_d1
                mr      r4,_d0
                li      r6,0
                CALLPOWERPC     AllocVecPPC
                epilog
;;/
;// FreePPCMem_PPC (frees memory allocated by GetPPCMem_PPC)
******************************************************************************
*
*       FreePPCMem_PPC (_a1)
*
*       frees memory allocated by GetPPCMem_PPC
*
*       In:  _a1 -> memory
******************************************************************************
FreePPCMem_PPC
                prolog  256
                mr      r4,_a1
                CALLPOWERPC     FreeVecPPC
                epilog
;;/
;// Calculation_PPC_T (calculates one voxelspace frame - column width 1)
******************************************************************************
*
*       Calculation_PPC_T
*
*       calculates one voxelspace frame with column width = 1
*       the results are written into the chunkybuffer
*       optimized for direct rendering into GfxRAM
*
******************************************************************************
Calculation_PPC_T
                prolog  256
                pushgpr r14-r31
                stw     r13,-12(stack)
                lf      f6,_CITF_0
                lh      r22,PixelCount          ;r22 = pixel count
                lw      r5,MapFile+FILE_ADDRESS ;r5 -> map
                lw      r6,ChunkyBuffer         ;r6 -> chunky buffer
                lh      r7,AreaHeight           ;r7 = area height
                lh      r8,BitmapWidth            ;r8 = area width
                subi    r9,r7,1
                mullw   r9,r9,r8
                add     r3,r6,r9                ;last line in chunky buffer
                lw      r4,ViewAngle            ;r4 -> view angle structure
                subi    r4,r4,4                 ;prepare for postincrement
                lw      r6,TempBuffer           ;r6 -> TempBuffer

                lh      r9,Direction
                lh      r10,Ray_Count
                subi    r13,r10,1
                lh      r11,Angle
                mullw   r10,r10,r11
                li      r12,360*2
                divwu   r10,r10,r12             ;subtract half angle from dir.
                subf    r9,r10,r9               ;r9 = starting ray
                and     r9,r9,r13               ;wrap around
                slwi    r9,r9,4
                slwi    r13,r13,4               ;r13 = view angle mask

                lh      r14,ActualHeight
                mr      r24,r14                 ;r24 = actual height
                lb      r10,SkyScroll
                lh      r12,SkyPos
                extsh   r12,r12
                divwu   r11,r14,r10             ;calc sky scroll value
                subf    r11,r12,r11             ;subtract offset
                neg     r11,r11                 ;r11 = sky offset
                lw      r10,SkyData             ;r10 -> sky definition
                lw      r14,PosYDet
                slwi    r14,r14,9
                lw      r17,PosXDet             ;r17 = pos x value
                slwi    r17,r17,9

                slwi    r15,r7,8
                citf    f1,f6,r15
                srwi    r23,r7,1
                lh      r18,ViewDistance
                citf    f5,f6,r18
                lh      r21,MaxRange
                lh      r18,DispHeight
                citf    f2,f6,r18
                fmul    f0,f1,f5
                fdiv    f0,f0,f2
                lh      r18,MinRange
                citf    f1,f6,r18
                fadd    f5,f1,f5
                citf    f2,f6,r21
                lh      r21,Pix_Count
                citf    f3,f6,r21
                fsub    f2,f2,f1
                fdiv    f2,f2,f3
                lh      r15,ColumnCount         ;number of columns
                mr      r27,r15                 ;r27 = column count
.loop
                fmr     f1,f5
                lw      r17,PosXDet             ;r17 = pos x value
                slwi    r17,r17,9
                lh      r28,HRotActual          ;r28 = HRotActual
                extsh   r28,r28
                mr      r18,r14                 ;temp pos y shifted value
                lw      r19,ViewCircle          ;r19 -> view circle structure
                subi    r19,r19,4               ;prepare for postincrement
                subi    r20,r6,4                ;r20 = temp. chunky buffer ptr
                lwzu    r16,4(r4)
                add     r9,r9,r16               ;jump to next ray
                and     r9,r9,r13               ;mask out
                add     r19,r19,r9              ;r19 -> new view circle
                lwzu    r26,4(r19)
                add     r18,r18,r26
                lwzu    r26,4(r19)
                add     r17,r17,r26
                lwzu    r21,4(r19)              ;r21 = delta y
                lwzu    r0,4(r19)
                mr      r19,r0                  ;r19 = delta x
                slwi    r29,r28,8
                srwi    r25,r27,1
                divw    r29,r29,r25             ;/half column count
                neg     r26,r15
                add     r26,r26,r25
                add     r26,r26,r26
                subi    r26,r26,1
                mullw   r29,r29,r26
                srawi   r29,r29,17              ;r29 = hor. rotation offset
                subf    r29,r23,r29
                mr      r28,r29
                mtctr   r22                     ;store pix count to CTR
.loop2
                rlwinm  r12,r18,27,11,20
                rlwimi  r12,r17,17,21,30
                fdivs   f4,f0,f1
                lhzx    r0,r5,r12
                fctiw   f4,f4
                stfd    f4,-8(stack)
                extrwi  r26,r0,8,16
                fadd    f1,f1,f2
                subf    r26,r24,r26
                lwz     r25,-4(stack)
                mullw   r25,r25,r26
                srawi   r25,r25,8
                subf.   r31,r28,r25
                add     r17,r17,r19
                add     r18,r18,r21
                ble     .loopend
                mr      r28,r25
.copy
                subic.  r31,r31,1
                stbu    r0,4(r20)
                bne     .copy
.loopend
                bdnz    .loop2
.colOK
                subf    r28,r29,r28
                subf    r28,r7,r28              ;area height - actual height
                neg.    r28,r28                 ;r28 = sky height to draw
;                li      r0,-1
                li      r0,0
                sth     r0,SKY_COUNT(r10)       ;nosky
                ble     .jump                   ;no sky to draw -> jump
                sth     r28,SKY_COUNT(r10)      ;write sky height
                subf    r25,r29,r11             ;subtract hor. rotation value
                subf    r25,r23,r25
                lh      r28,SkyHeight
                add     r25,r25,r28
                subf    r25,r7,r25              ;calc real sky offset
                lh      r28,SkyWidth2
                mullw   r25,r25,r28             ;multiply by sky width
                stw     r25,SKY_SOURCE(r10)     ;write sky offset
.jump
                addi    r6,r6,1                 ;next column
                addi    r10,r10,SKY_SIZE        ;next sky definition


                subi    r0,r15,1
                andi.   r0,r0,$3
                bne     .loopend2
                mr      r17,r3
                addi    r3,r3,4
                subi    r20,r6,4+4              ;postincrement
                lha     r26,-4*SKY_SIZE+SKY_COUNT(r10)
                lha     r16,-3*SKY_SIZE+SKY_COUNT(r10)
                lha     r18,-2*SKY_SIZE+SKY_COUNT(r10)
                lha     r19,-SKY_SIZE+SKY_COUNT(r10)
                mr      r28,r19
                cmpw    r18,r28
                bge     .cmp1
                mr      r28,r18
.cmp1
                cmpw    r16,r28
                bge     .cmp2
                mr      r28,r16
.cmp2
                cmpw    r26,r28
                bge     .cmp3
                mr      r28,r26
.cmp3
                subf    r28,r28,r7
                add     r17,r17,r8
                tstw    r28
                ble     .nodraw
                subf    r26,r28,r26
                subf    r16,r28,r16
                subf    r18,r28,r18
                subf    r19,r28,r19
                mtctr   r28
.copycol
                lwzu    r0,4(r20)
                subf    r17,r8,r17
                stw     r0,0(r17)
                bdnz    .copycol
.nodraw
                subi    r6,r6,4
.loopend2
                subic.  r15,r15,1
                bne     .loop
                lh      r3,SkyWidth2
                lw      r4,SkyBuffer            ;r4 -> sky graphics
                lh      r5,Direction            ;get direction
                lh      r6,Ray_Count
                lh      r7,SkyWidth
                mullw   r5,r5,r3
                divwu   r5,r5,r6                ;calc sky hor. position
                cmpw    r5,r7                   ;check for overflow
                blt     .cont
                subf    r5,r7,r5
.cont
                andi.   r5,r5,$fffe
                add     r4,r4,r5                ;r4 -> sky start pos
                lw      r9,SkyData           ;r9 -> sky definition
                lw      r10,ChunkyBuffer        ;r10 -> chunky buffer
.loop3
                lwz     r11,SKY_SOURCE(r9)      ;get sky source offset
                mr      r12,r4                  ;temp. SkyBuffer
                mr      r13,r10                 ;temp. ChunkyBuffer
                add     r12,r12,r11             ;r12 -> sky start pos
                cmpwi   r27,4                   ;if last turn
                blt     .normal                 ;then normal draw
                andi.   r0,r27,$3
                bne     .normal
                lwz     r14,SKY_SOURCE+SKY_SIZE(r9)
                cmpw    r11,r14                 ;next offset equal?
                bne     .normal                 ;no -> normal draw
                lwz     r14,SKY_SOURCE+2*SKY_SIZE(r9)
                cmpw    r11,r14                 ;next offset equal?
                bne     .normal                 ;no -> normal draw
                lwz     r14,SKY_SOURCE+3*SKY_SIZE(r9)
                cmpw    r11,r14                 ;next offset equal?
                bne     .normal                 ;no -> normal draw
                lha     r14,SKY_COUNT(r9)
                lha     r15,SKY_COUNT+SKY_SIZE(r9)
                lha     r16,SKY_COUNT+2*SKY_SIZE(r9)
                lha     r17,SKY_COUNT+3*SKY_SIZE(r9)
                subi    r27,r27,3               ;draw optimized
                mr      r18,r14
                cmpw    r15,r18
                bge     .scmp1
                mr      r18,r15
.scmp1
                cmpw    r16,r18
                bge     .scmp2
                mr      r18,r16
.scmp2
                cmpw    r17,r18
                bge     .scmp3
                mr      r18,r17
.scmp3
                tstw    r18
                ble     .ssingle1
                subf    r14,r18,r14
                subf    r15,r18,r15
                subf    r16,r18,r16
                subf    r17,r18,r17
                mtctr   r18
.drawsky4
                lwz     r0,0(r12)               ;draw 2 columns at once
                stw     r0,0(r13)
                add     r13,r13,r8
                add     r12,r12,r3
                bdnz    .drawsky4
.ssingle1
                tstw    r14
                ble     .ssingle2
                mtctr   r14
                mr      r19,r12
                mr      r20,r13
.ssloop1
                lbz     r0,0(r12)
                stb     r0,0(r13)
                add     r13,r13,r8
                add     r12,r12,r3
                bdnz    .ssloop1
                mr      r12,r19
                mr      r13,r20
.ssingle2
                tstw    r15
                ble     .ssingle3
                mtctr   r15
                mr      r19,r12
                mr      r20,r13
.ssloop2
                lbz     r0,1(r12)
                stb     r0,1(r13)
                add     r13,r13,r8
                add     r12,r12,r3
                bdnz    .ssloop2
                mr      r12,r19
                mr      r13,r20
.ssingle3
                tstw    r16
                ble     .ssingle4
                mtctr   r16
                mr      r19,r12
                mr      r20,r13
.ssloop3
                lbz     r0,2(r12)
                stb     r0,2(r13)
                add     r13,r13,r8
                add     r12,r12,r3
                bdnz    .ssloop3
                mr      r12,r19
                mr      r13,r20
.ssingle4
                tstw    r17
                ble     .ssingle5
                mtctr   r17
.ssloop4
                lbz     r0,3(r12)
                stb     r0,3(r13)
                add     r13,r13,r8
                add     r12,r12,r3
                bdnz    .ssloop4
.ssingle5
                subic.  r27,r27,1
                addi    r4,r4,4                 ;increase by 4 columns
                addi    r10,r10,4
                addi    r9,r9,SKY_SIZE*4
                bne     .loop3
                b       .end
.normal
                lha     r14,SKY_COUNT(r9)       ;get sky height
                tstw    r14
;                blt     .next
                beq     .next
                mtctr   r14
.drawsky
                lbz     r0,0(r12)               ;now draw the longer one
                stb     r0,0(r13)
                add     r13,r13,r8
                add     r12,r12,r3
                bdnz    .drawsky
.next
                subic.  r27,r27,1
                addi    r4,r4,1                 ;next column
                addi    r10,r10,1
                addi    r9,r9,SKY_SIZE
                bne     .loop3
.end
                lwz     r13,-12(stack)
                popgpr
                epilog
;;/
;// Calculation_PPC_T_A (calculates one voxelspace frame - column width 1)
******************************************************************************
*
*       Calculation_PPC_T_A
*
*       calculates one voxelspace frame with column width = 1
*       the results are written into the chunkybuffer
*       optimized for direct rendering into GfxRAM
*       approximation routine
*
******************************************************************************
Calculation_PPC_T_A
                prolog  256
                pushgpr r14-r31
                stw     r13,-12(stack)
                lf      f6,_CITF_0
                lh      r22,PixelCount          ;r22 = pixel count
                lw      r5,MapFile+FILE_ADDRESS ;r5 -> map
                lw      r6,ChunkyBuffer         ;r6 -> chunky buffer
                lh      r7,AreaHeight           ;r7 = area height
                lh      r8,BitmapWidth            ;r8 = area width
                subi    r9,r7,1
                mullw   r9,r9,r8
                add     r3,r6,r9                ;last line in chunky buffer
                lw      r4,ViewAngle            ;r4 -> view angle structure
                subi    r4,r4,4                 ;prepare for postincrement
                lw      r6,TempBuffer           ;r6 -> TempBuffer

                lh      r9,Direction
                lh      r10,Ray_Count
                subi    r13,r10,1
                lh      r11,Angle
                mullw   r10,r10,r11
                li      r12,360*2
                divwu   r10,r10,r12             ;subtract half angle from dir.
                subf    r9,r10,r9               ;r9 = starting ray
                and     r9,r9,r13               ;wrap around
                slwi    r9,r9,4
                slwi    r13,r13,4               ;r13 = view angle mask

                lh      r14,ActualHeight
                mr      r24,r14                 ;r24 = actual height
                lb      r10,SkyScroll
                lh      r12,SkyPos
                extsh   r12,r12
                divwu   r11,r14,r10             ;calc sky scroll value
                subf    r11,r12,r11             ;subtract offset
                neg     r11,r11                 ;r11 = sky offset
                lw      r10,SkyData             ;r10 -> sky definition
                lw      r14,PosYDet
                slwi    r14,r14,9
                lw      r17,PosXDet             ;r17 = pos x value
                slwi    r17,r17,9

                slwi    r15,r7,8
                citf    f1,f6,r15
                srwi    r23,r7,1
                lh      r18,ViewDistance
                citf    f5,f6,r18
                lh      r21,MaxRange
                lh      r18,DispHeight
                citf    f2,f6,r18
                fmul    f0,f1,f5
                fdiv    f0,f0,f2
                lh      r18,MinRange
                citf    f1,f6,r18
                fadd    f5,f1,f5
                citf    f2,f6,r21
                lh      r21,Pix_Count
                citf    f3,f6,r21
                fsub    f2,f2,f1
                fdiv    f2,f2,f3
                lh      r15,ColumnCount         ;number of columns
                mr      r27,r15                 ;r27 = column count
.loop
                fmr     f1,f5
                lw      r17,PosXDet             ;r17 = pos x value
                slwi    r17,r17,9
                lh      r28,HRotActual          ;r28 = HRotActual
                extsh   r28,r28
                mr      r18,r14                 ;temp pos y shifted value
                lw      r19,ViewCircle          ;r19 -> view circle structure
                subi    r19,r19,4               ;prepare for postincrement
                subi    r20,r6,4                ;r20 = temp. chunky buffer ptr
                lwzu    r16,4(r4)
                add     r9,r9,r16               ;jump to next ray
                and     r9,r9,r13               ;mask out
                add     r19,r19,r9              ;r19 -> new view circle
                lwzu    r26,4(r19)
                add     r18,r18,r26
                lwzu    r26,4(r19)
                add     r17,r17,r26
                lwzu    r21,4(r19)              ;r21 = delta y
                lwzu    r0,4(r19)
                mr      r19,r0                  ;r19 = delta x
                slwi    r29,r28,8
                srwi    r25,r27,1
                divw    r29,r29,r25             ;/half column count
                neg     r26,r15
                add     r26,r26,r25
                add     r26,r26,r26
                subi    r26,r26,1
                mullw   r29,r29,r26
                srawi   r29,r29,17              ;r29 = hor. rotation offset
                subf    r29,r23,r29
                mr      r28,r29
                mtctr   r22                     ;store pix count to CTR
.loop2
                rlwinm  r12,r18,27,11,20
                rlwimi  r12,r17,17,21,30
                fdivs   f4,f0,f1
                lhzx    r0,r5,r12
                fctiw   f4,f4
                stfd    f4,-8(stack)
                extrwi  r26,r0,8,16
                fadd    f1,f1,f2
                subf    r26,r24,r26
                lwz     r25,-4(stack)
                mullw   r25,r25,r26
                srawi   r25,r25,8
                subf.   r31,r28,r25
                add     r17,r17,r19
                add     r18,r18,r21
                ble     .loopend
                mr      r28,r25
.copy
                subic.  r31,r31,1
                stbu    r0,4(r20)
                bne     .copy
                bdnz    .loop2
                b       .colOK
.approx
                bdz     .colOK
                add     r18,r18,r21
                fadd    f1,f1,f2
                add     r17,r17,r19
                bdnz    .loop2
                b       .colOK
.loopend
                blt     .approx
                bdnz    .loop2
.colOK
                subf    r28,r29,r28
                subf    r28,r7,r28              ;area height - actual height
                neg.    r28,r28                 ;r28 = sky height to draw
;                li      r0,-1
                li      r0,0
                sth     r0,SKY_COUNT(r10)       ;nosky
                ble     .jump                   ;no sky to draw -> jump
                sth     r28,SKY_COUNT(r10)      ;write sky height
                subf    r25,r29,r11             ;subtract hor. rotation value
                subf    r25,r23,r25
                lh      r28,SkyHeight
                add     r25,r25,r28
                subf    r25,r7,r25              ;calc real sky offset
                lh      r28,SkyWidth2
                mullw   r25,r25,r28             ;multiply by sky width
                stw     r25,SKY_SOURCE(r10)     ;write sky offset
.jump
                addi    r6,r6,1                 ;next column
                addi    r10,r10,SKY_SIZE        ;next sky definition
                subi    r0,r15,1
                andi.   r0,r0,$3
                bne     .loopend2
                mr      r17,r3
                addi    r3,r3,4
                subi    r20,r6,4+4              ;postincrement
                lha     r26,-4*SKY_SIZE+SKY_COUNT(r10)
                lha     r16,-3*SKY_SIZE+SKY_COUNT(r10)
                lha     r18,-2*SKY_SIZE+SKY_COUNT(r10)
                lha     r19,-SKY_SIZE+SKY_COUNT(r10)
                mr      r28,r19
                cmpw    r18,r28
                bge     .cmp1
                mr      r28,r18
.cmp1
                cmpw    r16,r28
                bge     .cmp2
                mr      r28,r16
.cmp2
                cmpw    r26,r28
                bge     .cmp3
                mr      r28,r26
.cmp3
                subf    r28,r28,r7
                add     r17,r17,r8
                tstw    r28
                ble     .nodraw
                mtctr   r28
.copycol
                lwzu    r0,4(r20)
                subf    r17,r8,r17
                stw     r0,0(r17)
                bdnz    .copycol
.nodraw
                subi    r6,r6,4
.loopend2
                subic.  r15,r15,1
                bne     .loop
                lh      r3,SkyWidth2
                lw      r4,SkyBuffer            ;r4 -> sky graphics
                lh      r5,Direction            ;get direction
                lh      r6,Ray_Count
                lh      r7,SkyWidth
                mullw   r5,r5,r3
                divwu   r5,r5,r6                ;calc sky hor. position
                cmpw    r5,r7                   ;check for overflow
                blt     .cont
                subf    r5,r7,r5
.cont
                andi.   r5,r5,$fffe
                add     r4,r4,r5                ;r4 -> sky start pos
                lw      r9,SkyData           ;r9 -> sky definition
                lw      r10,ChunkyBuffer        ;r10 -> chunky buffer
.loop3
                lwz     r11,SKY_SOURCE(r9)      ;get sky source offset
                mr      r12,r4                  ;temp. SkyBuffer
                mr      r13,r10                 ;temp. ChunkyBuffer
                add     r12,r12,r11             ;r12 -> sky start pos
                cmpwi   r27,4                   ;if last turn
                blt     .normal                 ;then normal draw
                andi.   r0,r27,$3
                bne     .normal
                lwz     r14,SKY_SOURCE+SKY_SIZE(r9)
                cmpw    r11,r14                 ;next offset equal?
                bne     .normal                 ;no -> normal draw
                lwz     r14,SKY_SOURCE+2*SKY_SIZE(r9)
                cmpw    r11,r14                 ;next offset equal?
                bne     .normal                 ;no -> normal draw
                lwz     r14,SKY_SOURCE+3*SKY_SIZE(r9)
                cmpw    r11,r14                 ;next offset equal?
                bne     .normal                 ;no -> normal draw
                lha     r14,SKY_COUNT(r9)
                lha     r15,SKY_COUNT+SKY_SIZE(r9)
                lha     r16,SKY_COUNT+2*SKY_SIZE(r9)
                lha     r17,SKY_COUNT+3*SKY_SIZE(r9)
                subi    r27,r27,3               ;draw optimized
                mr      r18,r14
                cmpw    r15,r18
                bge     .scmp1
                mr      r18,r15
.scmp1
                cmpw    r16,r18
                bge     .scmp2
                mr      r18,r16
.scmp2
                cmpw    r17,r18
                bge     .scmp3
                mr      r18,r17
.scmp3
                tstw    r18
                ble     .ssingle1
                subf    r14,r18,r14
                subf    r15,r18,r15
                subf    r16,r18,r16
                subf    r17,r18,r17
                mtctr   r18
.drawsky4
                lwz     r0,0(r12)               ;draw 2 columns at once
                stw     r0,0(r13)
                add     r13,r13,r8
                add     r12,r12,r3
                bdnz    .drawsky4
.ssingle1
                tstw    r14
                ble     .ssingle2
                mtctr   r14
                mr      r19,r12
                mr      r20,r13
.ssloop1
                lbz     r0,0(r12)
                stb     r0,0(r13)
                add     r13,r13,r8
                add     r12,r12,r3
                bdnz    .ssloop1
                mr      r12,r19
                mr      r13,r20
.ssingle2
                tstw    r15
                ble     .ssingle3
                mtctr   r15
                mr      r19,r12
                mr      r20,r13
.ssloop2
                lbz     r0,1(r12)
                stb     r0,1(r13)
                add     r13,r13,r8
                add     r12,r12,r3
                bdnz    .ssloop2
                mr      r12,r19
                mr      r13,r20
.ssingle3
                tstw    r16
                ble     .ssingle4
                mtctr   r16
                mr      r19,r12
                mr      r20,r13
.ssloop3
                lbz     r0,2(r12)
                stb     r0,2(r13)
                add     r13,r13,r8
                add     r12,r12,r3
                bdnz    .ssloop3
                mr      r12,r19
                mr      r13,r20
.ssingle4
                tstw    r17
                ble     .ssingle5
                mtctr   r17
.ssloop4
                lbz     r0,3(r12)
                stb     r0,3(r13)
                add     r13,r13,r8
                add     r12,r12,r3
                bdnz    .ssloop4
.ssingle5
                subic.  r27,r27,1
                addi    r4,r4,4                 ;increase by 4 columns
                addi    r10,r10,4
                addi    r9,r9,SKY_SIZE*4
                bne     .loop3
                b       .end
.normal
                lha     r14,SKY_COUNT(r9)       ;get sky height
                tstw    r14
;                blt     .next
                beq     .next
                mtctr   r14
.drawsky
                lbz     r0,0(r12)               ;now draw the longer one
                stb     r0,0(r13)
                add     r13,r13,r8
                add     r12,r12,r3
                bdnz    .drawsky
.next
                subic.  r27,r27,1
                addi    r4,r4,1                 ;next column
                addi    r10,r10,1
                addi    r9,r9,SKY_SIZE
                bne     .loop3
.end
                lwz     r13,-12(stack)
                popgpr
                epilog
;;/
;// Calculation2_PPC_T (calculates one voxelspace frame - column width 2)
******************************************************************************
*
*       Calculation2_PPC_T
*
*       calculates one voxelspace frame with column width = 2
*       the results are written into the chunkybuffer
*       optimized for direct rendering into GfxRAM
*
******************************************************************************
Calculation2_PPC_T
                prolog  256
                pushgpr r14-r31
                stw     r13,-12(stack)
                lf      f6,_CITF_0
                lh      r22,PixelCount          ;r22 = pixel count
                lw      r5,MapFile+FILE_ADDRESS ;r5 -> map
                lw      r6,ChunkyBuffer         ;r6 -> chunky buffer
                lh      r7,AreaHeight           ;r7 = area height
                lh      r8,BitmapWidth            ;r8 = area width
                subi    r9,r7,1
                mullw   r9,r9,r8
                add     r3,r6,r9                ;r3 -> last line in chunky buffer
                lw      r4,ViewAngle            ;r4 -> view angle structure
                subi    r4,r4,4                 ;prepare for postincrement
                lw      r6,TempBuffer           ;r6 -> TempBuffer

                lh      r9,Direction
                lh      r10,Ray_Count
                subi    r13,r10,1
                lh      r11,Angle
                mullw   r10,r10,r11
                li      r12,360*2
                divwu   r10,r10,r12             ;subtract half angle from dir.
                subf    r9,r10,r9               ;r9 = starting ray
                and     r9,r9,r13               ;wrap around
                slwi    r9,r9,4
                slwi    r13,r13,4               ;r13 = view angle mask

                lh      r14,ActualHeight
                mr      r24,r14                 ;r24 = actual height
                lb      r10,SkyScroll
                lh      r12,SkyPos
                extsh   r12,r12
                divwu   r11,r14,r10             ;calc sky scroll value
                subf    r11,r12,r11             ;subtract offset
                neg     r11,r11                 ;r11 = sky offset
                lw      r10,SkyData             ;r10 -> sky definition

                slwi    r15,r7,8
                citf    f1,f6,r15
                srwi    r23,r7,1
                lh      r18,ViewDistance
                citf    f5,f6,r18
                lh      r21,MaxRange
                lh      r18,DispHeight
                citf    f2,f6,r18
                fmul    f0,f1,f5
                fdiv    f0,f0,f2
                lh      r18,MinRange
                citf    f1,f6,r18
                fadd    f5,f1,f5
                citf    f2,f6,r21
                lh      r21,Pix_Count
                citf    f3,f6,r21
                fsub    f2,f2,f1
                fdiv    f2,f2,f3
                lh      r15,ColumnCount         ;number of columns
                mr      r27,r15                 ;r27 = column count
.loop
                fmr     f1,f5

                lw      r18,PosYDet
                slwi    r18,r18,9
                lw      r17,PosXDet
                slwi    r17,r17,9

                lh      r28,HRotActual          ;r28 = HRotActual
                extsh   r28,r28
                lw      r19,ViewCircle          ;r19 -> view circle structure
                subi    r19,r19,4               ;prepare for postincrement
                subi    r20,r6,4                ;r20 = temp. chunky buffer ptr
                lwzu    r16,4(r4)
                add     r9,r9,r16               ;jump to next ray
                and     r9,r9,r13               ;mask out
                add     r19,r19,r9              ;r19 -> new view circle
                lwzu    r26,4(r19)
                add     r18,r18,r26
                lwzu    r26,4(r19)
                add     r17,r17,r26
                lwzu    r21,4(r19)              ;r21 = delta y
                lwzu    r0,4(r19)
                mr      r19,r0                  ;r19 = delta x
                slwi    r29,r28,8
                srwi    r25,r27,1
                divw    r29,r29,r25             ;/half column count
                neg     r26,r15
                add     r26,r26,r25
                add     r26,r26,r26
                subi    r26,r26,1
                mullw   r29,r29,r26
                srawi   r29,r29,17              ;r29 = hor. rotation offset
                subf    r29,r23,r29
                mr      r28,r29
                mtctr   r22                     ;store pix count to CTR
.loop2
                rlwinm  r12,r18,27,11,20
                rlwimi  r12,r17,17,21,30
                fdivs   f4,f0,f1
                lhzx    r0,r5,r12
                fctiw   f4,f4
                stfd    f4,-8(stack)
                extrwi  r26,r0,8,16
                fadd    f1,f1,f2
                subf    r26,r24,r26
                lwz     r25,-4(stack)
                mullw   r25,r25,r26
                srawi   r25,r25,8
                subf.   r31,r28,r25
                add     r17,r17,r19
                add     r18,r18,r21
                ble     .loopend
                mr      r28,r25
                insrwi  r0,r0,8,16
.copy
                subic.  r31,r31,1
                sthu    r0,4(r20)
                bne     .copy
.loopend
                bdnz    .loop2
                b       .colOK
.colOK
                subf    r28,r29,r28
                subf    r28,r7,r28              ;area height - actual height
                neg.    r28,r28                 ;r28 = sky height to draw
;                li      r0,-1
                li      r0,0
                sth     r0,SKY_COUNT(r10)       ;nosky
                ble     .jump                   ;no sky to draw -> jump
                sth     r28,SKY_COUNT(r10)      ;write sky height
                subf    r25,r29,r11             ;subtract hor. rotation value
                subf    r25,r23,r25
                lh      r28,SkyHeight
                add     r25,r25,r28
                subf    r25,r7,r25              ;calc real sky offset
                lh      r28,SkyWidth2
                mullw   r25,r25,r28             ;multiply by sky width
                stw     r25,SKY_SOURCE(r10)     ;write sky offset
.jump
                addi    r6,r6,2                 ;next column
                addi    r10,r10,SKY_SIZE        ;next sky definition
                andi.   r0,r15,$1
                beq     .loopend2
                mr      r17,r3
                addi    r3,r3,4
                subi    r20,r6,4+4              ;postincrement
                lha     r18,-2*SKY_SIZE+SKY_COUNT(r10)
                lha     r19,-SKY_SIZE+SKY_COUNT(r10)
                subf    r18,r18,r7
                subf    r19,r19,r7
                cmpw    r18,r19
                ble     .noexg1
                mr      r0,r18
                mr      r18,r19
                mr      r19,r0
.noexg1
                add     r17,r17,r8
                tstw    r19
                ble     .nodraw
                mtctr   r19
.copycol1
                lwzu    r0,4(r20)
                subf    r17,r8,r17
                stw     r0,0(r17)
                bdnz    .copycol1
.nodraw
                subi    r6,r6,4
.loopend2
                subic.  r15,r15,1
                bne     .loop
                lh      r3,SkyWidth2
                lw      r4,SkyBuffer            ;r4 -> sky graphics
                lh      r5,Direction            ;get direction
                lh      r6,Ray_Count
                lh      r7,SkyWidth
                mullw   r5,r5,r3
                divwu   r5,r5,r6                ;calc sky hor. position
                cmpw    r5,r7                   ;check for overflow
                blt     .cont
                subf    r5,r7,r5
.cont
                andi.   r5,r5,$fffe
                add     r4,r4,r5                ;r4 -> sky start pos
                lw      r9,SkyData              ;r9 -> sky definition
                lw      r10,ChunkyBuffer        ;r10 -> chunky buffer
.loop3
                lwz     r11,SKY_SOURCE(r9)      ;get sky source offset
                mr      r12,r4                  ;temp. SkyBuffer
                mr      r13,r10                 ;temp. ChunkyBuffer
                add     r12,r12,r11             ;r12 -> sky start pos
                cmpwi   r27,1                   ;if last turn
                beq     .normal                 ;then normal draw
                lwz     r14,SKY_SOURCE+SKY_SIZE(r9)
                cmpw    r11,r14                 ;next offset equal?
                bne     .normal                 ;no -> normal draw
                lha     r14,SKY_COUNT(r9)
                tstw    r14                     ;sky height >0?
                beq     .next
;                blt     .next                   ;no -> no draw
                lha     r15,SKY_COUNT+SKY_SIZE(r9)
                tstw    r15                     ;next sky height > 0?
;                blt     .next                   ;no -> no draw
                beq     .next
                subi    r27,r27,1               ;draw optimized
                li      r16,2
                cmpw    r14,r15                 ;compare sky heights
                ble     .noexg                  ;of both columns
                mr      r0,r15                  ;change if necessary
                mr      r15,r14
                mr      r14,r0
                li      r16,0
.noexg
                mtctr   r14
.drawsky2
                lwz     r0,0(r12)               ;draw 2 columns at once
                stw     r0,0(r13)
                add     r13,r13,r8
                add     r12,r12,r3
                bdnz    .drawsky2
                subf.   r15,r14,r15             ;subtract heights
                ble     .next2                  ;equal -> done
                mtctr   r15
                add     r12,r12,r16
                add     r13,r13,r16
.drawsky3
                lhz     r0,0(r12)               ;now draw the longer one
                sth     r0,0(r13)
                add     r13,r13,r8
                add     r12,r12,r3
                bdnz    .drawsky3
.next2
                subic.  r27,r27,1
                addi    r4,r4,4                 ;increase by 2 columns
                addi    r10,r10,4
                addi    r9,r9,SKY_SIZE*2
                bne     .loop3
                b       .end
.normal
                lha     r14,SKY_COUNT(r9)       ;get sky height
                tstw    r14
                beq     .next
;                blt     .next
                mtctr   r14
.drawsky
                lhz     r0,0(r12)               ;now draw the longer one
                sth     r0,0(r13)
                add     r13,r13,r8
                add     r12,r12,r3
                bdnz    .drawsky
.next
                subic.  r27,r27,1
                addi    r4,r4,2                 ;next column
                addi    r10,r10,2
                addi    r9,r9,SKY_SIZE
                bne     .loop3
.end
                lwz     r13,-12(stack)
                popgpr
                epilog
;;/
;// Calculation2_PPC_T_A (calculates one voxelspace frame - column width 2)
******************************************************************************
*
*       Calculation2_PPC_T_A
*
*       calculates one voxelspace frame with column width = 2
*       the results are written into the chunkybuffer
*       optimized for direct rendering into GfxRAM
*       approximation routine
*
******************************************************************************
Calculation2_PPC_T_A
                prolog  256
                pushgpr r14-r31
                stw     r13,-12(stack)
                lf      f6,_CITF_0
                lh      r22,PixelCount          ;r22 = pixel count
                lw      r5,MapFile+FILE_ADDRESS ;r5 -> map
                lw      r6,ChunkyBuffer         ;r6 -> chunky buffer
                lh      r7,AreaHeight           ;r7 = area height
                lh      r8,BitmapWidth            ;r8 = area width
                subi    r9,r7,1
                mullw   r9,r9,r8
                add     r3,r6,r9                ;r3 -> last line in chunky buffer
                lw      r4,ViewAngle            ;r4 -> view angle structure
                subi    r4,r4,4                 ;prepare for postincrement
                lw      r6,TempBuffer           ;r6 -> TempBuffer

                lh      r9,Direction
                lh      r10,Ray_Count
                subi    r13,r10,1
                lh      r11,Angle
                mullw   r10,r10,r11
                li      r12,360*2
                divwu   r10,r10,r12             ;subtract half angle from dir.
                subf    r9,r10,r9               ;r9 = starting ray
                and     r9,r9,r13               ;wrap around
                slwi    r9,r9,4
                slwi    r13,r13,4               ;r13 = view angle mask

                lh      r14,ActualHeight
                mr      r24,r14                 ;r24 = actual height
                lb      r10,SkyScroll
                lh      r12,SkyPos
                extsh   r12,r12
                divwu   r11,r14,r10             ;calc sky scroll value
                subf    r11,r12,r11             ;subtract offset
                neg     r11,r11                 ;r11 = sky offset
                lw      r10,SkyData             ;r10 -> sky definition

                slwi    r15,r7,8
                citf    f1,f6,r15
                srwi    r23,r7,1
                lh      r18,ViewDistance
                citf    f5,f6,r18
                lh      r21,MaxRange
                lh      r18,DispHeight
                citf    f2,f6,r18
                fmul    f0,f1,f5
                fdiv    f0,f0,f2
                lh      r18,MinRange
                citf    f1,f6,r18
                fadd    f5,f1,f5
                citf    f2,f6,r21
                lh      r21,Pix_Count
                citf    f3,f6,r21
                fsub    f2,f2,f1
                fdiv    f2,f2,f3
                lh      r15,ColumnCount         ;number of columns
                mr      r27,r15                 ;r27 = column count
.loop
                fmr     f1,f5

                lw      r18,PosYDet
                slwi    r18,r18,9
                lw      r17,PosXDet
                slwi    r17,r17,9

                lh      r28,HRotActual          ;r28 = HRotActual
                extsh   r28,r28
                lw      r19,ViewCircle          ;r19 -> view circle structure
                subi    r19,r19,4               ;prepare for postincrement
                subi    r20,r6,4                ;r20 = temp. chunky buffer ptr
                lwzu    r16,4(r4)
                add     r9,r9,r16               ;jump to next ray
                and     r9,r9,r13               ;mask out
                add     r19,r19,r9              ;r19 -> new view circle
                lwzu    r26,4(r19)
                add     r18,r18,r26
                lwzu    r26,4(r19)
                add     r17,r17,r26
                lwzu    r21,4(r19)              ;r21 = delta y
                lwzu    r0,4(r19)
                mr      r19,r0                  ;r19 = delta x
                slwi    r29,r28,8
                srwi    r25,r27,1
                divw    r29,r29,r25             ;/half column count
                neg     r26,r15
                add     r26,r26,r25
                add     r26,r26,r26
                subi    r26,r26,1
                mullw   r29,r29,r26
                srawi   r29,r29,17              ;r29 = hor. rotation offset
                subf    r29,r23,r29
                mr      r28,r29
                mtctr   r22                     ;store pix count to CTR
.loop2
                rlwinm  r12,r18,27,11,20
                rlwimi  r12,r17,17,21,30
                fdivs   f4,f0,f1
                lhzx    r0,r5,r12
                fctiw   f4,f4
                stfd    f4,-8(stack)
                extrwi  r26,r0,8,16
                fadd    f1,f1,f2
                subf    r26,r24,r26
                lwz     r25,-4(stack)
                mullw   r25,r25,r26
                srawi   r25,r25,8
                subf.   r31,r28,r25
                add     r17,r17,r19
                add     r18,r18,r21
                ble     .loopend
                mr      r28,r25
                insrwi  r0,r0,8,16
.copy
                subic.  r31,r31,1
                sthu    r0,4(r20)
                bne     .copy
                bdnz    .loop2
                b       .colOK
.approx
                bdz     .colOK
                add     r18,r18,r21
                add     r17,r17,r19
                fadd    f1,f1,f2
                bdnz    .loop2
                b       .colOK
.loopend
                blt     .approx
                bdnz    .loop2
                b       .colOK
.colOK
                subf    r28,r29,r28
                subf    r28,r7,r28              ;area height - actual height
                neg.    r28,r28                 ;r28 = sky height to draw
;                li      r0,-1
                li      r0,0
                sth     r0,SKY_COUNT(r10)       ;nosky
                ble     .jump                   ;no sky to draw -> jump
                sth     r28,SKY_COUNT(r10)      ;write sky height
                subf    r25,r29,r11             ;subtract hor. rotation value
                subf    r25,r23,r25
                lh      r28,SkyHeight
                add     r25,r25,r28
                subf    r25,r7,r25              ;calc real sky offset
                lh      r28,SkyWidth2
                mullw   r25,r25,r28             ;multiply by sky width
                stw     r25,SKY_SOURCE(r10)     ;write sky offset
.jump
                addi    r6,r6,2                 ;next column
                addi    r10,r10,SKY_SIZE        ;next sky definition
                andi.   r0,r15,$1
                beq     .loopend2
                mr      r17,r3
                addi    r3,r3,4
                subi    r20,r6,4+4              ;postincrement
                lha     r18,-2*SKY_SIZE+SKY_COUNT(r10)
                lha     r19,-SKY_SIZE+SKY_COUNT(r10)
                subf    r18,r18,r7
                subf    r19,r19,r7
                cmpw    r18,r19
                ble     .noexg1
                mr      r0,r18
                mr      r18,r19
                mr      r19,r0
.noexg1
                add     r17,r17,r8
                tstw    r19
                ble     .nodraw
                mtctr   r19
.copycol1
                lwzu    r0,4(r20)
                subf    r17,r8,r17
                stw     r0,0(r17)
                bdnz    .copycol1
.nodraw
                subi    r6,r6,4
.loopend2
                subic.  r15,r15,1
                bne     .loop
                lh      r3,SkyWidth2
                lw      r4,SkyBuffer            ;r4 -> sky graphics
                lh      r5,Direction            ;get direction
                lh      r6,Ray_Count
                lh      r7,SkyWidth
                mullw   r5,r5,r3
                divwu   r5,r5,r6                ;calc sky hor. position
                cmpw    r5,r7                   ;check for overflow
                blt     .cont
                subf    r5,r7,r5
.cont
                andi.   r5,r5,$fffe
                add     r4,r4,r5                ;r4 -> sky start pos
                lw      r9,SkyData              ;r9 -> sky definition
                lw      r10,ChunkyBuffer        ;r10 -> chunky buffer
.loop3
                lwz     r11,SKY_SOURCE(r9)      ;get sky source offset
                mr      r12,r4                  ;temp. SkyBuffer
                mr      r13,r10                 ;temp. ChunkyBuffer
                add     r12,r12,r11             ;r12 -> sky start pos
                cmpwi   r27,1                   ;if last turn
                beq     .normal                 ;then normal draw
                lwz     r14,SKY_SOURCE+SKY_SIZE(r9)
                cmpw    r11,r14                 ;next offset equal?
                bne     .normal                 ;no -> normal draw
                lha     r14,SKY_COUNT(r9)
                tstw    r14                     ;sky height >0?
;                blt     .next                   ;no -> no draw
                beq     .next
                lha     r15,SKY_COUNT+SKY_SIZE(r9)
                tstw    r15                     ;next sky height > 0?
                beq     .next
;                blt     .next                   ;no -> no draw
                subi    r27,r27,1               ;draw optimized
                li      r16,2
                cmpw    r14,r15                 ;compare sky heights
                ble     .noexg                  ;of both columns
                mr      r0,r15                  ;change if necessary
                mr      r15,r14
                mr      r14,r0
                li      r16,0
.noexg
                mtctr   r14
.drawsky2
                lwz     r0,0(r12)               ;draw 2 columns at once
                stw     r0,0(r13)
                add     r13,r13,r8
                add     r12,r12,r3
                bdnz    .drawsky2
                subf.   r15,r14,r15             ;subtract heights
                ble     .next2                  ;equal -> done
                mtctr   r15
                add     r12,r12,r16
                add     r13,r13,r16
.drawsky3
                lhz     r0,0(r12)               ;now draw the longer one
                sth     r0,0(r13)
                add     r13,r13,r8
                add     r12,r12,r3
                bdnz    .drawsky3
.next2
                subic.  r27,r27,1
                addi    r4,r4,4                 ;increase by 2 columns
                addi    r10,r10,4
                addi    r9,r9,SKY_SIZE*2
                bne     .loop3
                b       .end
.normal
                lha     r14,SKY_COUNT(r9)       ;get sky height
                tstw    r14
;                blt     .next
                beq     .next
                mtctr   r14
.drawsky
                lhz     r0,0(r12)               ;now draw the longer one
                sth     r0,0(r13)
                add     r13,r13,r8
                add     r12,r12,r3
                bdnz    .drawsky
.next
                subic.  r27,r27,1
                addi    r4,r4,2                 ;next column
                addi    r10,r10,2
                addi    r9,r9,SKY_SIZE
                bne     .loop3
.end
                lwz     r13,-12(stack)
                popgpr
                epilog
;;/
;// Calculation4_PPC (calculates one voxelspace frame - column width 4)
******************************************************************************
*
*       Calculation4_PPC
*
*       calculates one voxelspace frame with column width = 4
*       the results are written into the chunkybuffer
*
******************************************************************************
Calculation4_PPC
                prolog  256
                pushgpr r14-r31
                stw     r13,-12(stack)
                lf      f6,_CITF_0
                lh      r22,PixelCount          ;r22 = pixel count
                lw      r5,MapFile+FILE_ADDRESS ;r5 -> map
                lw      r6,ChunkyBuffer         ;r6 -> chunky buffer
                lh      r7,AreaHeight           ;r7 = area height
                lh      r8,BitmapWidth            ;r8 = area width
                subi    r9,r7,1
                mullw   r9,r9,r8
                add     r6,r6,r9                ;last line in chunky buffer
                lw      r3,ViewCircle           ;r3 -> view circle structure
                lw      r4,ViewAngle            ;r4 -> view angle structure
                subi    r3,r3,4                 ;prepare for postincrement
                subi    r4,r4,4                 ;prepare for postincrement

                lh      r9,Direction
                lh      r10,Ray_Count
                subi    r13,r10,1
                lh      r11,Angle
                mullw   r10,r10,r11
                li      r12,360*2
                divwu   r10,r10,r12             ;subtract half angle from dir.
                subf    r9,r10,r9               ;r9 = starting ray
                and     r9,r9,r13               ;wrap around
                slwi    r9,r9,4
                slwi    r13,r13,4               ;r13 = view angle mask

                lh      r14,ActualHeight
                mr      r24,r14                 ;r24 = actual height
                lb      r10,SkyScroll
                lh      r12,SkyPos
                extsh   r12,r12
                divwu   r11,r14,r10             ;calc sky scroll value
                subf    r11,r12,r11             ;subtract offset
                neg     r11,r11                 ;r11 = sky offset
                lw      r10,SkyData             ;r10 -> sky definition
                lw      r14,PosYDet
                slwi    r14,r14,9

                slwi    r15,r7,8
                citf    f1,f6,r15
                srwi    r23,r7,1
                lh      r18,ViewDistance
                citf    f5,f6,r18
                lh      r21,MaxRange
                lh      r18,DispHeight
                citf    f2,f6,r18
                fmul    f0,f1,f5
                fdiv    f0,f0,f2
                lh      r18,MinRange
                citf    f1,f6,r18
                fadd    f5,f1,f5
                citf    f2,f6,r21
                lh      r21,Pix_Count
                citf    f3,f6,r21
                fsub    f2,f2,f1
                fdiv    f2,f2,f3
                lh      r15,ColumnCount         ;number of columns
                mr      r27,r15                 ;r27 = column count
.loop
                fmr     f1,f5
                lw      r17,PosXDet             ;r17 = pos x value
                slwi    r17,r17,9
                lh      r28,HRotActual          ;r28 = HRotActual
                extsh   r28,r28
                mr      r18,r14                 ;temp pos y shifted value
                mr      r19,r3                  ;temp. view circle ptr
                lw      r19,ViewCircle          ;r19 -> view circle structure
                subi    r19,r19,4               ;prepare for postincrement
                mr      r20,r6                  ;temp. chunky buffer ptr
                lwzu    r16,4(r4)
                add     r9,r9,r16               ;jump to next ray
                and     r9,r9,r13               ;mask out
                add     r19,r19,r9              ;r19 -> new view circle
                lwzu    r26,4(r19)
                add     r18,r18,r26
                lwzu    r26,4(r19)
                add     r17,r17,r26
                lwzu    r21,4(r19)              ;r21 = delta y
                lwzu    r0,4(r19)
                mr      r19,r0                  ;r19 = delta x
                slwi    r29,r28,8
                srwi    r25,r27,1
                divw    r29,r29,r25             ;/half column count
                neg     r26,r15
                add     r26,r26,r25
                add     r26,r26,r26
                subi    r26,r26,1
                mullw   r29,r29,r26
                srawi   r29,r29,17              ;r29 = hor. rotation offset
                subf    r29,r23,r29
                clrw    r28                     ;old height
                mtctr   r22                     ;store pix count to CTR
.loop2
                rlwinm  r12,r18,27,11,20
                rlwimi  r12,r17,17,21,30
                add     r18,r18,r21
                add     r17,r17,r19
                fdivs   f4,f0,f1
                lhzx    r0,r5,r12
                fctiw   f4,f4
                extrwi  r26,r0,8,16
                stfd    f4,-8(stack)
                subf    r26,r24,r26
                lwz     r25,-4(stack)
                fadd    f1,f1,f2
                mullw   r25,r25,r26
                srawi   r25,r25,8
                subf    r25,r29,r25             ;subtract HRot offset
                subf.   r25,r28,r25
                ble     .loopend
                add     r28,r28,r25             ;calc new height
                cmpw    r28,r7
                bge     .cut
                insrwi  r0,r0,8,16
                insrwi  r0,r0,16,0
.copy
                subic.  r25,r25,1
                stw     r0,0(r20)
                subf    r20,r8,r20
                bne     .copy
.loopend
                bdnz    .loop2
                b       .colOK
.cut
                subf    r28,r7,r28
                subf.   r25,r28,r25
                beq     .zero
                insrwi  r0,r0,8,16
                insrwi  r0,r0,16,0
.copy2
                subic.  r25,r25,1
                stw     r0,0(r20)
                subf    r20,r8,r20
                bne     .copy2
.zero
;                li      r0,-1
                li      r0,0
                sth     r0,SKY_COUNT(r10)       ;nosky
                b       .jump                   ;column done
.colOK
                subf    r28,r7,r28              ;area height - actual height
                neg.    r28,r28                 ;r28 = sky height to draw
;                li      r0,-1
                li      r0,0
                sth     r0,SKY_COUNT(r10)       ;nosky
                ble     .jump                   ;no sky to draw -> jump
                sth     r28,SKY_COUNT(r10)      ;write sky height
                subf    r25,r29,r11             ;subtract hor. rotation value
                subf    r25,r23,r25
                lh      r28,SkyHeight
                add     r25,r25,r28
                subf    r25,r7,r25              ;calc real sky offset
                lh      r28,SkyWidth2
                mullw   r25,r25,r28             ;multiply by sky width
                stw     r25,SKY_SOURCE(r10)     ;write sky offset
.jump
                subic.  r15,r15,1
                addi    r6,r6,4                 ;next column
                addi    r10,r10,SKY_SIZE        ;next sky definition
                bne     .loop
                lh      r3,SkyWidth2
                lw      r4,SkyBuffer            ;r4 -> sky graphics
                lh      r5,Direction            ;get direction
                lh      r6,Ray_Count
                lh      r7,SkyWidth
                mullw   r5,r5,r3
                divwu   r5,r5,r6                ;calc sky hor. position
                cmpw    r5,r7                   ;check for overflow
                blt     .cont
                subf    r5,r7,r5
.cont
                andi.   r5,r5,$fffe
                add     r4,r4,r5                ;r4 -> sky start pos
                lw      r9,SkyData              ;r9 -> sky definition
                lw      r10,ChunkyBuffer        ;r10 -> chunky buffer
.loop3
                lwz     r11,SKY_SOURCE(r9)      ;get sky source offset
                mr      r12,r4                  ;temp. SkyBuffer
                mr      r13,r10                 ;temp. ChunkyBuffer
                add     r12,r12,r11             ;r12 -> sky start pos
                cmpwi   r27,1                   ;if last turn
                beq     .normal                 ;then normal draw
                lwz     r14,SKY_SOURCE+SKY_SIZE(r9)
                cmpw    r11,r14                 ;next offset equal?
                bne     .normal                 ;no -> normal draw
                lha     r14,SKY_COUNT(r9)
                tstw    r14                     ;sky height >0?
;                blt     .next                   ;no -> no draw
                beq     .next
                lha     r15,SKY_COUNT+SKY_SIZE(r9)
                tstw    r15                     ;next sky height > 0?
;                blt     .next                   ;no -> no draw
                beq     .next
                subi    r27,r27,1               ;draw optimized
                li      r16,4
                cmpw    r14,r15                 ;compare sky heights
                ble     .noexg                  ;of both columns
                mr      r0,r15                  ;change if necessary
                mr      r15,r14
                mr      r14,r0
                li      r16,0
.noexg
                mtctr   r14
.drawsky2
                lwz     r0,0(r12)               ;draw 2 columns at once
                stw     r0,0(r13)
                lwz     r0,4(r12)               ;draw 2 columns at once
                stw     r0,4(r13)
                add     r13,r13,r8
                add     r12,r12,r3
                bdnz    .drawsky2
                subf.   r15,r14,r15             ;subtract heights
                ble     .next2                  ;equal -> done
                mtctr   r15
                add     r12,r12,r16
                add     r13,r13,r16
.drawsky3
                lwz     r0,0(r12)               ;now draw the longer one
                stw     r0,0(r13)
                add     r13,r13,r8
                add     r12,r12,r3
                bdnz    .drawsky3
.next2
                subic.  r27,r27,1
                addi    r4,r4,8                 ;increase by 2 columns
                addi    r10,r10,8
                addi    r9,r9,SKY_SIZE*2
                bne     .loop3
                b       .end
.normal
                lha     r14,SKY_COUNT(r9)       ;get sky height
                tstw    r14
;                blt     .next
                beq     .next
                mtctr   r14
.drawsky
                lwz     r0,0(r12)               ;now draw the longer one
                stw     r0,0(r13)
                add     r13,r13,r8
                add     r12,r12,r3
                bdnz    .drawsky
.next
                subic.  r27,r27,1
                addi    r4,r4,4                 ;next column
                addi    r10,r10,4
                addi    r9,r9,SKY_SIZE
                bne     .loop3
.end
                lwz     r13,-12(stack)
                popgpr
                epilog
;;/
;// Calculation4_PPC_A (calculates one voxelspace frame - column width 4)
******************************************************************************
*
*       Calculation4_PPC_A
*
*       calculates one voxelspace frame with column width = 4
*       the results are written into the chunkybuffer
*       approximation routine
*
******************************************************************************
Calculation4_PPC_A
                prolog  256
                pushgpr r14-r31
                stw     r13,-12(stack)
                lf      f6,_CITF_0
                lh      r22,PixelCount          ;r22 = pixel count
                lw      r5,MapFile+FILE_ADDRESS ;r5 -> map
                lw      r6,ChunkyBuffer         ;r6 -> chunky buffer
                lh      r7,AreaHeight           ;r7 = area height
                lh      r8,BitmapWidth            ;r8 = area width
                subi    r9,r7,1
                mullw   r9,r9,r8
                add     r6,r6,r9                ;last line in chunky buffer
                lw      r3,ViewCircle           ;r3 -> view circle structure
                lw      r4,ViewAngle            ;r4 -> view angle structure
                subi    r3,r3,4                 ;prepare for postincrement
                subi    r4,r4,4                 ;prepare for postincrement

                lh      r9,Direction
                lh      r10,Ray_Count
                subi    r13,r10,1
                lh      r11,Angle
                mullw   r10,r10,r11
                li      r12,360*2
                divwu   r10,r10,r12             ;subtract half angle from dir.
                subf    r9,r10,r9               ;r9 = starting ray
                and     r9,r9,r13               ;wrap around
                slwi    r9,r9,4
                slwi    r13,r13,4               ;r13 = view angle mask

                lh      r14,ActualHeight
                mr      r24,r14                 ;r24 = actual height
                lb      r10,SkyScroll
                lh      r12,SkyPos
                extsh   r12,r12
                divwu   r11,r14,r10             ;calc sky scroll value
                subf    r11,r12,r11             ;subtract offset
                neg     r11,r11                 ;r11 = sky offset
                lw      r10,SkyData             ;r10 -> sky definition
                lw      r14,PosYDet
                slwi    r14,r14,9

                slwi    r15,r7,8
                citf    f1,f6,r15
                srwi    r23,r7,1
                lh      r18,ViewDistance
                citf    f5,f6,r18
                lh      r21,MaxRange
                lh      r18,DispHeight
                citf    f2,f6,r18
                fmul    f0,f1,f5
                fdiv    f0,f0,f2
                lh      r18,MinRange
                citf    f1,f6,r18
                fadd    f5,f1,f5
                citf    f2,f6,r21
                lh      r21,Pix_Count
                citf    f3,f6,r21
                fsub    f2,f2,f1
                fdiv    f2,f2,f3
                lh      r15,ColumnCount         ;number of columns
                mr      r27,r15                 ;r27 = column count
.loop
                fmr     f1,f5
                lw      r17,PosXDet             ;r17 = pos x value
                slwi    r17,r17,9
                lh      r28,HRotActual          ;r28 = HRotActual
                extsh   r28,r28
                mr      r18,r14                 ;temp pos y shifted value
                mr      r19,r3                  ;temp. view circle ptr
                lw      r19,ViewCircle          ;r19 -> view circle structure
                subi    r19,r19,4               ;prepare for postincrement
                mr      r20,r6                  ;temp. chunky buffer ptr
                lwzu    r16,4(r4)
                add     r9,r9,r16               ;jump to next ray
                and     r9,r9,r13               ;mask out
                add     r19,r19,r9              ;r19 -> new view circle
                lwzu    r26,4(r19)
                add     r18,r18,r26
                lwzu    r26,4(r19)
                add     r17,r17,r26
                lwzu    r21,4(r19)              ;r21 = delta y
                lwzu    r0,4(r19)
                mr      r19,r0                  ;r19 = delta x
                slwi    r29,r28,8
                srwi    r25,r27,1
                divw    r29,r29,r25             ;/half column count
                neg     r26,r15
                add     r26,r26,r25
                add     r26,r26,r26
                subi    r26,r26,1
                mullw   r29,r29,r26
                srawi   r29,r29,17              ;r29 = hor. rotation offset
                subf    r29,r23,r29
                clrw    r28                     ;old height
                mtctr   r22                     ;store pix count to CTR
.loop2
                rlwinm  r12,r18,27,11,20
                rlwimi  r12,r17,17,21,30
                add     r18,r18,r21
                add     r17,r17,r19
                fdivs   f4,f0,f1
                lhzx    r0,r5,r12
                fctiw   f4,f4
                extrwi  r26,r0,8,16
                stfd    f4,-8(stack)
                subf    r26,r24,r26
                lwz     r25,-4(stack)
                fadd    f1,f1,f2
                mullw   r25,r25,r26
                srawi   r25,r25,8
                subf    r25,r29,r25             ;subtract HRot offset
                subf.   r25,r28,r25
                ble     .loopend
                add     r28,r28,r25             ;calc new height
                cmpw    r28,r7
                bge     .cut
                insrwi  r0,r0,8,16
                insrwi  r0,r0,16,0
.copy
                subic.  r25,r25,1
                stw     r0,0(r20)
                subf    r20,r8,r20
                bne     .copy
                bdnz    .loop2
                b       .colOK
.approx
                bdz     .colOK
                add     r18,r18,r21
                add     r17,r17,r19
                fadd    f1,f1,f2
                bdnz    .loop2
                b       .colOK
.loopend
                blt     .approx
                bdnz    .loop2
                b       .colOK
.cut
                subf    r28,r7,r28
                subf.   r25,r28,r25
                beq     .zero
                insrwi  r0,r0,8,16
                insrwi  r0,r0,16,0
.copy2
                subic.  r25,r25,1
                stw     r0,0(r20)
                subf    r20,r8,r20
                bne     .copy2
.zero
;                li      r0,-1
                li      r0,0
                sth     r0,SKY_COUNT(r10)       ;nosky
                b       .jump                   ;column done
.colOK
                subf    r28,r7,r28              ;area height - actual height
                neg.    r28,r28                 ;r28 = sky height to draw
                li      r0,-1
                sth     r0,SKY_COUNT(r10)       ;nosky
                ble     .jump                   ;no sky to draw -> jump
                sth     r28,SKY_COUNT(r10)      ;write sky height
                subf    r25,r29,r11             ;subtract hor. rotation value
                subf    r25,r23,r25
                lh      r28,SkyHeight
                add     r25,r25,r28
                subf    r25,r7,r25              ;calc real sky offset
                lh      r28,SkyWidth2
                mullw   r25,r25,r28             ;multiply by sky width
                stw     r25,SKY_SOURCE(r10)     ;write sky offset
.jump
                subic.  r15,r15,1
                addi    r6,r6,4                 ;next column
                addi    r10,r10,SKY_SIZE        ;next sky definition
                bne     .loop
                lh      r3,SkyWidth2
                lw      r4,SkyBuffer            ;r4 -> sky graphics
                lh      r5,Direction            ;get direction
                lh      r6,Ray_Count
                lh      r7,SkyWidth
                mullw   r5,r5,r3
                divwu   r5,r5,r6                ;calc sky hor. position
                cmpw    r5,r7                   ;check for overflow
                blt     .cont
                subf    r5,r7,r5
.cont
                andi.   r5,r5,$fffe
                add     r4,r4,r5                ;r4 -> sky start pos
                lw      r9,SkyData              ;r9 -> sky definition
                lw      r10,ChunkyBuffer        ;r10 -> chunky buffer
.loop3
                lwz     r11,SKY_SOURCE(r9)      ;get sky source offset
                mr      r12,r4                  ;temp. SkyBuffer
                mr      r13,r10                 ;temp. ChunkyBuffer
                add     r12,r12,r11             ;r12 -> sky start pos
                cmpwi   r27,1                   ;if last turn
                beq     .normal                 ;then normal draw
                lwz     r14,SKY_SOURCE+SKY_SIZE(r9)
                cmpw    r11,r14                 ;next offset equal?
                bne     .normal                 ;no -> normal draw
                lha     r14,SKY_COUNT(r9)
                tstw    r14                     ;sky height >0?
;                blt     .next                   ;no -> no draw
                beq     .next
                lha     r15,SKY_COUNT+SKY_SIZE(r9)
                tstw    r15                     ;next sky height > 0?
;                blt     .next                   ;no -> no draw
                beq     .next
                subi    r27,r27,1               ;draw optimized
                li      r16,4
                cmpw    r14,r15                 ;compare sky heights
                ble     .noexg                  ;of both columns
                mr      r0,r15                  ;change if necessary
                mr      r15,r14
                mr      r14,r0
                li      r16,0
.noexg
                mtctr   r14
.drawsky2
                lwz     r0,0(r12)               ;draw 2 columns at once
                stw     r0,0(r13)
                lwz     r0,4(r12)               ;draw 2 columns at once
                stw     r0,4(r13)
                add     r13,r13,r8
                add     r12,r12,r3
                bdnz    .drawsky2
                subf.   r15,r14,r15             ;subtract heights
                ble     .next2                  ;equal -> done
                mtctr   r15
                add     r12,r12,r16
                add     r13,r13,r16
.drawsky3
                lwz     r0,0(r12)               ;now draw the longer one
                stw     r0,0(r13)
                add     r13,r13,r8
                add     r12,r12,r3
                bdnz    .drawsky3
.next2
                subic.  r27,r27,1
                addi    r4,r4,8                 ;increase by 2 columns
                addi    r10,r10,8
                addi    r9,r9,SKY_SIZE*2
                bne     .loop3
                b       .end
.normal
                lha     r14,SKY_COUNT(r9)       ;get sky height
                tstw    r14
;                blt     .next
                beq     .next
                mtctr   r14
.drawsky
                lwz     r0,0(r12)               ;now draw the longer one
                stw     r0,0(r13)
                add     r13,r13,r8
                add     r12,r12,r3
                bdnz    .drawsky
.next
                subic.  r27,r27,1
                addi    r4,r4,4                 ;next column
                addi    r10,r10,4
                addi    r9,r9,SKY_SIZE
                bne     .loop3
.end
                lwz     r13,-12(stack)
                popgpr
                epilog
;;/
;// ChunkyToPlanar_PPC (converts chunky data to bitplane data)

merge           macro
                and     r18,\1,\3
                xor     \1,r18,\1
                and     r19,\2,\3
                xor     \2,r19,\2
                slwi    r18,r18,\4
                srwi    \2,\2,\4
                or      \1,\1,\2
                or      \2,r19,r18
                endm

******************************************************************************
*
*       ChunkyToPlanar_PPC
*
*       converts chunky data into bitplane data (using Bitmap Structure)
*       works ONLY with a depth of 8!
*
*       original algorithm by James McCoull (I found the source somewhere
*       on the AMINET CD's)
*
******************************************************************************
ChunkyToPlanar_PPC
                prolog  256
                pushgpr r14-r28
                subi    local,local,32          ; space for temporary variables
                lw      r3,HiddenBitmap
                la      r3,bm_Planes+32(r3)     ;r11 -> after 8 plane ptrs
                lwzu    r16,-4(r3)              ;read 8 plane ptrs
                lwzu    r15,-4(r3)
                lwzu    r14,-4(r3)
                lwzu    r28,-4(r3)
                lwzu    r12,-4(r3)
                lwzu    r11,-4(r3)
                lwzu    r10,-4(r3)
                lwzu    r9,-4(r3)
                subi    r9,r9,4                 ;prepare for postincrement
                subi    r10,r10,4
                subi    r11,r11,4
                subi    r12,r12,4
                subi    r28,r28,4
                subi    r14,r14,4
                subi    r15,r15,4
                subi    r16,r16,4
                lw      r3,ChunkyBuffer

; r3 = chunky buffer
; r9-r16 = output area

                lh      r5,AreaHeight
                mulli   r5,r5,320
                add     r4,r3,r5                ;r4 -> end of chunky data
                liw     r5,$00ff00ff            ;load mask values
                liw     r6,$0f0f0f0f
                liw     r7,$33333333
                liw     r8,$55555555
first_case
                lwz     r21,0(r3)
                lwz     r23,4(r3)
                lwz     r20,8(r3)
                lwz     r22,12(r3)
                lwz     r24,2(r3)
                lwz     r25,10(r3)
                lwz     r26,6(r3)
                lwz     r27,14(r3)
                lhz     r17,16(r3)
                mh      r21,r17
                lhz     r17,24(r3)
                mh      r20,r17
                lhz     r17,20(r3)
                mh      r23,r17
                lhz     r17,28(r3)
                mh      r22,r17
                lhz     r17,18(r3)
                mh      r24,r17
                lhz     r17,26(r3)
                mh      r25,r17
                lhz     r17,22(r3)
                mh      r26,r17
                lhz     r17,30(r3)
                mh      r27,r17
                addi    r3,r3,32

                merge   r21,r20,r5,8            ;now convert it
                merge   r23,r22,r5,8
                merge   r21,r23,r6,4
                merge   r20,r22,r6,4
                merge   r24,r25,r5,8
                merge   r26,r27,r5,8
                merge   r24,r26,r6,4
                merge   r25,r27,r6,4
                merge   r23,r26,r7,2
                merge   r22,r27,r7,2
                merge   r23,r22,r8,1
                merge   r26,r27,r8,1
                merge   r21,r24,r7,2
                merge   r20,r25,r7,2
                merge   r21,r20,r8,1
                merge   r24,r25,r8,1

                stw     r27,0*4(local)          ;plane 0
                stw     r26,1*4(local)          ;plane 1
                stw     r22,2*4(local)          ;plane 2
                stw     r23,3*4(local)          ;plane 3
                stw     r25,4*4(local)          ;plane 4
                stw     r24,5*4(local)          ;plane 5
                stw     r20,6*4(local)          ;plane 6
                stw     r21,7*4(local)          ;plane 7

                cmpw    r4,r3
                beq     final_case
main_case
                lwz     r21,0(r3)
                lwz     r23,4(r3)
                lwz     r20,8(r3)
                lwz     r22,12(r3)
                lwz     r24,2(r3)
                lwz     r25,10(r3)
                lwz     r26,6(r3)
                lwz     r27,14(r3)
                lhz     r17,16(r3)
                mh      r21,r17
                lhz     r17,24(r3)
                mh      r20,r17
                lhz     r17,20(r3)
                mh      r23,r17
                lhz     r17,28(r3)
                mh      r22,r17
                lhz     r17,18(r3)
                mh      r24,r17
                lhz     r17,26(r3)
                mh      r25,r17
                lhz     r17,22(r3)
                mh      r26,r17
                lhz     r17,30(r3)
                mh      r27,r17
                addi    r3,r3,32

                lwz     r17,0*4(local)
                stwu    r17,4(r9)
                merge   r21,r20,r5,8
                merge   r23,r22,r5,8
                lwz     r17,1*4(local)
                stwu    r17,4(r10)
                merge   r21,r23,r6,4
                merge   r20,r22,r6,4
                lwz     r17,2*4(local)
                stwu    r17,4(r11)
                merge   r24,r25,r5,8
                merge   r26,r27,r5,8
                lwz     r17,3*4(local)
                stwu    r17,4(r12)
                merge   r24,r26,r6,4
                merge   r25,r27,r6,4
                lwz     r17,4*4(local)
                stwu    r17,4(r28)
                merge   r23,r26,r7,2
                merge   r22,r27,r7,2
                lwz     r17,5*4(local)
                stwu    r17,4(r14)
                merge   r23,r22,r8,1
                merge   r26,r27,r8,1
                lwz     r17,6*4(local)
                stwu    r17,4(r15)
                merge   r21,r24,r7,2
                merge   r20,r25,r7,2
                lwz     r17,7*4(local)
                stwu    r17,4(r16)
                merge   r21,r20,r8,1
                merge   r24,r25,r8,1
                stw     r27,0*4(local)          ;plane 0
                stw     r26,1*4(local)          ;plane 1
                stw     r22,2*4(local)          ;plane 2
                stw     r23,3*4(local)          ;plane 3
                stw     r25,4*4(local)          ;plane 4
                stw     r24,5*4(local)          ;plane 5
                stw     r20,6*4(local)          ;plane 6
                stw     r21,7*4(local)          ;plane 7

                cmpw    r4,r3
                bne     main_case

final_case
                lwz     r17,0*4(local)
                stwu    r17,4(r9)
                lwz     r17,1*4(local)
                stwu    r17,4(r10)
                lwz     r17,2*4(local)
                stwu    r17,4(r11)
                lwz     r17,3*4(local)
                stwu    r17,4(r12)
                lwz     r17,4*4(local)
                stwu    r17,4(r28)
                lwz     r17,5*4(local)
                stwu    r17,4(r14)
                lwz     r17,6*4(local)
                stwu    r17,4(r15)
                lwz     r17,7*4(local)
                stwu    r17,4(r16)
exit
                addi    local,local,32
                popgpr
                epilog
;;/

