;-----------------------------------------------------------;
;                                                           ;
; Invaded                                                   ;
; Version 1.0                                               ;
; Miscellaneous Routines                                    ;
;                                                           ;
;-----------------------------------------------------------;

#ifndef MIRAGE                                  ; MirageOS has it's own version of this function
;------------------------------------------------
; directIn - Get keypresses from the key port
;
; Input:    A = Port to read keypresses from
; Output:   A = Keypresses from that port
;------------------------------------------------
directIn:
        ld      b,a                             ; Save mask
        ld      a,$FF                           ; Value used to reset keyport
        out     (1),a                           ; Reset keyport (sort of)
        ld      a,b                             ; Get mask again
        out     (1),a                           ; Open the group we wanna check
        in      a,(1)                           ; Get any keypresses
        ret
#endif

;------------------------------------------------
; waitKey - Waits for a key press
;
; Input:    None
; Output:   A = Keycode (_getcsc style)
;------------------------------------------------
waitKey:
        ei                                      ; We need interrupts so we can use 'halt'
        res     apdrunning,(iy+apdflags)
wKeyLoop:
        halt                                    ; Save a bit of battery life
        bcall(GET_KEY)                          ; Get any keypresses
        or      a                               ; Has a key been pressed?
        jr      z,wKeyLoop                      ; If not, keep waiting
        set     apdrunning,(iy+apdflags)
        ret

;------------------------------------------------
; waitKeyA - Waits for a key press other than arrow keys
;
; Input:    None
; Output:   A = Keycode (_getcsc style)
;------------------------------------------------
waitKeyA:
        call    waitKey                         ; Wait for any keypress
        cp      5                               ; Was it an arrow key?
        ret     nc                              ; If not, we can leave
        jr      waitKeyA                        ; Otherwise, wait for another keypress

#ifdef MIRAGE
vPuts           = setVPuts                      ; MirageOS has it's own version of this function
#else
;------------------------------------------------
; vPuts - Save coords DE and writes small font
;
; Input:    DE = Y, X Coordinates to write text
;           HL => Null terminated string
; Output:   None
;------------------------------------------------
vPuts:
        ld      (pencol),de                     ; Save coords
        bcall(_vputs)                           ; Write it
        ret
#endif

;------------------------------------------------
; puts - Save coords DE and write large font
;
; Input:    DE = X, Y Coordinates to write text
;           HL => Null terminating string
; Output:   None
;------------------------------------------------
puts:
        ld      (currow),de                     ; Save coords
        bcall(_puts)                            ; Write string
        ret

;------------------------------------------------
; pause - Pause the game
;
; Input:    None
; Output:   None
;------------------------------------------------
pause:
        ld      hl,strPaused
        ld      de,5*256+3
        call    puts                            ; "Paused"
paused:
        ld      a,KG_5
        call    directIn
        bit     DI_ENTER,a
        jr      nz,paused
        ei
        ret

;------------------------------------------------
; teacherKey - Turn off the calculator until [ON] is pressed
;
; Input:    None
; Output:   None
;------------------------------------------------
teacherKey:
        ld      a,1
        out     (3),a
        halt
        ld      a,11
        out     (3),a
        ret

;------------------------------------------------
; invertArea - Invert a block of memory
;
; Input:    HL => Start of where to invert
;           BC = Number of bytes to invert
; Output:   HL => Data after inverted area
;           BC = 0
;------------------------------------------------
invertArea:
        ld      a,(hl)                          ; Get byte
        cpl                                     ; Take the complement
        ld      (hl),a                          ; Save it
        inc     hl                              ; Next byte
        dec     bc                              ; Decrement counter
        ld      a,c
        or      b                               ; Does BC = 0 ?
        jr      nz,invertArea                   ; If not, invert another byte
        ret

;------------------------------------------------
; checkPixel - Get tile at exact coords and see if it can be moved through, check also for hurty tiles
;
; Input:    A = Y Coord
;           HL = X Coord
; Output:   A = Tile
;           CA = 1 if can't move through tile
;------------------------------------------------
checkPixel:
        call    getTileAtExactCoords            ; Get tile
        ld      hl,hurtyTiles
        cp      (hl)                            ; Is it a hurty tile?
        jr      nc,checkPixelPlayerDead         ; If so, the player is dead :(
        ld      hl,solidTiles
        cp      (hl)                            ; Is it a solid tile?
        ccf                                     ; Complement Carry Flag
        ret                                     ; Return the carry value
checkPixelPlayerDead:
        ld      a,INI_DEAD
        ld      (dead),a                        ; Player is dead
        scf                                     ; Set Carry Flag
        ret                                     ; Return the carry value

;------------------------------------------------
; getTileAtExactCoords - Get a tile number at exact coordinates
;
; Input:    A = Y Coord
;           HL = X Coord
; Output:   A = Tile
;           HL => Tile
;------------------------------------------------
getTileAtExactCoords:
        call    divHLby8                        ; HL = HL / 8
        ld      h,7
        bcall(_htimesl)                         ; Now, multiply it by 7
        call    divAby8                         ; A = A / 8
        ld      e,a
        ld      d,0                             ; DE = A / 8
        add     hl,de                           ; HL = Offset to tile in level data
        ld      de,(tempMem)
        add     hl,de                           ; HL => Tile
        ld      a,(hl)                          ; A = Tile
        ret

;------------------------------------------------
; divHLby8 - Divide HL by 8
;
; Input:    HL = Number
; Output:   HL = Number / 8
;------------------------------------------------
divHLby8:
        srl     h
        rr      l                               ; HL = HL / 2
        srl     h
        rr      l                               ; HL = HL / 4
        srl     h
        rr      l                               ; HL = HL / 8
        ret

;------------------------------------------------
; divAby8 - Divide A by 8
;
; Input:    A = Number
; Output:   A = Number / 8
;------------------------------------------------
divAby8:
        srl     a                               ; A = A / 2
        srl     a                               ; A = A / 4
        srl     a                               ; A = A / 8
        ret

;------------------------------------------------
; showHL - Show HL preceded by set number of zeros
;
; Input:    HL = Number to show
;           B = Number of characters to show
;           C = 1 to show an extra 0 on the end
; Output:   HL => String to display
;------------------------------------------------
showHL:
        ld      de,showHLBuffer+6               ; End of string storage
        xor     a
        ld      (de),a                          ; Put in the NULL terminator
        dec     c                               ; Is C = 1?
        jr      nz,sHLLoop                      ; If not, don't add extra 0
        dec     de                              ; Decrement string pointer
        ld      a,'0'                           ; 0 character
        ld      (de),a                          ; Save it to add extra 0
sHLLoop:
        dec     de                              ; Move pointer back a byte
        bcall(_divhlby10)                       ; Get smallest unit of HL to A
        add     a,'0'                           ; Format it for display
        ld      (de),a                          ; Store it
        djnz    sHLLoop                         ; Next character
        ex      de,hl                           ; (HL) = String to display
        ret

.end
