;;==========================================================================;;
;; Joe Zbiciak's Singed Earth?                                              ;;
;; Copyright 2003, Joe Zbiciak, intvnut AT gmail DOT com                    ;;
;;==========================================================================;;

;------------------------------------------------------------------------------
; Include system information and macro libraries
;------------------------------------------------------------------------------
            INCLUDE "../library/gimini.asm"
            INCLUDE "../macro/util.mac"
            INCLUDE "../macro/stic.mac"
            INCLUDE "../macro/gfx.mac"
            INCLUDE "../macro/print.mac"

            CFGVAR  "name" = "SDK-1600 Singed Earth? Tank Demo"
            CFGVAR  "short_name" = "Singed Earth?"
            CFGVAR  "author" = "Joe Zbiciak"
            CFGVAR  "year" = 2003
            CFGVAR  "license" = "GPLv2+"
            CFGVAR  "description" = "Singed Earth is a play on Scorched Earth."
            CFGVAR  "publisher" = "SDK-1600"

;------------------------------------------------------------------------------
; Global constants and configuration.
;------------------------------------------------------------------------------
TSKQM       EQU     $7              ; Task queue is 8 entries large

;------------------------------------------------------------------------------
; Allocate 8-bit variables in Scratch RAM
;------------------------------------------------------------------------------
SCRATCH     ORG     $100, $100, "-RWBN"

ISRVEC      RMB     2               ; Always at $100 / $101

            ; Task-oriented 8-bit variables
TSKQHD      RMB     1               ; Task queue head
TSKQTL      RMB     1               ; Task queue tail
TSKDQ       RMB     2*(TSKQM+1)     ; Task data queue

            ; Hand-controller 8-bit variables
SH_TMP      RMB     1               ; Temp storage.
SH_LR0      RMB     3               ;\
SH_FL0      EQU     SH_LR0 + 1      ; |-- Three bytes for left controller
SH_LV0      EQU     SH_LR0 + 2      ;/
SH_LR1      RMB     3               ;\
SH_FL1      EQU     SH_LR1 + 1      ; |-- Three bytes for right controller
SH_LV1      EQU     SH_LR1 + 2      ;/

            ; MOB data tables
MOB_PIC     RMB     16              ; MOB picture table
MOB_ATR     RMB     8               ; MOB attribute table
MOB_XYP     RMB     32              ; MOB X/Y position table
MOB_FLG     RMB     1               ; MOB update flags.

            ; Tank status variables
TNK0_VEL    RMB     1               ; Tank #0 desired velocity
TNK1_VEL    RMB     1               ; Tank #1 desired velocity
TNK0_MOV    RMB     1               ; Tank #0 movement (actual velocity)
TNK1_MOV    RMB     1               ; Tank #1 movement (actual velocity)
TNK0_AVL    RMB     1               ; Tank #0 angular velocity for turret
TNK1_AVL    RMB     1               ; Tank #1 angular velocity for turret
TNK0_ANG    RMB     1               ; Tank #0 turret angle (in 10 deg incrs.)
TNK1_ANG    RMB     1               ; Tank #1 turret angle (in 10 deg incrs.)
TNK0_POW    RMB     1               ; Tank #0 firing strength
TNK1_POW    RMB     1               ; Tank #1 firing strength
TNK0_FLP    RMB     1               ; Tank #0 flipped left/right
TNK1_FLP    RMB     1               ; Tank #1 flipped left/right

B0_TICK     RMB     1               ; Bullet 0 "no-hit timer" counter
B1_TICK     RMB     1               ; Bullet 1 "no-hit timer" counter

            ; Misc other stuff
FR_BUSY     RMB     1               ; Per-frame updates busy flag.
AVL_TICK    RMB     1               ; tick counter for angular velocity upd.
DO_STATS    RMB     1               ; need to draw status line.

_SCRATCH    EQU     $               ; end of scratch area



;------------------------------------------------------------------------------
; Allocate 16-bit variables in System RAM 
;------------------------------------------------------------------------------
SYSTEM      ORG     $2F0, $2F0, "-RWBN"
STACK       RMB     32              ; Reserve 32 words for the stack

            ; Task-oriented 16-bit variables
TSKQ        RMB     (TSKQM + 1)     ; Task queue

            ; Hand-controller 16-bit variables
SHDISP      RMB     1               ; ScanHand dispatch

            ; STIC shadow
MOB_DIS     RMB     1               ; MOB collision dispatch table ptr
MOB_IGN     RMB     1               ; MOB collision ignore table ptr
STICSH      RMB     32              ; Room for X, Y, and A regs only.

            ; Tank status
TNK0_PTS    RMB     1
TNK1_PTS    RMB     1

            ; Bullet details
BUL0_XVL    RMB     1               ; bullet 0's X velocity (8.8)
BUL0_YVL    RMB     1               ; bullet 0's Y velocity (8.8)
BUL1_XVL    RMB     1               ; bullet 1's X velocity (8.8)
BUL1_YVL    RMB     1               ; bullet 1's Y velocity (8.8)

_SYSTEM     EQU     $               ; end of system area


;------------------------------------------------------------------------------
; Misc equates
;------------------------------------------------------------------------------
ISRRET      EQU     $1014           ; EXEC's ISR return pointer

;------------------------------------------------------------------------------
; EXEC-friendly ROM header.
;------------------------------------------------------------------------------
            ORG     $5000           ; Use default memory map
ROMHDR:     BIDECLE ZERO            ; MOB picture base   (points to NULL list)
            BIDECLE ZERO            ; Process table      (points to NULL list)
            BIDECLE MAIN            ; Program start address
            BIDECLE ZERO            ; Bkgnd picture base (points to NULL list)
            BIDECLE ONES            ; GRAM pictures      (points to NULL list)
            BIDECLE TITLE           ; Cartridge title/date
            DECLE   $03C0           ; No ECS title, run code after title,
                                    ; ... no clicks
ZERO:       DECLE   $0000           ; Screen border control
            DECLE   $0000           ; 0 = color stack, 1 = f/b mode
ONES:       DECLE   C_BLU, C_BLU    ; Initial color stack 0 and 1: Blue
            DECLE   C_BLU, C_BLU    ; Initial color stack 2 and 3: Blue
            DECLE   C_BLU           ; Initial border color: Blue
;------------------------------------------------------------------------------


;; ======================================================================== ;;
;;  TITLE  -- Display our modified title screen & copyright date.           ;;
;; ======================================================================== ;;
TITLE:      PROC
            STRING  103, "Tank", 0
            BEGIN
          
            ; Put up our own title screen.
            CALL    CLRSCR
                                    ;     01234567890123456789
            PRINT_CSTK  1,  2, White,      ">>> SDK-1600 <<<"
            PRINT_CSTK  2,  6, White,          "Presents"
            PRINT_CSTK  6,  4, Yellow,       "Singed Earth"
            PRINT_CSTK 10,  3, White,       "Copyright 2003"
          
            ; Done.
            RETURN                  ; Return to EXEC for title screen display
            ENDP

;; ======================================================================== ;;
;;  PROGRAM-SPECIFIC MACROS AND UTILITY FUNCTIONS.                          ;;
;; ======================================================================== ;;
            INCLUDE "util.asm"                  ; Utility functions, macros

;; ======================================================================== ;;
;;  DATA                                                                    ;;
;; ======================================================================== ;;
            INCLUDE "gfx_data.asm"              ; pictures
            INCLUDE "atr_data.asm"              ; STIC attribute records
            INCLUDE "mob_data.asm"              ; MOB collision dispatch tbls

;; ======================================================================== ;;
;;  PROGRAM MODULES                                                         ;;
;; ======================================================================== ;;
            INCLUDE "mob_ll.asm"                ; Low-level MOB routines
            INCLUDE "objects.asm"               ; Tank/bullet code
            INCLUDE "status.asm"                ; Status bar code

;; ======================================================================== ;;
;;  LIBRARY INCLUDES                                                        ;;
;; ======================================================================== ;;
            INCLUDE "../library/print.asm"      ; PRINT.xxx routines
            INCLUDE "../library/prnum16.asm"    ; PRNUM16.x routines
            INCLUDE "../library/fillmem.asm"    ; CLRSCR/FILLZERO/FILLMEM
            INCLUDE "../library/memcpy.asm"     ; MEMCPY
            INCLUDE "../library/memunpk.asm"    ; MEMCPY
            INCLUDE "../task/scanhand.asm"      ; SCANHAND
            INCLUDE "../task/taskq.asm"         ; RUNQ/QTASK

;; ======================================================================== ;;
;;  MAIN:  Here's our main program code.                                    ;;
;; ======================================================================== ;;
MAIN:       PROC
            DIS
            MVII    #STACK, R6      ; Set up our stack

            MVII    #$25D,  R1      ;\
            MVII    #$102,  R4      ; |-- Clear all of memory
            CALL    FILLZERO        ;/

            SETISR  INITISR,  R0    ;\    Do GRAM initialization in ISR.
                                    ; |-- INITISR will the point to the 
                                    ;/    regular ISR when it's done.
          
            ;; ------------------------------------------------------------ ;;
            ;;  Set up our hand-controller dispatch.                        ;;
            ;; ------------------------------------------------------------ ;;
            MVII    #HAND,  R0      ;\__ Set up scanhand dispatch table
            MVO     R0,     SHDISP  ;/

            CALL    INIT_TANK
            CALL    INIT_STAT

            EIS

            ;; ------------------------------------------------------------ ;;
            ;;  Fall into the RUNQ.  We should never exit the RUNQ in this  ;;
            ;;  demo, since we never call SCHEDEXIT.                        ;;
            ;; ------------------------------------------------------------ ;;
            CALL    RUNQ            ; Run until a SCHEDEXIT happens

            ;; ------------------------------------------------------------ ;;
            ;;  If a SCHEDEXIT *does* happen (say, due to a bug), crash     ;;
            ;;  gracefully.                                                 ;;
            ;; ------------------------------------------------------------ ;;
            PRINT_CSTK 11, 0, Red, "SCHEDEXIT WAS CALLED"
            DECR    PC              ; Can't get here normally
          
            ENDP

STUB        JR      R5

;; ======================================================================== ;;
;;  HAND    Dispatch table.                                                 ;;
;; ======================================================================== ;;
HAND        PROC
            DECLE   HIT_KEYPAD
            DECLE   HIT_ACTION
            DECLE   HIT_DISC
            ENDP

;; ======================================================================== ;;
;;  HIT_KEYPAD -- Someone hit a key on a keypad.                            ;;
;; ======================================================================== ;;
HIT_KEYPAD  PROC
            SWAP    R2
            MOVR    R2,         R1      ;\__ R1 gets tank #
            ANDI    #1,         R1      ;/
            ADDI    #TNK0_POW,  R1      ; point to tank firing strength
            SWAP    R2
            BPL     @@pressed
            JR      R5

@@pressed:  ANDI    #$FF,       R2      ;\__ [0] key means '10'
            BEQ     @@force10           ;/
            CMPI    #10,        R2      ;\__ [1]..[9] mean 1 through 9
            BLE     @@ok                ;/
@@force10:  MVII    #10,        R2      ;    [C], [E], and [0] are all 10

@@ok:       MVO@    R2,         R1      ; Store firing strength for this tank

            MVII    #1,         R1      ;\__ need to update status bar.
            MVO     R1,         DO_STATS;/
            JR      R5

            ENDP

;; ======================================================================== ;;
;;  HIT_ACTION -- Someone hit a key on a keypad.                            ;;
;; ======================================================================== ;;
HIT_ACTION  PROC
            SWAP    R2
            MOVR    R2,         R1      ;\__ R1 gets tank #
            ANDI    #1,         R1      ;/
            MOVR    R1,         R0      ; save tank #
            ADDI    #TNK0_AVL,  R1      ; point to turret angular velocity
            SWAP    R2
            BPL     @@pressed

@@stop_tur  CLRR    R2
@@upd_angv  MVO@    R2,         R1      ; store updated turret velocity
@@leaveR5   JR      R5

@@pressed   ANDI    #$FF,       R2
            DECR    R2                  ; 1 is "top", 2 is "left", 3 is "right"
            BNEQ    @@upd_angv          ; if it's 1 or 2, update angular vel.
            MVO@    R2,         R1      ; otherwise force angular vel to 0

@@fire:     B       FIRE_BULLET         ; Fire the bullet.  (Chained return)
            
            ENDP

;; ======================================================================== ;;
;;  HIT_DISC   -- Someone hit a key on a keypad.                            ;;
;; ======================================================================== ;;
HIT_DISC    PROC

            SWAP    R2
            MOVR    R2,     R1
            ANDI    #1,     R1      ; R1 gets Tank # (0 or 1)
            ADDI    #TNK0_VEL,R1
            SWAP    R2
            BPL     @@pressed

@@stop:     CLRR    R3
@@store:    MVO@    R3,     R1
            JR      R5

@@pressed:  ADDI    #4,     R2      ; rotate disc.  SSE thru NNE go right
            ANDI    #$F,    R2
            BEQ     @@stop          ; position 0 is south.  Discard.
            CMPI    #8,     R2
            BEQ     @@stop          ; position 8 is north.  Discard.
            BLT     @@go_right      ; less than 8 is right, greater is left.

            ;; go left
            MVII    #$FE,   R3      ; This velocity will be divided by 8
            B       @@store

@@go_right: ;; go right
            MVII    #$02,   R3      ; This velocity will be divided by 8
            B       @@store

            ENDP
    

;; ======================================================================== ;;
;;  ISR -- Just keep the screen on, and copy the STIC shadow over.          ;;
;; ======================================================================== ;;
ISR         PROC
            ;; ------------------------------------------------------------ ;;
            ;;  Basics:  Update color stack and video enable.               ;;
            ;; ------------------------------------------------------------ ;;
            MVO     R0,     STIC.viden  ; Enable display
            MVI     STIC.mode, R0       ; ...in color-stack mode

            MVII    #C_CYN, R0          ;\__ sky is cyan
            MVO     R0,     STIC.cs0    ;/
            MVII    #C_BLU, R0          ;\__ status is blue
            MVO     R0,     STIC.cs1    ;/
            MVII    #C_GRY, R0          ;\__ border is grey
            MVO     R0,     STIC.bord   ;/

            CALL    MOB_ISR             ; Update MOBs


            MVI     FR_BUSY,    R0      ;\    test per-frame busy flag.  
            XORI    #1,         R0      ; |__ never let it be 1 more than
            MVO     R0,         FR_BUSY ; |   one frame at a time, though,   
            BEQ     ISRRET              ;/    in case task queue saturates.

            CALL    MOB_COLDISP         ; do collision dispatches in ISR ctx.

            MVII    #FR_TASK,   R0      ; \
            MVII    #ISRRET,    R5      ;  |- Queue the per-frame work
            JD      QTASK               ; /   and return via QTASK

            ENDP

;; ======================================================================== ;;
;;  FR_TASK -- per frame work to do.                                        ;;
;; ======================================================================== ;;
FR_TASK     PROC
            PSHR    R5
            ;; ------------------------------------------------------------ ;;
            ;;  Per-tick work to do.                                        ;;
            ;;   -- Move tanks based on velocity.                           ;;
            ;;   -- Update ballistics                                       ;;
            ;;   -- Update STIC shadow                                      ;;
            ;;   -- Scan for collision dispatches.                          ;;
            ;; ------------------------------------------------------------ ;;

            CALL    UPD_TANKS 
            CALL    UPD_BULLET
            CALL    MOB_STICSH
            CALL    UPD_STATUS

            CLRR    R0
            MVO     R0,         FR_BUSY ; let a new frame's work begin

            PULR    PC                  ; done
            ENDP


;; ======================================================================== ;;
;;  INITISR -- Copy our GRAM image over, and then do the plain ISR.         ;;
;; ======================================================================== ;;
INITISR     PROC
            DIS     ; this could take a couple frames

            ;; ------------------------------------------------------------ ;;
            ;;  Force the MOBs to all be disabled, with no collision bits.  ;;
            ;; ------------------------------------------------------------ ;;
            MVII    #32,        R1      ;\
            MVII    #0,         R4      ; |-- Clear MOB registers
            CALL    FILLZERO            ;/

            ;; ------------------------------------------------------------ ;;
            ;;  Load our initial GRAM image.                                ;;
            ;; ------------------------------------------------------------ ;;
            CALL    MEMUNPK 
            DECLE   $3800, GFX_DATA.gram_img, GFX.gram_size

            ;; ------------------------------------------------------------ ;;
            ;;  Do the main ISR starting with the next frame.               ;;
            ;; ------------------------------------------------------------ ;;
            SETISR  ISR,        R0

            JE      ISRRET              ; return and reenable interrupts.
            ENDP



;* ======================================================================== *;
;*  This program is free software; you can redistribute it and/or modify    *;
;*  it under the terms of the GNU General Public License as published by    *;
;*  the Free Software Foundation; either version 2 of the License, or       *;
;*  (at your option) any later version.                                     *;
;*                                                                          *;
;*  This program is distributed in the hope that it will be useful,         *;
;*  but WITHOUT ANY WARRANTY; without even the implied warranty of          *;
;*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       *;
;*  General Public License for more details.                                *;
;*                                                                          *;
;*  You should have received a copy of the GNU General Public License       *;
;*  along with this program; if not, write to the Free Software             *;
;*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *;
;* ======================================================================== *;
;*                   Copyright (c) 2003, Joseph Zbiciak                     *;
;* ======================================================================== *;
