********************************************************************
*
*       Landscape_Calc
*
*       Calculation routines for 'landscape' (PPC)
*
*       assemble with:
*       powerasm Landscape_Calc.s to Landscape_Calc.o
*
*       link with smalldata and smallcode enabled
*
*       © 1997 HAAGE&PARTNER Computer GmbH
*
********************************************************************


;// XDEF / XREF
                xref    PrepareFlight
                xref    _PowerPCBase
                xref    ChunkyBuffer
                xref    MapSize
                xref    MapSizeExp
                xref    MapMem
                xref    MapMemEnd
                xref    MapScale
                xref    browntab
                xref    Code
                xref    H
                xref    Iterations
                xref    Variation
                xref    Water
                xref    Shadow
                xref    LightDir
                xref    LightAngle
                xref    RanCount
                xref    Highest
                xref    Lowest
                xref    tantab
                xref    MapDim
                xref    MapHeight
                xref    AreaWidth
                xref    AreaHeight
                xref    BitmapWidth

                xdef    CreateLandscape_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: intermediate GP-Register (MUST point to the value $4330000000000000)
*       4: source GP-Register
*
*       r0 is trashed

citf            macro
                xoris   trash,\4,$8000
                stw     trash,4(\3)
                lfd     \1,0(\3)
                fsub    \1,\1,\2
                endm
;;/

                CPU     POWERPC
                smalldata
                smallcode

                section "Lanscape_Calc_Code",code

* landscape generator stuff

;// CreateLandscape_PPC (creates the landscape)
******************************************************************************
*
*       CreateLandscape_PPC
*
*       creates the landscape
*
******************************************************************************
CreateLandscape_PPC
                prolog  1024
                pushgpr r14-r16/r28-r31
                pushfpr f14-f16
                liw     r14,630360016           ;r14 = GLOBAL (for URN30)
                liw     r15,$7fffffff           ;r15 = GLOBAL (for URN30)
                la      r16,CITF_TEMP           ;r16 = GLOBAL (for macro CITF)
                lf      f14,CITF_0              ;f14 = GLOBAL (for macro CITF)
                citf    f15,f14,r16,r14         ;f15 = GLOBAL (for URN30)
                citf    f16,f14,r16,r15         ;f16 = GLOBAL (for URN30)
                bl      SetRNDModeRZ            ;enable rounding mode RZ
                mr      r31,r3                  ;save old FPSCR
                lw      r30,MapMem              ;-> map space
                mr      r3,r30
                la      r4,browntab             ;-> math table
                lb      r5,MapSizeExp           ;map size exponential
                lb      r6,Iterations           ;iterations for subdivision
                lb      r7,H                    ;fractal parameter
                lb      r29,RanCount
                mr      r8,r29
                bl      BuildLandscape          ;build landscape
                mr      r3,r30                  ;-> map space
                lw      r28,MapSize             ;map size
                mr      r4,r28
                lb      r5,Water                ;water area
                bl      ScaleLandscape          ;scale landscape
                mr      r3,r30                  ;-> map space
                mr      r4,r28                  ;map size
                lb      r5,Variation            ;color variation
                mr      r6,r29
                bl      CreateColors            ;define colors
                lb      r3,Shadow               ;shadow enabled?
                tstw    r3
                beq     .noshadow               ;no -> jump
                mr      r3,r30                  ;-> map space
                la      r4,tantab               ;tangens table
                mr      r5,r28                  ;map size
                lb      r6,LightDir             ;light direction
                lb      r7,LightAngle           ;light angle
                bl      CreateShadow            ;create shadow
.noshadow
                mr      r3,r31                  ;get FPSCR
                bl      RestoreRNDMode          ;restore FPSCR
                popfpr
                popgpr
                epilog
;;/
;// BuildLandscape (creates the landscape using a fractal algorithm)
******************************************************************************
*
*       BuildLandscape (r3,r4,r5,r6,r7,r8,r9)
*
*       creates the landscape using a fractal algorithm
*       height = average_height + random * 0.5^(Iterations*H)
*
*       In: r3 -> map memory
*           r4 -> math table for fractal computation
*           r5 = map border size (exp.)
*           r6 = number of iterations for subdivision
*           r7 = H (fractal parameter)
*           r8 = number of uniform random numbers for one normal random number
*
******************************************************************************
BuildLandscape
                pushlr
                pushgpr r17-r31
                mr      r31,r3
                slwi    r0,r6,5                 ;calc offset into math table
                add     r30,r4,r0               ;r30 -> current entry
                add     r7,r7,r7                ;calc offset for H parameter
                add     r30,r30,r7              ;r30 -> 0.5^(It.*H)<<14
                mr      r29,r8                  ;save random count
                subf    r28,r6,r5               ;r28 = number of iterations
                li      r0,1
                slw     r27,r0,r5               ;r27 = map border size
                slw     r26,r0,r6               ;r26 = vertical loop counter
                slw     r25,r0,r6               ;r25 = horizontal loop counter
                srw     r0,r27,r6               ;calc map step value
                add     r24,r0,r0               ;r24 = horizontal step value
                mullw   r23,r24,r27             ;r23 = vertical step value
                add     r3,r27,r27              ;calc map mask values
                subi    r22,r3,1                ;r22 = horizontal map mask
                mullw   r21,r3,r27
                subi    r21,r21,1               ;r21 = vertical map mask
.loop
                mr      r20,r26                 ;r20 = vertical loop counter
                li      r18,0                   ;reset vertical position
.loop2
                mr      r19,r25                 ;r19 = horizontal loop counter
                li      r17,0                   ;reset horizontal position
.loop3
                mr      r3,r31
                mr      r4,r30
                mr      r5,r22
                mr      r6,r18
                mr      r7,r23
                mr      r8,r17
                mr      r9,r24
                mr      r10,r21
                mr      r11,r29
                bl      SetCenter               ;calc height of center field
                add     r17,r17,r24             ;increase horizontal position
                subic.  r19,r19,1
                bne     .loop3
                add     r18,r18,r23             ;increase vertical position
                subic.  r20,r20,1
                bne     .loop2
                addi    r30,r30,32              ;next math table entry
                mr      r20,r26                 ;r20 = vertical loop counter
                li      r18,0                   ;reset vertical position
.loop4
                mr      r19,r25                 ;r19 = horizontal loop counter
                li      r17,0                   ;reset horizontal position
.loop5
                mr      r3,r31
                mr      r4,r30
                mr      r5,r22
                mr      r6,r18
                mr      r7,r23
                mr      r8,r17
                mr      r9,r24
                mr      r10,r21
                mr      r11,r29
                bl      SetUpper                ;calc height of upper field
                mr      r3,r31
                mr      r4,r30
                mr      r5,r22
                mr      r6,r18
                mr      r7,r23
                mr      r8,r17
                mr      r9,r24
                mr      r10,r21
                mr      r11,r29
                bl      SetLeft                 ;calc height of lower field
                add     r17,r17,r24             ;increase horizontal position
                subic.  r19,r19,1
                bne     .loop5
                add     r18,r18,r23             ;increase vertical position
                subic.  r20,r20,1
                bne     .loop4
                addi    r30,r30,32              ;next math table entry
                add     r25,r25,r25             ;double horizontal counter
                add     r26,r26,r26             ;double vertical counter
                srwi    r24,r24,1               ;halve horizontal step value
                srwi    r23,r23,1               ;halve vertical step value
                subic.  r28,r28,1
                bne     .loop                   ;next iteration
                popgpr
                poplr
                blr
;;/
;// SetCenter (sets the height of the center of a specific square)
******************************************************************************
*
*       SetCenter (r3,r4,r5,r6,r7,r8,r9,r10,r11)
*
*       sets the height of the center of a specific square
*
*       In: r3 -> map memory
*           r4 -> fractal exponent
*           r5 = horizontal map mask
*           r6 = vertical offset of the top border of the square
*           r7 = differential vertical offset
*           r8 = horizontal offset of the left border of the square
*           r9 = differential horizontal offset
*           r10 = vertical map mask
*           r11 = number of uniform random numbers for one normal random number
*
******************************************************************************
SetCenter
                pushlr
                pushgpr r27-r31
                mtctr   r11
                mr      r30,r4
                add     r11,r6,r8
                lhax    r31,r3,r11              ;read left top height
                add     r4,r8,r9
                and     r0,r4,r5
                add     r0,r0,r6
                lhax    r0,r3,r0                ;read right top height
                add     r31,r31,r0              ;add to r31
                add     r12,r6,r7
                and     r0,r12,r10
                add     r0,r0,r8
                lhax    r0,r3,r0                ;read left bottom height
                add     r31,r31,r0              ;add to r31
                and     r0,r4,r5
                and     r4,r12,r10
                add     r0,r0,r4
                lhax    r0,r3,r0                ;read right bottom height
                add     r31,r31,r0              ;add to r31
                srawi   r31,r31,2               ;calc average height
                srwi    r9,r9,1                 ;halve square width
                srwi    r7,r7,1                 ;halve square height
                add     r0,r11,r9
                add     r0,r0,r7                ;calc offset into center
                add     r29,r3,r0               ;r29 -> center field
                li      r28,0                   ;init sum value
                liw     r27,$3fffffff
.loop
                bl      URN30                   ;get random value
                subf    r3,r27,r3               ;scale random value
                srawi   r3,r3,4
                add     r28,r28,r3              ;add to sum value
                bdnz    .loop
                srawi   r28,r28,16
                lhz     r3,0(r30)               ;read fractal exponent
                mullw   r3,r3,r28               ;multiply with random value
                srawi   r3,r3,12                ;scale result
                add     r31,r31,r3              ;add to average height
                lh      r3,Highest              ;check if highest point
                cmpw    r31,r3
                ble     .cont
                sh      r31,Highest             ;yes -> replace
.cont
                lhs     r3,Lowest               ;check if lowest point
                cmpw    r31,r3
                bge     .cont2
                sh      r31,Lowest              ;yes -> replace
.cont2
                sth     r31,0(r29)              ;store height into center field
                popgpr
                poplr
                blr
;;/
;// SetUpper (sets the height of the upper point of a specific square)
******************************************************************************
*
*       SetUpper (r3,r4,r5,r6,r7,r8,r9,r10,r11)
*
*       sets the height of the upper point of a specific square
*
*       In: r3 -> map memory
*           r4 -> fractal exponent
*           r5 = horizontal map mask
*           r6 = vertical offset of the top border of the square
*           r7 = differential vertical offset
*           r8 = horizontal offset of the left border of the square
*           r9 = differential horizontal offset
*           r10 = vertical map mask
*           r11 = number of uniform random numbers for one normal random number
*
******************************************************************************
SetUpper
                pushlr
                pushgpr r27-r31
                mtctr   r11
                mr      r30,r4
                add     r0,r6,r8
                lhax    r31,r3,r0               ;read left top height
                add     r0,r8,r9
                and     r0,r0,r5
                add     r0,r0,r6
                lhax    r0,r3,r0                ;read right top height
                add     r31,r31,r0              ;add to r31
                srwi    r7,r7,1                 ;halve square width
                srwi    r9,r9,1                 ;halve square height
                add     r11,r8,r9
                add     r4,r7,r6
                and     r4,r4,r10
                add     r0,r4,r11
                lhax    r0,r3,r0                ;read center bottom height
                add     r31,r31,r0              ;add to r31
                subf    r4,r7,r6
                and     r4,r4,r10
                add     r0,r4,r11
                lhax    r0,r3,r0                ;read center top height
                add     r31,r31,r0              ;add to r31
                srawi   r31,r31,2               ;calc average height
                add     r0,r11,r6               ;calc offset into upper field
                add     r29,r3,r0               ;r29 -> upper field
                li      r28,0                   ;init sum value
                liw     r27,$3fffffff
.loop
                bl      URN30                   ;get random value
                subf    r3,r27,r3               ;scale random value
                srawi   r3,r3,4
                add     r28,r28,r3              ;add to sum value
                bdnz    .loop
                srawi   r28,r28,16
                lhz     r3,0(r30)               ;read fractal exponent
                mullw   r3,r3,r28               ;multiply with random value
                srawi   r3,r3,12                ;scale result
                add     r31,r31,r3              ;add to average height
                lh      r3,Highest              ;check if highest point
                cmpw    r31,r3
                ble     .cont
                sh      r31,Highest             ;yes -> replace
.cont
                lhs     r3,Lowest               ;check if lowest point
                cmpw    r31,r3
                bge     .cont2
                sh      r31,Lowest              ;yes -> replace
.cont2
                sth     r31,0(r29)              ;store height into center field
                popgpr
                poplr
                blr
;;/
;// SetLeft (sets the height of the left point of a specific square)
******************************************************************************
*
*       SetLeft (r3,r4,r5,r6,r7,r8,r9,r10,r11)
*
*       sets the height of the left point of a specific square
*
*       In: r3 -> map memory
*           r4 -> fractal exponent
*           r5 = horizontal map mask
*           r6 = vertical offset of the top border of the square
*           r7 = differential vertical offset
*           r8 = horizontal offset of the left border of the square
*           r9 = differential horizontal offset
*           r10 = vertical map mask
*           r11 = number of uniform random numbers for one normal random number
*
******************************************************************************
SetLeft
                pushlr
                pushgpr r27-r31
                mtctr   r11
                mr      r30,r4
                add     r11,r6,r8
                lhax    r31,r3,r11              ;read left top height
                add     r4,r6,r7
                and     r0,r4,r10
                add     r0,r0,r8
                lhax    r0,r3,r0                ;read left bottom height
                add     r31,r31,r0              ;add to r31
                srwi    r7,r7,1                 ;halve square width
                srwi    r9,r9,1                 ;halve square height
                add     r11,r7,r6
                add     r4,r9,r8
                and     r4,r4,r5
                add     r0,r4,r11
                lhax    r0,r3,r0                ;read center right height
                add     r31,r31,r0              ;add to r31
                subf    r4,r9,r8
                and     r4,r4,r5
                add     r0,r4,r11
                lhax    r0,r3,r0                ;read center left height
                add     r31,r31,r0              ;add to r31
                srawi   r31,r31,2               ;calc average height
                add     r0,r11,r8               ;calc offset into upper field
                add     r29,r3,r0               ;r29 -> upper field
                li      r28,0                   ;init sum value
                liw     r27,$3fffffff
.loop
                bl      URN30                   ;get random value
                subf    r3,r27,r3               ;scale random value
                srawi   r3,r3,4
                add     r28,r28,r3              ;add to sum value
                bdnz    .loop
                srawi   r28,r28,16
                lhz     r3,0(r30)               ;read fractal exponent
                mullw   r3,r3,r28               ;multiply with random value
                srawi   r3,r3,12                ;scale result
                add     r31,r31,r3              ;add to average height
                lh      r3,Highest              ;check if highest point
                cmpw    r31,r3
                ble     .cont
                sh      r31,Highest             ;yes -> replace
.cont
                lhs     r3,Lowest               ;check if lowest point
                cmpw    r31,r3
                bge     .cont2
                sh      r31,Lowest              ;yes -> replace
.cont2
                sth     r31,0(r29)              ;store height into center field
                popgpr
                poplr
                blr
;;/
;// ScaleLandscape (scales the landscape)
******************************************************************************
*
*       ScaleLandscape (r3,r4,r5)
*
*       scales the landscape
*
*       In: r3 -> map memory
*           r4 = map border size
*           r5 = water area
*
******************************************************************************
ScaleLandscape
                pushlr
                subi    r3,r3,2                 ;prepare for postincrement
                li      r9,100
                li      r11,255
                lhs     r6,Highest              ;read highest point
                lhs     r7,Lowest               ;read lowest point
                subf    r8,r7,r6                ;calc difference
                mullw   r0,r8,r5
                divwu   r0,r0,r9
                add     r7,r7,r0                ;r7 = water NULL height
                subf    r6,r7,r6                ;r6 = height above water
                mr      r9,r4
.loop
                mr      r10,r4
.loop2
                lha     r5,2(r3)                ;read height
                subf    r0,r7,r5                ;shift up/down height
                mullw   r0,r0,r11               ;scale height
                divw    r0,r0,r6
                sthu    r0,2(r3)                ;write new height
                subic.  r10,r10,1
                bne     .loop2
                subic.  r9,r9,1
                bne     .loop
                poplr
                blr
;;/
;// CreateColors (defines the color values for each zone)
******************************************************************************
*
*       CreateColors (r3,r4,r5,r6)
*
*       defines the color values for each zone
*
*       In: r3 -> map memory
*           r4 = map border size
*           r5 = variation parameter (0 = standard)
*           r6 = number of uniform random numbers for one normal random number
*
******************************************************************************
CreateColors
                pushlr
                pushgpr r23-r31
                mr      r24,r3
                mr      r31,r5
                mr      r30,r6
                mullw   r29,r4,r4
                add     r29,r29,r29             ;r29 = map full size (in bytes)
                add     r23,r4,r4               ;r23 = line size in bytes
                subf    r29,r29,r23             ;r29=offs. from last to 1st line
                neg     r28,r23                 ;r28 = offs. from right to left
                subi    r27,r4,1                ;create loop counters (one less
                subi    r26,r4,1                ;than usual)
                mr      r25,r27                 ;save inner loop counter
                mtctr   r25
.loop
                mr      r27,r25
.loop2
                lha     r4,0(r24)               ;calc average height of
                lha     r0,2(r24)               ;corresponding polygon
                add     r4,r4,r0
                lhax    r0,r24,r23
                add     r4,r4,r0
                addi    r0,r23,2
                lhax    r0,r24,r0
                add     r4,r4,r0
                srawi   r4,r4,2                 ;r4 = average height
                mr      r3,r24
                mr      r5,r31
                mr      r6,r30
                bl      DefineColor             ;assign color
                addi    r24,r24,2               ;next height
                subic.  r27,r27,1
                bne     .loop2
                lha     r4,0(r24)               ;special case: polygon between
                lha     r0,2(r24)               ;rightmost and leftmost point
                add     r4,r4,r0
                lhax    r0,r24,r23
                add     r4,r4,r0
                addi    r0,r28,2
                lhax    r0,r24,r0
                add     r4,r4,r0
                srawi   r4,r4,2                 ;r4 = average height
                mr      r3,r24
                mr      r5,r31
                mr      r6,r30
                bl      DefineColor             ;assign color
                addi    r24,r24,2               ;next height
                subic.  r26,r26,1
                bne     .loop
.loop3
                lha     r4,0(r24)               ;special case: polygons between
                lha     r0,2(r24)               ;bottom line and top line
                add     r4,r4,r0
                lhax    r0,r24,r29
                add     r4,r4,r0
                addi    r0,r29,2
                lhax    r0,r24,r0
                add     r4,r4,r0
                srawi   r4,r4,2                 ;r4 = average height
                mr      r3,r24
                mr      r5,r31
                mr      r6,r30
                bl      DefineColor             ;assign color
                addi    r24,r24,2               ;next height
                bdnz    .loop3
                lha     r4,0(r24)               ;special case: polygon between
                lhax    r0,r24,r28              ;right-bottom point and left-top
                add     r4,r4,r0                ;point
                addi    r0,r28,2
                lhax    r0,r24,r0
                add     r4,r4,r0
                lhax    r0,r24,r29
                add     r4,r4,r0
                add     r0,r28,r29
                lhax    r0,r24,r0
                add     r4,r4,r0
                srawi   r4,r4,2                 ;r4 = average height
                mr      r3,r24
                mr      r5,r31
                mr      r6,r30
                bl      DefineColor             ;assign color
                popgpr
                poplr
                blr
;;/
;// DefineColor (calulates one color value)
******************************************************************************
*
*       DefineColor (r3,r4,r5,r6)
*
*       defines the color values for each zone
*
*       In: r3 -> 16 bit height element
*           r4 = average height of corresponding polygon
*           r5 = variation parameter
*           r6 = number of uniform random numbers for one normal random number
*
******************************************************************************
DefineColor
                pushlr
                pushctr
                pushgpr r26-r31
                lha     r31,0(r3)               ;read height
                mr      r26,r3
                mr      r27,r31
                mr.     r28,r5                  ;any variation wanted?
                beq     .novariation            ;no -> jump
                mtctr   r6                      ;number of random numbers
                li      r30,0                   ;init sum value
                liw     r29,$3fffffff
.loop
                bl      URN30                   ;calc random value
                subf    r3,r29,r3               ;scale random value
                srawi   r3,r3,4
                add     r30,r30,r3              ;add to sum
                bdnz    .loop
                srawi   r30,r30,16
                mullw   r30,r30,r28             ;multiply with variation
                srawi   r30,r30,14              ;scale result
                tstw    r31                     ;polygon in water?
                ble     .water1                 ;yes -> jump
                add.    r27,r27,r30             ;add variation to height
                bgt     .cont                   ;still over water? -> jump
                li      r27,1                   ;lowest point above water
                b       .novariation
.cont
                cmpwi   r27,255                 ;overflow?
                ble     .novariation            ;no -> jump
                li      r27,255                 ;limit to highest point
                b       .novariation
.water1
                add.    r27,r27,r30             ;add variation to height
                ble     .novariation            ;still under water? -> jump
                li      r27,0                   ;least deep water
.novariation
                tstw    r31                     ;polygon in water?
                ble     .water                  ;yes -> jump
                subfic  r27,r27,255
                stb     r31,0(r26)              ;store height in first byte
                srawi.  r27,r27,2               ;calc color value
                bne     .cont2                  ;not zero?
                li      r27,1                   ;if zero than one (no water)
.cont2
                stb     r27,1(r26)              ;store color into second byte
                b       .end
.water
                neg     r27,r27
                srawi   r27,r27,2
                addi    r27,r27,64              ;calc color value
                li      r0,0
                stb     r0,0(r26)               ;height = 0
                cmpwi   r27,127                 ;if water too deep
                ble     .cont3
                li      r27,127                 ;limit to darkest blue
.cont3
                stb     r27,1(r26)              ;store color
.end
                popgpr
                popctr
                poplr
                blr
;;/
;// CreateShadow (calculates the shadow)
******************************************************************************
*
*       CreateShadow (r3,r4,r5,r6,r7)
*
*       divides the landscape in smaller parts
*
*       In: r3 -> map memory
*           r4 -> tangens table for tangens calculation
*           r5 = map border size
*           r6 = light direction (0-3)
*           r7 = light angle (0-89)
*
******************************************************************************
CreateShadow
                pushlr
                pushgpr r27-r31
                mr      r30,r5
                slwi    r7,r7,8                 ;calc tan (lightangle)
                li      r0,90
                divwu   r0,r7,r0
                add     r0,r0,r0
                lhzx    r29,r4,r0               ;r29 = tan (angle) << 7
                mullw   r5,r5,r5
                add     r5,r5,r5                ;r5 = map size in bytes
                tstw    r6                      ;case direction
                beq     .left
                cmpwi   r6,1
                beq     .top
                cmpwi   r6,2
                beq     .right
.bottom
                add     r3,r3,r5                ;rays from bottom
                subi    r3,r3,2                 ;r3 -> last element in map
                add     r28,r30,r30
                neg     r28,r28                 ;vertical step value
                li      r27,-2                  ;horizontal line step value
                b       .cont
.right
                add     r3,r3,r5                ;rays from right
                subi    r3,r3,2                 ;r3 -> last element in map
                add     r27,r30,r30
                neg     r27,r27                 ;horizontal step value
                li      r28,-2                  ;vertical line step value
                b       .cont
.top
                add     r28,r30,r30
                li      r27,2
                b       .cont
.left
                add     r27,r30,r30
                li      r28,2
.cont
                mtctr   r30
                mr      r31,r3
.loop
                mr      r4,r30
                mr      r3,r31
                mr      r5,r29
                mr      r6,r28
                bl      ShadowLine
                add     r31,r31,r27
                bdnz    .loop
                popgpr
                poplr
                blr
;;/
;// ShadowLine (shadows one map line)
******************************************************************************
*
*       ShadowLine (r3,r4,r5,r6)
*
*       shadows one map line
*
*       In: r3 -> map memory (or last element)
*           r4 = map border size
*           r5 = vertical difference
*           r6 = map step value
*
******************************************************************************
ShadowLine
                pushlr
                mr      r7,r3
                li      r8,0                    ;init point counter
.loop
                lbz     r9,0(r3)                ;read height
                slwi    r9,r9,7                 ;shift left
                subf    r9,r5,r9                ;subtract tangens
.entry
                add     r3,r3,r6                ;goto next point
                addi    r8,r8,1
                cmpw    r8,r4                   ;warp around?
                bne     .cont                   ;no -> jump
                mr      r3,r7                   ;begin again
.cont
                lbz     r10,0(r3)               ;read height of next pixel
                slwi    r10,r10,7
                cmpw    r10,r9                  ;below shadow line?
                blt     .shade                  ;yes -> shade point
                cmpw    r8,r4                   ;if no shadow and line done
                bgt     .end                    ;-> exit
                b       .loop                   ;try next point
.shade
                lbz     r11,1(r3)               ;read color value
                cmpwi   r11,127                 ;already shaded?
                bgt     .next                   ;yes -> jump
                addi    r11,r11,128             ;shade point
                stb     r11,1(r3)               ;store new color value
.next
                subf    r9,r5,r9                ;subtract tangens
                b       .entry
.end
                poplr
                blr
;;/
;// SetRNDModeRZ (set rounding mode for the FPU to 'round to zero')
******************************************************************************
*
*       r3 = SetRNDModeRZ
*
*       set rounding mode for the FPU to 'round to zero'
*
*       Out: r3 = old FPCR value
*
******************************************************************************
SetRNDModeRZ
                mffs    f0
                stfd    f0,-8(local)
                lwz     r3,-4(local)
                ori     r0,r3,$1
                stw     r0,-4(local)
                lfd     f0,-8(local)
                mtfsf   $ff,f0
                blr
;;/
;// RestoreRNDMode (restores rounding mode for the FPU)
******************************************************************************
*
*       RestoreRNDMode (r3)
*
*       restores rounding mode for the FPU
*
*       In:  r3 = FPCR value to be restored
*
******************************************************************************
RestoreRNDMode
                stw     r3,-4(local)
                lfd     f0,-8(local)
                mtfsf   $ff,f0
                blr
;;/
;// URN30 (calculates one uniform random number)
******************************************************************************
*
*       r3 = URN30 (GLOBAL r14, GLOBAL r15, GLOBAL r16
*                   GLOBAL f14, GLOBAL f15, GLOBAL f16)
*
*       calculates one uniform random number (rounding mode for the FPU
*       MUST be set to 'round to zero')
*       'Code' must hold a start random value if it's first used
*       URN30 algorithm is taken: Xn+1 = 630360016 * Xn mod $7fffffff
*
*       In:  GLOBAL r14 = 630360016
*            GLOBAL r15 = $7fffffff
*            GLOBAL r16 -> temporary space for macro CITF
*            GLOBAL f14 = $4330000080000000
*            GLOBAL f15 = 630360016
*            GLOBAL f16 = double($7fffffff)
*
*       Out: d0 = new random number (0-$7ffffffe)
*
******************************************************************************
URN30
                lw      r3,Code                 ;get previous result/start res.
                citf    f0,f14,r16,r3
                fmul    f1,f0,f15
                mullw   r4,r3,r14
                fdiv    f2,f1,f16
                fctiw   f3,f2
                stfd    f3,-8(local)
                lwz     r5,-4(local)
                mullw   r0,r15,r5
                subf    r3,r0,r4                ;r3 = new random number
                sw      r3,Code                 ;store actual result
                blr
;;/


                section "Lanscape_Calc_Data",data

CITF_0          dc.l    $43300000,$80000000
CITF_TEMP       dc.l    $43300000,0

