* ___________________________________________________________________________ * * YZIP INTERPRETER FOR THE MACINTOSH * * INFOCOM, INC. COMPANY CONFIDENTIAL -- NOT FOR DISTRIBUTION * * WRITTEN BY DUNCAN BLANCHARD * ___________________________________________________________________________ * * YZIP-MAC MODIFICATION HISTORY: * * 01 APR 88 DBB currow, curcol, clearLines - NOW 0-ORIGIN * 02 MAY 88 DBB ADDED YZIP WINDOW CALLS, ETC * 06 JUL 88 DBB ADDED ZBEEP, NOW READLN -> ZBEEP -> DOSOUND * WAS TRASHING D1-D3; FIXES 'D3BUG', I THINK * ADJUSTED PLENTH/PSTART FOR MOBY GAMES * YZIP (VERSION) #1 FROZEN [NEW ID SCHEME] * YZIP #2: * 15 NOV 88 DBB CHANGED UNHUFFH SO CAN BE INTERRUPTED * 30 NOV 88 DBB ADDED PCHRSET SETUP IN INIT, MODIFIED CHRBYT/ZWORD * * YZIP #3: * 16 DEC 88 DBB FIXED SLIGHT BUG IN SHRINK75 LOOP COUNTER * ShowGFXS now supports incremental display * XZIP-MAC MODIFICATION HISTORY: * * 14 JUL 87 DBB PORTED FROM ST * 14 SEP 87 DBB XZIP 'A' FROZEN * 05 OCT 87 DBB (PASCAL) ROW/COL VARS ALLOW BIG-SCREEN WINDOW * TIMEOUT COUNTER STOPS WHEN DA ACTIVE * PUTLIN1 <-> PUTLIN * OPINPUT/OPPRNT CALL PUTLIN (FIX HINT-WRAP BUG) * FKEYS THAT AREN'T TCHARS REJECTED IN OPREAD * ADDED UNDO AND MOUSE SUPPORT CHECKS * 1-CHAR INPUT DISABLES MENU "CMD-STRINGS" * 13 OCT 87 DBB DESKTOP RESTORE SETS SL REFRESH BIT * BUFFER NOW DUMPED IN CURSET/SPLIT/SCREEN * 14 OCT 87 DBB TO ALLOW SCREEN1 BUFFERING: * BUFFER ALSO ZEROED FOR ABOVE 3 (CURSOR MOVED) * SIZEQP NO LONGER SHRINKS BUF SIZE (ST ITALIC HACK) * XZIP 'B' FROZEN * 16 FEB 88 DBB ADDED SOUND, SOUND INTERRUPTS (GAMINT) * FIXED COPYT/PRINTT PAGING BUG * MOVED 'UNDO' SETUP BEFORE PAGING * XZIP 'C' FROZEN * XZIP-ATARI MODIFICATION HISTORY: * * 02 FEB 87 DBB MODIFIED EZIP * 21 MAY 87 DBB ADDED LOWCORE, MOUSE VARS * 02 JUN 87 DBB MOVED DUPNAM CHECK (_exist_file) INTO C * 25 JUN 87 DBB CHANGED OPFONT TO IGNORE REDUNDANT FONT CHANGES * FIXED STACK BUG, RESTORE VS. TIMER INTERRUPT * 13 JUL 87 DBB BUFFER FLUSHED IN OPSCRN, OPDIRO, OPERASE, OPCLEAR * CHKDSK MODIFIED FOR FULL PRELOAD SITUATION, * RESTART, $VER MAKE SPECIAL CHECKS FOR GAME DISK * XZIP 'A' FROZEN * ZIP/EZIP (ATARI) MODIFICATION HISTORY: * * 02 AUG 85 ZIP A FROZEN * 09 AUG 85 CLSGAM CHECKS WHETHER GAME FILE WAS OPENED * 09 AUG 85 REBUILT OBJECT FILE WITH NEW LIBRARIES, * INCREASED MACHINE STACK TO 2K (IN ZIPSTART) * 09 AUG 85 ZIP B FROZEN * EZIP A FROZEN * 10 FEB 86 PURE PRELOAD MAY EXCEED 32K (PUT, PUTB, PTSIZE) * OPSPLT (EZIP) NO LONGER CLEARS SCREEN * 10 APR 86 CHANGED PUTCHR (SPECIAL HANDLING FOR TABLE OUTPUT) * ADDED SCRNAM, SCRIPTS SAVE/RESTORE FILENAMES * 18 APR 86 CHANGED NXTLIN/BUFOUT/LINOUT. BUFOUT CALLS NXTLIN * SO [MORE] IS TIMED CORRECTLY DURING BOLDFACE, ETC * CHANGED OPATTR AND DQUE INIT, FOR ITALICS HACK * FIXED GETMEM, PREVENTS ST BUG WITH ODD MEM REQUEST * 08 MAY 86 FIXED QUECHR (QCX2A), ALLOW FOR EMPTY [DUMPED] BUFFER * CHANGED OPREAD, ONLY OVERFLOW WORDS ARE FLUSHED * 13 MAY 86 LINES(A6) NOW NORMALLY RESET TO ZERO, UPDATED INCHR * OPINPUT CHECKS VOBUFF(A6) * OPSPLIT CHECKS MAXIMUM SIZE OF split_row * NXTLIN TURNS OFF HIGHLIGHTING BEFORE PRINTING [MORE] * COMBINED READLN AND INCHR * EZIP B FROZEN * XZIP: SUGGESTIONS FOR FURTHER OVERHAUL * * - WHEN READING ARGBLK, INDEX OFF A6, NOT A0. * - MAKE ALL OPERATORS TAKE AN ARGBLK RATHER THAN REGISTER ARGS, NOW THAT * SO MANY HAVE OPTIONALS. FOR CONVENIENCE, PASS A1 -> FIRST ARG * * - IMPLEMENT HIGHLIGHTING USING SPECIAL CHARS, PUT DIRECTLY INTO THE OUTPUT * STREAM/BUFFER. LOW-LEVEL OUTPUT ROUTINE SCANS FOR THESE SPECIALS. * AVOIDS NEED FOR MUCH SPECIAL FLUSHING OF BUFFER. * * --------------------------------------------------------------------------- * 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 * --------------------------------------------------------------------------- * ASSEMBLY FLAGS * --------------------------------------------------------------------------- * THE FIRST TWO FLAGS EXIST ONLY FOR HISTORIC REASONS: * XZIP CAN'T BE CONDITIONALLY ASSEMBLED AS EZIP OR CLASSIC ZIP EZIP EQU 1 * ALWAYS ON (XZIP) CZIP EQU 0 * ALWAYS OFF (XZIP) DEBUG EQU 0 * IF ON, ASSEMBLES DEBUGGING CODE D3BUG EQU 0 * REG D3 BEING TRASHED; TRY TO PINPOINT IT * * (FIXED IN READLN/ZBEEP) * --------------------------------------------------------------------------- * INDEXING BASE FOR THE DISPATCH TABLE * --------------------------------------------------------------------------- ZBASE NOP * DATA * ST LATTICE: BEGIN THE DATA SEGMENT * DC.W 0 * (KLUGE TO AVOID AN OBSCURE LINKER BUG ASSOCIATED * CODE * WITH SUCCESSIVE 'DC' STATEMENTS) * --------------------------------------------------------------------------- * 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.S %2 * ENDM * PRIOR TO CALLING A PASCAL FUNCTION, MUST MAKE SPACE ON THE STACK * FOR THE RESULT, WORD OR LONG. [FOR 'C' FUNCTIONS THIS WOULD BE A NOP.] MACRO RESWORD SUBQ.L #2,SP * QUICKEST INSTR *** TST.W -(SP) ENDM MACRO RESLONG SUBQ.L #4,SP ENDM * AFTER CALLING A PASCAL FUNCTION, POP THE RESULT FROM THE STACK INTO D0 * (PASCAL ONLY; MIMICS 'C' CONVENTION FOR PORTABILITY). MACRO POPWORD MOVE.W (SP)+,D0 ENDM MACRO POPLONG MOVE.L (SP)+,D0 ENDM * SET RESULT FLAGS [C ONLY, UNNECESSARY IN PASCAL] MACRO TSTWORD *** TST.W D0 ENDM MACRO TSTLONG *** TST.L D0 ENDM * WHEN CALLING ANY MAC PASCAL ROUTINE, THESE ARE THE REGISTERS THAT * SHOULD NORMALLY BE PRESERVED, AND WHICH PASCAL MIGHT TRASH. MACRO SAVEREGS *** MOVEM.L D1-D7/A1-A5,-(SP) * ULTRA-CONSERVATIVE SET MOVEM.L D1-D2/A1,-(SP) * STANDARD SET FOR MAC PASCAL ENDM MACRO RESTREGS *** MOVEM.L (SP)+,D1-D7/A1-A5 MOVEM.L (SP)+,D1-D2/A1 * (DON'T AFFECT FLAGS) ENDM * --------------------------------------------------------------------------- * GENERAL EQUATES * --------------------------------------------------------------------------- ARG0 EQU 0 * ARGUMENT COUNT ARG1 EQU 2 * ARGUMENT OFFSETS IN PARAMETER BLOCK ARG2 EQU 4 ARG3 EQU 6 ARG4 EQU 8 SKIP EQU 0 * 'PLACEHOLDER' IN DEFAULT-PARAMETER BLOCK DBQLEN EQU 16 * LENGTH OF DEBUGGER HISTORY QUEUE *** THIS INFO IS NOW DERIVED ELSEWHERE ... * YCHAR EQU 12 * CHAR CELL PIXEL SIZE (MAC, MONACO 9) * XCHAR EQU 6 IF EZIP THEN VCHARS EQU 9 * MAX CHARS IN AN EZIP VOCAB WORD ZCHARS EQU 6 * EZIP: BYTES PER ZWORD 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) ENDIF IF CZIP THEN VCHARS EQU 6 * MAX CHARS IN A ZIP VOCAB WORD ZCHARS EQU 4 * CZIP: BYTES PER ZWORD 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) ENDIF *-------------------------------------------------------------------------- * GENERALIZED OUTPUT-FOLDING PARAMETER BLOCK *-------------------------------------------------------------------------- * THE QUECHR ROUTINE IS CALLED WITH A POINTER TO A STRUCTURE CONTAINING * THE VARIABLES BELOW. THIS ARRANGEMENT ALLOWS FOR THE EXISTANCE OF MORE THAN * ONE STRUCTURE, USEFUL IF DISPLAYED TEXT AND SCRIPTED TEXT NEED TO FOLD AT * DIFFERENT POINTS. * THE STRUCTURE IDENTIFIES TWO ACTION ROUTINES. THE OUTPUT FUNCTION * DUMPS THE BUFFER WHEN IT BECOMES FULL. THE SIZE FUNCTION ALLOWS FOR THE * HANDLING OF PROPORTIONALLY SPACED TEXT. * THE AUTOCR/KEEPSP VARIABLES ARE CURRENTLY IGNORED, BUT MIGHT BE USEFUL * FOR IMPLEMENTING RECALCULATION OF THE FOLD POINTS FOR A PARAGRAPH OF TEXT, * AS WHEN A WINDOW CHANGES SIZE. * DATA STRUCTURE FOR QUEUE-PARAMETERS BLOCK: BUFPTR EQU 0 * START OF BUFFER NXTPTR EQU 4 * CURRENT POSITION WITHIN BUFFER ENDPTR EQU 8 * END OF BUFFER >> current not used << BUFSIZ EQU 12 * MAXIMUM UNITS IN BUFFER CURSIZ EQU 14 * CURRENT UNITS IN BUFFER SIZFUN EQU 16 * GIVEN A CHAR, RETURNS UNIT SIZE OUTFUN EQU 20 * GIVEN PTRS (BEG AND END), DUMPS BUFFER, ADDS CR RETFUN EQU 24 * (UNUSED -- THIS SHOULD ADD THE CR) * FLAGS: DUMPED EQU 28 * WAS BUFFER EMPTIED (WITHOUT CR) BEFORE FULL? AUTOCR EQU 29 * APPEND A CR TO EACH BUFFER DUMP? *** YES KEEPSP EQU 30 * DON'T DISCARD TRAILING SPACE? *** NO INUSE EQU 31 * SEMAPHORE TO AVOID RE-ENTRANCE QPLEN EQU 32 * LENGTH OF BLOCK (ALWAYS EVEN) *-------------------------------------------------------------------------- * DATA STRUCTURE FOR YZIP WINDOWS: *-------------------------------------------------------------------------- WYPOS EQU 0 * WINDOW POSITION WXPOS EQU 2 WYSIZE EQU 4 * WINDOW SIZE WXSIZE EQU 6 WYCURS EQU 8 * CURSOR POSITION WXCURS EQU 10 WLMARG EQU 12 * MARGINS WRMARG EQU 14 WCRINT EQU 16 * CR INTERRUPT FUNCTION, COUNTER WCRCNT EQU 18 WHLIGHT EQU 20 * HIGHLIGHT MODE WCOLOR EQU 22 * BACK/FORE COLORS WFONTID EQU 24 * FONT ID, SIZE WFONTYX EQU 26 WATTR EQU 28 * WRAP BIT, SCROLL BIT, ETC WLCNT EQU 30 * LINES (NOT PIX) DISPLAYED SINCE LAST [MORE] * PRIVATE VARIABLES: WCSIZ EQU 32 * "FULLNESS" OF LAST BUFFER (CURSIZ FROM DQUE) * END OF BLOCK: WBLKLEN EQU 34 * TOTAL LENGTH OF BLOCK (ALWAYS EVEN) MAXWIND EQU 8 * VALID WINDOW IDS ARE 0..7 * FLAG BITS IN WATTR: WFWRAP EQU 1 * WRAP BIT WFSCRL EQU 2 * SCROLL BIT WFSCRP EQU 4 * SCRIPT BIT WFBUFF EQU 8 * BUFFER BIT * --------------------------------------------------------------------------- * 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 MAXLOD EQU PAGTOT-2 * TOTAL BLOCKS IN GAME MAXFLG EQU MAXLOD-2 * FLAG SET IF GAME FILE IS WHOLLY PRELOADED TOPSP EQU MAXFLG-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 NARGS EQU ZPC2-2 * (LOW BYTE) OPTIONAL ARG COUNT ZLOCS EQU NARGS-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 NORMAL, OTHERWISE TOP OF SEQUENCE RCONST EQU RCYCLE-2 * CURRENT PLACE IN SEQUENCE BUFFER EQU RCONST-4 * START OF PRELOADED GAME CODE ARGBLK EQU BUFFER-18 * 8 ARGS MAX FOR EZIP, PLUS COUNT DEFBLK EQU ARGBLK-10 * DEFAULT ARGUMENT BLOCK (4 ARGS + COUNT) *** RDWSTR EQU DEFBLK-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 VWSORT EQU RDRET-2 * FLAG: SET IF VOCTAB SORTED VWBOFF EQU VWSORT-2 * INITIAL OFFSET FOR BINARY SEARCH WRDOFF EQU VWBOFF-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 CURRENT TABLE OUTPUT BUFFER (EZIP) TABPTR EQU TABOUT-4 * POINTS TO NEXT TABLE POSITION 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 2 WORDS LPAGE EQU RTIME-2 * LAST REFERENCED PAGE NUMBER LPLOC EQU LPAGE-4 * AND ITS CORE LOCATION LPTAB EQU LPLOC-4 * AND ITS TABLE POINTER TWAIT EQU LPTAB-2 * DELAY, IN 1/10'S SEC, BETWEEN TIMEOUTS TFUNC EQU TWAIT-2 * FUNCTION TO CALL UPON TIMEOUT TCLOCK EQU TFUNC-4 * REF TIME (60THS) OF LAST CHANGE IN TCOUNT TCOUNT EQU TCLOCK-2 * DELAY REMAINING (10THS) SFUNC EQU TCOUNT-2 * FUNCTION TO CALL UPON SOUND-END SCOUNT EQU SFUNC-2 * #OPS TO WAIT BEFORE NEXT SOUND-END CHECK QFOFF EQU SCOUNT-4 * OFFSET OF FUNCTION AREA (QUADS, LONG) QSOFF EQU QFOFF-4 * OFFSET OF STRING AREA (QUADS, LONG) * WIND1 * [DEAD] * ROW0 * WINDOW 0 (SAVED) CURSOR POSITION * COL0 * ROW1 * WINDOW 1 (SAVED) CURSOR POSITION * COL1 * LINES * [MOVED INTO EACH WBLOCK] CURWIND EQU QSOFF-2 * CURRENT WINDOW CURWP EQU CURWIND-4 * PTR TO CURWIND RECORD BLOCK WBLOCKP EQU CURWP-(MAXWIND*4) * PTRS TO ALL BLOCKS MSWIND EQU WBLOCKP-2 * CURRENT MOUSE WINDOW INLAST EQU MSWIND-2 * INPUT SETS IT, OUTPUT CLEARS IT, QUIT CHECKS CHRTOT EQU INLAST-2 * TOTAL CHARS INPUT SO FAR DURING OPREAD GAMFIL EQU CHRTOT-2 * REF NUMBER OF OPENED GAME FILE SAVFIL EQU GAMFIL-2 * REF NUMBER OF OPENED SAVE FILE MSAVEB EQU SAVFIL-4 * PTR TO A RAM BUFFER FOR ISAVE/IRESTORE MSAVEF EQU MSAVEB-2 * FLAG, SET FOR ISAVE/IRESTORE *** FONT EQU MSAVEF-2 * NONZERO WHEN USING SPECIAL (MONOSPACED) FONT MACBUF EQU FONT-4 * NEW VALUE FOR ENDBUF WHEN FONTSIZE CHANGES APPARM EQU MACBUF-4 * HANDLE TO APPLICATION PARAMETERS SHOWVE EQU APPARM-4 * POINTER TO "VERSION" STRING, ZERO IF NONE *** DBZPC1 EQU SHOWVE-2 * BREAK WHEN ZPC REACHES THIS ADDRESS DBZPC2 EQU DBZPC1-2 DBINST EQU DBZPC2-2 * BREAK WHEN NEXT INSTRUCTION HAS THIS VALUE DBITOT EQU DBINST-4 * TOTAL INSTRUCTIONS EXECUTED DBIBRK EQU DBITOT-4 * BREAK AFTER THIS MANY INSTRUCTIONS DBQUE EQU DBIBRK-DBQLEN * CIRCULAR QUEUE FOR INST HISTORY DBQPTR EQU DBQUE-4 * PTR, NEXT OPEN SLOT IN QUEUE DBQEND EQU DBQPTR-4 * PTR, END OF QUEUE *** ZVLEN EQU 0-DBQEND * TOTAL LENGTH OF ZIP'S VARIABLES FRAME EJECT ; PAGE * --------------------------------------------------------------------------- * INITIALIZATIONS * --------------------------------------------------------------------------- * LOW-CORE GAME VARIABLES PVERS1 EQU 0 * ZVERSION VERSION BYTE PVERS2 EQU 1 * ZVERSION MODE BYTE PZRKID EQU 2 * ZORK ID PENDLD EQU 4 * ENDLOD (BYTE OFFSET) 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 * FOR XZIP: PHWRD EQU 2*17 * * WIDTH OF DISPLAY, IN PIXEL UNITS PVWRD EQU 2*18 * * HEIGHT OF DISPLAY, IN PIXEL UNITS PFWRD EQU 2*19 * * FONT HEIGHT, WIDTH * PLMRG EQU 2*20 * DEAD * LEFT MARGIN, IN PIXEL UNITS * PRMRG EQU 2*21 * DEAD * RIGHT MARGIN, IN PIXEL UNITS PCLRWRD EQU 2*22 * COLOR, BACKGROUND/FOREGROUND PTCHARS EQU 2*23 * BYTE PTR, TABLE OF TERMINATING CHARACTERS * PCRCNT EQU 2*24 * DEAD * CR COUNTER * PCRFUNC EQU 2*25 * DEAD * CR FUNCTION PCHRSET EQU 2*26 * BYTE PTR, CHAR SET TABLE PLCTBL EQU 2*27 * BYTE PTR, LOW-CORE VARS EXTENSION TABLE * FOR YZIP (REPLACEMENTS FOR ABOVE): PFOFF EQU 2*20 * OFFSET OF FUNCTION AREA (x8) PSOFF EQU 2*21 * OFFSET OF STRING AREA (x8) PTWID EQU 2*24 * TABLE WIDTH IN PIXELS (FROM DIROUT) * EQU 2*25 * LOW CORE EXTENSION TABLE VARIABLES * (WORD OFFSETS -- ACCESS THROUGH 'LOWCORE' ROUTINE) PLCLEN EQU 0 * TABLE LENGTH, IN WORDS PMLOCX EQU 1 * MOUSE LOCATION WHEN LAST CLICKED PMLOCY EQU 2 * "PFLAGS" BIT DEFINITIONS * NOTE: IN GENERAL, CAPABILITY BITS ARE INITIALLY SET BY THE GAME TO * REQUEST A GIVEN FEATURE, AND SHOULD BE CLEARED BY THE INTERPRETER * IF THE FEATURE IS UNAVAILABLE. FSCRI EQU 0 * SCRIPTING ON [SET BY INTERPRETER ONLY] FFIXE EQU 1 * FIXED-WIDTH FONT NEEDED FSTAT EQU 2 * REQUEST FOR STATUS LINE REFRESH FDISP EQU 3 * GAME USES DISPLAY OPS FUNDO EQU 4 * GAME USES UNDO FMOUS EQU 5 * GAME USES MOUSE FCOLO EQU 6 * GAME USES (8) COLORS [FOR AMIGA, MAINLY] * * (SEE ALSO THE COLOR BIT IN PVERS2) FSOUN EQU 7 * GAME CONTAINS SOUNDS FMENU EQU 8 * GAME UNDERSTANDS MENU/ITEM EVENT CODES * 9-15 * RESERVED * HLIGHT ARGUMENT: BIT DEFS HLPLAIN EQU 0 * no highlight HLINV EQU 1 * reverse video HLBOLD EQU 2 * bold HLUNDER EQU 4 * underlining HLMONO EQU 8 * [use monospace font] * MICRO'S ID CODE, INTERPRETER VERSION LETTER (SEE ALSO OPVERI) DATA INTWRD DC.B 3 * MACHINE ID FOR MACINTOSH DC.B 3 * THIS YZIP INTERPRETER VERSION [WAS A-Z; NOW 1-255] SUBVER DC.W 0 * INTERPRETER SUB-VERSION, ZERO TO DISABLE CODE * INITIAL SET OF READ BREAK CHARS -- SPACE, TAB, CR, <.>, <,>, DATA IRBRKS DC.B $20,$09,$0D,$2E,$2C,$3F,0 * ASCIZ CODE ZMVERS EQU 6 * 'YZIP' Z-MACHINE VERSION NUMBER STKLEN EQU 512*2 * LENGTH OF GAME STACK (MULTIPLE OF 512) PAGMIN EQU 2 * MINIMUM # PAGES [NEEDED BY $VERIFY] * ---------------------- * ZSTART * ---------------------- ZSTART 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 STRX1 MOVE.L SP,TOPSP(A6) * SAVE THE SP FOR RESTARTS LEA ZVARS,A0 MOVE.L A6,(A0) * COPY A6 FOR EXTERNAL CALLS INTO ZIP ROUTINES *** careful about error msgs before screen & buffers are initialized ... MOVE.W #1,VOCONS(A6) * OUTPUT ERRORS TO SCREEN FOR NOW (NO BUFFER) MOVE.W #1,VIECHO(A6) * INPUT IS NORMALLY ECHOED *** MOVE.W #1,WIND1(A6) * AVOID PUTCHR/TSTSCR (CZIP ONLY) BUG DURING INIT BSR SYSIN1 * OPEN GAME FILE, WINDOW, ETC * SET UP ZIP DEBUGGER (IF REQUESTED) IF DEBUG THEN BSR INITDB * INIT SOME DEBUGGING VARS LEA MSGDBG,A0 BSR OUTMSG * INFORM/REMIND USER DATA MSGDBG DC.B 'ZIP Debugger installed',0 CODE ENDIF *** READ GAME BLOCK 0 INTO A TEMP STACK BUFFER ... SUBA.W #512,SP * CREATE THE BUFFER MOVE.L SP,A4 * SAVE POINTER HERE FOR NOW MOVE.L A4,A0 CLR.W D0 * BLOCK 0 BSR GETBLK * GET IT *** CHECK FOR ID CODE ... CMPI.B #ZMVERS,(A4) * PROPER Z-MACHINE VERSION? BEQ.S STRX3 * YES STRX2 CLR.W D0 * SOMETHING WRONG, DIE LEA MSGZMV,A0 BRA FATAL * 'Wrong Z-machine' DATA MSGZMV DC.B 'Wrong Z-machine version',0 CODE STRX3 MOVE.W PZRKID(A4),ZORKID(A6) * UNIQUE GAME ID, CHECKED BY "RESTORE" 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) * >> here for undo, below << * Allocate an "undo" buffer, if requested. This allocation now comes * BEFORE the preload/paging allocations. It /ought/ to be skipped if * it would leave either () not enough for preload, or () a critically low * (defined in some heuristic way) amount for paging. MOVEQ #0,D1 * ASSUME NO UNDO MOVE.W PFLAGS(A4),D2 BTST #FUNDO,D2 * DOES THIS GAME USE UNDO? BEQ.S STRX3B * NO MOVE.W PURBOT(A6),D0 * BLOCKS ADDQ.L #STKLEN/512,D0 BSR BLKBYT * TOTAL BYTES NEEDED FOR AN UNDO-SAVE BSR GETM * GET IT, WITHOUT ERROR TRAPPING BEQ.S STRX3B * ZERO: NOT ENOUGH MEM, FAILED CLR.W (A0) * OK, MARK THE BUFFER AS EMPTY MOVE.L A0,MSAVEB(A6) * AND STORE PTR MOVEQ #1,D1 * SUCCESS STRX3B MOVEQ #0,D0 * ASSUME NO MENU CAPABILITY BTST #FMENU,D2 * DOES THIS GAME ACCEPT MENU/ITEM CODES? BEQ.S STRX3C MOVEQ #1,D0 * YES STRX3C BSR SETMENU * SET MENU & UNDO FLAGS FOR PASCAL * ALLOC/INIT SOME WINDOW RECORDS (YZIP) MOVEQ #MAXWIND,D1 * TOTAL RECORDS TO CREATE MOVEQ #WBLKLEN,D0 * SPACE FOR ONE BLOCK MULU D1,D0 * ALLOC A BIG BLOCK [CLEARING IT FOR THE SAKE OF WATTR/SCRIPT BIT] BSR GETMEMC LEA WBLOCKP(A6),A1 INIWX1 MOVE.L A0,(A1)+ * STORE ALL THE POINTERS ADDA.W #WBLKLEN,A0 SUBQ.W #1,D1 BGT.S INIWX1 BSR INITWB * THEN, INIT EACH RECORDS *** CHECK MEMORY, SET ENDLOD & PAGTOT, DO PRELOAD STRX4 BSR MEMAVAIL * DETERMINE HOW MUCH FREE MEMORY EXISTS MOVE.L D0,D7 * REMEMBER THE AMOUNT MOVEQ #0,D0 MOVE.W PLENTH(A4),D0 * LENGTH OF GAME FILE (WORDS/QUADS/OCTS) ADD.L D0,D0 IF EZIP THEN ADD.L D0,D0 MOVE.W PFOFF(A4),D1 * IS THIS IS A MOBY GAME? ADD.W PSOFF(A4),D1 BEQ.S STRX4A * IF BOTH ZERO, NO ADD.L D0,D0 * YES, LENGTH WAS AN OCT-WORD STRX4A ENDIF IF DEBUG THEN MOVE.L D0,D1 BSR BYTBLK * TOTAL BLOCKS IN GAME FILE MOVE.W D0,MAXLOD(A6) * SAVE FOR DEBUGGING MOVE.L D1,D0 ENDIF CMP.L D7,D0 * ENOUGH ROOM TO PRELOAD ENTIRE GAME? BLT.S LOAD1 * YES MOVEQ #0,D0 MOVE.W PENDLD(A4),D0 * LENGTH OF PRELOAD SEGMENT (BYTES) CMP.L D7,D0 * ENOUGH ROOM FOR IT? BLT.S LOAD2 * YES BRA MEMERROR * NO, FAIL * WE HAVE MEGA-MEMORY, PRELOAD EVERYTHING ... LOAD1 BSR BYTBLK * LENGTH OF GAME FILE (IN BLOCKS) MOVE.W D0,ENDLOD(A6) * MAXIMIZE THE PRELOAD MOVE.W #PAGMIN,PAGTOT(A6) * MINIMIZE THE PAGING SPACE (FOR $VER) MOVE.W #1,MAXFLG(A6) * SET FLAG BRA.S LOAD3 * WE HAVE LIMITED MEMORY, PRELOAD ONLY WHAT'S NEEDED LOAD2 SUB.L D0,D7 * FIRST DETERMINE MEMORY LEFT AFTER PRELOAD BSR BYTBLK MOVE.W D0,ENDLOD(A6) * LENGTH OF PRELOAD (IN BLOCKS) DIVU #512+8,D7 * PAGES AVAIL (ALLOW 8 BYTES PER TABLE ENTRY) CMPI.W #2,D7 BGE.S LOADX1 MOVEQ #2,D7 * MUST HAVE AT LEAST TWO (FOR $VERIFY) LOADX1 MOVE.W D7,PAGTOT(A6) * MAXIMIZE THE PAGING SPACE LOAD3 MOVE.W ENDLOD(A6),D0 * SPACE NEEDED FOR PRELOAD, IN BLOCKS BSR BLKBYT * CONVERT TO BYTES BSR GETMEM * GET IT MOVE.L A0,BUFFER(A6) * SAVE POINTER MOVE.L A0,A4 * ALSO HERE FOR REMAINING INIT MOVE.W ENDLOD(A6),D1 * NUMBER OF BLOCKS TO PRELOAD CLR.W D0 * STARTING WITH BLOCK 0 BSR GTBLKS * READ THEM IN *** CLR.W WIND1(A6) * RESTORE NORMAL VALUE (AFTER PREV KLUGE) * ------------------------------------------------------------------------ *** INITIALIZE MAJOR TABLE POINTERS STRX6 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) BSR EZERR * CHECK OBJTAB ALIGNMENT 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) * AND SEGMENT OFFSETS MOVEQ #0,D0 MOVE.W PFOFF(A4),D0 * OFFSET OF FUNCTION AREA ("OCTS") ADD.L D0,D0 * STORE AS QUADS (LONG) MOVE.L D0,QFOFF(A6) MOVEQ #0,D0 MOVE.W PSOFF(A4),D0 * OFFSET OF STRING AREA ("OCTS") ADD.L D0,D0 * STORE AS QUADS (LONG) MOVE.L D0,QSOFF(A6) *** 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 MAXLEN EQU 160 * MAX LENGTH OF LINE BUFFER (BYTES) SCRLEN EQU 65 ** 80 * LENGTH OF SCRIPT BUFFER (BYTES) BSR MAXSCRN * FULL SCREEN WIDTH (UNITS) MOVE.W D1,D2 MOVE.W #MAXLEN,D1 * (BYTES) LEA LINOUT,A1 * SCREEN DISPLAY FUNCTION LEA DCHSIZ,A2 BSR INITQP * SET UP DISPLAY QUEUE STUFF MOVE.L A0,DQUE(A6) * SAVE BLOCK POINTER MOVE.W #SCRLEN,D1 * SCRIPTING WIDTH, NEVER CHANGES MOVE.W D1,D2 LEA SCROUT,A1 * SCRIPTING DISPLAY FUNCTION LEA SCHSIZ,A2 BSR INITQP * SET UP SCRIPT QUEUE STUFF MOVE.L A0,SQUE(A6) * SAVE THIS POINTER TOO * AND SET UP MACBUF ... * ALLOCATE AND SET UP BREAK-CHAR TABLE MOVE.L #64,D0 * MAX BREAK CHARS BSR GETMEM * ALLOCATE BUFFER FOR BREAK-CHAR TABLE MOVE.L A0,RBRKS(A6) MOVE.L VOCTAB(A6),A1 * (DEFAULT) VOCAB TABLE CLR.W D0 MOVE.B (A1)+,D0 * FIRST BYTE OF VOCTAB IS # OF SI BREAK CHARS BRA.S STRX11 * (ZERO CHECK) STRX10 MOVE.B (A1)+,(A0)+ * TRANSFER SI BREAKS FIRST STRX11 DBF D0,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 STRX12 * ASCIZ *** 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 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) * CHECK FOR CUSTOM CHARSET TABLE (NOW THAT PAGING IS SET UP!) MOVE.W PCHRSET(A4),D0 * CUSTOM TABLE PTR BEQ.S STRX18 * IF NONE, USE INTERPRETER DEFAULTS BSR BSPLTB * SPLIT THE BYTE POINTER LEA ZCHRS,A2 * DEFAULT TBL (IN INTERPRETER DATA SPACE) MOVEQ #(26*3)-1,D3 * TABLE LENGTH (IMPLICIT) STRX17 BSR GETBYT * UPDATE D0/D1, RESULT IN D2 MOVE.B D2,(A2)+ * COPY ONE ITEM DBF D3,STRX17 * INITIALIZE THE RANDOM NUMBER SEEDS STRX18 BSR GTSEED MOVE.W D0,RSEED1(A6) SWAP D0 MOVE.W D0,RSEED2(A6) * PUT HIGH WORD HERE, "RELATIVELY CONSTANT" MOVE.W #1,VOBUFF(A6) * BEGIN BUFFERING OUTPUT BSR ENDTITLE * PAUSE FOR TITLE SCREEN, IF SHOWING BRA.S START1 * ---------------------- * RESTRT * ---------------------- * 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 FLAGS BSR INITWB * RE-INIT WINDOW RECORDS START1 MOVE.L TOPSP(A6),SP * RESET 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/FRAME MOVE.L BUFFER(A6),A2 ORI.B #2,PVERS2(A2) * DISPLAY OP IS AVAILABLE ORI.B #32+16+8+4,PVERS2(A2) * SOUND, MONOSPACE, ITALIC, BOLD BSR INITDISP * GET/STORE TTY-SPECIFIC LOWCORE VARS MOVE.W INTWRD,PINTWD(A2) * SET INTERPRETER ID/VERSION WORD CLR.W RCYCLE(A6) * ALWAYS RESTART WITH NORMAL RANDOMNESS MOVE.W #1,MSWIND(A6) * YZIP: INITIALLY CONSTRAIN MOUSE TO W1 MOVEQ #0,D0 MOVE.W PSTART(A2),D0 * BYTE/QUAD PTR TO STARTING LOCATION MOVE.L QFOFF(A6),D1 * QUAD FUNC OFF -- IS THIS IS A MOBY GAME? *** "NOW ALWAYS A FUNC PTR, EVEN IF QFOFF = 0" * BNE.S STA1X1 * YES * BSR BSPLTB * SPLIT INTO BLOCK AND BYTE * BRA.S STA1X2 STA1X1 BSR BSPLTQ2 * SPLIT INTO BLOCK AND BYTE ADDQ.W #1,D1 * AND SKIP OVER #LOCS BYTE STA1X2 MOVE.W D0,ZPC1(A6) * INITIALIZE THE ZPC MOVE.W D1,ZPC2(A6) BSR NEWZPC * GET THE PAGE TO EXECUTE * SYSIN2 SHOULD BE THE /LAST/ CALL BEFORE NXTINS, BECAUSE OF STACK HACKING * (FOR KLUDGY TIMEOUTS) IN OPREST. BSR SYSIN2 * MAC -- BUT LOAD A SAVED GAME IF REQUESTED BRA NXTINS * TALLY HO * ---------------------- * INITWB * ---------------------- * INITIALIZE (OR RE-INITIALIZE) ALL WINDOW RECORDS (ALREADY ALLOC'ED) INITWB MOVEM.L D1-D2/A1-A2,-(SP) LEA WBLOCKP(A6),A2 MOVEQ #MAXWIND,D2 * TOTAL RECORDS TO INIT INWBX2 MOVE.L (A2)+,A0 * NEXT REC BSR IWBONE SUBQ.W #1,D2 BGT.S INWBX2 * THEN DO SOME SPECIAL INITS FOR THE FIRST TWO WINDOWS BSR MAXSCRN * GET D0.W = ROWS, D1.W = COLS LEA WBLOCKP(A6),A2 MOVE.L (A2)+,A0 * GET POINTER TO WINDOW 0 RECORD MOVE.W D0,WYSIZE(A0) * W0 GETS SEVERAL SPECIAL INIT VALS MOVE.W D1,WXSIZE(A0) ORI.W #WFWRAP+WFSCRL+WFSCRP,WATTR(A0) MOVE.L A0,CURWP(A6) * THIS IS INITIAL RECORD POINTER CLR.W CURWIND(A6) * AND INITIAL WINDOW MOVE.L (A2)+,A0 * GET POINTER TO WINDOW 1 RECORD MOVE.W D1,WXSIZE(A0) * W1 GETS ONE SPECIAL INIT VAL MOVEM.L (SP)+,D1-D2/A1-A2 RTS * ---------------------- * IWBONE * ---------------------- * INIT ONE RECORD, A0 -> BLOCK, USES A1/D1 IWBONE MOVE.L A0,A1 * SAVE HERE MOVE.W WATTR(A1),-(SP) * PRESERVE THE SCRIPTING FLAG, ETC MOVEQ #WBLKLEN,D0 IWB1X1 CLR.B (A0)+ * ZERO THE BLOCK SUBQ.W #1,D0 BNE.S IWB1X1 MOVE.W (SP)+,WATTR(A1) * [CLEARED AT INITIAL ALLOC ONLY] * INIT ALL NON-ZERO SLOTS MOVEQ #1,D0 MOVE.W D0,WYPOS(A1) * EACH WINDOW LIVES INITIALLY AT 1,1 MOVE.W D0,WXPOS(A1) MOVE.W D0,WYCURS(A1) * CURSOR INITIALLY AT UPPER LEFT MOVE.W D0,WXCURS(A1) MOVE.W D0,WFONTID(A1) * INITIALLY FONT #1 BSR GETFYX * GET (DEFAULT) FONT SIZE MOVE.W D0,WFONTYX(A1) MOVEQ #0,D0 * GET DEFAULT COLORS MOVEQ #0,D1 BSR MDCOLOR MOVE.W D0,WCOLOR(A1) * (BACK/FORE) ORI.W #WFBUFF,WATTR(A1) * BUFFERING ON RTS * ---------------------- * INITDISP * ---------------------- * GET/STORE TTY-SPECIFIC LOWCORE VARS * [MAY CHANGE BETWEEN MAC & MACII -- ALSO CALLED AFTER RESTORE] INITDISP MOVEM.L D1-D3/A2,-(SP) MOVE.L BUFFER(A6),A2 BSR GETFYX MOVE.W D0,PFWRD(A2) * FONT SIZE, HEIGHT/WIDTH (PIXELS) *** MOVE.W D0,D2 *** ROR.W #8,D2 * SWAP BYTES (BUG IN YZIP20) *** MOVE.W D2,PFWRD(A2) ** PFWRD/PVWRD/PHWRD DEAD IN 'YZIP', BUT KEEP FOR NOW, FOR BACKWARD COMPAT ... MOVE.W D0,D2 MOVE.W D0,D3 LSR.W #8,D2 * UNPACK HEIGHT ANDI.W #$FF,D3 * UNPACK WIDTH BSR MAXSCRN * SCREEN SIZE, PIXELS MOVE.W D0,PVWRD(A2) MOVE.W D1,PHWRD(A2) EXT.L D0 DIVU D2,D0 LSL.W #8,D0 * ROWS (ROUNDED DOWN) IN HIGH BYTE EXT.L D1 DIVU D3,D1 MOVE.B D1,D0 * COLUMNS IN LOW MOVE.W D0,PSCRWD(A2) * SCREEN SIZE, CHARS * INIT COLOR STUFF TOO MOVEQ #0,D0 * GET DEFAULT COLORS (OR BLACK/WHITE) MOVEQ #0,D1 BSR MDCOLOR MOVE.W D0,PCLRWRD(A2) * (BACK/FORE) TST.W D1 * COLOR MACHINE? BEQ.S IDSPX8 * NO ORI.B #1,PVERS2(A2) * YES, COLOR IS AVAILABLE BSET #FCOLO,PFLAGS+1(A2) * [ALSO ADJUST THIS BIT] BRA.S IDSPX9 IDSPX8 ANDI.B #$FE,PVERS2(A2) * (FORCE BIT -> 0) BCLR #FCOLO,PFLAGS+1(A2) IDSPX9 MOVEM.L (SP)+,D1-D3/A2 RTS * ---------------------- * EZERR * ---------------------- IF EZIP THEN * FOR EZIP/XZIP, MAKE SURE D0.L = OBJ TABLE BASE IS WORD ALIGNED EZERR BTST #0,D0 * WORD ALIGNED? BNE.S EZERX1 * NO, FAIL RTS EZERX1 CLR.W D0 LEA MSGEZR,A0 BRA FATAL * 'OBJTAB align err' DATA MSGEZR DC.B 'OBJTAB align err',0 CODE ENDIF EJECT ; PAGE * --------------------------------------------------------------------------- * MISC FUNCTIONS * --------------------------------------------------------------------------- * ------------------------------ * COPYB * ------------------------------ * COPY BYTES * GIVEN A0 -> SRC, D0 = LEN, A1 -> DEST CPBX1 MOVE.B (A0)+,(A1)+ * COPY THEM COPYB DBF D0,CPBX1 * ZERO CHECK << ENTRY POINT >> RTS * ------------------------------ * COPYS * ------------------------------ * COPY A STRING, AND TACK ON A NULL BYTE * GIVEN A0 -> SRC, A1 -> DEST, D0 = LEN, D1 = MAX LEN COPYS CMP.W D1,D0 * LEN WITHIN MAX? BLE.S CPSX1 MOVE.W D1,D0 * NO, TRUNCATE IT CPSX1 BRA.S CPSX3 * ZERO CHECK CPSX2 MOVE.B (A0)+,(A1)+ CPSX3 DBF D0,CPSX2 CLR.B (A1) * ASCIZ RTS * -------------------------- * COMPS * -------------------------- * COMPARE STRINGS, PTRS IN A0 AND A1, LENGTHS IN D0.W * RETURN FLAGS, 'EQ' IF SAME COMPS TST.W D0 BLE.S CMPSX4 * ZERO CHECK CMPSX2 CMP.B (A0)+,(A1)+ BNE.S CMPSX4 * MISMATCH, RETURN "DIFFERENT" SUBQ.W #1,D0 BNE.S CMPSX2 * IF DONE, RETURN "SAME" CMPSX4 RTS * ---------------------- * STRLEN * ---------------------- * FIND LENGTH OF AN NULL-TERMINATED STRING, POINTER IN A0 * RETURN POINTER IN A0, LENGTH IN D0 STRLEN MOVE.L A0,-(SP) * SAVE START STRLX1 TST.B (A0)+ * SEARCH FOR NULL BNE.S STRLX1 MOVE.L A0,D0 * FOUND IT SUBQ.L #1,D0 * BACKUP TO THE NULL MOVE.L (SP)+,A0 * RETURN ORIGINAL POINTER SUB.L A0,D0 * RETURN LENGTH RTS * ------------------------------ * RELABS [RRELABS] * ------------------------------ * CONVERT A RELATIVE (BYTE) OFFSET (D0.W) TO AN ABSOLUTE PTR (A0) RELABS MOVE.L BUFFER(A6),A0 *** CMP.W PPURBT(A0),D0 * MAX FOR READ/WRITE CMP.W PENDLD(A0),D0 * MAX FOR READ-ONLY (USED BY OPLEX!) BHI.S RLBSX2 * REQUEST TOO HIGH RLBSX1 SWAP D0 CLR.W D0 * ZERO THE HIGH WORD (NO SIGN-EXTENDING) SWAP D0 * [14 cycles vs 16] ADDA.L D0,A0 * ABSOLUTIZE IT RTS RLBSX2 LEA MSGRLB,A0 *** CLR.W D0 BRA FATAL DATA MSGRLB DC.B 'Out of range in RELABS',0 CODE * ---------------------- * BLKBYT * ---------------------- * 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 * ---------------------- * BYTBLK * ---------------------- * GIVEN A BYTE COUNT IN D0.L, RETURN A ZIP BLOCK COUNT IN D0.W, ROUNDING UP BYTBLK MOVE.W D0,-(SP) * SAVE LOW WORD LSR.L #8,D0 LSR.L #1,D0 * EXTRACT BLOCK NUMBER ANDI.W #$01FF,(SP)+ * EXACT MULTIPLE OF 512? BEQ.S BYTBX1 * YES ADDQ.W #1,D0 * NO, ROUND UP TO NEXT BLOCK BYTBX1 RTS * ---------------------- * LOWCORE * ---------------------- * USE THIS ROUTINE TO ACCESS LOW-CORE EXTENSION-TABLE VARS * GIVEN D0 = VAR (WORD OFFSET) * RETURN A0 (MAY BE ODD) -> VAR, AND FLAGS (ZERO IF INVALID VAR) LOWCORE MOVEM.L D1,-(SP) MOVE.W D0,D1 MOVE.L BUFFER(A6),A0 MOVEQ #0,D0 * GET EXTENSION TABLE OFFSET (MAY BE >32K, ODD) MOVE.W PLCTBL(A0),D0 * EXISTS? BEQ.S LWCX1 * NO, ERROR ADDA.L D0,A0 * TABLE BASE BSR GTAWRD * TABLE LEN (WORDS) CMP.W D0,D1 * ENOUGH? BGT.S LWCX1 * NO, ERROR SUBQ.L #2,A0 ADD.W D1,D1 * BYTE OFFSET ADDA.W D1,A0 * POINT TO DESIRED VAR BRA.S LWCX2 * NONZERO FLAGS LWCX1 MOVEQ #0,D0 * ZERO FLAGS LWCX2 MOVEM.L (SP)+,D1 * DON'T DISTURB FLAGS RTS * ---------------------- * GTAWRD * ---------------------- * 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 * ---------------------- * PTAWRD * ---------------------- * WRITE WORD TO CORE, ABSOLUTE POINTER IN A0, VALUE IN D0, UPDATE A0 PTAWRD MOVE.B D0,1(A0) * STORE LOW-ORDER BYTE ASR.W #8,D0 MOVE.B D0,(A0) * STORE HIGH-ORDER BYTE ADDQ.L #2,A0 RTS * --------------------------------------------------------------------------- * LOW LEVEL ZIP FUNCTIONS * --------------------------------------------------------------------------- * ---------------------- * GETBYT * ---------------------- * 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 * ---------------------- * GETWRD * ---------------------- * 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 * ---------------------- * NXTBYT * ---------------------- * 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 * ---------------------- * NXTWRD * ---------------------- * 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 * ---------------------- * GETARG * ---------------------- * 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 * ---------------------- * GETVAR * ---------------------- * 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 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 * ---------------------- * PUTVAR * ---------------------- * 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 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 * ---------------------- * PUTVAL, BYTVAL * ---------------------- * 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 * ---------------------- * PFALSE, PTRUE * ---------------------- * 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 * ---------------------- * BSPLTB * ---------------------- * 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) IF DEBUG THEN CMP.W MAXLOD(A6),D0 * VALID BLOCK NUMBER? BCC BLKERR * BHS * NO, FAIL ENDIF RTS * ---------------------- * BSPLIT * ---------------------- * 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 IF DEBUG THEN CMP.W MAXLOD(A6),D0 * VALID BLOCK NUMBER? BCC BLKERR * BHS * NO, FAIL ENDIF RTS * ---------------------- * BSPLTQ * ---------------------- * SPLIT QUAD-POINTER IN D0.W * INTO BLOCK NUMBER IN D0.W & BYTE OFFSET IN D1.W -- 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 ** IF DEBUG THEN ** CMP.W MAXLOD(A6),D0 * VALID BLOCK NUMBER? ** BCC BLKERR * BHS * NO, FAIL ** ENDIF ** RTS * ---------------------- * BSPLTQ2 * ---------------------- * COMBINE/SPLIT QUAD-POINTERS IN D0.L AND D1.L * INTO BLOCK NUMBER IN D0.W & BYTE OFFSET IN D1.W -- EZIP ONLY BSPLTQ2 ADD.L D1,D0 MOVE.W D0,D1 LSR.L #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 IF DEBUG THEN CMP.W MAXLOD(A6),D0 * VALID BLOCK NUMBER? BCC BLKERR * BHS * NO, FAIL ENDIF RTS * ---------------------- * BLKERR * ---------------------- IF DEBUG THEN BLKERR LEA MSGBLK,A0 BRA FATAL * 'Block range error' DATA MSGBLK DC.B 'Block range error',0 CODE ENDIF