]> wirehaze git hosting - MS-DOS.git/blob - v4.0/src/DEV/DISPLAY/INIT.ASM

wirehaze git hosting

MZ is back!
[MS-DOS.git] / v4.0 / src / DEV / DISPLAY / INIT.ASM
1 PAGE ,132
2 TITLE DOS - CON Code Page Switching Device Driver (INIT)
3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4 ;
5 ; FILENAME: INIT.ASM
6 ; PROGRAM: DISPLAY.SYS (Load module)
7 ; LINK PROCEDURE: Linkk
8 ; INSTALLATION:
9 ;
10 ; This is the routine used to initialize the DOS CPS
11 ; (Code Page Switching) device driver. It is linked into the
12 ; DISPLAY.SYS file at the very end.
13 ;
14 ; PSEUDO CODE:
15 ; INIT PROC
16 ;
17 ; not specified yet....patience is a virtue!!!
18 ;
19 ; INIT ENDP
20 ;
21 ;
22 ; (C)Copyright 1988 Microsoft
23 ;
24 ; DATE: August 28, 1986
25 ;
26 ;Modification history *********************************************************
27 ;AN001; D358 New device driver INIT function package 12/07/87 J.K.
28 ;AN002; D493 Undo D358. 02/24/88 J.K.
29 ;******************************************************************************
30
31 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
32 IF1 ;
33 %OUT .COMPILING: INIT.ASM
34 %OUT . ô INSTALL CPS-CON DRIVER
35 %OUT . õ VERSION 3.30
36 %OUT .INCLUDE FILES:\a
37 ENDIF ;
38 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
39 ;
40 ; REFERENCES
41 ;
42 ; THESE REFERENCES ARE FOR VARIABLES SET WITHIN THE
43 ; MAIN-LINE PROGRAM, NOT CONTAINED IN THIS MODULE.
44 ;
45 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
46 ;
47 .XLIST ;
48 INCLUDE SYSMSG.INC ; WGR ;AN000;
49 MSG_UTILNAME <DISPLAY> ; WGR ;AN000;
50 .LIST ;
51 ;
52 ;
53 CODE SEGMENT PUBLIC BYTE 'CODE' ;
54 ASSUME CS:CODE,DS:CODE ;
55 PUBLIC INIT ;
56 ;
57 EXTRN ROM_INT_2F:WORD ;
58 EXTRN ROM_INT_10:WORD ;
59 EXTRN ROM_INT_1F:WORD ;
60 EXTRN OLD_INT_1F:WORD ;
61 EXTRN ROM_INT_44:WORD ;
62 EXTRN INT_2F_COM:NEAR ;
63 EXTRN INT_10_COM:NEAR ;
64 EXTRN EOF_MARKER:BYTE ;
65 EXTRN ABORT:BYTE ;
66 EXTRN CPD_ACTIVE:WORD ;
67 EXTRN CPD_CLASS:BYTE ;
68 EXTRN CPD_HDWR_N_MAX:ABS ;
69 EXTRN CPD_DESG_N_MAX:ABS ;
70 EXTRN CPD_HDWR_N:WORD ;
71 EXTRN CPD_DESG_N:WORD ;
72 EXTRN CPD_FONTS_N:WORD ;
73 EXTRN IRPT_2:NEAR ;
74 EXTRN IRPT_CMD_EXIT:NEAR ;
75 EXTRN FONT_SIZE:BYTE ;
76 EXTRN LOAD_MECH:BYTE ;
77 EXTRN CPD_FONT_PNTER:WORD ;
78 EXTRN PARSER:NEAR ;
79 EXTRN GET_DEVICE_ID:NEAR ;
80 EXTRN TABLE:BYTE ;
81 EXTRN ASK_BIOS_FONT_SIZE:NEAR ;
82 EXTRN ASK_BIOS_SCAN_LINES:NEAR;
83 EXTRN REDUCED_SUPPORT:ABS ;
84 EXTRN DEV_HDR:WORD ;
85 EXTRN MODE_VALUE:BYTE ;
86 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
87 ;
88 ; LOCAL VARIABLES
89 ;
90 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
91 HANDLE_ROUTINES LABEL WORD ; INDEX TABLE OF 'FUNCTIONS' TO
92 DW OFFSET HANDLE_DEVICE_NAME ; OPERATE ON THE COMMAND_LINE
93 DW OFFSET HANDLE_DEVICE_ID ;
94 DW OFFSET HANDLE_HDWR_CP ;
95 DW OFFSET HANDLE_DESG_CP ;
96 LEN_HANDLE_ROUTINES EQU ($-HANDLE_ROUTINES)/2
97 ;
98 RESIDENT_END DW OFFSET EOF_MARKER ; POINTER TO SEG:OFFSET OF CODE END!
99 RESIDENT_ENDS DW SEG CODE ;
100 ;
101 DEVICE_ID_INDEX DW 0 ; INDEX VALUE FOR DEVICE SUB-TYPE
102 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
103 ;
104 ; INCLUDE FILES
105 ;
106 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
107 INCLUDE MACROS.INC ; GENERAL PURPOSE 'MACROs'
108 INCLUDE DEF-EQU.INC ; CPS DRIVER STRUCTURES AND EQUATES
109 INCLUDE TABLES.INC ; DEVICE SUB-TYPE CONFIGURATION TABLES
110 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
111 ;
112 ; INITIALIZATION ROUTINE
113 ;
114 ; THE INIT PROC IS CALLED BY THE DEVICE DRIVER DURING DOS BOOT TIME!
115 ; THE CALL WILL BE MADE ONCE, AND ONLY ONCE. THEREFORE, WHEN THIS
116 ; CODE IS COMPLETED, IT IS DISCARDED INTO THAT 'great bit bucket
117 ; in the sky!
118 ;
119 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
120 INIT PROC ;
121 PUSH DS ;
122 ;
123 PUSH CS ;
124 POP DS ; FIRST SET DS = CS
125 ;
126 PUSH BX ; WGR ;AN000;
127 CALL SYSLOADMSG ; WGR load messages ;AN000;
128 JNC INIT_00 ; WGR if no error then continue.. ;AN000;
129 CALL SYSDISPMSG ; WGR display error message.. ;AN000;
130 POP BX ; WGR ;AN000;
131 JMP INIT_1 ; WGR exit with error status ;AN000;
132 INIT_00: ; WGR ;AN000;
133 POP BX ; WGR ;AN000;
134 MOV RESIDENT_ENDS,CS ; SET INITIAL RESIDENT END SEGMENT
135 ;
136 LES DI,DWORD PTR BUF.RH_PTRO; GET RH
137 CALL PARSER ;
138 JC INIT_1A ;
139 ;
140 MOV SI,OFFSET TABLE ; ADDRESS [ TABLE 1 ]
141 MOV CX,[SI].NUM_DEVICES ; CHECK THE NUMBER OF DEVICES SPECIFIED
142 CMP CX,ONE ; IF <> 1, THEN WE HAVE A PROBLEM...
143 JNE INIT_1A ; ERROR
144 MOV SI,[SI].DEVICE1_OFFSET ; MOVE FROM [ TABLE 1 ] TO [ TABLE 2 ]
145 MOV CX,[SI].NUM_ITEMS ;
146 LEA DI,HANDLE_ROUTINES ;
147 ;
148 INIT_0: CALL CS:[DI] ; CALL ROUTINE WITH '[SI].OFFSET_LIST'
149 ;
150 JC INIT_1 ; ERROR IN ROUTINE (COMMAND_LINE)
151 INC SI ; ADVANCE POINTERS FOR CALL AND
152 INC SI ; THE OFFSET_LIST!
153 INC DI ;
154 INC DI ;
155 LOOP INIT_0 ;
156 ;
157 CALL INSTALL_ID ; CONFIGURE DEVICE DRIVER FOR MATCHED
158 JC INIT_1 ; DISPLAY ADAPTER!
159 ;
160 PUSH BX ;
161 MOV AH,15 ; PERFORM CALL TO GET ACTIVE MODE
162 INT 10H ;
163 MOV MODE_VALUE,AL ; SET IT IN THE INT10COM.INC ROUTINE
164 POP BX ;
165 ;
166 JUMP INIT_2 ;
167 ;
168 INIT_1A: ;
169 PUSH AX ; WGR ;AN000;
170 PUSH DX ; WGR ;AN000;
171 MOV AX,ERROR_2 ; PARSING ERROR CONDITION ;AN000;
172 MOV DH,UTILITY_MSG_CLASS ; WGR ;AN000;
173 CALL ISSUE_MESSAGE ; WGR ;AN000;
174 POP DX ; WGR ;AN000;
175 POP AX ; WGR ;AN000;
176 ;
177 INIT_1: XOR AX,AX ; CLEAR ERROR CODE TO BE RETURNED
178 LES DI,DWORD PTR BUF.RH_PTRO; GET RH
179 MOV RH.RH0_ENDO,AX ; OFFSET = 0
180 MOV RH.RH0_ENDS,CS ;
181 MOV RH.RH0_UNIT,AL ; SET 0 UNITS....
182 ;
183 CMP NOT_CPS_ID,OFF ; WGR did we find a non-CPS id? ;AN000;
184 JNE INIT_1B ; WGR yes....do not set an error ;AN000;
185 OR BUF.STATUS,103H ; SET INIT ERROR OCCURRED
186 JMP INIT_1C ; WGR ;AN000;
187 ;
188 INIT_1B: ;
189 OR BUF.STATUS,AX ; WGR no error code..but do not load ;AN000;
190 ; mov RH.RH0_SYSINIT_MSG, 0 ;AN001;AN002; Ask IBMBIO not to show "Error in CONFIG.SYS lines= #" message
191 INIT_1C: ;
192 PUSH DI ; 'DETACH' THE LINK LIST TO THE
193 MOV AX,-1 ; NEXT DEVICE NAME....THIS MAY not
194 LEA DI,DEV_HDR ; NEED TO BE RESET FOR INIT ERROR....
195 MOV CS:[DI],AX ;
196 MOV CS:[DI+2],AX ;
197 POP DI ;
198 STC ; SET CY TO INDICATE FNC DONE
199 POP DS ;
200 RET ;
201 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
202 ;
203 ; NOW MOVE ONTO INSTALLATION OF INT 2F HEX
204 ;
205 ; SINCE WE ARE GOING TO CHAIN THE INTERRUPT 2FH VECTOR,
206 ; IT IS IMPORTANT THAT THE lower LEVEL IS VALID! THIS
207 ; IS VERIFIED BY SEEING IF THE ORIGINAL VECTOR <> 0000:0000.
208 ;
209 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
210 INIT_2: PUSH ES ;
211 XOR AX,AX ; SET ES TO INTERRUPT REGION
212 MOV ES,AX ;
213 MOV AX,ES:WORD PTR INT_2F_LOW;GET OFFSET VALUE OF INT 2F hex
214 MOV CS:ROM_INT_2F,AX ; &
215 MOV CX,ES:WORD PTR INT_2F_HI; ALSO THE SEGMENT VALUE
216 MOV CS:ROM_INT_2F+2,CX ;
217 OR AX,CX ; IS INT 2F hex = 0 ?
218 JNE INIT_6 ;
219 MOV AX,OFFSET ABORT ; YES: USE IRET AS THE LOWER CODE
220 MOV CS:ROM_INT_2F,AX ; REFER TO ABORT LABEL FOR IRET!
221 MOV AX,CS ;
222 MOV CS:ROM_INT_2F+2,AX ;
223 INIT_6: CLI ; NEXT CHANGE THE ACTIVE INT 2F hex
224 MOV ES:WORD PTR INT_2F_LOW,OFFSET INT_2F_COM;
225 MOV ES:WORD PTR INT_2F_HI,CS; TO THE NEWLY LOADED CODE (INT2FCOM)
226 STI ; (with interrupts off, of course)
227 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
228 ;
229 ; READ THE INTERRUPT 1F HEX FOR INT10COM MODULE
230 ; THIS IS READ DURING INITIAL LOAD TO RECORD THE
231 ; DEFAULT VALUE. THE CPS SUPPORT WILL not CHANGE
232 ; THE INT 1F HEX VECTOR IF IT WAS CHANGED FROM
233 ; THIS VALUE....ie. GRAFTABL.COM or other HAS THE
234 ; VECTOR.
235 ;
236 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
237 MOV CX,ES:WORD PTR INT_1F_LOW; GET OFFSET OF INTERRUPT 1FH
238 MOV CS:ROM_INT_1F,CX ; &
239 MOV CS:OLD_INT_1F,CX ;
240 MOV CX,ES:WORD PTR INT_1F_HI; SEGMENT OF INTERRUPT 1FH
241 MOV CS:ROM_INT_1F+2,CX ;
242 MOV CS:OLD_INT_1F+2,CX ;
243 ;
244 MOV CX,ES:WORD PTR INT_44_LOW; GET OFFSET OF INTERRUPT 44H
245 MOV CS:ROM_INT_44,CX ; &
246 MOV CX,ES:WORD PTR INT_44_HI; SEGMENT OF INTERRUPT 44H
247 MOV CS:ROM_INT_44+2,CX ;
248 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
249 ;
250 ; NOW MOVE ONTO INSTALLATION OF INT 10 HEX
251 ; THE INT 10H VECTOR IS TAKEN TO MONITOR THE
252 ; MODE_SET INTERFACE (AH=0). THIS IS THE KEY
253 ; TO THE CPS SUPPORT MECHANISM...ie. THE ACTIVE
254 ; CODE PAGE IS LOADED EVERYTIME A MODE_SET OCCURS!
255 ;
256 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
257 MOV CX,ES:WORD PTR INT_10_LOW; GET OFFSET OF INT 10H
258 MOV CS:ROM_INT_10,CX ; &
259 MOV CX,ES:WORD PTR INT_10_HI; SEGMENT OF INT 10H
260 MOV CS:ROM_INT_10+2,CX ;
261 CLI ; INSTALL THE NEW INT 10H CODE
262 MOV ES:WORD PTR INT_10_LOW,OFFSET INT_10_COM;
263 MOV ES:WORD PTR INT_10_HI,CS;
264 STI ; (with interrupts off, of course)
265 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
266 ;
267 ; INSTALL THE DEVICE DRIVER CODE. THE RESIDENT_END
268 ; VALUE HAS BEEN SET TO:
269 ;
270 ; 1 - REDUCED_SUPPORT used when #DESG = 0 (CGA, MONO)
271 ; 2 - LAST DESIGNATED BUFFER - calculated by #DESG x #FONTS
272 ;
273 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
274 POP ES ; RESTORE THE ES REGISTER
275 LES DI,DWORD PTR BUF.RH_PTRO; GET REQUEST HEADER ADDRESS
276 MOV AX,RESIDENT_END ; GET OFFSET OF RESIDENT END
277 MOV RH.RH0_ENDO,AX ;
278 INIT_7: MOV AX,RESIDENT_ENDS ; GET SEGMENT OF RESIDENT END
279 MOV RH.RH0_ENDS,AX ;
280 STC ; CY = 1, CALL FULLY SERVICED = ON
281 POP DS ;
282 RET ;
283 INIT ENDP ;
284 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
285 ;
286 ; DEVICE NAME PARSING IS LIMITED ONLY TO 1 DEVICE NAME
287 ;
288 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
289 DEVICE_NAMES DB "CON " ; ONLY ONE VALID NAME FOR DEVICE...
290 L_DEVICE_NAMES EQU ($-DEVICE_NAMES) ;
291 N_DEVICE_NAMES EQU ($-DEVICE_NAMES)/L_DEVICE_NAMES
292 ;
293 HANDLE_DEVICE_NAME PROC ; [ TABLE 3 ]
294 PUSH CX ;
295 PUSH SI ;
296 ;
297 MOV SI,[SI].OFFSET_LIST ;
298 MOV CX,[SI] ; TEST THAT DEVICE NAME IS 8 BYTES
299 ;
300 CMP CX,L_DEVICE_NAMES ;
301 JNE H_DN_0 ; LEN(DEVICE_NAME) <> 8, THEN ERROR
302 ;
303 PUSH ES ;
304 PUSH DI ;
305 ;
306 PUSH CS ;
307 POP ES ;
308 LEA DI,DEVICE_NAMES ; SET COMPARE STRING TO "CON "
309 INC SI ;
310 INC SI ; ADVANCE SI TO POINT TO DEVICE_NAME
311 REPE CMPSB ; CHECK OUT THE 1 NAME.....
312 POP DI ;
313 POP ES ;
314 JNE H_DN_0 ;
315 ;
316 POP SI ;
317 POP CX ;
318 CLC ;
319 RET ;
320 H_DN_0: POP SI ;
321 POP CX ;
322 CALL ISSUE_ERROR_1 ; ERROR OCCURRED...NOW ISSUE THE MESG
323 ;
324 STC ; TELL CALLER ABOUT ERROR!
325 RET ;
326 HANDLE_DEVICE_NAME ENDP ;
327 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
328 ;
329 ; THIS ROUTINE IS USED TO VERIFY THE ADAPTER 'NAME' AGAINST
330 ; THE SUPPORTED ONES. IF A MATCH IS FOUND THEN THE APPROPRIATE
331 ; CONFIGURATION TABLE IS LOADED INTO RESIDENT MEMORY, ELSE THE
332 ; 'CY' FLAG IS SET AND AN ERROR IS ISSUED.
333 ;
334 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
335 ID_NAMES DB "EGA " ;
336 L_ID_NAMES EQU ($-ID_NAMES) ;
337 DB "EGA 8 " ; INTERNAL USE ONLY
338 DB "EGA 14 " ; INTERNAL USE ONLY
339 DB "EGA 14M " ; INTERNAL USE ONLY
340 DB "LCD " ;
341 DB "MONO " ;
342 DB "CGA " ;
343 N_ID_NAMES EQU ($-ID_NAMES)/L_ID_NAMES
344 ;
345 HANDLE_DEVICE_ID PROC ; [ TABLE 4 ]
346 PUSH DI ;
347 PUSH CX ;
348 PUSH SI ;
349 ;
350 CALL MODIFY_ID_NAME ; THIS CALL IS USED TO CONVERT THE
351 JC HDID_4 ; 'EGA' CLASS TYPE INTO SUB-CATEGORY'S
352 ;
353 MOV SI,[SI].OFFSET_LIST ;
354 MOV CX,[SI] ; TEST THAT ID_NAME IS 8 BYTES
355 CMP CX,L_ID_NAMES ;
356 JNE HDID_4 ;
357 ;
358 INC SI ;
359 INC SI ; ADVANCE SI TO POINT TO ID_NAME
360 ;
361 LEA DI,ID_NAMES ; SET COMPARE STRING TO "DEVICEID"
362 MOV CX,N_ID_NAMES ;
363 ;
364 HDID_0: PUSH DI ; SAVE REGISTERS BETWEEN PASSES
365 PUSH ES ;
366 PUSH SI ;
367 PUSH CX ;
368 ;
369 PUSH CS ;
370 POP ES ;
371 MOV CX,L_ID_NAMES ;
372 REPE CMPSB ; TEST NAME (ALL 8 BYTES) AGAINST
373 ; THE NEXT NAME!
374 POP CX ;
375 POP SI ;
376 POP ES ;
377 POP DI ;
378 JE HDID_1 ;
379 ADD DI,L_ID_NAMES ;
380 LOOP HDID_0 ; TRY ALL ENTRIES FOR A MATCH...
381 HDID_4: ;
382 CMP NOT_CPS_ID,ON ; WGR did we find a non-CPS id? ;AN000;
383 JNE HDID_5 ; WGR no...not the problem..continue ;AN000;
384 STC ; WGR yes...so no message...but.. ;AN000;
385 JMP HDID_6 ; WGR set error for return ;AN000;
386 ;
387 HDID_5: ; WGR ;AN000;
388 POP SI ; IF NONE WERE FOUND, THEN ERROR...
389 POP CX ;
390 POP DI ;
391 ;
392 DEC SI ; BACK TO SUB-TYPE ID AND ISSUE
393 DEC SI ; THE ERROR MESSAGE.
394 CALL ISSUE_ERROR_1 ;
395 STC ; INFORM CALLER ABOUT THE ERROR!
396 RET ;
397 HDID_1: SUB CX,N_ID_NAMES ; ID NAME HAS BEEN FOUND
398 NEG CX ; NORMALIZE CX FOR TABLE INDEXING!!
399 ;
400 MOV DEVICE_ID_INDEX,CX ;
401 CLC ;
402 HDID_6: ; WGR ;AN000;
403 POP SI ;
404 POP CX ;
405 POP DI ;
406 RET ;
407 HANDLE_DEVICE_ID ENDP ;
408 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
409 ;
410 ; THIS ROUTINE CHECKS THE HARDWARE CP VALUE (if specified)!
411 ; THE VALUE OF THE HARDWARE CP IS NOT VERIFIED, ALLOWING
412 ; FUTURE ADAPTERS WITH non-437 HARDWARE PAGES.
413 ;
414 ; IF #HDWR_CP > 1 (FOR ANY DEVICES IN RELEASE 1.00) THEM
415 ; ERROR
416 ; ELSE
417 ; RECORD VALUE (1 WORD)
418 ; ENDIF
419 ;
420 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
421 HANDLE_HDWR_CP PROC ; [ TABLE 5 ]
422 PUSH CX ;
423 PUSH SI ;
424 MOV SI,[SI].OFFSET_LIST ;
425 MOV CX,[SI] ; GET THE NUMBER OF HDWR_CP'S
426 CMP CX,CPD_HDWR_N_MAX ; TEST IF GREATER THAN MAX ALLOWED!
427 JA H_HC_0 ;
428 ;
429 CMP CX,1 ; CHECK THE NUMBER OF HDWR CP's
430 JA H_HC_0 ; IF MORE THAN ONE..THEN WE HAVE A
431 ; PROBLEM....TELL USER!
432 PUSH CX ;
433 MOV CX,[SI+2] ; GET THE ACTUAL HARDWARE CP
434 CMP CX,-1 ; IS IT INVALID???
435 POP CX ;
436 JE H_HC_0 ;
437 ;
438 PUSH ES ;
439 PUSH DI ;
440 ;
441 PUSH CS ;
442 POP ES ;
443 LEA DI,CPD_HDWR_N ; POINT DESTINATION TO INTERNAL TABLE
444 INC CX ; ALSO ACCOUNT FOR COUNT N
445 REP MOVSW ; SI ALREADY POINTS TO 'N,CP1,CP2..'
446 ;
447 POP DI ;
448 POP ES ;
449 ;
450 POP SI ;
451 POP CX ;
452 CLC ;
453 RET ;
454 H_HC_0: POP SI ;
455 POP CX ;
456 ;
457 PUSH SI ; HARDWARE CP IN ERROR, PUT 'SI'
458 DEC SI ; BACK TO SUB-TYPE ID AND ISSUE
459 DEC SI ; THE ERROR MESSAGE.
460 DEC SI ; BACK TO SUB-TYPE ID AND ISSUE
461 DEC SI ; THE ERROR MESSAGE.
462 CALL ISSUE_ERROR_1 ;
463 POP SI ;
464 STC ;
465 RET ;
466 HANDLE_HDWR_CP ENDP ;
467 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
468 ;
469 ; THIS ROUTINE CHECKS THE LAST PARAMETER IN THE COMMAND LINE
470 ; IT CONTAINS THE INFORMATION FOR THE NUMBER OF DESIGNATES AND
471 ; AND THE NUMBER OF DISPLAY FONTS TO BE USED. ONLY MINIMAL
472 ; ERROR CHECKING OCCURS HERE.
473 ;
474 ; THE FOLLOWING IS A LIST OF THE POSSIBLE VALUE IN 'OFFSET_LIST'
475 ; ==============================================================
476 ;
477 ; COND: # 1 # 2 # 3
478 ; -----------------|--------------------|-----------------
479 ; TABLE: DW 0 DW 1 DW 2
480 ; DW ? DW n DW n
481 ; DW ? DW ? DW m
482 ;
483 ; DETAILS: no parameters only #desg both #desg
484 ; specified. specified & #font specified
485 ;
486 ; RESULT: #DESG = 0 #DESG = n #DESG = n
487 ; #FONT = 0 (maximum) #FONT = 0 (maximum) #FONT = m
488 ;
489 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
490 HANDLE_DESG_CP PROC ; [ TABLE 6 ]
491 PUSH AX ;
492 PUSH CX ;
493 PUSH DX ;
494 PUSH SI ;
495 MOV SI,[SI].OFFSET_LIST ;
496 ;
497 MOV CX,-1 ; SET #DESG DEFAULT = 1
498 MOV DX,-1 ; SET #FONT DEFAULT = 0 (maximum)
499 MOV AX,[SI] ; GET DESCRIPTOR FOR PARAMETER LIST
500 ;
501 OR AX,AX ; CHECK FOR <CONDITION #1>
502 JE H_DC_2 ; SET DRIVER TO DEFAULTS
503 ;
504 MOV CX,[SI+2] ;
505 CMP CX,CPD_DESG_N_MAX ; CHECK IF THIS VALUE IS ABOVE MAXIMUM!
506 JA H_DC_5 ;
507 CMP AX,ONE ; CHECK FOR <CONDITION #2>
508 JE H_DC_2 ; SET DRIVER TO DEFAULTS
509 ;
510 MOV DX,[SI+4] ; HAS TO BE <CONDITION #3>
511 ;
512 H_DC_2: MOV CPD_DESG_N,CX ; RECORD THE #DESG & THE
513 MOV CPD_FONTS_N,DX ; THE #FONT FROM THE SET VALUES
514 ;
515 POP SI ;
516 POP DX ;
517 POP CX ;
518 POP AX ;
519 CLC ;
520 RET ;
521 H_DC_5: POP SI ;
522 POP DX ;
523 POP CX ;
524 PUSH DX ; WGR ;AN000;
525 MOV AX,ERROR_3 ; WGR ;AN000;
526 MOV DH,UTILITY_MSG_CLASS ; WGR ;AN000;
527 CALL ISSUE_MESSAGE ; WGR ;AN000;
528 POP DX ; WGR ;AN000;
529 POP AX ; WGR ;AN000;
530 STC ;
531 RET ;
532 HANDLE_DESG_CP ENDP ;
533 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
534 ;
535 ; INSTALL_ID
536 ;
537 ; THIS ROUTINE PERFORMS THE DISPLAY_CONFIG TABLE
538 ; LOAD WHICH IS USED FOR THE REMAINDER OF THE SESSION
539 ;
540 ; INPUT:
541 ; DEVICE_ID_INDEX = INDEX TO LIST OF SUPPORTED DEVICES
542 ;
543 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
544 INSTALL_ID PROC ; ROUTINE TO INSTALL INFO FOR DEVICE
545 CALL INSTALL_TABLE ;
546 JNC INSI_3 ;
547 ;
548 PUSH SI ;
549 MOV SI,OFFSET TABLE ; ADDRESS [ TABLE 1 ]
550 MOV SI,[SI].DEVICE1_OFFSET ; MOVE FROM [ TABLE 1 ] TO [ TABLE 2 ]
551 ; INC SI ;
552 ; INC SI ;
553 CALL ISSUE_ERROR_1 ;
554 POP SI ;
555 STC ;
556 INSI_3: RET ;
557 INSTALL_ID ENDP ;
558 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
559 ;
560 ;
561 ;
562 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
563 INSTALL_TABLE PROC ;
564 PUSH AX ;
565 PUSH CX ;
566 PUSH DX ;
567 PUSH DI ;
568 PUSH SI ;
569 PUSH DS ;
570 PUSH ES ;
571 ;
572 PUSH CS ;
573 POP DS ;
574 PUSH CS ;
575 POP ES ;
576 ;
577 MOV AX,DEVICE_ID_INDEX ;
578 MOV CX,DC_ENTRY ;
579 MUL CX ;
580 LEA CX,DISPLAY_CONFIG ;
581 ADD CX,AX ;
582 ADD CX,8 ; ACCOUNT FOR 8 CHARACTER NAME
583 MOV DI,CX ;
584 ;
585 CALL INSTALL_MEMORY ;
586 JC IT_5 ;
587 ;
588 INC DI ; ACCOUNT FOR ENCODED MEMORY BYTES
589 MOV SI,[DI] ;
590 PUSH DI ;
591 MOV CX,NUM_MODES ;
592 LEA DI,LOAD_MECH ; DUPLICATE LOAD_MECH TABLE
593 REP MOVSB ;
594 POP DI ;
595 MOV SI,[DI+2] ;
596 MOV CX,NUM_MODES ;
597 LEA DI,FONT_SIZE ; DUPLICATE FONT_SIZE TABLE
598 REP MOVSB ;
599 CLC ;
600 ;
601 IT_5: POP ES ;
602 POP DS ;
603 POP SI ;
604 POP DI ;
605 POP DX ;
606 POP CX ;
607 POP AX ;
608 RET ;
609 INSTALL_TABLE ENDP ;
610 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
611 ;
612 ; INSTALL MEMORY
613 ;
614 ; ENTRY:
615 ; ES : DI = POINTER TO ENCODED SCAN LINES ALLOWED
616 ; EXIT:
617 ; CREATION OF CPD_FONT_PNTER TABLE
618 ; CALCULATION OF RESIDENT_END VALUE
619 ;
620 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
621 MEMORY_SIZE_INDEX LABEL WORD ; THIS CORRESPONDS TO THE MEM RQMENTS
622 DW 0,0,0,0 ;
623 DW 19*256+6 ;
624 DW 16*256+6 ;
625 DW 14*256+6 ;
626 DW 8*256+6 ; BYTE IN 'TABLES.SRC'.
627 NUM_MEMORY_SIZE EQU ($-MEMORY_SIZE_INDEX)/2
628 ;
629 INSTALL_MEMORY PROC ;
630 PUSH AX ;
631 PUSH BX ;
632 PUSH CX ;
633 PUSH DX ;
634 PUSH SI ;
635 PUSH DI ;
636 PUSH ES ;
637 ;
638 PUSH CS ;
639 POP ES ; SET EXTRA SEGMENT
640 ;
641 MOV AL,[DI] ; GET ENCODED VALUE FROM TABLE
642 CALL ASK_BIOS_SCAN_LINES ; IF PERMITTED...BIOS KNOWS SCAN LINES
643 ;
644 IM_0Y: PUSH AX ;
645 PUSH CX ;
646 MOV CX,NUM_MEMORY_SIZE ; COUNT THE NUMBER OF FONTS POSSIBLE
647 XOR DX,DX ; DX (INIT=0) WILL = #DIF FONT TYPES
648 IM_0A: SAL AL,1 ;
649 JNC IM_0B ;
650 INC DX ;
651 IM_0B: LOOP IM_0A ;
652 POP CX ;
653 POP AX ;
654 ; ELSE, STAY WITH INITIAL VALUE!!!!
655 MOV CX,CPD_FONTS_N ; FIRST CHECK TO SEE IF #FONTS>TYPE
656 CMP CX,DX ; FIND OUT IF > ALLOWED...
657 JBE IM_0P ; IF NOT, THEN
658 MOV CX,-1 ; SET BACK TO DEFAULT VALUE
659 ;
660 IM_0P: CMP CX,-1 ; CHECK FOR FONTS = DEFAULT VALUE
661 JNE IM_0R ;
662 MOV CPD_FONTS_N,DX ; SET TO THE MAXIMUM FOR THE HARDWARE
663 ;
664 IM_0R: MOV CX,CPD_DESG_N ;
665 CMP CX,-1 ; CHECK FOR #DESG = DEFAULT VALUE
666 JNE IM_0T ;
667 MOV CPD_DESG_N,DX ; DX = #FONTS ALLOWED FOR THIS DEVICE
668 OR DX,DX ; TEST IF > 0 ?
669 JZ IM_0T ;
670 MOV CPD_DESG_N,ONE ;
671 ;
672 IM_0T: CMP CPD_DESG_N,ZERO ; TEST VALUE OF DESIGNATED CP's
673 JE IM_8 ; IF THE #DESG=0, THEN REDUCED SUPPORT
674 ;
675 CMP CPD_FONTS_N,ZERO ; TEST VALUE OF FONTS, (knowing DESG>0)
676 JE IM_9 ; ERROR OCCURRED!!!
677 ;
678 IM_0: MOV BX,CPD_FONTS_N ; BX=#FONTS REQUESTED
679 MOV CX,NUM_MEMORY_SIZE ; CX = 8 BITS
680 LEA SI,MEMORY_SIZE_INDEX ; SI SETUP FOR MEMORY VALUES, CX=#FONTS
681 XOR DX,DX ; DX=buffer size (INIT=0)
682 IM_1: SAL AL,1 ; TEST NEXT BIT FOR ACTIVATION
683 JNC IM_2 ; IF NOT ON...THEN IGNORE
684 OR BX,BX ; TEST IF MORE FONTS REQUESTED...
685 JE IM_2 ;
686 DEC BX ; LESS #FONTS REQUESTED BY ONE
687 ADD DX,[SI] ; AND ADD THE LARGEST BUFFER SIZE ON
688 IM_2: INC SI ; ADVANCE MEMORY INDEX POINTER
689 INC SI ; ADVANCE MEMORY INDEX POINTER
690 LOOP IM_1 ;
691 ;
692 MOV AX,DX ; SET AX=completed buffer size
693 ;
694 IM_5: MOV CX,CPD_DESG_N ; NOW, SETUP POINTERS & CALC FONT BUFFER
695 LEA SI,CPD_FONT_PNTER ; FIND THE DATA_POINTERS
696 MOV DX,RESIDENT_END ; GET LAST USEABLE ADDRESS
697 ;
698 PUSH BX ; SAVE VALUE OF BX FOR RESTORATION...
699 MOV BX,ES ; SET ES TO BX SO PNTER IS 'BX:DX'
700 IM_6: PUSH DX ; SET SEGMENT:OFFSET OF BUFFER 'X'
701 SHR DX,1 ; STRIP OFF LOW 4 BITS OF OFFSET....
702 SHR DX,1 ; TO TOP OFF THE 'ES' SEGMENT REGISTER
703 SHR DX,1 ;
704 SHR DX,1 ;
705 ADD BX,DX ; AND MINIMIZE VALUE OF OFFSET
706 POP DX ;
707 AND DX,000FH ; THIS IS DONE TO PREVENT STRADDLING
708 MOV [SI],DX ; A SEGMENT BOUNDARY WITH THE DATA BUF
709 MOV [SI+2],BX ;
710 ;
711 ADD SI,4 ;
712 ADD DX,AX ;
713 LOOP IM_6 ;
714 ;
715 IM_7A: MOV RESIDENT_END,DX ; SET FINAL OFFSET & SEGMENT TO
716 MOV RESIDENT_ENDS,BX ; TERMINATE THE 'INIT' WITH
717 POP BX ;
718 CLC ;
719 JUMP IM_A ;
720 ;
721 IM_8: MOV DX,REDUCED_SUPPORT ; SET POINTER TO REDUCED SUPPORT
722 PUSH BX ;
723 MOV BX,ES ;
724 JUMP IM_7A ;
725 ;
726 IM_9: STC ;
727 IM_A: POP ES ;
728 POP DI ;
729 POP SI ;
730 POP DX ;
731 POP CX ;
732 POP BX ;
733 POP AX ;
734 RET ;
735 INSTALL_MEMORY ENDP ;
736 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; WGR
737 ; ; WGR
738 ; ISSUE MESSAGE ; WGR
739 ; ; WGR
740 ; THIS ROUTINE IS USED TO PERFORM THE MESSAGE ; WGR
741 ; RETRIVER. ; WGR
742 ; ; WGR
743 ; INPUT: ; WGR
744 ; AX = MESSAGE NUMBER ; WGR
745 ; DH = MESSAGE CLASS ; WGR
746 ; ; WGR
747 ; OUTPUT: ; WGR
748 ; none ; WGR
749 ; ; WGR
750 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; WGR
751 ISSUE_MESSAGE PROC ; ; WGR ;AN000;
752 PUSH DS ; WGR ;AN000;
753 PUSH BX ; WGR ;AN000;
754 PUSH CX ; WGR ;AN000;
755 PUSH CS ; WGR ;AN000;
756 POP DS ; WGR ;AN000;
757 MOV BX,STDERR ; WGR ;AN000;
758 XOR CX,CX ; WGR ;AN000;
759 XOR DL,DL ; WGR ;AN000;
760 CALL SYSDISPMSG ; WGR ;AN000;
761 POP CX ; WGR ;AN000;
762 POP BX ; WGR ;AN000;
763 POP DS ; WGR ;AN000;
764 RET ; WGR ;AN000;
765 ISSUE_MESSAGE ENDP ;
766 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
767 ;
768 ; ISSUE_ERROR_1
769 ;
770 ; THIS IS USED TO CONSTRUCT AND OUTPUT THE ERROR MESSAGE;
771 ;
772 ; DEVICE_ID + 'code page driver cannot be initialized'
773 ;
774 ; THE DEVICE_ID IS PULLED FROM THE COMMAND_PARSER. IF ONE
775 ; IS NOT DEFINED OR UNREADABLE, THEN A CONDENSED MESSAGE
776 ; WITHOUT THE DEVICE_ID IS USED.
777 ;
778 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
779
780 SUB_SIZE EQU 11 ; WGR sublist size ;AN000;
781 LEFT_ASCIIZ EQU 00010000B ; WGR left-aligned asciiz string ;AN000;
782 UNLIMITED EQU 0 ; WGR unlimited message size. ;AN000;
783 ; WGR ;AN000;
784 SUBLIST LABEL DWORD ; WGR ;AN000;
785 DB SUB_SIZE ; WGR ;AN000;
786 DB 0 ; WGR ;AN000;
787 MSG_PTR DW ? ; WGR ;AN000;
788 MSG_SEG DW SEG CODE ; WGR ;AN000;
789 DB 1 ; WGR ;AN000;
790 DB LEFT_ASCIIZ ; WGR ;AN000;
791 DB UNLIMITED ; WGR ;AN000;
792 DB 1 ; WGR ;AN000;
793 DB " " ; WGR ;AN000;
794 ;
795 ISSUE_ERROR_1 PROC ;
796 PUSH AX ;
797 PUSH BX ; WGR ;AN000;
798 PUSH CX ;
799 PUSH DX ;
800 PUSH SI ;
801 ;
802 MOV SI,[SI].OFFSET_LIST ; POINT TO NAME TO PRINTOUT
803 INC SI ;
804 INC SI ;
805 ;
806 PUSH SI ;
807 MOV CX,8 ; MAX LENGTH OF NAME
808 MOV AL,' ' ;
809 IN_0: CMP [SI],AL ;
810 JBE IN_3 ;
811 INC SI ;
812 LOOP IN_0 ;
813 IN_3: MOV AL,ZERO ; SET 0 TO TERMINATE ASCII STRING
814 MOV [SI],AL ; OVERWRITE LAST BYTE - THIS AFFECTS
815 ; DATA IMMEDIATELY AFTER NAME. NOT
816 ; IMPORTANT SINCE FOLLOWING DATA IS IN
817 ; ERROR
818 POP SI ; GET START OF NAME
819 MOV MSG_PTR,SI ; WGR ;AN000;
820 MOV MSG_SEG,CS ; WGR ;AN000;
821 MOV AX,ERROR_1 ; WGR ;AN000;
822 MOV BX,STDERR ; WGR ;AN000;
823 MOV CX,ONE ; WGR ;AN000;
824 XOR DL,DL ; WGR ;AN000;
825 LEA SI,SUBLIST ; WGR ;AN000;
826 MOV DH,UTILITY_MSG_CLASS ; WGR ;AN000;
827 CALL SYSDISPMSG ; WGR ;AN000;
828 ; WGR ;AN000;
829 POP SI ;
830 POP DX ;
831 POP CX ;
832 POP BX ; WGR ;AN000;
833 POP AX ;
834 RET ;
835 ISSUE_ERROR_1 ENDP ;
836 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
837 ;
838 ; MODIFY_ID_NAME
839 ;
840 ; THE USER NEED ONLY SPECIFY THE CLASS OF THE DISPLAY ADAPTER.
841 ; THE AVAILABLE DESCRIPTIONS ARE 'EGA, LCD, CGA, and MONO'.
842 ; THIS ROUTINE IS USED TO FURTHER DETAIL WHAT TYPE OF 'EGA'
843 ; CLASS. THIS IS USED SPECIFICALLY FOR THE EGA (1501200) ADAPTER
844 ; AND ITS MANY CONFIGURATION SETTINGS.
845 ;
846 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
847 MODIFY_NAME DB "EGA " ;
848 NEW_NAME DB "EGA 14M " ;
849 DB "EGA 14 " ;
850 DB "EGA 8 " ;
851 NUM_NEW_NAME EQU ($-NEW_NAME)/L_ID_NAMES
852 ;
853 NOT_CPS_ID DB OFF ; WGR device id does not support CPS ;AN000;
854 ;
855 MODIFY_ID_NAME PROC ;
856 PUSH DI ;
857 PUSH AX ;
858 PUSH BX ;
859 PUSH CX ;
860 PUSH SI ;
861 ;
862 MOV SI,[SI].OFFSET_LIST ; GET START OF ID_NAME
863 CMP WORD PTR [SI],EIGHT ; WGR ;AN000;
864 JE MIN_00 ; WGR ;AN000;
865 CALL GET_DEVICE_ID ; WGR ;AN000;
866 JNC MIN_00 ; WGR CPS id?...yes continue ;AN000;
867 MOV NOT_CPS_ID,ON ; WGR no....set flag ;AN000;
868 JMP MIN_4 ; WGR exit with carry set ;AN000;
869 MIN_00: ; WGR ;AN000;
870 INC SI ;
871 INC SI ; ADVANCE SI TO POINT TO ID_NAME
872 ;
873 PUSH SI ; MOVE A COPY OF THE NAME TO CPD_CLASS
874 PUSH ES ; BEFORE IT IS Revised....
875 PUSH CX ;
876 PUSH CS ;
877 POP ES ;
878 MOV CX,L_ID_NAMES ;
879 LEA DI,CPD_CLASS ;
880 REP MOVSB ;
881 POP CX ;
882 POP ES ;
883 POP SI ;
884 ;
885 LEA DI,MODIFY_NAME ; SET COMPARE STRING TO "EGA "
886 ;
887 PUSH DI ; SAVE REGISTERS BETWEEN PASSES
888 PUSH ES ;
889 PUSH SI ;
890 ;
891 PUSH CS ;
892 POP ES ;
893 MOV CX,L_ID_NAMES ;
894 REPE CMPSB ; TEST NAME (ALL 8 BYTES) AGAINST
895 ; THE NEXT NAME!
896 POP SI ;
897 POP ES ;
898 POP DI ;
899 JNE MIN_1 ; THIS MAY NOT BE THE MATCH....
900 ;
901 CALL ASK_BIOS_FONT_SIZE ; CHECK IF THIS IS AN ADVANCED EGA?
902 JNC MIN_1 ; IF CY=0, THEN ADVANCED...ELSE,
903 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
904 ;
905 ;
906 ;
907 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
908 MOV AH,12H ; SET FOR ALTERNATE SELECT, EGA INFO
909 MOV BL,10H ;
910 INT 10H ; ASK BIOS FOR INFORMATION
911 CMP BL,10H ; (CHECK IF THIS CALL IS INVALID?)
912 JE MIN_4 ; IF BL UNCHANGED, THEN NOT EGA!
913 ; ELSE, CL=SWITCH SETTINGS
914 MOV AX,L_ID_NAMES ; SET DEFAULT SUB-TYPE TO 1ST ENTRY
915 CMP BH,ONE ; IF ZERO THEN COLOUR, IF ONE THEN MONO
916 JE MIN_0 ;
917 ADD AX,L_ID_NAMES ; MOVE TO NEXT SUB-TYPE
918 AND CL,0FH ; STRIP OFF LEADING NIBBLE FROM SWITCH
919 CMP CL,9 ; SETTINGS AND TEST FOR 5154 CONFIG
920 JE MIN_0 ;
921 CMP CL,THREE ;
922 JE MIN_0 ; IF NOT 5154, 5151; THEN MUST BE 5153!
923 ADD AX,L_ID_NAMES ;
924 ;
925 MIN_0: ADD DI,AX ; SET UP INDEX REGISTER TO NEW SUBTYPE
926 PUSH DS ;
927 PUSH ES ;
928 ;
929 PUSH CS ;
930 POP ES ;
931 XCHG SI,DI ; SWITCH SOURCE-DESTINATION REGISTERS
932 MOV CX,L_ID_NAMES ;
933 REP MOVSB ; MOVE IN NEW STRING
934 POP ES ;
935 POP DS ;
936 ;
937 MIN_1: CLC ;
938 JUMP MIN_5 ;
939 MIN_4: STC ;
940 MIN_5: POP SI ; IF NOT FOUND, THEN ERROR...
941 POP CX ;
942 POP BX ;
943 POP AX ;
944 POP DI ;
945 RET ;
946 MODIFY_ID_NAME ENDP ;
947 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
948 ;
949 ;
950 ;
951 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
952 .XLIST
953 MSG_SERVICES <MSGDATA> ; WGR ;AN000;
954 MSG_SERVICES <DISPLAYmsg,LOADmsg,CHARmsg> ; WGR ;AN000;
955 MSG_SERVICES <DISPLAY.CL1> ; WGR ;AN000;
956 MSG_SERVICES <DISPLAY.CL2> ; WGR ;AN000;
957 MSG_SERVICES <DISPLAY.CLA> ; WGR ;AN000;
958 .LIST ;
959 ;
960 include msgdcl.inc ;
961 ;
962 CODE ENDS ;
963 END ;
964 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
965