PAGE 90,132 ;A2 TITLE GRTAB - DEFINE ROM GRAPHIC CHARACTERS FOR 128-255 IF1 %OUT GRTAB.SAL... ELSE ; %OUT GRTAB.SAL... ENDIF LISTPARM = 1 ;0=SUPPRESS LIST; 1=ALLOW LIST ;AN000; ;.XLIST ; ;AN000; ;****************** START OF SPECIFICATIONS ***************************** ; MODULE NAME: GRTAB ; (MAIN ROUTINE FOR UTILITY "GRAFTABL") ; DESCRIPTIVE NAME: Makes resident a 1K block of data defining the ; graphic character set when in graphics mode. ;FUNCTION: When in normal text mode (BASIC SCREEN 0), the CGA will properly ; handle all 255 characters in the screen display. ; However, when in graphics mode (BASIC SCREEN 1), then only the ; first 128 characters are properly shown on the screen. ; The upper 128 characters are defined in graphics mode by ; the 8 by 128 byte table pointed to by interrupt 1FH ; vector, which is normally set to 0:0, thus producing ; garbage on the screen for the upper set of characters. ; The purpose of this routine is to define an 8 by 128 byte ; table that defines each of these graphic characters in ; the upper 128 byte range, and also to put the vector ; pointer to this table into the interrupt 1FH. Once ; loaded, this table remains resident. ; An interrupt handler is hooked into the INT 2FH vector that ; screens INT 2FH calls for the MULTIPLEX ID value of hex B0, ; as defined by an equate, MY_MULTIPLEX_NUMBER, in GRATABHAN. ; The response indicates that GRAFTABL has been loaded, thus ; permitting the redefinition of the original 1K table with ; some new specification. ; ENTRY POINT: Entry_Point, JMP from GRTABHAN.SAL at his ORG 100H. ; LINKAGE: [d:][path] GRAFTABL [437 | 850 | 860 | 863 | 865 | ? | /STATUS] ; INPUT: (DOS COMMAND LINE PARAMETERS) ; '/STATUS'- (OR /STA) Identify the table already loaded, if any. ; '?' - Display the list of operands supported by GRAFTABL. ; 437 - Install the USA Graphic Character Set ; (BLANK) - Means same as '437', the 'USA' definition table ; 850 - Install the Multi-lingual Graphic Character Set ; 860 - Install the Portuguese Graphic Character Set ; 863 - Install the Canadian French Graphic Character Set ; 865 - Install the Nordic Graphic Character Set ; EXIT-NORMAL: ERRORLEVEL 0 - Leaving the 1K block of newly defined ; characters resident. There was no ; previously defined character table. ; Available RAM reduced by hex 1360 bytes. ; ERRORLEVEL 1 - No change in size of available RAM storage. ; A previously loaded character table exists. ; If a new table was requested, it has replaced ; the previous table at its original location. ; ERRORLEVEL 2 - No change in size of available RAM storage. ; No previously loaded character table exists. ; ; (The request for status, with parm="/sta[tus]", ; or the request for HELP, with parm="?", ; will result in either code 1 or 2.) ; EXIT-ERROR: ERRORLEVEL 3 - Incorrect parameter. ; No action taken, assumes "?" requested HELP. ; No change in size of available RAM storage. ; ERRORLEVEL 4 - Incorrect version of DOS, DOS 4.0 required ; EFFECTS: Either the desired table is hooked into Interrupt 1FH, ; or the identity of the previously loaded table is ; displayed. ; INTERNAL REFERENCES: ; ROUTINES: ; FINDTYPE - Scan existing table to see who is already loaded ; MOVTAB - Moves the specified table to overlay a portion of the PSP ; BADPARMS - Displays error message, and sets error ERRORLEVEL code ; SENDMSG - passes parms to regs and invokes the system message routine. ; DATA AREAS: ; PSP - Contains the DOS command line parameters. Partly overlayed ; with the installation of the character table. ; WORKAREA - Temporary storage ; EXTERNAL REFERENCES: ; ROUTINES: ; GRTABHAN (ENTRY is "HANDLER") - hooked into INT 2FH to identify ; that GRAFTABL is loaded and resident. ; SYSDISPMSG - Uses the MSG parm lists to construct the messages ; on STDOUT. ; SYSLOADMSG - Loads messages, makes them accessable. ; SYSPARSE - Processes the DOS Command line, finds parms. ; PARSE - Interfaces with the system Parser. ; DATA AREAS: ; GRTABUS - 1k binary table of the USA graphic character set ; GRTABML - 1k binary table of the Multi-Lingual graphic ; character set ; GRTABPO - 1k binary table of the Portuguese graphic ; character set ; GRTABCF - 1k binary table of the Canada French graphic ; character set ; GRTABNO - 1k binary table of the Nordic graphic character ; set ; GRTABSM - Definition of messages, text and MSG parm lists, ; and COPYRIGHT notice ; GRTABPAR - Control blocks to define the DOS command line parms. ; MPEXNUM - Byte containing the value of the multiplex number ; (For ease of patching, if such should ever become needed, ; this byte is immediately just before the interrupt 2FH ; handler's entry point, after that handler is loaded. To ; change this value here in these source modules, that value ; is defined in GRTABHAN as the equate: MY_MULTIPLEX_NUMBER. ; For purposes of patching the GRAFTABL.EXE file, this byte ; is at offset 5FH into the module.) ; NOTES: ; This module should be processed with the SALUT preprocessor ; with the re-alignment not requested, as: ; SALUT GRTAB,NUL ; To assemble these modules, the alphabetical or sequential ; ordering of segments may be used. ; Sample LINK command: ; LINK @GRTABLK.ARF ; Where the GRTABLK.ARF is defined as: ; GRTABHAN+ (must be first in this list) ; GRTABUS+ (these languages must be linked in this order) ; GRTABML+ (Multi-Lingual) ; GRTABPO+ (Portuguese) ; GRTABCF+ (Canadian French) ; GRTABNO+ (Nordic) ; GRTABSM+ (contains COPYRIGHT, SYSDISPMSG, SYSLOADMSG code) ; GRTABPAR+ (contains PARSE control blocks, code to call SYSPARSE) ; GRTABP+ (contains SYSPARSE to decode COMMAND line parms) ; GRTAB (MAIN ROUTINE) ; GRAFTABL; ; These modules must be linked in this order. The load module is ; a COM file, to be converted to COM with EXE2BIN. ; REVISION HISTORY: ; A000 Version 4.00: add PARSER, System Message Handler, ; A001 PTM 382 display "ACTIVE" OR "PREVIOUS" CP. ; A002 PTM 474 Avoid duplicate switches ; A003 PTM 538 Display parm in error ; A004 PTM1821 INCLUDE COPYRIGH.INC moved to msg_service macro. ; A005 PTM3262 specify BASESW EQU 1 before PARSE.ASM ; A006 PTM3512 PATHGEN START/END LABELS ; A007 PTM3621 break up large help msg into smaller messages ; A008 PTM3899 Free Environment, close all STDxxx handles ; when leaving a resident portion ; ; COPYRIGHT: The following notice is found in the OBJ code generated from ; the "GRTABSM.ASM" module: ; "Version 4.00 (C) Copyright Microsoft Corp 1981, 1988" ; "Licensed Material - Program Property of Microsoft" ;****************** END OF SPECIFICATIONS ***************************** HEADER INCLUDE PATHMAC.INC ;AN006; ; $SALUT (0,36,41,52) DOSCALL MACRO FN,SF ;; ;AN000; IFNB ;;ARE THERE ANY PARMS AT ALL?;AN000; IFNB ;; ;AN000; MOV AX,(FN SHL 8)+SF ;;AH=FN;AH=SF ;AN000; ELSE ;;SINCE THERE IS NO SUB FUNC ;AN000; MOV AH,FN ;; ;AN000; ENDIF ;; ;AN000; ENDIF ;; ;AN000; INT 21H ;; ;AN000; ENDM ;; ;AN000; ; = = = = = = = = = = = = ; $SALUT (4,19,23,36) FIXLIST MACRO LP,DOIT ;; ;AN000; IF LP ;; ;AN000; DOIT ;; ;AN000; ENDIF ;; ;AN000; ENDM ;; ;AN000; ; = = = = = = = = = = = = HEADER MACRO TEXT ;; ;AN000; FIXLIST LISTPARM,.XLIST ;; ;AN000; SUBTTL TEXT ;; ;AN000; FIXLIST LISTPARM,.LIST ;; ;AN000; PAGE ;; ;AN000; ENDM ;; ;AN000; ; = = = = = = = = = = = = ; DEFINITION OF FUNCTIONS TO BE REQUESTED OF INT 2FH GET_INST_STATE EQU 0 ;FUNCTION = "GET INSTALLED STATE" WHERE_R_U EQU 1 ;FUNCTION = "WHERE ARE YOU?" ; REQUESTS VECTOR OF LOADED TABLE BE ; PUT IN VECTOR POINTED TO BY DS:[BX] ; DOS FUNCTIONS: SHOW_MSG EQU 09H ;"SEND MESSAGE TO CONSOLE" DOS FUNCTION SET_VECT EQU 25H ;"SET VECTOR" DOS FUNCTION GET_VERSION EQU 30H ;"GET DOS VERSION" RET_RES EQU 31H ;"RETURN TO DOS" REMAIN RESIDENT GET_VECT EQU 35H ;"GET VECTOR" DOS FUNCTION CLOSE EQU 3EH ;AN008; CLOSE A FILE HANDLE FREE_AL_MEM EQU 49H ;AN008; FREE ALLOCATED MEM RET_FN EQU 4CH ;"RETURN TO DOS" NOT REMAIN RESIDENT ; VECTOR TABLE ENTRIES USED VEC_GRAF_CHAR EQU 1FH ;VECTOR THAT POINTS TO GRAPHIC CHAR TABLE VEC_MULTIPLX EQU 2FH ;VECTOR OF MULTIPLEX HANDLER VEC_DOS EQU 21H ;VECTOR POINTS TO DOS FUNCTIONS VEC_RET EQU 20H ;RETURN TO DOS, WITHOUT RET CODE ;AN000; ; DOS COMMAND LINE PARAMETERS RETCODE_QUESTION EQU -1 ;VALUE IN BX, IF PARM=? ZERO EQU 0 ;VALUE IN BX IF PARM=/STATUS OR /STA FIXLIST LISTPARM,.XLIST ; ;AN000; ;SLASH EQU "/" ;REQUEST FOR STATUS ;PARM? EQU "?" ;REQUEST FOR HELP ; THE PARM THAT ASKS FOR A PARTICULAR LANGUAGE ; IS THE TWO CHAR PAIR, DEFINED AS "LANID" ; IN THE STRUC, "LANGUAGE" FIXLIST LISTPARM,.LIST ; ;AN000; ; STANDARD FILE HANDLES STDIN EQU 0 ;AN008; STANDARD INPUT DEVICE STDOUT EQU 1 ;STANDARD OUTPUT DEVICE STDERR EQU 2 ;STANDARD ERROR OUTPUT DEVICE STDAUX EQU 3 ;AN008; STANDARD AUX DEVICE STDPRN EQU 4 ;AN008; STANDARD PRINTER DEVICE ; OTHER EQUATES BLANK EQU " " ;BLANK CHARACTER NIBBLE_SIZE EQU 4 ;SHIFT COUNT TO MOVE ONE NIBBLE ;AN000; FIXLIST LISTPARM,.XLIST ; ;AN000; ;CASEBIT EQU 0FFH-20H ;TURN OFF THIS BIT TO MAKE UPPER CASE ;LOWERA EQU 'a' ;LOWER CASE CHARACTER 'a' ;LOWERZ EQU "z" ;LOWER CASE CHARACTER 'z' FIXLIST LISTPARM,.LIST ; ;AN000; EXTRN HANDLER_SIZE:ABS ;THE BYTE SIZE REQUIREMENTS EXTRN CPID_L:ABS ;NO. BYTES IN EACH CPID ENTRY VECTOR STRUC ;DEFINITION OF ANY DOUBLE WORD VECTOR POINTER VECOFF DW ? ;OFFSET PORTION OF VECTOR POINTER VECSEG DW ? ;SEGMENT PORTION OF VECTOR POINTER VECTOR ENDS ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = LANGUAGE STRUC ;DEFINITION OF EACH LANGUAGE TABLE LANCHAR DB 1024 DUP(?) ;8 BYTES PER EACH OF 128 CHARACTERS LANID DW ? ;TWO BYTE CODEPAGE ID, TO MATCH ; GRAFTABL CMD LINE PARM LANNAME DB 14 DUP(?) ;ASCIIZ STRING NAME OF LANGUAGE LANGUAGE ENDS TABSIZE EQU SIZE LANCHAR + SIZE LANID + SIZE LANNAME ;SIZE OF ; EACH GRAPHIC CHAR TABLE + ID + NAME ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ; VALUES FOR THE MSG_DESC CONTROL BLOCK ONE_SUBS EQU 1 ;ONE VARIABLE FIELD IN MESSAGE ;AN000; TWO_SUBS EQU 2 ;TWO VARIABLE FIELDS IN MESSAGE ;AN000; CLASS_1 EQU 0100H ;CLASS 1 (DOS EXTENDED ERRORS) ;AN000; CLASS_2 EQU 0200H ;CLASS 2 (PARSE ERRORS) ;AN000; CLASS_A EQU 0A00H ;CLASS A TYPE MESSAGE ;AN000; ;THIS MESSAGE DESCRIPTOR CONTROL BLOCK IS GENERATED, ONE PER MESSAGE, ;TO DEFINE THE SEVERAL PARAMETERS THAT ARE EXPECTED TO BE PASSED IN ;CERTAIN REGISTERS WHEN THE SYSDISPMSG FUNCTION IS TO BE INVOKED. MSG_DESC STRUC ; ;AN000; MSG_NUM DW 0 ;MESSAGE NUMBER (TO AX) ;AN000; MSG_HANDLE DW STDOUT ;HANDLE OF OUTPUT DEVICE (TO BX) ;AN000; MSG_SUBLIST DW 0 ;POINTER TO SUBLIST (TO SI) ;AN000; MSG_COUNT DW 0 ;SUBSTITUTION COUNT (TO CX) ;AN000; MSG_CLASS DW CLASS_A ;MESSAGE CLASS (IN HIGH BYTE, TO DH) ;AN000; ; LOW BYTE HAS 0 (FUNCTION "NO INPUT", TO DL) MSG_DESC ENDS ; ;AN000; ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = SUBLIST STRUC ; ;AN000; SUB_SIZE DB TYPE SUBLIST ;SUBLIST SIZE (POINTER TO NEXT SUBLIST) ;AN000; SUB_RES DB 0 ;RESERVED ;AN000; ;NEXT FIELD IS TO BE USED AS A DOUBLE WORD SUB_VALUE DW 0 ;TIME, DATE, OR PTR TO DATA ITEM ;AN000; SUB_VALUE_SEG DW 0 ;SEG ID OF PTR ;AN000; ;(ABOVE FIELD MUST BE FILLED AT EXECUTION TIME ; IF THIS IS A .COM FILE) SUB_ID DB 0 ;N OF %N ;AN000; SUB_FLAGS DB 0 ;DATA TYPE FLAGS ;AN000; SUB_MAX_WIDTH DB 0 ;MAXIMUM FIELD WIDTH (0=UNLIMITED) ;AN000; SUB_MIN_WIDTH DB 0 ;MINIMUM FIELD WIDTH ;AN000; SUB_PAD_CHAR DB " " ;CHARACTER FOR PAD FIELD ;AN000; SUBLIST ENDS ; ;AN000; ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = DEFPSP STRUC DB 2CH DUP(?) ;AN008; ENVIRON_SEG DW ? ;AN008; SEG ID OF ENVIRONMENT DB 32H DUP(?) ;AN008; SET WHERE MOV_DEST DB 20H DUP(?) ; INT HANDLER IS TO BE MOVED TO ;AT MOV_DEST+HANDLER_SIZE WILL GO THE ; TABLE ITSELF PARMCNT DB ? ;COUNT OF CHARS IN DOS COMMAND LINE PARM LIST PARMDOS DB 127 DUP(?) ;DOS COMMAND LINE PARM TEXT DEFPSP ENDS PSPSIZE EQU SIZE DEFPSP ;SIZE OF THE PSP ITSELF SHIFT_SIZE EQU PSPSIZE - MOV_DEST ; HOW FAR HANDLER/TABLE MOVED ;WHEN THEY BECAME RESIDENT SHIFT_SIZE_SEG EQU SHIFT_SIZE SHR NIBBLE_SIZE ;DIVIDE BY 16 ;AN000; ; TO CONVERT BYTES TO SEGS ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = .LIST HEADER ; $SALUT (4,6,12,28) CSEG SEGMENT WORD PUBLIC ASSUME CS:CSEG ;AS A .COM FILE, THE DOS ASSUME DS:CSEG ; LOADER HAS ALREADY ASSUME ES:CSEG ; INITIALIZED ALL THESE ASSUME SS:CSEG ; SEGMENT REGISTERS GRTAB_BASE EQU $ ;FOR EASE IN DEBUGGING ;AN000; PUBLIC GRTAB_BASE ; TELL LINK MAP WHERE THIS IS ;AN000; EXTRN END_PSP:BYTE ;MOVE RESIDENT CODE FROM HERE TO "MOV_DEST" EXTRN MPEXNUM:BYTE ;MULTIPLEXOR ID VALUE EXTRN HANDLER:NEAR ;ENTRY TO INT2FH HANDLER EXTRN PREV_OWN:DWORD ;VECTOR TO SAVE PREVIOUS INT2FH OWNER EXTRN PATCH_OFF:WORD ;THESE TWO PATCH LOCATION IN GRTABHAN.SAL EXTRN PATCH_SEG:WORD ; ARE TO RECEIVE LOCATION WHERE TABLE IS MOVED TO EXTRN TABLEUS:BYTE ;START OF THE USA CHAR TABLE EXTRN COPYRIGHT:BYTE ;USED TO MARK THE END OF THE ARRAY OF CHAR TABLES ; THE COPYRIGHT TEXT IS ITSELF UN-REFERENCED FIXLIST LISTPARM,.XLIST ; ;AN000; ; EXTRN MSG1:WORD ;NON-STD VER OF GRAPHIC CHAR SET TABLE IS ALREADY LOADED ; EXTRN MSG2:WORD ;XXX VER OF GRAPHIC CHAR SET TABLE IS ALREADY LOADED ; EXTRN MSG3:WORD ;XXX VER OF GRAPHIC CHAR SET HAS JUST BEEN LOADED ; EXTRN MSG4:WORD ;INCORRECT PARAMETER ; EXTRN MSG5:WORD ;NO VER OF GRAPHIC CHAR SET TABLE IS ALREADY LOADED ; EXTRN MSG6:WORD ;INCORRECT DOS VERSION ; EXTRN MSG7:WORD ;DOS COMMAND LINE PARAMETERS SUPPORTED: ; EXTRN MSG8:WORD ;ID - LANGUAGE NAME ; EXTRN LANGUAGE_NAME:BYTE ;14 BYTE AREA TO RECEIVE ASCIIZ OF LANGUAGE NAME FIXLIST LISTPARM,.LIST ; ;AN000; EXTRN MSGNUM_EXTERR:WORD ;ALL DOS EXTENDED ERRORS ;AN000; EXTRN MSGNUM_PARSE:WORD ;ALL PARSING ERRORS ;AN000; EXTRN SUBLIST_PARSE:WORD ;DEFINES THE BAD PARM AS %0 ;AN003; EXTRN MSGNUM_VER:WORD ;"Incorrect DOS Version" ;AN000; EXTRN MSGNUM_ACTIVE:WORD ;"Active Code Page: %1" ;AN000; EXTRN MSGNUM_PREVIOUS:WORD ;"Previous Code Page: %1" ;AN000; EXTRN CPID:BYTE ;4 BYTE STRING OF CODE PAGE ID ;AN000; EXTRN SLIST_23:WORD ;SET VECTOR TO POINT TO "NONE" OR "NON-STANDARD", ;AN000; ; OR TO ONE OF THE "CPID" ENTRIES EXTRN MSGNUM_NONE:WORD ;"None" ;AN000; EXTRN MSGNUM_NSTD:WORD ;"Non-Standard" ;AN000; EXTRN MSGNUM_HELP_TITLE:WORD ;"DOS command line parameters supported:" ;AN000; EXTRN MSGNUM_HELP_TITLE7:WORD ;AN007; EXTRN MSGNUM_HELP_TITLE8:WORD ;AN007; EXTRN MSGNUM_HELP_TITLE9:WORD ;AN007; EXTRN MSGNUM_HELP_TITLE10:WORD ;AN007; EXTRN SYSDISPMSG:NEAR ;DISPLAY MESSAGE SUBROUTINE ;AN000; EXTRN SYSLOADMSG:NEAR ;LOAD MESSAGE SUBROUTINE ;AN000; EXTRN SYSGETMSG:NEAR ;GET MESSAGE SUBROUTINE ;AN000; EXTRN PARSER:NEAR ;INVOKES SYSTEM DOS COMMAND LINE PARSER ;AN000; ; $SALUT (4,17,22,32) WHERE DD 0 ;VECTOR POINTING TO PREVIOUS GRAFTABL TABLE ; VECTOR AS SET BY "GRTABHAN" MULTIPLEX HANDLER. ;THIS IS NOT NECESSARILY WHAT INT 1FH HAS. ADPSP DW 0 ;SEG ID OF PSP. ; CHANGED TO SHOW ITS SHIFTED LOCATION FIXLIST LISTPARM,.XLIST ; ;AN000; ;ACC DW 0 ;ACCUMULATES VALUE OF CODEPAGE ID ;TEN DW 10 ;CONSTANT TO CONVERT ASCII DECIMAL TO BINARY ;TOKEN DB " " ;RECEIVES THE TEXT OF DOS PARMS, AND OVERFLOW AREA ;TOKEN_SIZE EQU $-TOKEN FIXLIST LISTPARM,.LIST ; ;AN000; RESSIZE_PARA DW 0 ;SIZE OF RESIDENT PORTION, HANDLER+TABLE, IN PARAGRAPHS RESSIZE_BYTE DW 0 ;SIZE OF RESIDENT PORTION, HANDLER+TABLE, IN BYTES SAVESI DW 0 ;REMEMBER WHERE CURRENT TABLE STARTS CPIDPOINTER DW CPID ;POINTER TO ENTRY IN CPID TABLE OF PREVIOUS ENTRY ACTIVECPID DW CPID ;POINTER TO ENTRY IN CPID TABLE OF ACTIVE ENTRY PUBLIC ACTIVECPID IDXXX DW 0 ;ID OF PREVIOUSLY LOADED TABLE INSTALLED DB 0 ;OUTPUT OF INT 2FH, "FF"=GRAFTABL ALREADY INSTALLED ; AND 'WHERE' WILL POINT TO PREVIOUS TABLE ;"00"=GRAFTABL NOT INSTALLED ; DEFINITIONS OF VALUES OF CONTENTS OF "INSTALLED". LOADED EQU 0FFH ;GRAFTABLE IS ALREADY IN VECTOR ; DEFINITIONS OF VALUES OF CONTENTS OF 'EXITFL'. ; THESE VALUES ARE THE RETURN CODES CHECKED BY ERRORLEVEL. EXVER EQU 4 ;RETURN TO DOS, INVALID DOS VERSION EXPAR EQU 3 ;RETURN TO DOS, INVALID DOS COMMAND LINE PARMS ; OR SYSTEM MESSAGE HANDLER ERROR EXNONE EQU 2 ;RETURN TO DOS, NO TABLE WAS LOADED EXDOS EQU 1 ;RETURN TO DOS, CHAR TABLE PREVIOUSLY LOADED EXRES EQU 0 ;RETURN TO DOS, LEAVING THE 1K BLOCK OF CHAR RESIDENT EXITFL DB EXDOS ;ERRORLEVEL RETURN CODE, INITIALLY SET TO "EXDOS" PUBLIC EXITFL BAD1F DB 0 ;FLAG, GET SET TO "RESET" IF GRAFTABL FONT IS RESET EQU 1 ; LOADED, BUT 1FH DOES NOT POINT TO IT ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = PATHLABL GRTAB ;AN006; ; $SALUT (3,4,9,32) HEADER MAIN PROC NEAR ENTRY_POINT LABEL NEAR ;JUMPED TO FROM ENTRY POINT IN GRTABHAN PUBLIC ENTRY_POINT ;VERSION CHECKING AND SYSTEM MESSAGE INITIALIZATION CALL SYSLOADMSG ; INIT SYSMSG HANDLER ;AN000; ; $IF C ; IF THERE WAS A PROBLEM ;AN000; JNC $$IF1 CALL SYSDISPMSG ; LET HIM SAY WHY HE HAD A PROBLEM ;AN000; MOV EXITFL,EXVER ; TELL ERRORLEVEL BAD DOS VERSION ;AN000; MOV AH,RET_FN ;RETURN TO DOS, DO NOT STAY RESIDENT ;AN000; ; $ELSE ; SINCE SYSDISPMSG IS HAPPY ;AN000; JMP SHORT $$EN1 $$IF1: CLD ;CLEAR DIRECTION TO AUTO-INCREMENT ;AN000; CALL MAIN_GRTAB ;PERFORM REST OF GRAFTABL FUNCTIONS ;AN000; ;AH=DOS FUNCTION OF TYPE OF RETURN TO DOS ; $ENDIF ;LOAD OF SYS MSGS OK? ;AN000; $$EN1: MOV AL,EXITFL ;PASS BACK ERRORLEVEL RET CODE INT VEC_DOS ;(21H) RETURN TO DOS WITH RET CODE INT VEC_RET ;(20H) IF ABOVE NOT WORK, EXIT ANYWAY ;AN000; MAIN ENDP ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = HEADER MAIN_GRTAB PROC NEAR PUBLIC MAIN_GRTAB ;INPUT: SYSTEM MESSAGE HANDLER IS LOADED, DOS VERSION IS CORRECT. ;OUTPUT: AH=FUNCTION NUMBER FOR PROPER TYPE OF RETURN TO DOS. MOV SLIST_23.SUB_VALUE_SEG,CS ;DO MY OWN SEGMENT FIXUPS ;AN000; MOV SUBLIST_PARSE.SUB_VALUE_SEG,CS ; ;AN003; MOV ADPSP,ES ;SAVE SEG ID OF PSP SUB ADPSP,SHIFT_SIZE_SEG ;WHERE THE SEG BASE OF MOVED INT HANDLER WILL BE PUSH ES ;SAVE PSP SEGID MOV AX,HANDLER_SIZE ;GET SIZE OF MULTIPLEX HANDLER (NOT PSP) ;AN000; ADD AX,TABSIZE ;ADD THE SIZE OF THE CHAR TABLE MOV RESSIZE_BYTE,AX ;SAVE BYTE LENGTH OF HANDLER + CHAR TABLE ; THIS IS THE AMOUNT TO BE SHIFTED ADD AX,OFFSET MOV_DEST ;ADD ON PART OF PSP NOT OVERLAID BY CODE MOVE ;AN000; MOV CL,NIBBLE_SIZE ;DIVIDE ;AN000; SHR AX,CL ; BYTE SIZE BY 16 MOV RESSIZE_PARA,AX ;SAVE PARA LENGTH OF HANDLER + CHAR TABLE ; AND FIRST PART OF PSP ;THIS IS THE AMOUNT TO STAY RESIDENT ;PATCH INT2FH HANDLER IN CASE LATER ; IT BECOMES RESIDENT AND IS ASKED ; TO TELL WHERE ITS CHAR TABLE WENT MOV AX,ADPSP ;TELL INT2FH HANDLER WHERE TO SAY HIS TABLE IS MOV PATCH_SEG,AX MOV PATCH_OFF,OFFSET TABLEUS ;TELL INT2FH HANDLER ; WHERE TO SAY HIS TABLE IS MOV AH,GET_VECT ;REQUEST "GET VECTOR" FUNCTION MOV AL,VEC_MULTIPLX ; FOR INTERRUPT 2FH INT VEC_DOS ;OUTPUT: ES:BX = VECTOR OF CONTENTS ASSUME ES:NOTHING ;SINCE ORIG PSP POINTER IS LOST ;PATCH INT2FH HANDLER TO TELL HIM WHERE ; THE CURRENT INT2FH HANDLER IS IN CASE ; THIS NEW HANDLER REPLACES THE OLD ONE MOV PREV_OWN.VECOFF,BX ;REMEMBER WHERE THE PREVIOUS MOV PREV_OWN.VECSEG,ES ; OWNER OF INT 2FH WAS POP ES ;RESTORE THE PSP SEGID BAS ;AN000; ASSUME ES:CSEG ;REG IS RESET BACK LIKE IT WAS CALL FINDTYPE ;SET 'IDXXX' TO SHOW ; WHAT IS IN THE LOW RAM TABLE NOW FIXLIST LISTPARM,.XLIST ; ;AN000; ; CALL PROCESS ;RESPOND TO REQUEST DEFINED BY PARMS ; ; SETTING 'EXITFL' TO INDICATE RESULTS FIXLIST LISTPARM,.LIST ; ;AN000; CALL PARSER ;LOOK AT DOS COMMAND LINE PARMS ;AN000; ;IF A CODEPAGE NUMBER WAS SPECIFIED ; BX = OFFSET TO LANGUAGE TABLE TO BE LOADED ; DX = INTEGER VALUE OF CODEPAGE SPECIFIED ;IF /STATUS WAS SPECIFIED ; BX = 0 ;IF QUESTION MARK WAS SPECIFIED ; BX=-1 CALL DOFUNCTION ; RESPOND TO PARMS ;AN000; ; SETTING 'EXITFL' TO INDICATE RESULTS FIXLIST LISTPARM,.XLIST ; ;AN000; ; $ELSE ;SINCE THE DOS VERSION IS NOT ACCEPTABLE, ; THE LOCATION, "MSG6", CONTAINS OFFSET TO TEXT OF ; MOV DX,MSG6 ;"INCORRECT DOS VERSION" (THIS MSG ENDS WITH "$") ; ;GET POINTER TO MESSAGE TEXT TO DS:DX ; MOV AH,SHOW_MSG ;'WRITE TO CONSOLE' DOS FUNCTION ; INT VEC_DOS ; ; MOV EXITFL,EXVER ;SET ERROR CODE TO ERROR TERMINATION, BAD VERSION ; $ENDIF ;CHECK DOS VERSION NUMBER FIXLIST LISTPARM,.LIST ; ;AN000; CMP EXITFL,EXRES ;CHECK THE EXIT TYPE FLAG ; $IF E ;IF NEW TABLE HAS JUST BEEN LOADED JNE $$IF4 ;THE INT2FH HANDLER AND THE CHAR TABLE HAVE ALREADY BEEN MOVED INTO THE PSP. ;CHANGE THE TWO VECTORS TO POINT TO WHERE THEN WENT. ;THE TWO VECTORS ARE: ; 2FH - MULTIPLEX INTERRUPT HANDLER ; 1FH - 128 CHAR DEFINITION TABLE PUSH DS MOV AX,ADPSP MOV DS,AX ;FIND SEG WHERE TABLE WENT ASSUME DS:NOTHING ;SET INTERRUPT VECTOR 1FH TO POINT TO WHERE THE CHAR TABLE IS LEA DX,TABLEUS ;WHERE CHAR TABLE IS ; DS:DX = VECTOR POINTING TO CHAR TABLE AFTER MOVE MOV AH,SET_VECT ;FUNCTION TO MOVE DS:DX INTO VECTOR FOR INT 1FH MOV AL,VEC_GRAF_CHAR ;INTERRUPT NUMBER TO RECEIVE NEW CONTENTS INT VEC_DOS ;CHANGE THE VECTOR ;SET INTERRUPT VECTOR 2FH (MULTIPLEXOR) TO WHERE THE INTERRUPT HANDLER IS LEA DX,HANDLER ;SET DS:DX = INT 2FH INTERRUPT HANDLER MOV AH,SET_VECT ;FUNCTION TO MOVE DS:DX INTO VECTOR FOR INT 2FH MOV AL,VEC_MULTIPLX ;CHANGE THE CONTENTS OF THE MULTIPLEX INTERRUPT INT VEC_DOS ;HOOK IN THE INTERRUPT HANDLER POP DS ;RESTORE SEG REG ASSUME DS:CSEG ;FREE THE SEGMENT CONTAINING THE ENVIRONMENT PUSH ES ;AN008; SAVE NORMAL ES MOV AX,DS:ENVIRON_SEG ;AN008; FROM PSP GET SEG OF ENVIRONMENT MOV ES,AX ;AN008; SET SEGREG TO POINT TO ENVIRONMENT SEG ASSUME ES:NOTHING ;AN008; ES NOW HAS SEG OF ENVIRONMENT MOV AH,FREE_AL_MEM ;AN008; (49H) FREE MEM ALLOC TO ENVIRON ;ES = SEGID OF BLOCK BEING RETURNED INT VEC_DOS ;AN008; FREE ENVIRONMENT ;IF CARRY IS SET, THERE WAS A PROBLEM ;THIS IS NOT CHECKED, IGNORING ANY ERROR POP ES ;AN008; RESTORE ES TO NORMAL VALUE ASSUME ES:CSEG ;AN008; ;LOOP THRU ALL THE STANDARD EXTERNALLY OPENED HANDLES, 0-4, ; AND CLOSE EACH ONE BEFORE RETURNING TO DOS, STAYING RESIDENT. MOV BX,STDIN ;AN008; START WITH FIRST STANDARD HANDLE ; $DO COMPLEX JMP SHORT $$SD5 $$DO5: INC BX ;AN008; SELECT NEXT HANDLE ; $STRTDO $$SD5: MOV AH,CLOSE ;AN008; (3EH) CLOSE A FILE HANDLE ; BX=FILE HANDLE INT VEC_DOS ;AN008; CLOSE THE HANDLE ;CARRY IS SET IF A PROBLEM WITH CLOSE ;IN THIS CASE, ERRORS ARE IGNORED. CMP BX,STDPRN ;AN008; WAS THIS THE LAST ONE? ; $ENDDO E ;AN008; QUIT IF LAST ONE JNE $$DO5 ;SET UP TO LEAVE A PORTION OF GRAFTABL RESIDENT: ; THE MULTIPLEXOR INTERRUPT HANDLER, AND ; THE FIRST 1K PIXEL TABLE. MOV DX,RESSIZE_PARA ;MARK END OF AREA TO REMAIN RESIDENT MOV AH,RET_RES ;FUNCTION TO RETURN TO DOS, BUT STAY RESIDENT ; $ELSE ;SINCE NEW TABLE NOT LOADED JMP SHORT $$EN4 $$IF4: ; MAYBE BECAUSE TABLE ALREADY LOADED ; OR MAYBE BECAUSE BAD DOS COMMAND LINE PARMS MOV AH,RET_FN ;RETURN TO DOS, DO NOT STAY RESIDENT ; $ENDIF $$EN4: RET ;RETURN TO CALLER MAIN_GRTAB ENDP ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = HEADER FINDTYPE PROC NEAR PUBLIC FINDTYPE ;OUTPUT = IDXXX HAS 2 CHAR ID OF WHATEVER IS ALREADY LOADED ; OR IS JUST 0 IF 1FH DOES NOT POINT TO A GRAFTABL DEFINED FONT. ; SUBLIST_23 IS SET TO CONTAIN THE ORIGINAL CP PREVIOUSLY LOADED ; OR "NONE". THIS SUBLIST IS USED BY BOTH MESSAGES 2 AND 3 ; WHICH STATE THE "ACTIVE CODEPAGE" AND "PREVIOUS CODEPAGE". ; THE MESSAGE ACTUALLY TO USE THIS SUBLIST IS SELECTED IN "DOFUNCTION" ; AFTER INTERROGATING THE PARMS, SO THAT "/STATUS" & "?" WILL REFER TO ; THE "ACTIVE CODEPAGE", AND OTHER REQUESTS WILL SAY "PREVIOUS CP". ASSUME ES:NOTHING MOV AH,MPEXNUM ;REQUEST "GET INSTALLED STATE" MOV AL,GET_INST_STATE ;IDENTIFY THAT IT IS ME I AM LOOKING FOR ;AH=MULTIPLEXOR NUMBER, AL=FUNCTION REQUEST INT VEC_MULTIPLX ;SEE IF I AM ALREADY LOADED MOV INSTALLED,AL ;SAVE THE "INSTALLED?" INDICATOR CMP AL,LOADED ; $IF E ;IF I AM ALREADY INSTALLED JNE $$IF10 ; GRAFTABL HAS BEEN LOADED. SEVERAL CONDITIONS MAY EXIST: ; INT 1FH STILL POINTS TO THE TABLE GRAFTABL LOADED ; AND THAT TABLE HAS NOT BEEN ALTERED. ; INT 1FH STILL POINTS TO THE TABLE GRAFTABL LOADED ; BUT THE CONTENTS OF THAT TABLE HAS BEEN ALTERED. ; INT 1FH NO LONGER POINTS TO THE TABLE GRAFTABL LOADED, ; BUT POINTS TO SOME OTHER CHARACTER TABLE. ; NOW WE ASK THE MULTIPLEXOR HANDLER OF GRAFTABLE, SINCE WE ; KNOW HE HAS BEEN LOADED, TO TELL US WHERE HIS GRAFTABL ; CHARACTER FONT TABLE IS IN RESIDENT RAM, BY SETTING THE ; DWORD AT "WHERE" TO POINT TO THE OLD GRAFTABL FONT TABLE. ;AH STILL SHOULD HAVE "MY_MULTIPLEX_NUMBER" MOV AL,WHERE_R_U ;ASK "WHERE ARE YOU" LEA BX,WHERE ;PASS POINTER TO VECTOR TO RECEIVE ANSWER ;AH=MULTIPLEXOR NUMBER, AL=FUNCTION REQUEST ;DS:BX POINTS TO "WHERE", TO RECEIVE RESPONSE INT VEC_MULTIPLX ;SET VECTOR "WHERE" TO POINT TO HIS TABLE ; COMPARE THE CONTENTS OF VECTOR 1FH WITH THE VECTOR AT "WHERE" ; WHICH POINTS TO THE CURRENTLY LOADED TABLE OF GRAFTABL. ; THE USER MAY HAVE ALTERED THE CONTENTS OF VECTOR 1FH AFTER ; HAVING PREVIOUSLY LOADED A GRAFTABL CHARACTER FONT. XOR AX,AX ;ZERO A REG MOV ES,AX ;LOOK AT THE VECTOR TABLE ;ES IS STILL ASSUMED "NOTHING" MOV AX,ES:[VEC_GRAF_CHAR * DWORD] ;AN000; CMP AX,WHERE.VECOFF ; $IF E,AND JNE $$IF11 MOV AX,ES:[VEC_GRAF_CHAR * 4]+2 ;AN000; CMP AX,WHERE.VECSEG ; $IF E ;IF THE 1FH VECTOR IS POINTING TO A GRAFTABLE JNE $$IF11 ; DEFINED CHARACTER TABLE. ;NOW TO FIND OUT WHICH TABLE HE IS POINT TO. LEA SI,TABLEUS ;GET WHERE NEW TABLE IS IN THIS LOAD MODULE ; DS:SI POINT TO NEW TABLE ; IN THIS SEARCH, WE ARE GOING TO STEP THRU THE ARRAY OF ; TABLES WE HAVE DEFINED, COMPARING EACH ONE WITH WHATEVER "WHERE" ; POINTS TO, TO SEE IF WHAT WAS PREVIOUSLY LOADED IS LIKE ONE ; OF THE TABLES WE HAVE DEFINED HERE. A MATCH LETS US IDENTIFY ; THE ONE PREVIOUSLY LOADED; A NON-MATCH MEANS THAT WHATEVER ; THAT WAS PREVIOUSLY LOADED HAS APPARENTLY BEEN ALTERED, ; SO WHATEVER IT WAS, WE CANNOT SAY WHICH TABLE IT IS, AND SO WE ; IDENTIFY IT AS SIMPLY A NON-STANDARD TABLE. THIS SEARCH WILL ; SELECT WHICH OF TWO MESSAGES TO BE DISPLAYED. MOV SAVESI,SI ;SAVE WHERE TABLE STARTS ; $SEARCH COMPLEX JMP SHORT $$SS12 $$DO12: ADD CPIDPOINTER,CPID_L ;BUMP TO NEXT ENTRY IN CPID TABLE. ;AN000; MOV SI,SAVESI ;GO BACK TO START OF TABLE ;AN000; ADD SI,TABSIZE ;BUMP TO NEXT TABLE ;AN000; MOV SAVESI,SI ;SAVE WHERE TABLE STARTS ;AN000; ; $STRTSRCH $$SS12: ; THIS CHANGES ES TO PREVIOUSLY LOADED TABLE LES DI,WHERE ;GET THE CONTENTS OF THE VECTOR ;ES:DI POINTS TO THE OLD TABLE OF CHARACTERS ;ES IS STILL ASSUMED "NOTHING" MOV CX,TABSIZE ;GET SIZE OF TABLE REP CMPSB ;COMPARE ES:[DI] WITH DS:[SI] ; $EXITIF E ;IF THIS TABLE ALREADY LOADED JNE $$IF12 LES DI,WHERE ;RESTORE THE POINTERS TO RESIDENT TABLE MOV AX,ES:[DI].LANID ;PICK UP 2 CHAR ID OF PREVIOUS TABLE MOV IDXXX,AX ;REMEMBER WHAT THAT WAS PREVIOUSLY LOADED PUSH DS ;SET UP THE ES REG TO ;AN000; POP ES ; BE THE SAME AS DS, THE COMMON SEGMENT ;AN000; ASSUME ES:CSEG ; ;AN000; MOV AX,CPIDPOINTER ;GET OFFSET TO CURRENT CPID ENTRY ;AN000; MOV SLIST_23.SUB_VALUE,AX ;PUT CP NAME IN MSG ;AN000; ;SO MSG IS "PREVIOUS CODE PAGE: XXX" FIXLIST LISTPARM,.XLIST ; ;AN000; ; LEA DI,LANGUAGE_NAME ;TO THE MESSAGES' VARIABLE NAME OF LANGUAGE FIELD ; MOV SI,SAVESI ;FROM THE NAME OF THE LANGUAGE ; ADD SI,OFFSET LANNAME ; IN THE NEW TABLE ; MOV CX,SIZE LANNAME ;PASS NAME OF LANGUAGE ; REP MOVSB ; TO THE MESSAGES ; ; AND THEN TELL THE OPERATOR WHAT WAS FOUND ; LEA AX,MSG2 ;XXX VER OF GRAPHIC CHAR SET TABLE IS ALREADY LOADED FIXLIST LISTPARM,.LIST ; ;AN000; ; $ORELSE ;SINCE THIS VERSION IS NOT ALREADY LOADED JMP SHORT $$SR12 $$IF12: ASSUME ES:NOTHING ;SINCE BASE REG NOT RESET YET, LEA AX,COPYRIGHT ;WHICH IS IMMEDIATELY FOLLOWING THE LAST TABLE CMP AX,SI ;HAVE WE INCREMENTED THE INDEX TO BE BEYOND ; THE LAST TABLE TO BE CHECKED ; $ENDLOOP BE ;QUIT IF NO NEXT TABLE TO BE LOOKED AT JNBE $$DO12 PUSH DS ;SET UP THE ES REG TO ;AN000; POP ES ; BE THE SAME AS DS, THE COMMON SEGMENT ;AN000; ASSUME ES:CSEG ;TELL THE ASSEMBLER WHAT I JUST DID ;AN000; FIXLIST LISTPARM,.XLIST ; ;AN000; ; LEA AX,MSG1 ;NON-STD VER OF GRAPHIC CHAR SET TABLE IS ALREADY LOADED FIXLIST LISTPARM,.LIST ; ;AN000; CALL PREV_NONSTD ;SET MSG TO SAY "NON STANDARD" ;AN000; ; SO MSG IS "PREVIOUS CODE PAGE: NON-STANDARD" ; $ENDSRCH $$SR12: ; $ELSE ;SINCE THE 1FH VECTOR DOES NOT POINT TO JMP SHORT $$EN11 $$IF11: ; THE SAME PLACE AS "WHERE" ; THEN THE USER MUST HAVE USED GRAFTABL TO ; LOAD A CHAR FONT, THEN LOADED SOME OTHER ; TABLE AND CHANGED VECTOR 1FH TO POINT TO THE NEW ONE. PUSH DS ;SET UP THE ES REG TO ;AN000; POP ES ; BE THE SAME AS DS, THE COMMON SEGMENT ;AN000; ASSUME ES:CSEG ;TELL THE ASSEMBLER WHAT I JUST DID ;AN000; CALL PREV_NONSTD ;SET MSG TO SAY "NON STANDARD" ;AN000; FIXLIST LISTPARM,.XLIST ; ;AN000; ; LEA AX,MSG1 ;NON-STD VER OF GRAPHIC CHAR SET TABLE IS ALREADY LOADED FIXLIST LISTPARM,.LIST ; ;AN000; MOV BAD1F,RESET ;INDICATE THAT THE 1FH VECTOR DOES NOT POINT ; TO THE GRAFTABL FONT ; $ENDIF ;HAS 1Fh BEEN CHANGED? $$EN11: ; $ELSE ;SINCE GRAFTABLE IS NOT LOADED, JMP SHORT $$EN10 $$IF10: PUSH DS ;SET UP THE ES REG TO ;AN000; POP ES ; BE THE SAME AS DS, THE COMMON SEGMENT ;AN000; ASSUME ES:CSEG ;TELL THE ASSEMBLER WHAT I JUST DID ;AN000; CALL PREV_NONE ;SET MSG TO SAY "NONE" ;AN000; FIXLIST LISTPARM,.XLIST ; ;AN000; ; LEA AX,MSG5 ;NO VER OF CHAR TABLE IS ALREADY LOADED FIXLIST LISTPARM,.LIST ; ;AN000; ; $ENDIF ;ALREADY INSTALLED? $$EN10: RET FINDTYPE ENDP ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = HEADER ; ;AN000; PREV_NONSTD PROC NEAR ; ;AN000; PUBLIC PREV_NONSTD ; ;AN000; ;SET UP SUBLIST FOR MSGS 2-3 TO HAVE THE VARIABLE TEXT: "NON-STANDARD". ASSUME ES:CSEG ; ;AN000; MOV AX,MSGNUM_NSTD.MSG_NUM ;PASS MESSAGE NUMBER OF "NON-STANDARD" ;AN000; MOV DH,BYTE PTR MSGNUM_NSTD.MSG_CLASS+BYTE ;PASS MSG'S CLASS ;AN000; CALL SYSGETMSG ;FIND WHERE THE TEXT OF "NON-STANDARD" IS ;AN000; ;ES:SI=VECTOR TO MESSAGE TEXT MOV SLIST_23.SUB_VALUE,SI ;PUT OFFSET INTO SUBLIST ;AN000; RET ;RETURN TO CALLER ;AN000; PREV_NONSTD ENDP ; ;AN000; ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = HEADER ; ;AN000; PREV_NONE PROC NEAR ; ;AN000; PUBLIC PREV_NONE ; ;AN000; ;SET UP SUBLIST FOR MSGS 2-3 TO HAVE THE VARIABLE TEXT: "NONE". ASSUME ES:CSEG ; ;AN000; MOV AX,MSGNUM_NONE.MSG_NUM ;PASS MESSAGE NUMBER OF "NONE" ;AN000; MOV DH,BYTE PTR MSGNUM_NONE.MSG_CLASS+BYTE ;PASS MSG'S CLASS ;AN000; CALL SYSGETMSG ;FIND WHERE THE TEXT OF "NONE" IS ;AN000; ;ES:SI=VECTOR TO MESSAGE TEXT MOV SLIST_23.SUB_VALUE,SI ;PUT OFFSET INTO SUBLIST ;AN000; RET ;RETURN TO CALLER ;AN000; PREV_NONE ENDP ; ;AN000; ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = FIXLIST LISTPARM,.XLIST ; ;AN000; ; HEADER ;PROCESS PROC NEAR ;LOOK AT RESPONSE TO DOS COMMAND LINE PARMS ; PUBLIC PROCESS ;INPUT: DS, ES - PSP SEG ID ;OUTPUT:EXITFL IS SET TO REFLECT EXISTING CONDITIONS ; CALL PARSER ;LOOK AT DOS COMMAND LINE PARMS ; ; ;IF A CODEPAGE NUMBER WAS SPECIFIED ; ; BX = OFFSET TO LANGUAGE TABLE TO BE LOADED ; ; DX = INTEGER VALUE OF CODEPAGE SPECIFIED ; ;IF /STATUS WAS SPECIFIED ; ; BX = 0 ; ;IF QUESTION MARK WAS SPECIFIED ; ; BX=-1 ; ; CALL DOFUNCTION ; RESPOND TO PARMS ; ; SETTING 'EXITFL' TO INDICATE RESULTS ; ; ASSUME ES:CSEG ; PUSH ES ;SAVE BASE REG ; MOV SI,OFFSET PARMDOS ;GET WHERE DOS PARMS START ; SUB DI,DI ;INIT INDEX TO ZERO, WHERE TO PUT PARMS IN TOKEN ; MOV CL,DS:PARMCNT ;GET HOW MANY CHARS ARE IN THE DOS COMMAND LINE ; XOR CH,CH ;CLEAR COUNTER OF OUTPUT CHARS ; CALL UPCASE ;CONVERT ANY LOWER CASE CHARS TO UPPERCASE ; ; $SEARCH ; CMP CL,0 ;ANY DOS PARMS? ; $LEAVE BE ;QUIT IF NOT PARMS ; MOV DL,BYTE PTR [SI] ;SET DL TO A PARM CHAR FROM PARMDOS IN PSP ; CMP DL,BLANK ;IGNORE THE SPECIAL CHARS: ; $IF A ; BLANK AND LOWER NUMBERED CONTROL CHARS ; CMP DL,"?" ;IS THE SPECIFIED PARAMETER ; $IF E ; A QUESTION MARK? ; MOV BYTE PTR TOKEN[DI],DL ;PUT DL CONVERTED TO TOKEN ; INC DI ;BUMP TO NEXT AVAIL SPOT IN TOKEN ; ADD CH,3 ;COUNT THIS AS AN OUTPUT CHAR,WITH NO ROOM FOR MORE ; $ELSE ;SINCE NOT "?" ; CMP DL,'0' ;IF CHAR IN RANGE OF NUMERICS ; $IF AE,AND ;UNSIGNED TEST ; CMP DL,'9' ; $IF BE ; PUSH DX ; MOV AX,ACC ; IMUL TEN ;CLOBBERS DX ; POP DX ;FIX IT BACK ; SUB DL,'0' ;CONVERT FROM NUMERIC CHAR TO BINARY ; ADD AL,DL ;ADD NEW NUMBER FROM PARM ; ADC AH,0 ;PROPOGATE CARRY ; MOV ACC,AX ;SAVE RESULTS SO FAR ; INC CH ;COUNT THIS AS AN OUTPUT CHAR ; $ELSE ;SINCE NOT A NUMERIC CHARACTER ; MOV CH,TOKEN_SIZE ;FORCE PARM ERROR, MAY BE CHANGED TO OK ; CMP CL,4 ; $IF AE ;IF AT LEAST 4 CHARS ARE PRESENT ; CMP WORD PTR [SI],"S/" ;FIRST TWO CHARS OF "/STA" ; $IF E,AND ; CMP WORD PTR [SI]+WORD,"AT" ;NEXT TWO CHARS OF "/STA" ; $IF E ; MOV BYTE PTR TOKEN[DI],'/' ;PUT "/" CONVERTED TO TOKEN ; INC DI ;BUMP TO NEXT AVAIL SPOT IN TOKEN ; MOV CH,3 ;COUNT THIS AS AN OUTPUT CHAR,WITH NO ROOM FOR MORE ; MOV CL,1 ;PRETEND THAT IS ALL OF THE COMMAND LINE THERE IS ; $ENDIF ;"/STA"? ; $ENDIF ;LENGTH 4? ; $ENDIF ;IS CHAR IN NUMERIC RANGE? ; $ENDIF ;IS PARM A QUESTION MARK? ; $ENDIF ;BLANK OR LOWER VALUED CONTROL CHARS? ; CMP CH,TOKEN_SIZE ;IS OUTPUT AREA OVERLY FULL? ; $EXITIF GE ; CALL BADPARMS ;FUSS ABOUT INVALID PARMS ; $ORELSE ; INC SI ;BUMP INDEX TO NEXT PARM CHAR IN PSP ; DEC CL ;DEC COUNT OF INPUT CHARS FROM PARMS ; $ENDLOOP ; ;SINCE CL COUNT WENT TO ZERO, ; CMP CH,0 ;ANY DOS PARMS LEFT AFTER CLEANUP? ; $IF E ;IF NONE, ; MOV WORD PTR TOKEN,437 ;MAKE IT LOOK LIKE "US" WAS SPECIFIED ; $ELSE ;SOME PARM WAS SPECIFIED ; CMP BYTE PTR TOKEN,PARM? ; $IF NE,AND ;IF NOT A QUESTION MARK, AND ; CMP BYTE PTR TOKEN,SLASH ; $IF NE ;IF NOT A SLASH (FOR /STATUS) ; MOV AX,ACC ;GET ACCUMULATOR ; MOV WORD PTR TOKEN,AX ; TO TOKEN ; $ENDIF ;QUESTION MARK? ; $ENDIF ;ANY DOS PARMS? ; CALL DOFUNCTION ;RESPOND TO PARAMETER IN "TOKEN" ; ; $ENDSRCH ;SCANNING DOS COMMAND LINE FOR PARMS ; ; POP ES ;RESTORE BASE REG ; ASSUME ES:CSEG ; ; RET ;PROCESS ENDP ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ;UPCASE PROC NEAR ;;CONVERT CHARACTERS IN PARMLIST TO UPPER CASE ;;INPUT: SI=OFFSET IN DS: TO PARM TEXT ;; CX=NUMBER OF CHARS OF PARMS ; ; OR CX,CX ;IF THERE ARE CHARS IN PARMLIST ; $IF NZ ; THEN GO LOOK AT EACH CHAR ; PUSH SI ;SAVE POINTER TO PARMS ; PUSH CX ;SAVE COUNTER OF PARMS ; $DO ;STEP THRU ALL CHARS OF PARM LIST, CONVERTING TO UPPER CASE ; MOV AL,[SI] ;GET CHAR FROM PARMLIST TO AL ; CMP AL,LOWERA ;COMPARE WITH LOWER CASE "a" ; $IF AE,AND ;UNSIGNED TEST ; CMP AL,LOWERZ ;COMPARE WITH LOWER CASE "z" ; $IF BE ;IF CHAR IS LOWER CASE ; AND AL,CASEBIT ;CONVERT TO UPPER CASE BY DELETING THE 20H BIT ; MOV [SI],AL ;RESTORE CHAR TO PARMLIST ; $ENDIF ; INC SI ;BUMP INDEX TO LOOK AT NEXT CHAR ; $ENDDO LOOP ; POP CX ;RESTORE COUNTER OF PARMS ; POP SI ;RESTORE POINTER TO PARMS ; $ENDIF ;ANY CHARS IN PARMLIST? ; ; RET ;UPCASE ENDP ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = FIXLIST LISTPARM,.LIST ; ;AN000; HEADER ;AC000; DOFUNCTION PROC NEAR ;RESPOND TO PARM ;AC000; PUBLIC DOFUNCTION ;INPUT: IF A CODEPAGE NUMBER WAS SPECIFIED ; BX = OFFSET TO LANGUAGE TABLE TO BE LOADED ; DX = INTEGER VALUE OF CODEPAGE SPECIFIED ; IF /STATUS WAS SPECIFIED ; BX = 0 ; IF QUESTION MARK WAS SPECIFIED ; BX=-1 ASSUME ES:CSEG CMP BX,RETCODE_QUESTION ;IS QUESTION MARK SPECFIED? ; $IF E JNE $$IF22 CALL HELP ;DISPLAY RESULTS OF "?" SPECIFICATION ; $ELSE ;SINCE QUESTION MARK IS NOT PARM SPECIFIED JMP SHORT $$EN22 $$IF22: CMP BX,ZERO ;IS /STATUS SPECIFIED? ; $IF NE ;IF NOT STATUS, MUST BE REQUEST TO LOAD A TABLE JE $$IF24 LEA DI,MSGNUM_PREVIOUS ;"Previous Code Page: xxx" ;AN001; CALL SENDMSG ;SEND THE MSG TO STDOUT ;AN001; MOV DX,[BX].LANID ;FETCH THE TWO CHAR ID FROM TABLE CMP DX,IDXXX ;IS THIS ONE ALREADY LOADED? ; $IF NE ;IF NOT, LOAD IT JE $$IF25 FIXLIST LISTPARM,.XLIST ; ;AN000; ; MOV CX,LENGTH LANNAME ;GET LENGTH OF NAME FIELD ; LEA SI,[BX].LANNAME ;GET WHERE NAME FIELD IS IN THE NEW TABLE ; LEA DI,LANGUAGE_NAME ;WHERE WHERE TO PUT NAME IN VARIABLE MESSAGE FIELD ; REP MOVSB ;MOVE LANGUAGE NAME TO PRINTF VARIABLE FIELD FIXLIST LISTPARM,.LIST ; ;AN000; MOV SI,BX ;PASS START OF CHAR TABLE CALL MOVTAB ;PUT THIS TABLE INTO THE USA POSITION FIXLIST LISTPARM,.XLIST ; ;AN000; ; LEA AX,MSG3 ;XXXXX VER OF GRAPHIC CHAR SET HAS JUST BEEN LOADED FIXLIST LISTPARM,.LIST ; ;AN000; LEA DI,MSGNUM_ACTIVE ;"ACTIVE CODE PAGE: XXX" ;AN000; MOV AX,ACTIVECPID ;GET POINTER TO CP JUST ACTIVATED ;AN000; MOV SLIST_23.SUB_VALUE,AX ;INTO SUBLIST ;AN000; CALL SENDMSG ;SHOW "ACTIVE CODE PAGE: XXX" ;AN000; CMP BAD1F,RESET ;THIS FLAG SET TO '1' MEANS INT 1FH POINTS TO ; $IF E ; A TABLE OTHER THAN ONE LOADED BY GRAFTABL JNE $$IF26 PUSH DS ASSUME DS:NOTHING LDS DX,WHERE ;SET DS:DX POINT TO PREVIOUSLY LOADED GRAFTABL FONT MOV AH,SET_VECT ;FUNCTION TO MOVE DS:DX INTO VECTOR FOR INT 1FH MOV AL,VEC_GRAF_CHAR ;INTERRUPT NUMBER TO RECEIVE NEW CONTENTS INT VEC_DOS ;CHANGE THE VECTOR POP DS ASSUME DS:CSEG ; $ENDIF ;BAD 1FH? $$IF26: ; $ENDIF ;THIS TABLE ALREADY LOADED? $$IF25: FIXLIST LISTPARM,.XLIST ; ;AN000; ; ADD BX,TYPE LANGUAGE ;STEP BASE TO NEXT TABLE ; LEA AX,COPYRIGHT ;AT START OF MSGS, BEYOND LAST TABLE ; CMP BX,AX ; $ENDLOOP AE ;GO TRY THE NEXT TABLE, IF ANY ; ;NOT ANY NEXT TABLE ; CALL BADPARMS ;FUSS ABOUT INVALID PARMS ; ; $ENDSRCH ;COMPARING TOKEN WITH ID IN TABLES FIXLIST LISTPARM,.LIST ; ;AN000; ; $ELSE ;SINCE /STATUS SPECIFIED, JMP SHORT $$EN24 $$IF24: LEA DI,MSGNUM_ACTIVE ;POINT TO "ACTIVE CODE PAGE: XXX" ;AN001; CALL SENDMSG ; VARIABLE FILLED BY "FINDTYPE" ;AN001; CMP IDXXX,ZERO ;SEE WHO IS LOADED, IF ANYBODY ; $IF E JNE $$IF30 MOV EXITFL,EXNONE ;SET EXIT CODE TO SAY NO TABLE LOADED AT ALL ; $ELSE ;SINCE SOMEONE IS LOADED, JMP SHORT $$EN30 $$IF30: MOV EXITFL,EXDOS ;SAY A TABLE IS LOADED ; $ENDIF ;ANY TABLE PREVIOUSLY LOADED? $$EN30: ; $ENDIF ;/STATUS? $$EN24: ; $ENDIF ;QUESTION MARK? $$EN22: RET DOFUNCTION ENDP ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = HEADER MOVTAB PROC NEAR PUBLIC MOVTAB ;INPUT: SI = OFFSET OF SOURCE TABLE ; ES = PSP ASSUME ES:CSEG ;OUTPUT: THE SOURCE TABLE WILL BE MOVED TO ONE OF TWO PLACES, ; EITHER ; (IF THIS IS THE FIRST TIME FOR GRAFTABL) ; TO THE "TABLEUS" IN THE PSP (IF USA NOT SPECIFIED), ; AND THEN BOTH INT2FH AND TABLEUS MOVED TO MOV_DEST IN THE PSP, ; OR ; ON TOP OF THE PREVIOUS TABLE LEFT BY A PREVIOUS GRAFTABL CALL, ; AS POINTED TO BY THE VECTOR, "WHERE". PUSH ES ;SAVE THE PSP CMP INSTALLED,LOADED ;IF A PREVIOUS COPY OF GRAFTABL ; $IF E ; HAS ALREADY BEEN LOADED JNE $$IF35 LES DI,WHERE ;REMEMBER WHERE PREVIOUSLY TABLE WENT ASSUME ES:NOTHING ;ES IS BASE OF OLD PREVIOUSLY LOADED TABLE MOV CX,TABSIZE ;THE TABLE,2 CHAR ID,& LANGUAGE NAME ARE TO BE MOVED REP MOVSB ;MOVE NEW TABLE ON TOP OF OLD TABLE ;WHEN EXITING, LEAVE NOTHING RESIDENT ; $ELSE ;SINCE NO PREVIOUS LOAD OF GRAFTABL EXISTS, JMP SHORT $$EN35 $$IF35: ASSUME ES:CSEG ;SINCE ES WAS NOT CHANGED, MOV EXITFL,EXRES ;WHEN EXITING, LEAVE TABLE RESIDENT ; ALONG WITH THE INT2FH HANDLER ;SINCE IT IS THE USA TABLE THAT IS ; PHYSICALLY NEXT TO THE INTERRUPT HANDLER, ; THAT PAIR OF AREAS IS WHAT WILL STAY ; RESIDENT. IF THE USA TABLE IS NOT THE ; DESIRED VERSION, THEN FIRST MOVE THE ; VERSION DESIRED ON TOP OF THE USA VERSION, ; THEN MOVE THE PAIR DOWN ON TOP OF THE PSP ; WHERE THEY WILL STAY RESIDENT. LEA DI,TABLEUS ;FIND WHERE FIRST TABLE NOW IS CMP SI,DI ; $IF NE ;IF NOT THE USA TABLE, JE $$IF37 MOV CX,TABSIZE ;SIZE OF THE TABLE REP MOVSB ;MOVE THE XX TABLE ONTO THE USA TABLE ; $ENDIF $$IF37: MOV DI,OFFSET MOV_DEST ;WHERE TO MOVE EVERYTHING TO LEA SI,END_PSP ;START WITH THE INT2FH HANDLER, ON THRU THE TABLE ;ES:DI POINT TO DESTINATION, DS:SI POINT TO SOURCE MOV CX,RESSIZE_BYTE ;GET SIZE OF TABLE + RESIDENT CODE INT HANDLER REP MOVSB ;MOVE THE TABLE ONTO THE PSP OF THIS LOAD ; $ENDIF $$EN35: POP ES ;RESTORE THE PSP POINTER TO ES RET MOVTAB ENDP ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = HEADER HELP PROC NEAR ;RESPOND TO "?" PARM SPECIFIED PUBLIC HELP ;INPUT: DS, ES = POINTS TO PSP ; IDXXX = CP OF WHO IS ALREADY LOADED ; EXITFL = ERROR LEVEL RET CODE ; NORMAL VALUE SAYS SOME TABLE HAS BEEN LOADED, BUT ; INVALID PARMS COULD HAVE ALREADY ALTERED THIS VALUE. ;OUTPUT: EXITFL MAY BE CHANGED TO "EXNONE", IF NO TABLE LOADED ASSUME ES:CSEG LEA DI,MSGNUM_ACTIVE ;POINT TO "ACTIVE CODE PAGE: XXX" ;AN001; CALL SENDMSG ; VARIABLE FILLED BY "FINDTYPE" ;AN001; CMP EXITFL,EXDOS ;IS RET CODE UNTOUCHED SO FAR? ; $IF E ;IF SO, REPORT WHO IS LOADED JNE $$IF40 CMP IDXXX,ZERO ;SEE WHO IS LOADED, IF ANYBODY ; $IF E JNE $$IF41 MOV EXITFL,EXNONE ;SET EXIT CODE TO SAY NO TABLE LOADED AT ALL ; $ENDIF ;ANY TABLE PREVIOUSLY LOADED? $$IF41: ; $ENDIF ;RET CODE UNTOUCHED? $$IF40: FIXLIST LISTPARM,.XLIST ; ;AN000; ; LEA AX,MSG7 ;"DOS command line parameters supported:" FIXLIST LISTPARM,.LIST ; ;AN000; LEA DI,MSGNUM_HELP_TITLE ;"DOS command line parameters supported:" ;AN000; CALL SENDMSG ;DISPLAY MSG IN STDOUT ;AN000; LEA DI,MSGNUM_HELP_TITLE7 ;AN007; CALL SENDMSG ;AN007;DISPLAY MSG IN STDOUT ;AN000; LEA DI,MSGNUM_HELP_TITLE8 ;AN007; CALL SENDMSG ;AN007;DISPLAY MSG IN STDOUT ;AN000; LEA DI,MSGNUM_HELP_TITLE9 ;AN007; CALL SENDMSG ;AN007;DISPLAY MSG IN STDOUT ;AN000; LEA DI,MSGNUM_HELP_TITLE10 ;AN007; CALL SENDMSG ;AN007;DISPLAY MSG IN STDOUT ;AN000; FIXLIST LISTPARM,.XLIST ; ;AN000; ; LEA SI,TABLEUS ;START WITH THE FIRST TABLE ; $DO ; LEA DI,LANGUAGE_NAME ;FIND WHERE NAME OF LANGUAGE GOES ; MOV CX,LENGTH LANNAME ;HOW LONG IS THIS FIELD ; SUB BX,BX ;CLEAR INDEX TO NAME FIELD TO ZERO ; $DO ; MOV AL,[SI][BX].LANNAME ;GET CHAR FROM LANGUAGE NAME IN TABLE ; MOV [DI][BX],AL ;MOVE THAT CHAR TO MSG VARIABLE FIELD ; INC BX ;POINT TO NEXT POSITION ; $ENDDO LOOP ; MOV AX,[SI].LANID ;PICK UP THE 2 CHAR ID ; MOV IDXXX,AX ;PUT IT WHERE MSG8 IS LOOKING FOR IT ; LEA AX,MSG8 ;"%d - %s" ; CALL SENDMSG ;DISPLAY "IDXXX" AND "LANGUAGE_NAME" ; ; ADD SI,TYPE LANGUAGE ;BUMP TO THE NEXT TABLE ; LEA AX,COPYRIGHT ;IT IMMEDIATELY FOLLOWS THE LAST TABLE ; CMP SI,AX ; $ENDDO AE FIXLIST LISTPARM,.LIST ; ;AN000; RET HELP ENDP ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = FIXLIST LISTPARM,.XLIST ; ;AN000; ;BADPARMS PROC NEAR ; LEA AX,MSG4 ;"INCORRECT PARAMETER" ; CALL SENDMSG ; ; CALL HELP ;DISPLAY RESULTS OF "?" SPECIFICATION ; ; MOV EXITFL,EXPAR ;ERRORLEVEL CODE TO "PARM ERROR" ; RET ;BADPARMS ENDP ; = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = FIXLIST LISTPARM,.LIST HEADER ;AN000; SENDMSG PROC NEAR ; ;AN000; PUBLIC SENDMSG ; ;AN000; ;INPUT - DI=POINTER TO MSG_DESC STRUC FOR THIS MESSAGE ;OUTPUT - IF CARRY SET, EXTENDED ERROR MSG ATTEMPTED DISPLAYED ; IF CARRY CLEAR, ALL OK ; IN EITHER CASE, DI AND AX ALTERED, OTHERS OK ; = = = = = = = = = = = = PUSH BX ; SAVE CALLER'S REGS ;AN000; PUSH CX ; ;AN000; PUSH DX ; ;AN000; PUSH SI ; ;AN000; ; PASS PARMS TO MESSAGE HANDLER IN ; THE APPROPRIATE REGISTERS IT NEEDS. MOV AX,[DI].MSG_NUM ;MESSAGE NUMBER ;AN000; MOV BX,[DI].MSG_HANDLE ;HANDLE TO DISPLAY TO ;AN000; MOV SI,[DI].MSG_SUBLIST ;OFFSET IN ES: OF SUBLIST, OR 0 IF NONE ;AN000; MOV CX,[DI].MSG_COUNT ;NUMBER OF %PARMS, 0 IF NONE ;AN000; MOV DX,[DI].MSG_CLASS ;CLASS IN HIGH BYTE, INPUT FUNCTION IN LOW ;AN000; CALL SYSDISPMSG ;DISPLAY THE MESSAGE ;AN000; ; $IF C ;IF THERE IS A PROBLEM ;AN000; JNC $$IF44 ;AX=EXTENDED ERROR NUMBER ;AN000; LEA DI,MSGNUM_EXTERR ;GET REST OF ERROR DESCRIPTOR ;AN000; MOV BX,[DI].MSG_HANDLE ;HANDLE TO DISPLAY TO ;AN000; MOV SI,[DI].MSG_SUBLIST ;OFFSET IN ES: OF SUBLIST, OR 0 IF NONE ;AN000; MOV CX,[DI].MSG_COUNT ;NUMBER OF %PARMS, 0 IF NONE ;AN000; MOV DX,[DI].MSG_CLASS ;CLASS IN HIGH BYTE, INPUT FUNCTION IN LOW ;AN000; CALL SYSDISPMSG ;TRY TO SAY WHAT HAPPENED ;AN000; STC ;REPORT PROBLEM ;AN000; ; $ENDIF ;PROBLEM WITH DISPLAY? ;AN000; $$IF44: POP SI ;RESTORE CALLER'S REGISTERS ;AN000; POP DX ; ;AN000; POP CX ; ;AN000; POP BX ; ;AN000; FIXLIST LISTPARM,.XLIST ; ;AN000; ;;INPUT: AX = OFFSET OF MSG PARM LIST ; PUSH AX ; PUSH CS ;MATCH REQUIREMENTS OF PRINTF, WHICH IS "FAR" ; CALL PRINTF ;USING MSG PARM LIST, BUILD MSG, DISPLAY MSG ; ;PRINTF WILL POP OFF THE PARM, PUSHED FROM AX ; FIXLIST LISTPARM,.LIST ; ;AN000; RET ; ;AN000; SENDMSG ENDP ; ;AN000; PATHLABL GRTAB ;AN006; CSEG ENDS END