Tagalong Todd Tutorial: Part 2 - Files
tag2a.asm
This is the code for the first version built in the tutorial - the player graphic moves across the screen quite rapidly.
;;==========================================================================;;
;; Joe Zbiciak's Tagalong Todd! ;;
;; Copyright 2002, Joe Zbiciak, intvnut AT gmail.com. ;;
;; http://spatula-city.org/~im14u2c/intv/ ;;
;;==========================================================================;;
;* ======================================================================== *;
;* TO BUILD IN BIN+CFG FORMAT: *;
;* as1600 -o tagalong.bin -l tagalong.lst tagalong.asm *;
;* *;
;* TO BUILD IN ROM FORMAT: *;
;* as1600 -o tagalong.rom -l tagalong.lst tagalong.asm *;
;* ======================================================================== *;
ROMW 16 ; Use 16-bit ROM
;------------------------------------------------------------------------------
; Include system information
;------------------------------------------------------------------------------
INCLUDE "gimini.asm"
;------------------------------------------------------------------------------
; Global constants and configuration.
;------------------------------------------------------------------------------
TSKQM EQU $7 ; Task queue is 8 entries large
MAXTSK EQU 3 ; Only one task
;------------------------------------------------------------------------------
; 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
TSKACT RMB 1 ; Number of active tasks
_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
TSKTBL RMB (MAXTSK * 4) ; Timer task table
; STIC shadow
STICSH RMB 24 ; Room for X, Y, and A regs only.
PLYR PROC
@@XP RMB 1 ; X position
@@YP RMB 1 ; Y position
ENDP
MOB_BUSY RMB 1
_SYSTEM EQU $ ; end of system area
;------------------------------------------------------------------------------
; 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 102, "Tagalong Todd", 0
BEGIN
; Patch the title string to say '=JRMZ=' instead of Mattel.
CALL PRINT.FLS ; Write string (ptr in R5)
DECLE C_WHT, $23D ; White, Point to 'Mattel' in top-left
STRING '=JRMZ=' ; Guess who? :-)
STRING ' Productions'
BYTE 0
CALL PRINT.FLS ; Write string (ptr in R1)
DECLE C_WHT, $2D0 ; White, Point to 'Mattel' in lower-right
STRING '2002 =JRMZ=' ; Guess who? :-)
BYTE 0
; Done.
RETURN ; Return to EXEC for title screen display
ENDP
;; ======================================================================== ;;
;; MAIN: Here's our main program code. ;;
;; ======================================================================== ;;
MAIN: PROC
DIS
MVII #STACK, R6 ; Set up our stack
MVII #$25E, R1 ;\
MVII #$102, R4 ; |-- Clear all of RAM memory
CALL FILLZERO ;/
MVII #INITISR, R0 ;\ Do GRAM initialization in ISR.
MVO R0, ISRVEC ; |__ INITISR will the point to the
SWAP R0 ; | regular ISR when it's done.
MVO R0, ISRVEC+1;/
;; ------------------------------------------------------------ ;;
;; Put the character on the screen ;;
;; ------------------------------------------------------------ ;;
MVII #$1000, R0
MVO R0, PLYR.XP
MVO R0, PLYR.YP
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. ;;
;; ------------------------------------------------------------ ;;
CALL PRINT.FLS
DECLE C_RED, $200 + 11*20
;01234567890123456789
STRING "SCHEDEXIT WAS CALLED",0
DECR PC ; Can't get here
ENDP
;; ======================================================================== ;;
;; MOB_UPDATE -- This updates the player's position ;;
;; ======================================================================== ;;
MOB_UPDATE PROC
PSHR R5
;; ------------------------------------------------------------ ;;
;; Merge our position with our MOB registers. ;;
;; ------------------------------------------------------------ ;;
MVII #@@mobr, R4 ; MOB information template
MVII #STICSH, R5
MVI PLYR.XP, R0 ;\
SWAP R0 ; |
ANDI #$00FF, R0 ; |- Player X position
XOR@ R4, R0 ; |
MVO@ R0, R5 ;/
ADDI #7, R5 ; Move pointer to Y coordinate section of the STICSH
MVI PLYR.YP, R0 ;\
SWAP R0 ; |
ANDI #$007F, R0 ; |- Player Y position
XOR@ R4, R0 ; |
MVO@ R0, R5 ;/
ADDI #7, R5 ; Move pointer to A register section of the STICSH
MVI@ R4, R0 ; \_ Player's A register
MVO@ R0, R5 ; /
CLRR R0
MVO R0, MOB_BUSY
PULR PC
;; ------------------------------------------------------------ ;;
;; Bits to copy into MOB registers. ;;
;; ------------------------------------------------------------ ;;
@@mobr DECLE STIC.mobx_visb ; make player visible
DECLE STIC.moby_yres ; make player 8x16 MOB
DECLE STIC.moba_fg1 + STIC.moba_gram + 0*8 ; Player is blue
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_GRY, R0 ;\
MVO R0, STIC.cs0 ; |__ Set display to grey
MVO R0, STIC.cs2 ; |
MVO R0, STIC.bord ;/
;; ------------------------------------------------------------ ;;
;; Update STIC shadow and queue updates for MOB velocities. ;;
;; ------------------------------------------------------------ ;;
MVI MOB_BUSY, R0
TSTR R0
BNEQ @@no_mobs
MVO PC, MOB_BUSY
CALL MEMCPY ;\__ Copy over the STIC shadow.
DECLE $0000, STICSH, 24 ;/
MVII #MOB_UPDATE, R0
JSRD R5, QTASK
MVII #MOVE_PLAYER, R0
JSRD R5, QTASK
@@no_mobs:
CALL DOTIMER ; Update timer-based tasks.
B $1014 ; return from interrupt.
ENDP
;; ======================================================================== ;;
;; MOVE_PLAYER -- Just programatically move the player around a bit. ;;
;; ======================================================================== ;;
MOVE_PLAYER PROC
PSHR R5
; Just for something to do we'll move across the screen, then
; down a row and back across, again and again until we get to the
; bottom at which time we'll start over
MVI PLYR.XP, R0 ;\
SWAP R0 ; >-- Get player X position
ANDI #$00FF, R0 ;/
ADDI #8, R0 ; move 8 X positions to the right
MVII #159, R1 ;\__ compare X against the right edge of the screen
CMPR R0, R1 ;/
BLT @@fixx
SWAP R0 ; put the integer part back into the upper byte
MVO R0, PLYR.XP ; update the X position
B @@done ; we're done
; here we've hit the right edge of the screen and should move down a row
@@fixx MVII #0, R0 ;\__ set X position back to zero
MVO R0, PLYR.XP ;/
MVI PLYR.YP, R0 ;\
SWAP R0 ; >-- Get player Y position
ANDI #$007F, R0 ;/
ADDI #8, R0 ; move 8 Y positions down
MVII #96, R1 ;\__ compare Y against the bottom edge of the screen
CMPR R0, R1 ;/
BLT @@fixy
SWAP R0 ; put the integer part back into the upper byte
MVO R0, PLYR.YP ; update the Y position
B @@done
; here we've hit the bottom edge of the screen and should move to the top
@@fixy MVII #0, R0 ;\__ set Y position back to zero
MVO R0, PLYR.YP ;/
@@done PULR PC
ENDP
;; ======================================================================== ;;
;; INITISR -- Copy our GRAM image over, and then do the plain ISR. ;;
;; ======================================================================== ;;
INITISR PROC
PSHR R5
CALL MEMCPY
DECLE $3800, GRAMIMG, GRAMIMG.end - GRAMIMG
MVII #ISR, R0
MVO R0, ISRVEC
SWAP R0
MVO R0, ISRVEC + 1
PULR PC
ENDP
;; ======================================================================== ;;
;; GRAMIMG -- Arrow pictures and other graphics to load into GRAM. ;;
;; ======================================================================== ;;
GRAMIMG PROC
@@person: ; Crappy person graphic.
DECLE %00010000
DECLE %00111000
DECLE %00111000
DECLE %00010000
DECLE %00010000
DECLE %01111100
DECLE %10111010
DECLE %10111010
DECLE %10111010
DECLE %10111010
DECLE %00111000
DECLE %00101000
DECLE %00101000
DECLE %00101000
DECLE %00101000
DECLE %01101100
@@end:
ENDP
;; ======================================================================== ;;
;; LIBRARY INCLUDES ;;
;; ======================================================================== ;;
INCLUDE "print.asm" ; PRINT.xxx routines
INCLUDE "fillmem.asm" ; CLRSCR/FILLZERO/FILLMEM
INCLUDE "memcpy.asm" ; MEMCPY
INCLUDE "timer.asm" ; Timer-based task stuff
INCLUDE "taskq.asm" ; RUNQ/QTASK
;* ======================================================================== *;
;* 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) 2002, Joseph Zbiciak *;
;* ======================================================================== *;
tag2b.asm
This is the code for the second version built in the tutorial - the player graphic moves across the screen at a much more reasonable pace.
;;==========================================================================;; ;; Joe Zbiciak's Tagalong Todd! ;; ;; Copyright 2002, Joe Zbiciak, intvnut AT gmail.com. ;; ;; http://spatula-city.org/~im14u2c/intv/ ;; ;;==========================================================================;; ;* ======================================================================== *; ;* TO BUILD IN BIN+CFG FORMAT: *; ;* as1600 -o tagalong.bin -l tagalong.lst tagalong.asm *; ;* *; ;* TO BUILD IN ROM FORMAT: *; ;* as1600 -o tagalong.rom -l tagalong.lst tagalong.asm *; ;* ======================================================================== *; ROMW 16 ; Use 16-bit ROM ;------------------------------------------------------------------------------ ; Include system information ;------------------------------------------------------------------------------ INCLUDE "gimini.asm" ;------------------------------------------------------------------------------ ; Global constants and configuration. ;------------------------------------------------------------------------------ TSKQM EQU $7 ; Task queue is 8 entries large MAXTSK EQU 3 ; Only one task ;------------------------------------------------------------------------------ ; 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 TSKACT RMB 1 ; Number of active tasks _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 TSKTBL RMB (MAXTSK * 4) ; Timer task table ; STIC shadow STICSH RMB 24 ; Room for X, Y, and A regs only. PLYR PROC @@XP RMB 1 ; X position @@YP RMB 1 ; Y position ENDP MOB_BUSY RMB 1 _SYSTEM EQU $ ; end of system area ;------------------------------------------------------------------------------ ; 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 102, "Tagalong Todd", 0 BEGIN ; Patch the title string to say '=JRMZ=' instead of Mattel. CALL PRINT.FLS ; Write string (ptr in R5) DECLE C_WHT, $23D ; White, Point to 'Mattel' in top-left STRING '=JRMZ=' ; Guess who? :-) STRING ' Productions' BYTE 0 CALL PRINT.FLS ; Write string (ptr in R1) DECLE C_WHT, $2D0 ; White, Point to 'Mattel' in lower-right STRING '2002 =JRMZ=' ; Guess who? :-) BYTE 0 ; Done. RETURN ; Return to EXEC for title screen display ENDP ;; ======================================================================== ;; ;; MAIN: Here's our main program code. ;; ;; ======================================================================== ;; MAIN: PROC DIS MVII #STACK, R6 ; Set up our stack MVII #$25E, R1 ;\ MVII #$102, R4 ; |-- Clear all of RAM memory CALL FILLZERO ;/ MVII #INITISR, R0 ;\ Do GRAM initialization in ISR. MVO R0, ISRVEC ; |__ INITISR will the point to the SWAP R0 ; | regular ISR when it's done. MVO R0, ISRVEC+1;/ ;; ------------------------------------------------------------ ;; ;; Set up character movement task ;; ;; ------------------------------------------------------------ ;; CALL STARTTASK DECLE 0 DECLE MOVE_PLAYER DECLE 30, 30 ; 4Hz MVII #1, R0 MVO R0, TSKACT ;; ------------------------------------------------------------ ;; ;; Put the character on the screen ;; ;; ------------------------------------------------------------ ;; MVII #$1000, R0 MVO R0, PLYR.XP MVO R0, PLYR.YP 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. ;; ;; ------------------------------------------------------------ ;; CALL PRINT.FLS DECLE C_RED, $200 + 11*20 ;01234567890123456789 STRING "SCHEDEXIT WAS CALLED",0 DECR PC ; Can't get here ENDP ;; ======================================================================== ;; ;; MOB_UPDATE -- This updates the player's position ;; ;; ======================================================================== ;; MOB_UPDATE PROC PSHR R5 ;; ------------------------------------------------------------ ;; ;; Merge our position with our MOB registers. ;; ;; ------------------------------------------------------------ ;; MVII #@@mobr, R4 ; MOB information template MVII #STICSH, R5 MVI PLYR.XP, R0 ;\ SWAP R0 ; | ANDI #$00FF, R0 ; |- Player X position XOR@ R4, R0 ; | MVO@ R0, R5 ;/ ADDI #7, R5 ; Move pointer to Y coordinate section of the STICSH MVI PLYR.YP, R0 ;\ SWAP R0 ; | ANDI #$007F, R0 ; |- Player Y position XOR@ R4, R0 ; | MVO@ R0, R5 ;/ ADDI #7, R5 ; Move pointer to A register section of the STICSH MVI@ R4, R0 ; \_ Player's A register MVO@ R0, R5 ; / CLRR R0 MVO R0, MOB_BUSY PULR PC ;; ------------------------------------------------------------ ;; ;; Bits to copy into MOB registers. ;; ;; ------------------------------------------------------------ ;; @@mobr DECLE STIC.mobx_visb ; make player visible DECLE STIC.moby_yres ; make player 8x16 MOB DECLE STIC.moba_fg1 + STIC.moba_gram + 0*8 ; Player is blue 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_GRY, R0 ;\ MVO R0, STIC.cs0 ; |__ Set display to grey MVO R0, STIC.cs2 ; | MVO R0, STIC.bord ;/ ;; ------------------------------------------------------------ ;; ;; Update STIC shadow and queue updates for MOB velocities. ;; ;; ------------------------------------------------------------ ;; MVI MOB_BUSY, R0 TSTR R0 BNEQ @@no_mobs MVO PC, MOB_BUSY CALL MEMCPY ;\__ Copy over the STIC shadow. DECLE $0000, STICSH, 24 ;/ MVII #MOB_UPDATE, R0 JSRD R5, QTASK @@no_mobs: CALL DOTIMER ; Update timer-based tasks. B $1014 ; return from interrupt. ENDP ;; ======================================================================== ;; ;; MOVE_PLAYER -- Just programatically move the player around a bit. ;; ;; ======================================================================== ;; MOVE_PLAYER PROC PSHR R5 ; Just for something to do we'll move across the screen, then ; down a row and back across, again and again until we get to the ; bottom at which time we'll start over MVI PLYR.XP, R0 ;\ SWAP R0 ; >-- Get player X position ANDI #$00FF, R0 ;/ ADDI #8, R0 ; move 8 X positions to the right MVII #159, R1 ;\__ compare X against the right edge of the screen CMPR R0, R1 ;/ BLT @@fixx SWAP R0 ; put the integer part back into the upper byte MVO R0, PLYR.XP ; update the X position B @@done ; we're done ; here we've hit the right edge of the screen and should move down a row @@fixx MVII #0, R0 ;\__ set X position back to zero MVO R0, PLYR.XP ;/ MVI PLYR.YP, R0 ;\ SWAP R0 ; >-- Get player Y position ANDI #$007F, R0 ;/ ADDI #8, R0 ; move 8 Y positions down MVII #96, R1 ;\__ compare Y against the bottom edge of the screen CMPR R0, R1 ;/ BLT @@fixy SWAP R0 ; put the integer part back into the upper byte MVO R0, PLYR.YP ; update the Y position B @@done ; here we've hit the bottom edge of the screen and should move to the top @@fixy MVII #0, R0 ;\__ set Y position back to zero MVO R0, PLYR.YP ;/ @@done PULR PC ENDP ;; ======================================================================== ;; ;; INITISR -- Copy our GRAM image over, and then do the plain ISR. ;; ;; ======================================================================== ;; INITISR PROC PSHR R5 CALL MEMCPY DECLE $3800, GRAMIMG, GRAMIMG.end - GRAMIMG MVII #ISR, R0 MVO R0, ISRVEC SWAP R0 MVO R0, ISRVEC + 1 PULR PC ENDP ;; ======================================================================== ;; ;; GRAMIMG -- Arrow pictures and other graphics to load into GRAM. ;; ;; ======================================================================== ;; GRAMIMG PROC @@person: ; Crappy person graphic. DECLE %00010000 DECLE %00111000 DECLE %00111000 DECLE %00010000 DECLE %00010000 DECLE %01111100 DECLE %10111010 DECLE %10111010 DECLE %10111010 DECLE %10111010 DECLE %00111000 DECLE %00101000 DECLE %00101000 DECLE %00101000 DECLE %00101000 DECLE %01101100 @@end: ENDP ;; ======================================================================== ;; ;; LIBRARY INCLUDES ;; ;; ======================================================================== ;; INCLUDE "print.asm" ; PRINT.xxx routines INCLUDE "fillmem.asm" ; CLRSCR/FILLZERO/FILLMEM INCLUDE "memcpy.asm" ; MEMCPY INCLUDE "timer.asm" ; Timer-based task stuff INCLUDE "taskq.asm" ; RUNQ/QTASK ;* ======================================================================== *; ;* 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) 2002, Joseph Zbiciak *; ;* ======================================================================== *;