mirror of
https://github.com/erkyrath/infocom-zcode-terps.git
synced 2026-02-08 01:01:24 +00:00
1050 lines
28 KiB
NASM
1050 lines
28 KiB
NASM
|
|
SECTION ZCODE,CODE * DEFINE TWO SEGMENTS
|
|
NOP
|
|
SECTION ZDATA,DATA
|
|
DC.W 0
|
|
SECTION ZCODE * AND START IN CODE SEGMENT
|
|
|
|
* ___________________________________________________________________________
|
|
*
|
|
* Z-LANGUAGE INTERPRETER FOR COMMODORE AMIGA
|
|
*
|
|
* INFOCOM, INC. COMPANY CONFIDENTIAL -- NOT FOR DISTRIBUTION
|
|
* ___________________________________________________________________________
|
|
*
|
|
|
|
* WRITTEN BY: Duncan Blanchard
|
|
*
|
|
* MODIFICATION HISTORY:
|
|
*
|
|
* 18 OCT 85 ZIP A FROZEN
|
|
* 29 OCT 85 FILE_SELECT LIMITS SAVE NAME TO 25 CHARS
|
|
* 29 OCT 85 SCRERR DISPLAYS A PRINTER ERROR MESSAGE UPON FAILURE
|
|
* ZIP B FROZEN
|
|
* EZIP A FROZEN
|
|
* 10 FEB 86 CHANGED PUT, PUTB, PTSIZE (PURE PRELOAD > 32K)
|
|
* 10 APR 86 CHANGED PUTCHR (SPECIAL HANDLING FOR TABLE OUTPUT)
|
|
|
|
* 07 MAY 86 CHANGED NXTLIN/BUFOUT/LINOUT. BUFOUT CALLS NXTLIN
|
|
* SO [MORE] IS TIMED CORRECTLY DURING BOLDFACE, ETC
|
|
* CHANGED OPREAD, ONLY OVERFLOW WORDS ARE FLUSHED
|
|
* 08 MAY 86 FIXED QUECHR (QCX2A), ALLOW FOR EMPTY [DUMPED] BUFFER
|
|
* EZIP B FROZEN
|
|
* 01 JUL 87 EXPANDED OPSOUND
|
|
* 22 JUL 87 ADDED UNHIDE [SCREEN] TO RDLINE, FOR ALERTBOX BUG
|
|
* SCRIPTING FIX, ETC, IN AMIGAZIP
|
|
* EZIP C FROZEN
|
|
* 26 AUG 87 ADDED VOLUME ARG TO OPSOUND
|
|
* ZIP C FROZEN
|
|
|
|
* ---------------------------------------------------------------------------
|
|
* REGISTER CONVENTIONS
|
|
* ---------------------------------------------------------------------------
|
|
|
|
* GENERALLY, SINGLE ARGUMENTS ARE PASSED IN D0 OR A0. SINGLE VALUES ARE
|
|
* LIKEWISE RETURNED IN D0 OR A0. IN ANY CASE, THESE ARE SCRATCH REGISTERS
|
|
* AND NEED NOT BE PRESERVED. ALL OTHER REGISTERS, EXCEPT WHERE OTHERWISE
|
|
* SPECIFIED, MUST BE PRESERVED ACROSS EACH SUBROUTINE CALL. NOTE THAT
|
|
* TOP-LEVEL ROUTINES, OPx ROUTINES, ARE EXCLUDED FROM THIS RESTRICTION.
|
|
|
|
* DEDICATED REGISTERS:
|
|
* A7 = SYSTEM SP
|
|
* A6 = FRAME POINTER FOR ZIP VARIABLES *** STATIC ***
|
|
* A5 = unused in this version
|
|
* A4 = VIRTUAL SP
|
|
|
|
* ---------------------------------------------------------------------------
|
|
* GENERAL MACRO DEFINITIONS
|
|
* ---------------------------------------------------------------------------
|
|
|
|
* MACRO ZERO
|
|
* MOVEQ #0,%1 * CLEAR A REGISTER QUICKLY (BOTH WORDS)
|
|
* ENDM
|
|
|
|
* MACRO SOB * SUBTRACT ONE AND BRANCH IF NOT ZERO
|
|
* SUBQ.W #1,%1
|
|
* BNE %2
|
|
* ENDM
|
|
|
|
* ---------------------------------------------------------------------------
|
|
* GENERAL EQUATES
|
|
* ---------------------------------------------------------------------------
|
|
|
|
ARG1 EQU 2 * ARGUMENT OFFSETS IN ARGBLOCK (COUNT IS AT 0)
|
|
ARG2 EQU 4
|
|
ARG3 EQU 6
|
|
ARG4 EQU 8
|
|
|
|
IFEQ EZIP
|
|
|
|
VCHARS EQU 9 * MAX CHARS IN AN EZIP VOCAB WORD
|
|
|
|
OPLEN EQU 63*2 * OBJECT PROPERTY DEFAULT TABLE LENGTH
|
|
OLEN EQU 14 * OBJECT LENGTH
|
|
|
|
LOC EQU 6 * PARENT
|
|
NEXT EQU 8 * NEXT SIBLING
|
|
FIRST EQU 10 * FIRST CHILD
|
|
PROP EQU 12 * PROPERTY TABLE POINTER
|
|
|
|
PMASK EQU $003F * PROPERTY NUMBER IS LOW 6 BITS (OF FIRST ID BYTE)
|
|
PLBIT EQU 6 * PROPERTY LENGTH BIT (IF LENGTH IS TWO OR ONE)
|
|
|
|
ENDC
|
|
IFEQ CZIP
|
|
|
|
VCHARS EQU 6 * MAX CHARS IN A ZIP VOCAB WORD
|
|
|
|
OPLEN EQU 31*2 * OBJECT PROPERTY DEFAULT TABLE LENGTH
|
|
OLEN EQU 9 * OBJECT LENGTH
|
|
|
|
LOC EQU 4 * PARENT
|
|
NEXT EQU 5 * NEXT SIBLING
|
|
FIRST EQU 6 * FIRST CHILD
|
|
PROP EQU 7 * PROPERTY TABLE POINTER
|
|
|
|
PMASK EQU $001F * PROPERTY NUMBER IS LOW 5 BITS (OF SINGLE ID BYTE)
|
|
PLBIT EQU 5 * PROPERTY LENGTH BIT (LOWEST OF 3 LENGTH BITS)
|
|
|
|
ENDC
|
|
|
|
* ---------------------------------------------------------------------------
|
|
* EXTERNALS
|
|
* ---------------------------------------------------------------------------
|
|
|
|
* EXTERNALLY DEFINED VARIABLES
|
|
|
|
XREF _columns * TOTAL COLUMNS IN DISPLAY
|
|
XREF _cur_column * 0 .. COLUMNS -1
|
|
|
|
XREF _rows * TOTAL ROWS IN DISPLAY
|
|
XREF _cur_row * 0 .. ROWS -1
|
|
XREF _split_row * FIRST ROW IN SCROLLING WINDOW
|
|
|
|
XREF _savename
|
|
XREF _saveback
|
|
|
|
** XREF _ms_tick
|
|
** XREF _ms_total
|
|
** XREF _otim_addr
|
|
|
|
XREF _temp_channel
|
|
XREF _temp_memory
|
|
|
|
* EXTERNALLY DEFINED ROUTINES
|
|
|
|
XREF _line_out * VOID line_out (STRPTR, LEN)
|
|
XREF _char_out * VOID char_out (CHAR)
|
|
XREF _char_in * CHAR char_in ()
|
|
|
|
XREF _show_status * VOID show_status (str1, len1, str2, len2)
|
|
XREF _show_more
|
|
XREF _highlight
|
|
|
|
XREF _clear_screen
|
|
XREF _clear_lines
|
|
XREF _clear_eol
|
|
|
|
* CALL THESE ROUTINES WHENEVER THE KERNEL ACCESSES THE CURRENT ROW/COLUMN
|
|
* (ENSURES CO-ORDINATION WITH THE CONSOLE DEVICE CURSOR FUNCTIONS)
|
|
|
|
XREF _read_cursor_pos
|
|
XREF _write_cursor_pos
|
|
|
|
XREF _exist_file
|
|
XREF _create_file
|
|
XREF _open_file
|
|
XREF _close_file
|
|
XREF _delete_file
|
|
|
|
XREF _read_file
|
|
XREF _write_file
|
|
|
|
XREF _open_game * LONG open_game ()
|
|
XREF _close_game * LONG close_game (refnum)
|
|
|
|
*** XREF _file_select * MOVED INTO 68K FOR NOW
|
|
XREF _new_default
|
|
XREF _drive_default
|
|
XREF _make_icon_file
|
|
|
|
XREF _c_getmem
|
|
XREF _c_maxmem
|
|
|
|
XREF _script_open
|
|
XREF _script_line
|
|
|
|
XREF _random_seed
|
|
XREF _window_resized
|
|
XREF _md_sound
|
|
XREF _unhide_screen
|
|
|
|
* EXTERNALLY REFERENCED ROUTINES
|
|
|
|
XDEF _START
|
|
|
|
XDEF _trap1
|
|
XDEF _trap2
|
|
XDEF _trap13
|
|
XDEF _trap14
|
|
|
|
|
|
* ---------------------------------------------------------------------------
|
|
* ZIP VARIABLES - INDEXED OFF A6
|
|
* ---------------------------------------------------------------------------
|
|
|
|
ZORKID EQU 0-2 * UNIQUE GAME AND VERSION ID
|
|
TIMEMD EQU ZORKID-2 * HOURS/MINUTES MODE FLAG
|
|
ENDLOD EQU TIMEMD-2 * END OF PRELOAD (FIRST PAGED BLOCK NUMBER)
|
|
PURBOT EQU ENDLOD-2 * END OF IMPURE (FIRST PURE BLOCK NUMBER)
|
|
|
|
VOCTAB EQU PURBOT-4 * VOCABULARY TABLE POINTER
|
|
OBJTAB EQU VOCTAB-4 * OBJECT TABLE POINTER
|
|
GLOTAB EQU OBJTAB-4 * GLOBAL TABLE POINTER
|
|
WRDTAB EQU GLOTAB-4 * FREQUENT WORD TABLE POINTER
|
|
|
|
RBRKS EQU WRDTAB-4 * POINTER TO STRING OF READ-BREAK CHARS
|
|
ESIBKS EQU RBRKS-4 * END OF SELF-INSERTING BREAK CHARS (+1)
|
|
|
|
VWLEN EQU ESIBKS-2 * NUMBER OF BYTES IN A VOCAB WORD ENTRY
|
|
VWORDS EQU VWLEN-2 * NUMBER OF VOCABULARY WORDS
|
|
VOCBEG EQU VWORDS-4 * POINTER TO FIRST VOCAB WORD
|
|
VOCEND EQU VOCBEG-4 * POINTER TO LAST VOCAB WORD
|
|
|
|
PAGTAB EQU VOCEND-4 * POINTER TO PAGE INFORMATION TABLE
|
|
PAGES EQU PAGTAB-4 * POINTER TO START OF PAGE BUFFERS
|
|
|
|
PAGTOT EQU PAGES-2 * NUMBER OF PAGE BUFFERS
|
|
MAXGAM EQU PAGTOT-4 * LARGEST POSS. PRELOAD (BYTES, ROUNDED UP)
|
|
MINGAM EQU MAXGAM-4 * SMALLEST POSS. PRELOAD
|
|
|
|
TOPSP EQU MINGAM-4 * TOP OF SYSTEM STACK
|
|
STKBOT EQU TOPSP-4 * BOTTOM OF GAME STACK
|
|
|
|
ZPC1 EQU STKBOT-2 * ZORK PC, BLOCK POINTER (RELATIVE ADDRESS)
|
|
ZPC2 EQU ZPC1-2 * ZORK PC, BYTE POINTER
|
|
ZLOCS EQU ZPC2-4 * POINTER TO LOCALS (ABSOLUTE ADDRESS)
|
|
|
|
RSEED1 EQU ZLOCS-2 * RANDOM NUMBER SEED, HIGH WORD
|
|
RSEED2 EQU RSEED1-2 * LOW WORD
|
|
RCYCLE EQU RSEED2-2 * ZERO MEANS RANDOM, OTHERWISE SEQUENCE LIMIT
|
|
RCOUNT EQU RCYCLE-2 * CURRENT POSITION IN SEQUENCE
|
|
|
|
BUFFER EQU RCOUNT-4 * START OF PRELOADED GAME CODE
|
|
ARGBLK EQU BUFFER-18 * 8 ARGS MAX (FOR EZIP), PLUS COUNT
|
|
|
|
***
|
|
|
|
RDWSTR EQU ARGBLK-10 * ASCIZ STRING BUFFER (9 CHARS MAX FOR EZIP)
|
|
RDZSTR EQU RDWSTR-6 * ZSTR BUFFER (3 WORDS MAX FOR EZIP)
|
|
|
|
RDBOS EQU RDZSTR-4 * BEGINNING OF INPUT STRING BUFFER
|
|
RDEOS EQU RDBOS-4 * END OF INPUT STRING BUFFER (+1)
|
|
RDRET EQU RDEOS-4 * RETURN TABLE
|
|
|
|
RDNWDS EQU RDRET-2 * NUMBER (BYTE) OF WORDS ACTUALLY READ
|
|
RDBOW EQU RDNWDS-4 * BEGINNING OF CURRENT INPUT WORD
|
|
WRDOFF EQU RDBOW-2 * OFFSET INTO WORD TABLE FOR CURRENT SET
|
|
|
|
* VIRTUAL I/O DEVICES
|
|
|
|
VOCONS EQU WRDOFF-2 * SET FOR SCREEN OUTPUT
|
|
VOPRNT EQU VOCONS-2 * SET FOR SCRIPTING
|
|
VOSTAT EQU VOPRNT-2 * SET FOR STATUS LINE OUTPUT
|
|
VOTABL EQU VOSTAT-2 * SET FOR TABLE OUTPUT
|
|
VOFILE EQU VOTABL-2 * SET FOR FILE OUTPUT
|
|
|
|
VIKEYB EQU VOFILE-2 * SET FOR KEYBOARD INPUT
|
|
VIFILE EQU VIKEYB-2 * SET FOR FILE INPUT
|
|
|
|
VOBUFF EQU VIFILE-2 * SET IF OUTPUT TO SCREEN IS BUFFERED
|
|
VIECHO EQU VOBUFF-2 * SET IF INPUT IS ECHOED
|
|
|
|
DQUE EQU VIECHO-4 * DISPLAY QUE PARAMETER BLOCK
|
|
SQUE EQU DQUE-4 * SCRIPT QUE PARAMETER BLOCK
|
|
|
|
TABOUT EQU SQUE-4 * POINTS TO TABLE-OUTPUT BUFFER (EZIP)
|
|
TABPTR EQU TABOUT-4 * POINTS TO NEXT POSITION IN TABLE
|
|
|
|
CURPAG EQU TABPTR-4 * CURRENT PAGE (WHERE ZPC IS) POINTER
|
|
CURBLK EQU CURPAG-2 * CURRENT BLOCK, USUALLY SAME AS ZPC1
|
|
CURTAB EQU CURBLK-4 * CURRENT PAGE TABLE POINTER
|
|
|
|
RTIME EQU CURTAB-4 * REFERENCE TIME (NOW USES 4 BYTES)
|
|
LPAGE EQU RTIME-2 * LAST REFERENCED PAGE NUMBER
|
|
LPLOC EQU LPAGE-4 * AND ITS CORE LOCATION
|
|
LPTAB EQU LPLOC-4 * AND ITS TABLE POINTER
|
|
|
|
TIMOUT EQU LPTAB-2 * OPTIONAL TIMOUT FUNCTION (EZIP), ZERO IF NONE
|
|
TDELAY EQU TIMOUT-2 * DELAY BEFORE TIMEOUT
|
|
TFUNC EQU 0 * (((DEAD)))
|
|
TBEGIN EQU TDELAY-4 * REFERENCE TIMEBASE FOR PENDING TIMEOUT
|
|
|
|
***
|
|
|
|
WIND1 EQU TBEGIN-2 * NON-ZERO IF CURRENTLY IN WINDOW 1
|
|
OLDWX EQU WIND1-2 * X-CURSOR IN WINDOW 0 (BEFORE SPLIT)
|
|
OLDWY EQU OLDWX-2 * Y-CURSOR IN WINDOW 0 (BEFORE SPLIT)
|
|
|
|
LINES EQU OLDWY-2 * SCREEN LINES DISPLAYED SINCE LAST INPUT
|
|
INLAST EQU LINES-2 * INPUT SETS IT, OUTPUT CLEARS IT, QUIT CHECKS
|
|
CHRTOT EQU INLAST-2 * TOTAL CHARS INPUT SO FAR DURING OPREAD
|
|
|
|
FONT EQU CHRTOT-2 * NONZERO WHEN USING SPECIAL (MONOSPACED) FONT
|
|
MACBUF EQU FONT-4 * NEW VALUE FOR ENDBUF WHEN FONTSIZE CHANGES
|
|
|
|
SLPTR EQU MACBUF-4 * CURRENT POSITION WITHIN STATUS LINE BUFFER
|
|
LOCPTR EQU SLPTR-4 * START OF STATUS LOCATION STRING
|
|
SCOPTR EQU LOCPTR-4 * START OF STATUS SCORE STRING
|
|
|
|
APPARM EQU SCOPTR-4 * HANDLE TO APPLICATION PARAMETERS
|
|
SHOWVE EQU APPARM-4 * POINTER TO "VERSION" STRING, ZERO IF NONE
|
|
|
|
GAMFIL EQU SHOWVE-4 * REF NUMBER OF OPENED GAME FILE
|
|
SAVFIL EQU GAMFIL-4 * REF NUMBER OF OPENED SAVE FILE
|
|
|
|
***
|
|
|
|
DBZPC1 EQU SAVFIL-2 * HALT WHEN ZPC REACHES THIS ADDRESS
|
|
DBZPC2 EQU DBZPC1-2
|
|
DBINST EQU DBZPC2-2 * HALT WHEN NEXT INSTRUCTION HAS THIS VALUE
|
|
|
|
DBTOT1 EQU DBINST-4 * TOTAL EXECUTION COUNT
|
|
DBTOT2 EQU DBTOT1-4 * DESIRED EXECUTION COUNT
|
|
|
|
***
|
|
|
|
ZVLEN EQU 0-DBTOT2 * TOTAL LENGTH OF ZIP'S VARIABLES FRAME
|
|
|
|
* ---------------------------------------------------------------------------
|
|
* ZIP DEBUGGING -- FOR DEVELOPEMENT ONLY
|
|
* ---------------------------------------------------------------------------
|
|
|
|
IFEQ DEBUG
|
|
|
|
* GO UNTIL ONE OF THE FOLLOWING CONDITIONS OCCURS:
|
|
* () ZPC REACHES A GIVEN ADDRESS
|
|
* () ZPC POINTS TO A GIVEN INSTRUCTION
|
|
* () A GIVEN NUMBER OF INSTRUCTIONS ARE EXECUTED
|
|
|
|
DBTEST RTS
|
|
|
|
ENDC * END OF CONDITIONAL ASSEMBLY
|
|
|
|
|
|
PAGE
|
|
* ---------------------------------------------------------------------------
|
|
* INITIALIZATIONS
|
|
* ---------------------------------------------------------------------------
|
|
|
|
PVERS1 EQU 0 * ZVERSION VERSION BYTE
|
|
PVERS2 EQU 1 * ZVERSION MODE BYTE
|
|
PZRKID EQU 2 * ZORK ID
|
|
PENDLD EQU 4 * ENDLOD (RELATIVE BYTE POINTER)
|
|
PSTART EQU 6 * START
|
|
PVOCTB EQU 8 * VOCTAB
|
|
POBJTB EQU 10 * OBJTAB
|
|
PGLOTB EQU 12 * GLOTAB
|
|
PPURBT EQU 14 * PURBOT
|
|
PFLAGS EQU 16 * USER FLAGS WORD
|
|
PSERNM EQU 18 * SERIAL NUMBER (6 BYTES)
|
|
PWRDTB EQU 24 * WRDTAB
|
|
PLENTH EQU 26 * LENGTH (EZIP QUADS, ZIP WORDS)
|
|
PCHKSM EQU 28 * CHECKSUM (ALL BYTES STARTING WITH BYTE 64)
|
|
|
|
PINTWD EQU 30 * INTERPRETER ID/VERSION
|
|
PSCRWD EQU 32 * SCREEN SIZE, ROWS/COLUMNS
|
|
|
|
IFEQ EZIP
|
|
ZMVERS EQU 4 * EZIP Z-MACHINE VERSION NUMBER
|
|
STKLEN EQU 512*2 * LENGTH OF GAME STACK (MULTIPLE OF 512)
|
|
ENDC
|
|
IFEQ CZIP
|
|
ZMVERS EQU 3 * CLASSIC Z-MACHINE VERSION NUMBER
|
|
STKLEN EQU 512*1 * LENGTH OF GAME STACK
|
|
ENDC
|
|
|
|
* MICRO'S ID CODE, ZIP'S VERSION LETTER (SEE ALSO OPVERI)
|
|
|
|
SECTION ZDATA
|
|
IFEQ EZIP
|
|
INTWRD DC.B 4 * MACHINE ID FOR COMMODORE AMIGA
|
|
DC.B 'C' * EZIP INTERPRETER VERSION
|
|
SUBVER DC.W 0 * INTRPRETER SUB-VERSION, ZERO TO DISABLE
|
|
ENDC
|
|
IFEQ CZIP
|
|
INTWRD DC.B 0 * (UNUSED)
|
|
DC.B 'C' * INTERPRETER VERSION
|
|
SUBVER DC.W 0 * INTRPRETER SUB-VERSION, ZERO TO DISABLE
|
|
ENDC
|
|
|
|
* INITIAL SET OF READ BREAK CHARS -- SPACE, TAB, CR, <.>, <,>, <?>
|
|
|
|
IRBRKS DC.W $2009,$0D2E,$2C3F,0 * ASCIZ
|
|
SECTION ZCODE
|
|
|
|
* ---------------------------------------------------------------------------
|
|
|
|
_START LINK A6,#-ZVLEN * CREATE A FRAME FOR ZIP VARIABLES
|
|
MOVE.L A6,A0 * TOP OF FRAME
|
|
|
|
MOVE.W #ZVLEN/2,D0
|
|
STRX1 CLR.W -(A0) * ALL INITIAL VALUES ARE ZERO
|
|
SUBQ.W #1,D0
|
|
BNE.S STRX1
|
|
|
|
MOVE.L SP,TOPSP(A6) * SAVE THE SP FOR RESTARTS
|
|
LEA ZVARS,A0
|
|
MOVE.L A6,(A0) * KEEP A COPY OF A6 IN A KNOWN PLACE
|
|
|
|
* Careful about error msgs before all buffers are initialized.
|
|
* For example, a call to TSTSCR (via PUTCHR) before the preload data is
|
|
* read into BUFFER would access an invalid pointer.
|
|
|
|
* Send any output directly to screen (VOBUFF off), until QUECHR stuff set up.
|
|
|
|
MOVE.W #1,VOCONS(A6) * CONSOLE OUTPUT NORMALLY ACTIVE
|
|
MOVE.W #1,VIECHO(A6) * INPUT IS NORMALLY ECHOED
|
|
|
|
* Avoid the TSTSCR bug by pretending we're in window 1 (never scripts).
|
|
|
|
MOVE.W #1,WIND1(A6) * IN WINDOW 1 UNTIL PRELOAD COMPLETED
|
|
BSR SYSINI * OPEN THE GAME FILE
|
|
|
|
IFEQ EZIP
|
|
MOVE.W _columns,D0
|
|
CMPI.W #80-1,D0 * 80 COLUMNS MINIMUM, LESS FUDGE (AMIGA)
|
|
BGE STRX2 * OK
|
|
|
|
LEA MSG80C,A0 * NOT ENOUGH, INFORM USER AND QUIT
|
|
BSR OUTMSG
|
|
BRA FINISH
|
|
|
|
SECTION ZDATA
|
|
MSG80C DC.B 'Your screen resolution is too low to continue. '
|
|
DC.B 'You must increase the resolution before starting the story.'
|
|
DC.B 0
|
|
SECTION ZCODE
|
|
ENDC
|
|
|
|
*** READ GAME BLOCK 0 INTO A TEMP STACK BUFFER
|
|
|
|
STRX2 SUBA.W #512,SP * CREATE A TEMP BUFFER
|
|
MOVE.L SP,A4 * SAVE POINTER HERE FOR NOW
|
|
|
|
MOVE.L A4,A0
|
|
CLR.W D0 * BLOCK 0
|
|
BSR GETBLK * GET IT
|
|
|
|
*** CHECK MACHINE VERSION NUMBER
|
|
|
|
CMPI.B #ZMVERS,(A4) * PROPER Z-MACHINE VERSION?
|
|
BEQ.S STRX4 * YES
|
|
|
|
STRX3 CLR.W D0 * SOMETHING WRONG, DIE
|
|
LEA MSGZMV,A0
|
|
BRA FATAL * 'Wrong Z-machine'
|
|
|
|
SECTION ZDATA
|
|
MSGZMV DC.B 'Wrong Z-machine version',0
|
|
SECTION ZCODE
|
|
|
|
STRX4 MOVE.W PZRKID(A4),ZORKID(A6) * UNIQUE GAME ID, CHECKED BY "RESTORE"
|
|
|
|
IFEQ CZIP
|
|
BTST #0,PVERS2(A4) * PROPER BYTE-SWAP MODE?
|
|
BNE STRX3 * NO, FAIL
|
|
|
|
CLR.W TIMEMD(A6) * ASSUME SCORE-MODE FOR STATUS LINE
|
|
BTST #1,PVERS2(A4) * TIME MODE REQUESTED?
|
|
BEQ.S STRX6 * NO
|
|
ADDQ.W #1,TIMEMD(A6) * YES, SET TIME-MODE FLAG
|
|
ENDC
|
|
|
|
|
|
*** DETERMINE OUR MEMORY REQUIREMENTS
|
|
|
|
STRX6 MOVEQ #0,D0
|
|
MOVE.W PLENTH(A4),D0 * LENGTH OF GAME FILE (WORDS OR QUADS)
|
|
ADD.L D0,D0
|
|
IFEQ EZIP
|
|
ADD.L D0,D0 * BYTES
|
|
ENDC
|
|
BSR ROUNDUP
|
|
MOVE.L D0,MAXGAM(A6)
|
|
|
|
MOVEQ #0,D0
|
|
MOVE.W PENDLD(A4),D0 * "NORMAL" LENGTH OF PRELOAD (BYTES)
|
|
BSR ROUNDUP
|
|
MOVE.L D0,MINGAM(A6)
|
|
|
|
*** INQUIRE FREE MEMORY (AMIGA -- SUPPLY OUR MAXIMUM REQUIREMENT ...)
|
|
|
|
MOVE.L MAXGAM(A6),D0
|
|
ADD.L #STKLEN+1024+512,D0 * PLUS ZSTACK, 2 PAGES, MISC
|
|
BSR MEMAVAIL * DETERMINE HOW MUCH FREE MEMORY EXISTS
|
|
MOVE.L D0,D7 * SAVE THE NUMBER HERE
|
|
|
|
* THE FOUR POSSIBLE MEMORY SITUATIONS ...
|
|
*
|
|
* (1) MEMAVAIL exceeds PLENTH. Preload the entire game, and create
|
|
* two page buffers (minimum needed for $VER).
|
|
*
|
|
* (2) MEMAVAIL exceeds ENDLOD by at least (say) 40 pages. Preload through
|
|
* ENDLOD, and create as many page buffers as possible.
|
|
*
|
|
* (3) MEMAVAIL barely exceeds ENDLOD. In this situation, performance
|
|
* degrades sharply. To free up some memory, preload only through the
|
|
* beginning of the vocabulary table, and create as many page buffers
|
|
* as possible.
|
|
*
|
|
* (4) MEMAVAIL does not exceed ENDLOD. Life is tough.
|
|
*
|
|
|
|
CMP.L MAXGAM(A6),D7 * ENOUGH ROOM TO PRELOAD ENTIRE GAME?
|
|
BGE.S LOAD2C * YES
|
|
|
|
MOVE.L D7,D0
|
|
SUBI.L #40*512,D0 * ALLOW ABOUT 40 PAGES OVERHEAD
|
|
CMP.L MINGAM(A6),D0 * ENOUGH ROOM FOR A "COMFORTABLE FIT"?
|
|
BGE.S LOAD2B * YES
|
|
|
|
CMP.L MINGAM(A6),D7 * ENOUGH ROOM FOR A "TIGHT FIT"?
|
|
BGE.S LOAD2A * YES
|
|
|
|
BRA MEMERR * NO, FAIL
|
|
|
|
* PATCH MINGAM(A6) SO THAT VOCAB TABLE IS NOT PRELOADED
|
|
|
|
LOAD2A MOVEQ #0,D0
|
|
MOVE.W PVOCTB(A4),D0 * START OF VOCAB TABLE
|
|
ADD.L #64,D0 * BUT, BE CAREFUL TO INCLUDE THE VOCTAB HEADER
|
|
BSR ROUNDUP
|
|
MOVE.L D0,MINGAM(A6) * AND FALL THROUGH ...
|
|
|
|
* GIVEN MINGAM, SET ENDLOD AND MAXIMIZE PAGTOT
|
|
|
|
LOAD2B MOVE.L MINGAM(A6),D0
|
|
BSR BYTBLK
|
|
MOVE.W D0,ENDLOD(A6) * LENGTH OF PRELOAD (IN BLOCKS)
|
|
|
|
MOVE.L D7,D0
|
|
SUB.L MINGAM(A6),D0 * MEMORY REMAINING AFTER PRELOAD
|
|
DIVU #512+8,D0 * PAGES AVAIL (ALLOW 8 BYTES PER TABLE ENTRY)
|
|
CMPI.W #2,D0
|
|
BGE.S LOAD2X
|
|
MOVEQ #2,D0 * ENSURE THAT WE HAVE AT LEAST TWO
|
|
LOAD2X MOVE.W D0,PAGTOT(A6) * SAVE FOR LATER
|
|
BRA.S LOAD3
|
|
|
|
* GIVEN MAXGAM, SET ENDLOD AND MINIMIZE PAGTOT
|
|
|
|
LOAD2C MOVE.L MAXGAM(A6),D0
|
|
BSR BYTBLK * LENGTH OF GAME FILE (IN BLOCKS)
|
|
MOVE.W D0,ENDLOD(A6) * PRELOAD EVERYTHING
|
|
|
|
MOVE.W #2,PAGTOT(A6) * TWO PAGES ONLY (FOR $VERIFY)
|
|
|
|
|
|
*** GIVEN ENDLOD, ALLOCATE SOME MEMORY AND DO THE PRELOAD
|
|
|
|
LOAD3
|
|
IFEQ DEBUG
|
|
MOVE.W ENDLOD(A6),D0
|
|
BSR OPPRNN * SHOW PRELOAD
|
|
MOVE.B #'/',D0
|
|
BSR PUTCHR
|
|
MOVE.W PAGTOT(A6),D0 * SHOW PAGE COUNT
|
|
BSR OPPRNN
|
|
BSR PUTNEW
|
|
ENDC
|
|
|
|
MOVE.W ENDLOD(A6),D0 * SPACE NEEDED FOR PRELOAD (IN BLOCKS)
|
|
BSR BLKBYT * CONVERT TO BYTES
|
|
BSR GETMEM
|
|
MOVE.L A0,BUFFER(A6) * KEEP POINTER HERE
|
|
|
|
MOVE.W ENDLOD(A6),D1 * NUMBER OF BLOCKS TO PRELOAD
|
|
CLR.W D0 * STARTING WITH BLOCK 0
|
|
BSR GTBLKS * READ THEM IN
|
|
|
|
MOVE.L BUFFER(A6),A4 * USE PRELOAD BUFFER FOR REMAINING INITS
|
|
ADDA.W #512,SP * FLUSH THE TEMP BUFFER
|
|
|
|
CLR.W WIND1(A6) * RESTORE NORMAL VALUE (FOR PUTCHR/TSTSCR)
|
|
|
|
* ------------------------------------------------------------------------
|
|
|
|
*** INITIALIZE MAJOR TABLE POINTERS
|
|
|
|
MOVEQ #0,D0
|
|
MOVE.W PVOCTB(A4),D0 * RELATIVE VOCAB TABLE POINTER
|
|
ADD.L A4,D0 * ABSOLUTIZE IT
|
|
MOVE.L D0,VOCTAB(A6) * AND SAVE IT
|
|
|
|
MOVEQ #0,D0
|
|
MOVE.W POBJTB(A4),D0 * RELATIVE OBJECT TABLE POINTER
|
|
ADD.L A4,D0
|
|
MOVE.L D0,OBJTAB(A6)
|
|
|
|
MOVEQ #0,D0
|
|
MOVE.W PGLOTB(A4),D0 * RELATIVE GLOBAL TABLE POINTER
|
|
ADD.L A4,D0
|
|
MOVE.L D0,GLOTAB(A6)
|
|
|
|
MOVEQ #0,D0
|
|
MOVE.W PWRDTB(A4),D0 * RELATIVE WORD TABLE POINTER
|
|
ADD.L A4,D0
|
|
MOVE.L D0,WRDTAB(A6)
|
|
|
|
MOVEQ #0,D0
|
|
MOVE.W PPURBT(A4),D0 * GET PURBOT BYTE POINTER
|
|
BSR BYTBLK * ROUND UP TO NEXT BLOCK BOUNDARY
|
|
MOVE.W D0,PURBOT(A6) * AND SAVE IT
|
|
|
|
*** ALLOCATE MEMORY FOR Z STACK
|
|
|
|
MOVE.L #STKLEN,D0
|
|
BSR GETMEM
|
|
MOVE.L A0,STKBOT(A6) * THIS WILL BE BOTTOM OF GAME STACK
|
|
|
|
*** INITIALIZE LINE BUFFER, SCRIPT BUFFER
|
|
|
|
SCRLEN EQU 80 * LENGTH OF SCRIPT BUFFER (CONST FOR NOW)
|
|
MAXLEN EQU 256 * MAX LENGTH OF LINE BUFFER
|
|
|
|
MOVE.W #MAXLEN,D1
|
|
MOVE.W _columns,D2 * CURRENT WIDTH OF SCREEN DISPLAY
|
|
LEA LINOUT,A1 * SCREEN DISPLAY FUNCTION
|
|
LEA CHSIZ,A2
|
|
|
|
BSR INITQP * SET UP DISPLAY QUEUE STUFF
|
|
MOVE.L A0,DQUE(A6) * SAVE BLOCK POINTER
|
|
|
|
MOVE.W #SCRLEN,D1 * SCRIPTING SIZE, NEVER CHANGES
|
|
MOVE.W D1,D2
|
|
LEA SCROUT,A1 * SCRIPTING DISPLAY FUNCTION
|
|
LEA CHSIZ,A2
|
|
|
|
BSR INITQP * SET UP SCRIPT QUEUE STUFF
|
|
MOVE.L A0,SQUE(A6) * SAVE THIS POINTER TOO
|
|
|
|
MOVE.W #1,VOBUFF(A6) * OKAY NOW TO BEGIN BUFFERING OUTPUT
|
|
|
|
*** ALLOCATE MEMORY FOR BREAK-CHAR TABLE, INIT VOCABULARY VARS
|
|
|
|
MOVE.L #64,D0 * MAX BREAK CHARS
|
|
BSR GETMEM
|
|
MOVE.L A0,RBRKS(A6) * THIS WILL BE START OF SI BREAK CHARS
|
|
|
|
MOVE.L VOCTAB(A6),A1
|
|
CLR.W D0
|
|
MOVE.B (A1)+,D0 * FIRST BYTE OF VOCTAB IS # OF SI BREAK CHARS
|
|
STRX10 MOVE.B (A1)+,(A0)+ * TRANSFER THEM
|
|
SUBQ.W #1,D0
|
|
BNE.S STRX10
|
|
|
|
MOVE.L A0,ESIBKS(A6) * REMEMBER END OF SI BREAKS
|
|
LEA IRBRKS,A2 * THESE ARE THE NORMAL BREAK CHARS
|
|
STRX12 MOVE.B (A2)+,(A0)+ * TRANSFER THEM TOO
|
|
BNE.S STRX12 * ASCIZ
|
|
|
|
CLR.W D0
|
|
MOVE.B (A1)+,D0 * THIS BYTE IS THE LENGTH OF EACH VOCTAB ENTRY
|
|
MOVE.W D0,VWLEN(A6) * SAVE IT
|
|
|
|
MOVE.B (A1)+,D0 * THIS WORD IS THE NUMBER OF VOCTAB ENTRIES
|
|
ASL.W #8,D0
|
|
MOVE.B (A1)+,D0
|
|
MOVE.W D0,VWORDS(A6) * SAVE IT
|
|
|
|
SUBA.L BUFFER(A6),A1 * RELATIVIZE NEXT TWO POINTERS
|
|
MOVE.L A1,VOCBEG(A6) * THIS IS BEGINNING OF ACTUAL VOCABULARY
|
|
SUBQ.W #1,D0 * CALCULATE POINTER TO LAST VOCAB ENTRY
|
|
MULU VWLEN(A6),D0
|
|
ADDA.L D0,A1
|
|
MOVE.L A1,VOCEND(A6) * AND SAVE IT
|
|
|
|
*** ALLOCATE MEMORY FOR PAGE TABLE & BUFFERS
|
|
|
|
MOVE.W PAGTOT(A6),D0 * PREVIOUSLY CALCULATED NUMBER OF PAGE BUFFERS
|
|
MULU #8,D0 * 8-BYTE TABLE ENTRY FOR EACH PAGE
|
|
ADDQ.L #2,D0 * ALLOW FOR THE END MARK
|
|
BSR GETMEM
|
|
MOVE.L A0,PAGTAB(A6) * THIS WILL BE START OF PAGE TABLE
|
|
|
|
MOVE.W PAGTOT(A6),D0 * PREVIOUSLY CALCULATED NUMBER OF PAGE BUFFERS
|
|
MULU #512,D0 * 512 BYTES EACH
|
|
BSR GETMEM
|
|
MOVE.L A0,PAGES(A6) * PAGES THEMSELVES WILL START HERE
|
|
|
|
*** INITIALIZE THE PAGE TABLE
|
|
|
|
MOVE.W PAGTOT(A6),D0 * PREVIOUSLY CALCULATED NUMBER OF PAGE BUFFERS
|
|
MOVE.L PAGTAB(A6),A0
|
|
|
|
STRX16 MOVE.W #-2,(A0)+ * BLOCK (NO BLOCK "$FFFE")
|
|
CLR.L (A0)+ * REF TIME IS ZERO
|
|
CLR.W (A0)+ * THIS SLOT UNUSED (BUT 8 BYTES SPEEDS CALCS)
|
|
SUBQ.W #1,D0
|
|
BNE.S STRX16
|
|
MOVE.W #-1,(A0) * MARK THE END OF THE TABLE (NO BLOCK "$FFFF")
|
|
|
|
MOVE.W #-1,CURBLK(A6) * MUST INIT THESE PAGING VARS TOO!
|
|
MOVE.W #-1,LPAGE(A6)
|
|
|
|
* ETCETERA ...
|
|
|
|
BSR GTSEED * INITIALIZE THE RANDOM NUMBER SEEDS
|
|
MOVE.W D0,RSEED1(A6)
|
|
SWAP D0
|
|
MOVE.W D0,RSEED2(A6) * PUT HIGH WORD HERE (RELATIVELY CONSTANT)
|
|
|
|
BRA.S START1
|
|
|
|
* RESTART EXECUTION HERE
|
|
|
|
RESTRT MOVE.L BUFFER(A6),A0
|
|
MOVE.W PFLAGS(A0),-(SP) * PRESERVE THE USER FLAGS (SCRIPT ETC)
|
|
|
|
CLR.W D0 * REREAD ALL OF THE IMPURE STUFF
|
|
MOVE.W PURBOT(A6),D1
|
|
BSR GTBLKS
|
|
|
|
MOVE.L BUFFER(A6),A0
|
|
MOVE.W (SP)+,PFLAGS(A0) * RESTORE USER FLAGS
|
|
|
|
START1 MOVE.L TOPSP(A6),SP * RE-INITIALIZE SYSTEM STACK POINTER
|
|
|
|
MOVE.L DQUE(A6),A0
|
|
MOVE.L BUFPTR(A0),NXTPTR(A0) * INITIALIZE OUTPUT BUFFER POINTER
|
|
|
|
MOVE.L STKBOT(A6),A4
|
|
ADDA.W #STKLEN,A4 * INITIALIZE GAME STACK POINTER
|
|
|
|
MOVE.L A4,ZLOCS(A6) * INITIALIZE POINTER TO LOCALS
|
|
SUBQ.L #2,ZLOCS(A6) * IF ANY, THEY WOULD START AT FIRST SLOT
|
|
|
|
MOVE.L BUFFER(A6),A2
|
|
|
|
IFEQ EZIP
|
|
* ORI.B #32 * NO SOUND (AMIGA)
|
|
ORI.B #16+8+4+2+1,PVERS2(A2) * CURSOR/HIGHLIGHTS/SPLIT
|
|
LEA INTWRD,A0
|
|
MOVE.B (A0)+,PINTWD(A2) * STORE THE MACHINE ID
|
|
MOVE.B (A0),PINTWD+1(A2) * AND THE INTERPRETER VERSION
|
|
|
|
MOVE.W _rows,D0
|
|
MOVE.W _columns,D1
|
|
ASL.W #8,D0 * ROWS IN HIGH BYTE, COLUMNS IN LOW
|
|
MOVE.B D1,D0
|
|
MOVE.W D0,PSCRWD(A2) * SET SCREEN-PARAMETERS WORD
|
|
|
|
CLR.W RCYCLE(A6) * ALWAYS RESTART WITH NORMAL RANDOMNESS
|
|
|
|
CLR.W _split_row * NO STATUS LINE INITIALLY
|
|
BSR EZERR * CHECK OBJTAB ALIGNMENT
|
|
ENDC
|
|
IFEQ CZIP
|
|
BSET #5,PVERS2(A2) * SPLIT-SCREEN IS AVAILABLE
|
|
MOVE.W #1,_split_row * ALLOW FOR ONE STATUS LINE
|
|
ENDC
|
|
|
|
MOVE.W PSTART(A2),D0 * GET STARTING LOCATION
|
|
BSR BSPLTB * SPLIT BLOCK AND BYTE POINTERS
|
|
|
|
MOVE.W D0,ZPC1(A6) * INITIALIZE THE ZPC
|
|
MOVE.W D1,ZPC2(A6)
|
|
BSR NEWZPC * GET THE FIRST PAGE TO EXECUTE
|
|
|
|
BSR BOOTSV * MAC -- BUT LOAD A SAVED GAME IF REQUESTED
|
|
BRA NXTINS * TALLY HO
|
|
|
|
IFEQ EZIP
|
|
|
|
* MAKE SURE OBJ TABLE IS WORD ALIGNED FOR EZIP
|
|
|
|
EZERR MOVE.L BUFFER(A6),A0
|
|
MOVE.W POBJTB(A0),D0 * OBJECT TABLE BASE
|
|
BTST #0,D0 * WORD ALIGNED?
|
|
BNE.S EZERX1 * NO, FAIL
|
|
RTS
|
|
|
|
EZERX1 CLR.W D0
|
|
LEA MSGEZR,A0
|
|
BRA FATAL * 'OBJTAB alignment error'
|
|
|
|
SECTION ZDATA
|
|
MSGEZR DC.B 'OBJTAB alignment error',0
|
|
SECTION ZCODE
|
|
|
|
ENDC
|
|
|
|
PAGE
|
|
* ---------------------------------------------------------------------------
|
|
* LOW LEVEL FUNCTIONS
|
|
* ---------------------------------------------------------------------------
|
|
|
|
* GIVEN A ZIP BLOCK COUNT IN D0.W, RETURN A BYTE COUNT IN D0.L
|
|
|
|
BLKBYT EXT.L D0 * CLEAR HIGH WORD
|
|
SWAP D0
|
|
LSR.L #7,D0 * x512
|
|
RTS
|
|
|
|
* GIVEN A BYTE COUNT IN D0.L, RETURN A ZIP BLOCK COUNT IN D0.W, ROUNDING UP
|
|
|
|
BYTBLK BSR ROUNDUP
|
|
LSR.L #8,D0
|
|
LSR.L #1,D0 * EXTRACT BLOCK NUMBER
|
|
RTS
|
|
|
|
* GIVEN A BYTE COUNT IN D0.L, ROUND UP TO NEAREST MULTIPLE OF 512
|
|
|
|
ROUNDUP
|
|
MOVE.W D0,-(SP)
|
|
ANDI.W #$01FF,(SP)+ * ARE THERE ANY FRACTIONAL BYTES?
|
|
BEQ.S RDUP1 * NO
|
|
|
|
ANDI.W #$FE00,D0 * YES, REMOVE THE FRACTIONAL BYTES
|
|
ADDI.L #$0200,D0 * AND ROUND UP
|
|
RDUP1 RTS
|
|
|
|
* GET CORE WORD, ABSOLUTE POINTER IN A0, RETURN THE WORD IN D0, UPDATE POINTER
|
|
|
|
GTAWRD
|
|
MOVE.B (A0)+,D0 * GET HIGH-ORDER BYTE, ADVANCE A0
|
|
ASL.W #8,D0 * POSITION IT
|
|
MOVE.B (A0)+,D0 * GET LOW-ORDER BYTE, ADVANCE A0
|
|
RTS
|
|
|
|
* UPDATE CORE WORD, ABSOLUTE POINTER IN A0, NEW VALUE IN D0
|
|
|
|
PTAWRD
|
|
MOVE.B D0,1(A0) * STORE LOW-ORDER BYTE
|
|
ASR.W #8,D0
|
|
MOVE.B D0,(A0) * STORE HIGH-ORDER BYTE
|
|
RTS
|
|
|
|
* GET A BYTE FROM GAME, BLOCK-POINTER IN D0, BYTE-POINTER IN D1, RESULT IN D2
|
|
* UPDATE D0 AND D1 TO REFLECT BYTE GOTTEN
|
|
|
|
GETBYT MOVE.W D0,-(SP)
|
|
CMP.W ENDLOD(A6),D0 * IS THIS A PRELOADED LOCATION?
|
|
BGE.S GETBX1 * NO
|
|
|
|
BSR BLKBYT * YES, RECONSTRUCT POINTER (MAY EXCEED 32K)
|
|
OR.W D1,D0
|
|
|
|
CLR.W D2 * CLEAR THE UNWANTED HIGH BYTE
|
|
MOVE.L BUFFER(A6),A0 * ABSOLUTE POINTER
|
|
MOVE.B 0(A0,D0.L),D2 * GET THE DESIRED BYTE
|
|
BRA.S GETBX2
|
|
|
|
GETBX1 BSR GETPAG * FIND THE PROPER PAGE (POINTER RETURNED IN A0)
|
|
CLR.W D2 * CLEAR THE UNWANTED HIGH BYTE
|
|
MOVE.B 0(A0,D1.W),D2 * GET THE DESIRED BYTE
|
|
|
|
GETBX2 MOVE.W (SP)+,D0
|
|
ADDQ.W #1,D1 * UPDATE BYTE-POINTER
|
|
CMPI.W #512,D1 * END OF PAGE?
|
|
BNE.S GETBX3 * NO, DONE
|
|
|
|
CLR.W D1 * YES, CLEAR BYTE-POINTER
|
|
ADDQ.W #1,D0 * AND UPDATE BLOCK-POINTER
|
|
GETBX3 RTS
|
|
|
|
* GET A WORD FROM GAME, BLOCK-POINTER IN D0, BYTE-POINTER IN D1, RESULT IN D2
|
|
|
|
GETWRD BSR GETBYT * GET HIGH-ORDER BYTE
|
|
ASL.W #8,D2 * POSITION IT
|
|
MOVE.W D2,-(SP) * SAVE IT
|
|
|
|
BSR GETBYT * GET LOW-ORDER BYTE
|
|
OR.W (SP)+,D2 * OR IN THE OTHER BYTE
|
|
RTS
|
|
|
|
* GET THE NEXT BYTE, RETURN IT IN D0
|
|
|
|
NXTBYT MOVE.L CURPAG(A6),A0 * INDEX INTO CURRENT PAGE
|
|
ADDA.W ZPC2(A6),A0
|
|
CLR.W D0 * CLEAR HIGH REGISTER AND
|
|
MOVE.B (A0),D0 * GET THE NEXT BYTE
|
|
|
|
ADDQ.W #1,ZPC2(A6) * UPDATE PC
|
|
CMPI.W #512,ZPC2(A6) * END OF PAGE?
|
|
BLT.S NXTBX1 * NO
|
|
|
|
MOVE.W D0,-(SP)
|
|
BSR NEWZPC * YES, UPDATE PAGE
|
|
MOVE.W (SP)+,D0
|
|
NXTBX1 RTS * AND RETURN
|
|
|
|
* GET THE NEXT WORD, RETURN IT IN D0
|
|
|
|
NXTWRD BSR NXTBYT * GET HIGH-ORDER BYTE
|
|
ASL.W #8,D0 * SHIFT TO PROPER POSITION
|
|
MOVE.W D0,-(SP) * SAVE IT
|
|
|
|
BSR NXTBYT * GET LOW-ORDER BYTE
|
|
OR.W (SP)+,D0 * OR IN THE OTHER BYTE
|
|
RTS
|
|
|
|
* GET AN ARGUMENT GIVEN ITS TYPE IN D0
|
|
|
|
GETARG SUBQ.W #1,D0 * EXAMINE ARGUMENT
|
|
BLT.S NXTWRD * 0 MEANT LONG IMMEDIATE
|
|
BEQ.S NXTBYT * 1 MEANT SHORT IMMEDIATE
|
|
|
|
BSR NXTBYT * 2 MEANT VARIABLE, GET THE VAR
|
|
TST.W D0 * STACK?
|
|
BNE.S GETV1 * NO, JUST GET THE VAR'S VALUE
|
|
MOVE.W (A4)+,D0 * YES, POP THE STACK
|
|
RTS
|
|
|
|
* GET VALUE OF A VARIABLE, VAR IN D0, VALUE RETURNED IN D0
|
|
|
|
GETVAR TST.W D0 * STACK?
|
|
BNE.S GETV1 * NO
|
|
MOVE.W (A4),D0 * YES, GET TOP-OF-STACK (DON'T POP)
|
|
RTS
|
|
|
|
GETV1 CMPI.W #16,D0 * LOCAL?
|
|
BGE.S GETVX2 * NO
|
|
MOVE.L ZLOCS(A6),A0 * YES, POINT TO PROPER STACK ELEMENT
|
|
SUBQ.W #1,D0 * ADJUST FOR NULL VAR
|
|
ADD.W D0,D0
|
|
SUBA.W D0,A0 * LOCALS BUILD DOWN
|
|
MOVE.W (A0),D0 * GET IT
|
|
RTS
|
|
|
|
GETVX2 SUB.W #16,D0 * GLOBAL, ADJUST FOR LOCALS
|
|
MOVE.L GLOTAB(A6),A0 * POINT TO PROPER GLOBAL TABLE ELEMENT
|
|
ADD.W D0,D0
|
|
ADDA.W D0,A0
|
|
BRA GTAWRD * GET IT AND RETURN
|
|
|
|
* UPDATE VALUE OF A VARIABLE, VAR IN D0, NEW VALUE IN D1
|
|
|
|
PUTVAR TST.W D0 * STACK?
|
|
BNE.S PUTVX1 * NO
|
|
MOVE.W D1,(A4) * YES, UPDATE TOP-OF-STACK (DON'T PUSH)
|
|
RTS
|
|
|
|
PUTVX1 CMPI.W #16,D0 * LOCAL?
|
|
BGE.S PUTVX2 * NO
|
|
MOVE.L ZLOCS(A6),A0 * YES, POINT TO PROPER STACK ELEMENT
|
|
SUBQ.W #1,D0 * ADJUST FOR NULL VAR
|
|
ADD.W D0,D0
|
|
SUBA.W D0,A0 * LOCALS BUILD DOWN
|
|
MOVE.W D1,(A0) * UPDATE IT
|
|
RTS
|
|
|
|
PUTVX2 SUB.W #16,D0 * GLOBAL, ADJUST FOR LOCALS
|
|
MOVE.L GLOTAB(A6),A0 * POINT TO PROPER GLOBAL TABLE ELEMENT
|
|
ADD.W D0,D0
|
|
ADDA.W D0,A0
|
|
MOVE.W D1,D0
|
|
BRA PTAWRD * UPDATE IT AND RETURN
|
|
|
|
* RETURN VAL IN D0 TO LOCATION SPECIFIED BY NEXTBYTE
|
|
* DESTROYS D1, BUT IS USUALLY CALLED AT END OF TOP-LEVEL FUNCTION
|
|
|
|
BYTVAL ANDI.W #$00FF,D0 * ENTER HERE TO CLEAR HIGH BYTE
|
|
PUTVAL MOVE.W D0,D1 * NORMAL ENTRY
|
|
BSR NXTBYT * GET VAR TO USE
|
|
TST.W D0 * STACK?
|
|
BNE.S PUTVAR * NO, GO STORE VALUE
|
|
MOVE.W D1,-(A4) * YES, PUSH ONTO STACK
|
|
RTS
|
|
|
|
* PREDICATE HANDLERS TRUE AND FALSE
|
|
* DESTROYS REGISTERS, BUT ARE ONLY CALLED FROM END OF TOP-LEVEL FUNCTIONS
|
|
|
|
PFALSE CLR.W D1 * PREDICATE WAS FALSE, CLEAR FLAG
|
|
BRA.S PTRUE1
|
|
|
|
PTRUE MOVEQ #1,D1 * PREDICATE WAS TRUE, SET FLAG
|
|
PTRUE1 BSR NXTBYT * GET FIRST (OR ONLY) PREDICATE JUMP BYTE
|
|
BCLR #7,D0 * NORMAL POLARITY PREDICATE?
|
|
BEQ.S PTRUX1 * NO, LEAVE FLAG ALONE
|
|
ADDQ.W #1,D1 * YES, INCREMENT FLAG
|
|
|
|
PTRUX1 BCLR #6,D0 * ONE-BYTE JUMP OFFSET?
|
|
BNE.S PTRUX3 * YES
|
|
|
|
ASL.W #8,D0 * NO, TWO-BYTE, POSITION HIGH-ORDER OFFSET BYTE
|
|
MOVE.W D0,D2
|
|
BSR NXTBYT * GET LOW-ORDER BYTE
|
|
OR.W D2,D0 * OR IN HIGH-ORDER BITS
|
|
BTST #13,D0 * IS NUMBER NEGATIVE (14-BIT 2'S COMP NUMBER)?
|
|
BEQ.S PTRUX3 * NO
|
|
ORI.W #$C000,D0 * YES, MAKE 16-BIT NUMBER NEGATIVE
|
|
|
|
PTRUX3 SUBQ.W #1,D1 * TEST FLAG
|
|
BEQ.S PTRUX6 * WAS 1, THAT MEANS DO NOTHING
|
|
TST.W D0 * ZERO JUMP?
|
|
BNE.S PTRUX4 * NO
|
|
BRA OPRFAL * YES, THAT MEANS DO AN RFALSE
|
|
|
|
PTRUX4 SUBQ.W #1,D0 * ONE JUMP?
|
|
BNE.S PTRUX5 * NO
|
|
BRA OPRTRU * YES, THAT MEANS DO AN RTRUE
|
|
|
|
PTRUX5 SUBQ.W #1,D0 * ADJUST OFFSET
|
|
ADD.W D0,ZPC2(A6) * ADD TO PC
|
|
BRA NEWZPC * AND UPDATE ZPC STUFF
|
|
PTRUX6 RTS
|
|
|
|
* SPLIT BYTE-POINTER IN D0.W (16 BIT UNSIGNED)
|
|
* INTO BLOCK NUMBER IN D0 & BYTE OFFSET IN D1
|
|
|
|
BSPLTB MOVE.W D0,D1
|
|
LSR.W #8,D0 * EXTRACT THE 7 BLOCK BITS (64K RANGE)
|
|
LSR.W #1,D0
|
|
ANDI.W #$01FF,D1 * EXTRACT THE 9 OFFSET BITS (0-511)
|
|
IFEQ DEBUG
|
|
BSR BLKCHK * CHECK FOR VALID BLOCK
|
|
ENDC
|
|
RTS
|
|
|
|
* SPLIT WORD-POINTER IN D0.W (16 BIT UNSIGNED)
|
|
* INTO BLOCK NUMBER IN D0 & BYTE OFFSET IN D1
|
|
|
|
BSPLIT MOVE.W D0,D1
|
|
LSR.W #8,D0 * EXTRACT THE 8 BLOCK BITS (128K RANGE)
|
|
ANDI.W #$00FF,D1 * EXTRACT THE 8 OFFSET BITS (0-255)
|
|
ADD.W D1,D1 * CONVERT OFFSET TO BYTES
|
|
IFEQ DEBUG
|
|
BSR BLKCHK * CHECK FOR VALID BLOCK
|
|
ENDC
|
|
RTS
|
|
|
|
* SPLIT QUAD-POINTER IN D0.W (16 BIT UNSIGNED)
|
|
* INTO BLOCK NUMBER IN D0 & BYTE OFFSET IN D1 -- EZIP ONLY
|
|
|
|
BSPLTQ MOVE.W D0,D1
|
|
LSR.W #7,D0 * EXTRACT THE 9 BLOCK BITS (256K RANGE)
|
|
ANDI.W #$007F,D1 * EXTRACT THE 7 OFFSET BITS (0-127)
|
|
ADD.W D1,D1 * CONVERT OFFSET TO BYTES
|
|
ADD.W D1,D1
|
|
IFEQ DEBUG
|
|
BSR BLKCHK * CHECK FOR VALID BLOCK
|
|
ENDC
|
|
RTS
|
|
|
|
IFEQ DEBUG
|
|
BLKCHK
|
|
* CMP.W MAXLOD(A6),D0 * VALID BLOCK NUMBER?
|
|
* BCC BLKERR * BHS * NO, FAIL
|
|
RTS
|
|
|
|
BLKERR LEA MSGBLK,A0
|
|
BRA FATAL * 'Block range error'
|
|
|
|
SECTION ZDATA
|
|
MSGBLK DC.B 'Block range error',0
|
|
SECTION ZCODE
|
|
|
|
ENDC
|