Files
erkyrath.infocom-zcode-terps/ibm/sysini.ezp
Andrew Plotkin b642da811e Initial commit.
2023-11-16 18:19:54 -05:00

379 lines
13 KiB
Plaintext

SUBTTL SYSINI - HIGH LEVEL IBMPC DEPENDENT STUFF
PAGE
;SYSTEM INITIALIZATION
; SYSINI HAS BEEN GREATLY MODIFIED TO INCLUDE DOS 2.0 FILE HANDLING,
; COMMAND LINE ARGUMENTS, COPY PROTECTION, AND DYNAMIC ALLOCATION OF
; PAGING SPACE.
;
; THE COPY PROTECTION SCHEME WORKS AS FOLLOWS: A NUMBER OF COMPUTERS ARE
; DEFINED AS COMPATIBLE WITH IBM IN THE DATA DECLARATIONS. INCLUDED FOR
; EACH IS THE FIRST 9 LETTERS OF THE COPYRIGHT NOTICE THAT EXISTS IN THE
; ROM. IF ANY OF THESE STRINGS IS FOUND IN THE ROM, COPY PROTECTION IS
; CHECKED, OTHERWISE IT IS NOT. IBM COMPATIBILITY MEANS TOTAL ROM BIOS
; COMPATIBILITY SUCH THAT WINDOWED SCROLLING AND SPECIAL DISK I/O MAY BE
; PERFORMED. NOT FINDING ANY OF THESE STRINGS RESULTS IN THE ZIP FUNCTIONING
; AS IF IT WERE ON A GENERIC MS-DOS BASED MACHINE.
;
; COMMAND LINE ARGUMENTS SET BITS IN THE VARIABLE CMDLIN IN THE ROUTINE
; SCANCMD. CMDLIN THEN AFFECTS VARIOUS PARAMETERS AND VARIABLES EITHER IN
; SYSINI OR SSETUP.
;
; THE PAGTAB IS SET UP ACCORDING TO AVAILABLE MEMORY. THERE EXISTS A WORD
; AT OFFSET 2 IN THE PSP (PROGRAM SEGMENT PREFIX, OR WHERE CS POINTS) WHICH
; INDICATES THE TOP OF PHYSICAL MEMORY. PAGTAB REPRESENTS THE LAST WORD USED
; BY THE ZIP. THE CODE SEGMENT REPRESENTS THE AMOUNT OF MEMORY TAKEN UP BY
; EVERYTHING UNDER THE ZIP SUCH AS THE OPERATING SYSTEM AND DEVICE DRIVERS.
; IF WE CONVERT PAGTAB TO PARAGRAPHS, THEN ALL OF THESE NUMBERS ARE IN
; PARAGRAPHS. SO:
;
; TOP_OF_MEM - (CS + PAGTAB) --> AVAILABLE MEMORY IN PARAGRAPHS
;
; AVAILABLE MEMORY IS CONVERTED INTO THE NUMBER OF BUFFERS AVAILABLE. FROM
; THIS NUMBER WE MUST SUBTRACT 1 OR 2 BUFFERS TO ALLOW FOR THE PAGTAB TO
; BE BUILT. KNOWING AVAILABLE BUFFERS TELLS US THE LENGTH OF OUR PAGTAB
; SINCE OUR PAGTAB IS 4 BYTES/BUFFER. AT THE NEXT PARAGRAPH BOUNDARDY BEYOND
; THE PAGTAB WE HAVE OUR FIRST GAME SEGMENT WHICH WILL BE MOVED TO ES AND
; STORED IN THE VARIABLE GAMESEG. ADDING 64K (IN PARAGRAPHS) TO GAMESEG
; WE ARRIVE AT OUT LOCATION FOR SEG1, THE SECOND GAME SEGMENT. THE PAGTAB
; IS THEN INITIALIZED.
;
PUBLIC SYSINI,SYS1,INITLP,SYSFTL,GOODOS,GODOS1
SYSINI PROC
MOV AH,DOSVER ; (7) GET DOS VERSION #
INT 21H ; (7) MUST BE 2.0 OR HIGHER
CMP AL,2 ; (7) DOS 2.0+
JGE GOODOS
FATAL FTL11 ; (7) DIE APPROPRIATELY
; ESTABLISH THE IBMNESS OF THE HOST
GOODOS: MOV IBMPC,0 ; (A9) PRESET TO NOT AN IBM
PUSH ES ; (A9)
PUSH DI ; (A9)
MOV BX,0F000H ; (A9) SEGMENT
MOV ES,BX ; (A9) LOAD THE SEGMENT
MOV DI,0E000H ; (A9) ES:DI OFFSET
MOV AX,OFFSET IBMSTR ; (A9) ^ IBM STRING
MOV CX,16H ; (A9) NO. CHARACTERS TO SEARCH
MOV DX,9 ; (A9) NO. OF CHARACTERS
CALL CHK ; (A9) SEE IF THIS IS AN IBM
POP DI ; (A9) RESTORE THOSE REGISTERS
POP ES ; (A9)
JC GODOS1 ; (A9) CARRY SET = IT'S NOT AN IBM
MOV IBMPC,1 ; (A9) SET FLAG TO INDICATE AN IBM
GODOS1: MOV AH,CURDSK ; (6) GET DEFAULT DRIVE
INT 21H ; (6) FROM DOS
MOV DEFDRV,AL ; (6) SAVE DEFAULT DRIVE
MOV CURDRV,AL ; (6) SAVE DEFAULT DRIVE
CALL SCANCMD ; (7) GET CMD LINE VARS
GOTONE: MOV SCROLL,0 ; (7) USE WINDOWED SCROLLING
NOCMD: MOV AH,CFOPENZ ; (6) ASCIZ STRINGS
MOV AL,0 ; (6) OPEN FOR READING
MOV DX,OFFSET GAMFILE
INT 21H
JNC SYSA$
JMP SYSFTL
SYSA$: MOV GAMHNDL,AX ; (6) SAVE THE FILE HANDLE
MOV BX,AX ; (7n) GET FILE HANDLE INTO BX
XOR CX,CX ; (7n) ZERO THESE
XOR DX,DX ; (7n) TO FIND EOF
MOV AH,CFSEEK ; (7n) SEEK TO END OF FILE
MOV AL,2 ; (7n) MOVE FILE PTR TO EOF
INT 21H ; (7n) DO IT
MOV CX,4 ; (7n) CONVERT AX TO PARAGRAPHS
SYSA0: SHR AX,1 ; (7n) TO SAVE AS FILESIZE
TEST DX,1 ; (A0) TEST HIBIT
JNZ SYSA1
SYSA2: SHR DX,1 ; (A0) MOVE HIWORD TOO
LOOP SYSA0
JMP SYSB$
SYSA1: OR AH,80H ; (7n) TURN ON THAT BIT
JMP SYSA2
SYSB$: MOV CL,5 ; (7n) REDUCE TO NUMBER OF 512 BLKS
SHR AX,CL ; (7n) FOR COMPARISON TO BUFFERS
MOV GAMESIZ,AX ; (7n) SAVE THIS SIZE FOR FITS
XOR CX,CX ; (7w) MOVE POINTER TO BOF
MOV DX,4 ; (7w) WE WANT THE WORD AT OFFSET 4
MOV AH,CFSEEK ; (7w) SEEK THERE
MOV AL,0 ; (7w) METHOD: OFFSET FROM BOF
INT 21H ; (7w) BX HAS FILE HANDLE
MOV AH,CRDRNDZ ; (7w) READ IN THE FIRST
MOV CX,2 ; (7w) READ THE WORD OF ENDLOD
MOV DX,OFFSET SSBUF ; (7w) ANY BUFFER BIG ENOUGH WILL DO
INT 21H ; (7w) READ IT
MOV AX,SSBUF ; (7w) GET THE WORD
XCHG AH,AL ; (7w) FLOP THE BYTES
TEST AX,1FFH ; (7w) ROUND UP TO NEXT BLOCK
JE SYSC$
AND AX,0FE00H ; (7w) TURN OF LOW BITS
ADD AX,200H ; (7w) ADD A BLOCK
SYSC$: MOV CL,9 ; (7w) CONVERT TO NUMBER OF BLOCKS
SHR AX,CL
MOV DX,AX ; (7w) AND SAVE NUMBER IN DX
MOV BX,2 ; (6) GET TOP OF MEMORY
MOV BX,CS:[BX] ; (6) FROM OUT OF THE PSP
MOV AX,CS ; (6) GET CODE SEG
SUB BX,AX ; (6) SUB CSEG FROM TOPMEM
MOV CL,4 ; (6) SHIFT COUNT
MOV AX,OFFSET PAGTAB ; (6) USE OFFSET TO FIGURE PARAG'S
SHR AX,CL ; (6) REDUCE THIS OFFSET TO PARAS
INC AX ; (6) SKIP ONE PARAGRAPH
AND AX,0FE0H ; (7z) BLOCKIFY THIS NUMBER
ADD AX,20H ; (7z) OTHERWISE LOSE A PAGE
SUB BX,AX ; (6) YIELDS PARAS AVAILABLE
TEST CMDLIN,4 ; (7) SET ON CMDLIN?
JZ SYS2
CMP BX,MEMORY ; (7) REASONABLE REQUEST
JBE SYS2 ; (7) NO, NOT REALLY THERE
MOV BX,MEMORY ; (7) USE USER SETTING
SYS2: CMP BX,MINMEM ; (7) AT LEAST 48K?
JAE SYS3 ; (7) YES
FATAL FTL12 ; (7) DIE APPROPRIATELY
SYS3: MOV CL,5 ; (6) DIVIDE BY 32 TO GET BUFFERS
SHR BX,CL ; (6) TO GET #BUFFERS
CMP BX,GAMESIZ ; (A0) IF LESS THEN NO PAGTAB NECES
JGE SYS4 ; (A0) SET THE FLAGS
SUB BX,DX ; (7w) SUBTRACT ALL PRELOD BLOCKS
JA SYS3A ; (A3) FATAL IF MORE PRELOD THAN BLKS
SYS3$: FATAL FTL12 ; (A3) SO DIE
SYS3A: CMP BX,5 ; (A3) THERE MUST BE AT LEAST 2 BUFS
JBE SYS3$ ; (A3) SO DIE IF NOT ENOUGH
SUB BX,4 ; (A0) SUB 4 BUFS FOR PAGTAB
CMP BX,255 ; (6) ABOVE 256, WE NEED MORE TBL
JB SYS1 ; (6) WE HAVE THIS MANY OR FEWER
SUB BX,2 ; (6) TAKE AWAY ANOTHER PAGE
CMP BX,383 ; (A0) ARE WE BETWEEN 3 AND 4 SEGS
JB SYS1 ; (A0) CHECK FOR FIT
SUB BX,2 ; (A0) WE GOT PLENTY, NEED 2 BUFFS
CMP BX,511 ; (6) THIS IS THE MOST WE WILL NEED
JLE SYS1 ; (6) DON'T MODIFY BX <= 255
MOV FITS,1 ; (6) FLAG THAT GAME FITS IN MEMORY
MOV BX,511 ; (6) DON'T ALLOW MORE THAN THIS
SYS1: PUSH BX ; (7w) SAVE THIS FOR FIDDLING
ADD BX,DX ;(7w) ADD IN THE BLOCKS PREV SBTRCTED
CMP BX,GAMESIZ ; (7n) CHECK FOR LUCKY FIT
POP BX ; (7w) AND RESTORE ACTUAL #BUFFERS
JBE SYSD$ ; (7n) IF BX IS GREATER, NO GO
SYS4: MOV FITS,1 ; (7n) IT DOES FIT AFTERALL!!!
MOV BX,OFFSET PAGTAB
JMP SYS5
SYSD$: MOV BUFFERS,BX ; (6) SAVE THIS NUMBER
MOV CL,3 ; (A0) MULTIPLY BUFFERS BY 8
SHL BX,CL ; (6) GET NUMBER OF BYTES IN PAGTBL
ADD BX,2 ; (A0) ADD 2 FOR TERMINATOR WORD
ADD BX,OFFSET PAGTAB ; (6) CALC TABLE LOCATION
SYS5: MOV CX,4 ; (6) REDUCE #BYTES IN TABLE = PARAS
SHR BX,CL ; (6) TO DYNAMICALLY ALLOCATE SPACE
MOV AX,DS ; (6) GET A COPY OF CURRENT SEG
ADD BX,AX ; (6) AND CALCULATE THE NEW SEG
ADD BX,1 ; (6) ADD ONE PARAGRAPH FOR SAFETY
MOV GAMESEG,BX ; (6) THIS WILL BE USED FOR ES:GAME
ADD BX,1000H ; (6) ADD 64K TO CALC 2ND SEG
MOV SEG1,BX ; (6) THIS IS SEG0+64K
TEST FITS,1 ; (A0) DON'T INIT A NON-EXISTANT TBL
JNZ SYS6
CALL TBLINI ; (7n) CALL TABLE INITIALIZATION
SYS6: CALL SSETUP
CALL INITSND ; (A0) INITIAL TIMER2 FOR SOUND
MOV AX,GAMESEG ; (A0) SET ES TO GAME SEG
MOV ES,AX
RET
SYSFTL: FATAL FTL9
SYSINI ENDP
; THIS ROUTINE INITIALIZES THE PAGE TABLE
;
TBLINI PROC
PUSH SI ; SAVES
PUSH DI
PUSH AX
PUSH BX
PUSH CX
MOV DI,OFFSET PAGTAB ; (6) GET BEGINNING ADDR
MOV CX,WORD PTR BUFFERS ; (6) GET NUMBER OF ENTRIES
MOV AX,DS ; (7)GET DATA SEG
MOV ES,AX ; (7) FIX ES
CLD ;(6) AUTO INCREMENT
INITLP: MOV SI,OFFSET INITTBL ; (6) POINT TO STRING TO INITIALIZE
PUSH CX ; (6) SAVE REP COUNT
MOV CX,8 ; (6) GET INNER LOOP COUNT
REP MOVSB ; (6) TRANSFER THE STRING TO TBL
POP CX ; (6) RESTORE COUNT
LOOP INITLP ; (6) AND FINISH TABLE INITIALIZING
MOV WORD PTR [DI],-1 ; (6) DEPOSIT A -1 TO INDICATE END
MOV BX,GAMESEG ;
MOV ES,BX ; (6) SET THE EXTRA SEG TO GAMESEG
POP CX ; RESTORES
POP BX
POP AX
POP DI
POP SI
RET
TBLINI ENDP
PUBLIC GAMOPEN
; THIS PROCEDURE OPENS THE GAME FILE AFTER CLOSING ALL FILES.
; IF THE GAME FILE IS NOT ON THE DISK, IT PROMPTS FOR REINSERTION
GAMOPEN PROC
PUSH DX
MOV DL,DEFDRV ; (7o) GET DRIVE WHERE GAME IS
MOV AH,CSELDSK ; (7o) TO MAKE OPEN WIN
INT 21H ; (7o) DO IT
MOV AH,CFCLOSZ ; (7s) TRY CLOSING INSTEAD OF RESET
MOV BX,GAMHNDL ; (7s) OF THE GAME FILE
INT 21H ; (7o) TO MAKE SURE THIS WINS
GOPEN0: MOV AH,CFOPENZ ; (6) ASCIZ STRINGS
MOV AL,0 ; (6) OPEN FOR READING
MOV DX,OFFSET GAMFILE ; (7o) OPEN THE FILE AGAIN
INT 21H
JNC GOPEN1 ; (7o) IF SUCCESS, CONTINUE
PRINT SAV3 ; (7o) OTHERWISE PROMPT
CALL MCHRI ; (7o) AND WAIT FOR A CHARACTER
JMP GOPEN0 ; (7o) AND LOOP
GOPEN1: MOV GAMHNDL,AX ; (7o) SAVE GAME HANDLE
MOV DL,CURDRV ; (7v) RESTORE SAVE DRIVE
MOV AH,CSELDSK ; (7v) SO THAT WE ARE NOT CONFUSED
INT 21H ; (7v) THANKS MAX
POP DX
RET
GAMOPEN ENDP
; GIVEN SOURCE PTR IN DS:AX, AND A DEST PTR IN ES:DI, CHK SEARCHES
; FOR THE DX CHARACTERS OF THE STRING POINTED TO BY DS:AX IN THE
; FIRST (CX) BYTES OF THE STRING POINTED TO BY ES:DI
PUBLIC CHK
CHK PROC
CLD ; (7) CLEAR THE DIRECTION FLAG
PUSH SI ; (7) SAVE THIS
PUSH DX ; (7) SAVE THIS FOR RETRIES
MOV BP,SP ; (7) GET A FRAME POINTER
MOV SI,AX ; (7) SET UP FIRST OFFSET
LUP: CMP BYTE PTR [SI],'$' ; (7) END CHAR
JE MATCH ; (7) REACHING END==MATCH
CMPSB ; (7) COMPARE TWO BYTES
JNE RESET ; (7) RESET SOURCE IF MISMATCH
DEC DX
LOOP LUP ; (7) DECREMENT COUNTER AND TRY AGAIN
JMP RTFAIL ; (7) OUT OF CHARS, FAILED
RESET: MOV SI,AX ; (7) MOVE SOURCE PTR BACK INTO SI
MOV DX,[BP] ; (7) RESTORE NUMBER OF BYTES IN STR
LOOP LUP ; (7) TRY AGAIN
RTFAIL: STC ; (7) FAIL BY RETURNING CARRY SET
POP DX
POP SI ; (7) RESTORE SI
RET
MATCH: TEST DX,DX ; (7) MATCH OF ENTIRE STRING
JNZ RTFAIL
CLC ; (7) GOT A MATCH, RETURN CARRY CLEAR
POP DX
POP SI ; (7) RESTORE SI
RET
CHK ENDP
; THIS ROUTINE CHECKS THE COPY PROTECTION
CHKCOP PROC
CLC ; FOR NOW, EVERYTHING WORKS
RET
CHKCOP ENDP
; THIS ROUTINE SETS SOME VARIABLES ACCORDING TO THE CMD LINE
; CURRENTLY THE 6 /PARAMETERS ARE SUPPORTED. THE FIRST THREE,
; /P INITIALIZE PRINTER THROUGH INT 17
; /M MONOCHROME
; /C COLOR
; /W WINDOWED SCROLLING
; /K<n> AMOUNT OF MEMORY IN K
; ARE INTENDED FOR THE USER. A FOURTH WILL NOT BE DOCUMENTED IS
; /G<gamefile.ext> WHICH WILL TEMPORARILY PATCH THE ZIP TO RUN THE
; GAME SPECIFIED.
;
PUBLIC SCANCMD,SCAN,SCAN0,SCAN1,SCAN2,SCAN3,SCAN4
PUBLIC SCAN5,SCAN6,SCAN7,SCAN8
SCANCMD PROC
CLD ; (7) AUTO INCREMENT
MOV SI,80H ; (7) GET # OF BYTES
LODSB ; (7) INTO AL
TEST AL,AL ; (7) ANY?
JNZ SCAN1
SCAN0: RET ; (7) NONE THERE
SCAN1: DEC AL ; (7) CARRIAGE RETURN DOESN'T COUNT
XOR DX,DX ; (7) ZERO THIS
MOV DL,AL ; (7) SAVE NUMBER OF BYTES
ADD DX,82H ; (7) ADDR OF LAST BYTE+1 ON LINE
INC SI ; (7) SKIP INITIAL SPACE
SCAN: CMP SI,DX ; (7) END OF CMD LINE?
LODSB ; (7) GET A DELIMITER
JZ SCAN0 ; (7) YEP, RETURN
CMP AL,'/' ; (7) WAS IT THE DELIMITER
JNZ SCAN ; (7) GET NEXT VALID CHAR
LODSB ; (7) GOT DELIMITER, GET BYTE
AND AL,5FH ; (7) UPPERCASIFY
CMP AL,'M' ; (7) DO THEY WANT MONOCHROME
JNZ SCAN2 ; (7) NOPE, TRY NEXT
OR CMDLIN,1 ; (7) SET FLAG IN CMDLIN VARIABLE
JMP SCAN
SCAN2: CMP AL,'W' ; (7) WINDOWED SCROLLING?
JNZ SCAN3
MOV SCROLL,0 ; (7) TURN ON SCROLLING
OR CMDLIN,8 ; (7) TURN ON 8 BIT
JMP SCAN
SCAN3: CMP AL,'G' ; (7) GAME FILE NAME?
JNZ SCAN5 ; (7) NOPE, CONTINUE ON...
MOV DI,OFFSET GAMFILE ; (7) MAKE THIS THE GAME
SCAN4: MOVSB ; (7) TRANSFER A BYTE
CMP DX,SI ; (7) THE END?
JNZ SCAN4
MOV AL,0 ; (7) DROP IN A NULL
STOSB ; (7) TO END THE STRING
RET
SCAN5: CMP AL,'C' ; (7) DO THEY WANT COLOR
JNZ SCAN6 ; (7) NOPE, TRY NEXT
OR CMDLIN,2 ; (7) SET FLAG IN CMDLIN VARIABLE
JMP SCAN
SCAN6: CMP AL,'K' ; (7) SET MEMORY SIZE
JNZ SCAN9 ; (7) NOPE LOOK ONWARD
MOV BX,0 ; (7) ZERO THIS
SCAN7: CMP DX,SI ; (7) THE END?
JNZ SCAN8 ; (7) NOPE
SCAN7A: OR CMDLIN,4 ; (7) TURN ON MEMORY SET BIT
MOV CL,6 ; (7w) CONVERT K TO PARAGRAPHS
SHL BX,CL ; (7) I THINK???
MOV MEMORY,BX ; (7) SAVE AMOUNT OF K SPECIFIED IN 512 BLKS
DEC SI ; (7v) BACKUP ONE
JMP SCAN
SCAN8: LODSB ; (7) GET FIRST BYTE
CMP AL,0D ; (7v) CR MEANS END OF STRING
JZ SCAN7A ; (7v) SO QUIT HERE
CMP AL,' ' ; (7v) SPACE MEANS NEXT STRING
JZ SCAN7A ; (7v) SO QUIT
CMP AL,'/' ; (7v) SLASH MEANS NEXT DELIMITER
JZ SCAN7A ; (7v) SO QUIT
XOR AH,AH ; (7) ZERO THIS
AAA ; (7) SCALE THE NUMBER DOWN
XCHG AX,BX ; (7) GET NUMBER (BX) INTO AC
PUSH DX ; (7) SAVE ENDPTR
MUL RADIX ; (7) MULTIPLY NUMBER BY TEN
ADD BX,AX ; (7) ADD IN NEW NUMBER
POP DX ; (7) RESTORE END PTR
JMP SCAN7
SCAN9: CMP AL,'P' ; (7w) DO WE NEED TO INITIALIZE THE PRINTER
JZ SCAN10 ; (7w) YES, DO IT
JMP SCAN
SCAN10: PUSH DX ; (7w) SAVE THIS
MOV DX,0 ; (7w) INITIALIZE FIRST PRINTER
MOV AH,1 ; (7w) FUNCTION NUMBER FOR INIT
INT 17H ; (7w) ASSUME IBM PC BECAUSE THEY USED /P
POP DX ; (7w) RESTORE END POINTER
JMP SCAN ; (7w) NOW GET BACK TO WORK
SCANCMD ENDP