; File SCREEN.S: Part of SIO2PC which contains ; routines which write to the screen and some ; keyboard related routines also. ; It also has the routines which get input from the ; keyboard ; This file contains: ; ; WS240; CLR_24; C_LINE; CLR_ALL; COLOR_BOX ; DO_TITLE; DO_MENU; COLOR_FFIELD; GET_PAGE ; VID_INIT; GET_SCRN; FIX_SCRN; PRINT1 ; PUT_LOC; PUT_SECNO; PT_STATS; TOG_STAT ; PUT_DEVID; PUT_ERCH; PUT_RAM; PRNT_LINE ; GET_TAIL; FLUSH; GET_TORK; WAIT4KEY; ALF ; CLR_SCRN; LINEFEED IS_A_KEY; GET_TAILS ; This subroutine prints a string terminated in $ at current ; cursor position. BP points to the string. It also expands tab ; chars using the PRNT_TAB routine. The tab function was added for ; the EPROM.S program, but I'm bringing it to SIO2PC R 3.12 for ; reference PRNT_LINE: PUSH DI,AX,BX MOV DI,0 L0: MOV AH,0Eh;; Write character MOV BH,VPAGE MOV AL,[BP+DI] CMP AL,'$' JE >L1 CMP AL, 9 ; TAB CHAR? JNE >L2 CALL PRNT_TAB JMP >L3 L2: PUSH BP, DI ; 3.16 for Chris Fleshner; maybe bad BIOS? INT 010h POP DI, BP L3: INC DI JMP L0 L1: POP BX,AX,DI RET ; The PRNT_TAB routine is usually called from PRNT_LINE when a ; tab (9) char is found. It prints the spaces found in TAB_LINE ; before the $. PRNT_TAB: PUSH DI,AX,BX,BP MOV BP, TAB_LINE MOV DI,0 L0: MOV AH,0Eh;; Write character MOV BH,VPAGE MOV AL,[BP+DI] CMP AL,'$' JE >L1 INT 010h INC DI JMP L0 L1: POP BP,BX,AX,DI RET ; CLEAR SCREEN ; A routine to clear the video screen in 80*25 mode ; No registers used or changed... ; VPAGE should point to video page in use. CLR_SCRN: PUSH AX,DS,CX,DI MOV DS,SCR_SEG MOV AL, ' ' ; byte to fill screen with MOV AH,CS:ATTR1; Attribute byte MOV CX,80*25 L1: MOV DI,CX DEC DI SHL DI,1; Word at a time, so DI = DI*2 MOV [DI],AX LOOP L1 POP DI,CX,DS,AX RET ; routine shift left and right nybbles of normal attribute for ; use as inverse attribute in memory fields: MAKE_INV: MOV AL, ATTR1 ; normal attribute used by clear screen routine MOV AH, AL MOV CL, 4 SHL AH, CL SHR AL, CL OR AL, AH AND AL, 07Fh ; mask high byte MOV INV_ATTR, AL RET ; SCREEN BLANK BLANKIT: CALL CLR_SCRN PSTATUS SAY_BLANK, ATTR9 TICKS 48 CALL CLR_ALL CMP BLANK, 0 ; already in blank mode?? JNE > L2 MOV BLANK, 0FFh MOV AL, D_STLINE MOV OLD_DST, AL MOV D_STLINE, 0FFh L2: RET ; clear the 3 info lines CLR_INFO: CURSET C_INFO1 PUT_CHARS ATTR9, ' ', 240 RET ; Routine to get and store the current VPAGE in use: GET_PAGE: PUSH AX,BX MOV AH,0Fh INT 010h MOV VPAGE,BH POP BX,AX RET ; DO_TITLE ; This routine prints the opening screen, with author credits and ; ordering information. DO_TITLE: CALL CLR_SCRN PRINTL TTL1 RET ; DO_MENU ; This routine prints the SIO-2-PC menu to the screen... DO_MENU: MOV AL, REV_FLAG; Get 'i' or space MOV TX1A, AL ; And put it in title rev field CALL COLOR_BOX CURSET 0112h POINT4: PRINTL TX1 CURSET 0404h PRINTL TX3 CURSET 042ch PRINTL TX35 CURSET 0504h PRINTL TX4 CURSET 052Ch PRINTL TX5 CURSET 0604h PRINTL TX7 CURSET 062Ch PRINTL TX8 CURSET 0704h PRINTL OPT3 CURSET 072Ch PRINTL TX10 CURSET 0804h PRINTL TX14 CURSET 082Ch PRINTL OPT5 CURSET 0904h PRINTL OPT4 CURSET 092Ch PRINTL OPT2 CURSET 0A04h PRINTL OPT6 CURSET 0B2Ch; REV 3.01 ADDED OPTION 'J' PRINTL TX9 CURSET 0A2Ch PRINTL TX9A CURSET 0B04h PRINTL OPT7 CALL PT_STATS CALL SU_DSKHDR RET ; COLOR_BOX puts the color attributes into their fields and ; makes the double line menu box. COLOR_BOX: ; first the title line CURSET 0111h PUT_CHARS ATTR2, ' ', 46 ; now, top and bottom lines of box: CURSET 0300h PUT_CHARS ATTR3, 205, 80 CURSET 0C00h PUT_CHARS ATTR3, 205, 80 ; the vertical double lines: CURSET 0400h PUT_CHARS ATTR3, 186, 640 ; fill in left window with attributes: POINT1: MOV CX,8 ; 8 rows L1: PUSH CX MOV AH,02 ; set cursor MOV BH,VPAGE MOV DH,CL ADD DH,3 ; rows 11 thru 4 MOV DL, 1 ; column 1 INT 010h ; set the cursor PUT_CHARS ATTR4, ' ', 39 POP CX LOOP L1 ; do it again for the right window: POINT2: MOV CX,8 ; 8 rows L1: PUSH CX MOV AH,02 ; set cursor MOV BH,VPAGE MOV DH,CL ADD DH,3 ; rows 11 thru 4 MOV DL, 41 ; column 41 for second window INT 010h ; set the cursor PUT_CHARS ATTR4, ' ', 38 POP CX LOOP L1 ; fill in the rest of the "fittings" for the box: CURSET 0C4Fh ;; lower right - row 12, col 79 PUT_CHARS ATTR3, 188, 1 CURSET 0300h PUT_CHARS ATTR3, 201, 1 CURSET 034Fh PUT_CHARS ATTR3, 187, 1 ;; upper right CURSET 0C00h PUT_CHARS ATTR3, 200, 1 ;; lower left CURSET 0328h ;; center top PUT_CHARS ATTR3, 203, 1 ;; tee down CURSET 0C28h ;; center bottom PUT_CHARS ATTR3, 202, 1 ;; tee up ; now, highlited fields within the menu box: CURSET 0618h ; Port # field PUT_CHARS ATTR13, ' ', 3 CURSET 0942h ; HEX address field PUT_CHARS ATTR13, ' ', 6 CURSET 0818h ; LOCKED/AUTO flag PUT_CHARS ATTR13,' ', 8 ; put black vertical borders on the window sides: POINT3: MOV AH,ATTR1 MOV AL, ' ' MOV ES, SCR_SEG MOV DI,(80*4)*2 ; initial cursor row MOV CX, 8 ; counter for 8 rows L1: MOV ES:[DI+2], AX ; col 1 MOV ES:[DI+78], AX ; col 39 MOV ES:[DI+82], AX ; col 41 MOV ES:[DI+156], AX ; col 78 ADD DI, 160 ; go to next row LOOP L1 PUSH CS POP ES PUSH CS POP DS ; now, put the color attributes for the field labels on the bottom ; (status) line: CURSET 1800h ; row 24, col 0 PUT_CHARS ATTR11, ' ', 80 ; put the color attributes for the entry fields within the status ;line MOV AL, ATTR12 MOV DS, SCR_SEG MOV SI, 24*160 ; start of bottom line MOV [SI+11], AL ; LOC MOV [SI+27], AL ; CMND MOV [SI+43], AL ; LAST MOV [SI+57], AL ; DEV MOV [SI+59], AL ; DEV MOV [SI+73], AL ; COM MOV [SI+87], AL ; ERR MOV CX, 5 L1: MOV [SI+103], AL INC SI INC SI LOOP L1 SUB SI, 10; put it where it was MOV [SI+125], AL MOV [SI+127], AL MOV [SI+129], AL MOV [SI+131], AL MOV [SI+149], AL; REV 3.01 FOR SPEED STATUS ; put attributes to info lines 18, 19, 20: PUSH CS POP DS CURSET 1200h ; line 18 PUT_CHARS ATTR9, ' ', 320 RET ; COLOR_FFIELD looks at the letter in WRITTN and puts the appropriate ; color attribute into the filename field pointed to by BP: COLOR_FFIELD: PUSH DI, DX, CX, BX, AX CMP B[WRITTN+BP], 'F' JNE >L1 MOV BL, ATTR8 JMP DO_COLIT L1: CMP B[WRITTN+BP],'W' JNE >L1 MOV BL, ATTR6 JMP DO_COLIT L1: CMP B[WRITTN+BP], 'N' JNE >L1; R 3.05 MOV BL, ATTR7 JMP DO_COLIT MOV BL, ATTR5; for no file, same as first part of line L1: CMP B[WRITTN+BP], 'S'; 3.05 MOV BL, ATTR9 ; Now, see which line BP points to: DO_COLIT: MOV CX, BLOCK_SIZE MOV DX, 0 MOV AX, BP DIV CX ; Yields 0, 1, 2, 3 in AL ; below: ROW 1 = 0Eh, COL FOR WRITTN = 20, 1 = offset to attribute MOV DI, 160*0Eh + 20*2 +1 MOV CX, 160 ; bytes per screen line MUL CX ; offset for line # in AX ADD DI, AX MOV ES, SCR_SEG CMP B[WRITTN+BP],'W'; 3.05: make sure 'W' gets put... JNE >L1 MOV BYTE PTR ES:[DI-1],'W' L1: MOV CX, 60; 60 chars in field to be colored ; Loop to fill alternating attr bytes with color: L1: MOV ES:[DI], BL INC DI INC DI LOOP L1 POP AX, BX, CX, DX, DI RET ; PT_STATS fills in the PRINT_THRU fields in the menu box PT_STATS: CURSET PFLD_CURS CMP [PRINTHRU], 0 JNE >L1 PUT_CHARS ATTR4, ' ', 18 RET L1: PRINTLA OPT5A, ATTR13 CMP [APRNDEV], 'P' JNE >L1 PRINTLA OPT5P, ATTR13 L1: CMP [APRNDEV], 'F' JNE >L1 PRINTLA OPT5F, ATTR13 L1: CMP [APRNDEV], 'S' JNE >L1 PRINTLA OPT5S, ATTR13 L1: CMP [EOLFIX], 0 JE >L1 PRINTLA OPT5B, ATTR13 L1: CMP [LF_TOO], 0 JE >L1 PRINTLA OPT5D, ATTR13 L1: CMP CONV_TAB, 0 JE >L1 PRINTLA OPT5E, ATTR13 L1: CMP [PRNMASK], 01111111xB JNE >L1 PRINTLA OPT5C, ATTR13 L1: RET ; DIR_BOX creates the box for the directory list DIR_BOX: BOX DB_ROW, DB_COL, DB_WIDE, DB_HIGH, 0, WHITE RET ; DO_MONO makes all color attributes = 07 for systems showing ; mono video (as shown by the COLOR flag) DO_MONO: MOV CX, 13 ; 13 attribute bytes MOV DI, 0 L1: MOV [ATTR1+DI], 07h INC DI LOOP L1 RET ; SU_DSKHDR - A routine to print the ramdisk heading info ; for the 4 status lines on screen. SU_DSKHDR: PUSH BP MOV DH,0Eh ; REV 1.02 CALL C_LINE; "" (FOUR PLACES) ; CURSET 0E00h PRINTL S_DISK MOV DH,0Fh CALL C_LINE ; CURSET 0F00h MOV BP,OFFSET S_DISK + BLOCK_SIZE CALL PRNT_LINE MOV DH,010h CALL C_LINE ; CURSET 01000h MOV BP, OFFSET S_DISK + 2*BLOCK_SIZE CALL PRNT_LINE MOV DH,011h CALL C_LINE ; CURSET 01100h MOV BP, OFFSET S_DISK + 3*BLOCK_SIZE CALL PRNT_LINE ; CURSET 01700h MOV BP,0 MOV CX, 4 L1: PUSH CX CALL COLOR_FFIELD ADD BP, BLOCK_SIZE POP CX LOOP L1 POP BP RET ; GET_SCRN - a routine to get the screen segment and ; store it in the SCR_SEG word variable. GET_SCRN: PUSH AX,BX MOV BX,0B800h ; Color card alpha screen segment MOV SCR_SEG,BX; Assume color MOV COLOR, 0FFh INT 011h ; Get equipment information AND AX,030h ; bits 5 & 6 set means Mono card CMP AX,030h JNE >L1 MOV BX,0B000h ; 0B000 if Mono card MOV SCR_SEG,BX MOV COLOR, 0 L1: POP BX,AX RET VID_INIT: INT 011h; Get equipment information MOV CL,03; Mode for all but MDA adapter; 4.07 - was mode 02 before AND AX,030h CMP AX,030h; 30 means MDA adapter JNE >L1 MOV CL,07; Mode for MDA adapter L1: MOV AL,CL MOV AH,00 INT 010h; Set video to mode in AL, and clear MOV AH,05 MOV AL,00 MOV VPAGE,AL INT 010h; Set display page 0 CALL MAKE_INV ; 4.11 get inverse video attribute RET ; C_LINE ; This routine clears the line of row # found in DH ; Also returns cursor to start of line C_LINE: PUSH BP,CX,AX,BX MOV DL,0; Col = 0 PUSH DX MOV BH,VPAGE MOV AH,02 INT 010h; BIOS function to position cursor ; Put 80 chars without changing attribute: MOV AH, 0Ah MOV AL, ' ' MOV BH, VPAGE MOV CX, 80 INT 010h ; PUT_CHARS ATTR1, ' ', 80 POP DX; Now return cursor to start of line MOV AH,02 INT 010h POP BX,AX,CX,BP RET ; CLR_ALL ; This routine clears the INFO (20-22) and STATUS (23) lines. ; To prevent a scroll, this program avoids the bottom (24) line. CLR_ALL: PUSH DX CALL CLR_INFO MOV DH,21 CALL C_LINE MOV DH,22 CALL C_LINE MOV DH,23 CALL C_LINE POP DX RET ; PRINT1 ; This subroutine prints the character in AL to the screen ; at current cursor location. 4.11 saved DI PRINT1: PUSH BX,AX,DI MOV AH,0Eh MOV BH,VPAGE INT 010h POP DI,AX,BX RET ; A subroutine using MACRO W_SCRN to print STAT_LINE to line #24, col #0: WS240: PUSH SI MOV SI, OFFSET STAT_LINE W_SCRN 24, 0 POP SI RET ; A subroutine using W_SCRN to clear line #24 without scroll. CLR_24: PUSH SI MOV SI, OFFSET BLANK_LINE W_SCRN 24,0 POP SI RET ; Subroutines to put the letter in AX to LOCATION, COMMAND, LASTCOM, ; ATARI, & COMLINE fields: PUT_LOC: #IF CARLM CMP CARL,0; DON'T UPDATE IN REMOTE KYBD MODE JNE >L1 #ENDIF #IF NOT DEBUGX RET ; 4.09 get rid of this routine #ENDIF CMP D_STLINE,0; D_STLINE is user's choice of display or JNE >L1; don't display status line. (0 = display) CMP [LAST_LOC],AL; Don't do it if letter is already there JE >L1 PUSH DI MOV DI, 24*160 + 10; REV 3.00 PUSH DS MOV AH, ATTR12 MOV DS, SCR_SEG MOV [DI], AX POP DS MOV [LAST_LOC],AL POP DI L1: RET ; PUT_SECNO gets the sector # from CFAUX1/2 and puts to the status ; line PUT_SECNO: #IF CARLM CMP CARL,0; DON'T UPDATE IN REMOTE KYBD MODE JNE >L4 #ENDIF CMP CMND, 'R' JE >L1 CMP CMND, 'W' JE >L1 CMP CMND, 'P' JE >L1 L4: RET; don't put sector # if N/A to command L1: PUSH SI,DI,AX MOV DI, OFFSET LSD_SECNO MOV AL, CFAUX1 MOV AH, CFAUX2 CALL INT2DEC ; that gets it into STAT_LINE, now, do a byte by byte compare for ; the screen ram CMP D_STLINE,0 JNE ADP MOV ES, SCR_SEG MOV DI, 24*160+110 ; point to LSD of screen string MOV SI, OFFSET LSD_SECNO MOV CX, 5 ; 5 digit compare ADO: MOV AL, [SI] CMP ES:[DI],AL JE >L1 MOV ES:[DI],AL L1: DEC SI DEC DI DEC DI LOOP ADO ADP: POP AX,DI,SI RET ; PUT_RAM will put the amount of ram in KB to the STATUS line ; **** REMEMBER: When Print_thru is active and selected to the SCREEN ; The status line will not be updated! This is not an error! PUT_RAM: #IF CARLM CMP CARL,0; DON'T UPDATE IN REMOTE KYBD MODE JE >L1 RET L1: #ENDIF PUSH BX,AX,DI MOV DI, OFFSET RAM_SPOT + 4 MOV AX, RAM ; Get # of paragraphs SUB DX, DX MOV BX, 64 ; # paragraphs/64 = #Kbytes DIV BX CALL INT2DEC ; now move into the STAT_LINE field MOV AL, B[RAM_SPOT+4] MOV [LSD_RAM],AL MOV AL, B[RAM_SPOT+3] MOV [LSD_RAM-1], AL MOV AL, B[RAM_SPOT+2] MOV [LSD_RAM-2], AL CMP D_STLINE, 0 JNE >L1 MOV ES, SCR_SEG MOV DI, 24*160+128 MOV AL, B[RAM_SPOT+4] MOV ES:[DI], AL MOV AL, B[RAM_SPOT+3] MOV ES:[DI-2], AL MOV AL, B[RAM_SPOT+2] MOV ES:[DI-4], AL L1: POP DI,AX,BX RET ; Put status of ultraspeed to status line: PUT_SPEED: #IF CARLM CMP CARL,0; DON'T UPDATE IN REMOTE KYBD MODE JNE >L3 #ENDIF PUSH AX PUSH DI PUSH ES CMP D_STLINE,0 JNE L1 MOV ES, SCR_SEG MOV DI, 24*160 + 148 MOV AL, SPEED MOV AH, ATTR12; get color MOV ES:[DI],AX L1: POP ES POP DI POP AX L3: RET ; With the rev 3.00 logic, PUT_COM will only change the LAST_CMND ; field if the current command has changed. The idea is to keep ; the last DIFFERENT command in LAST_CMND, instead of automatically ; stepping the CURRENT command over to LAST. PUT_COM: #IF CARLM CMP CARL,0; DON'T UPDATE IN REMOTE KYBD MODE JNE XAAA #ENDIF MOV AL, CMND CMP CUR_CMND, AL JE XAAA PUSH DI,BX MOV BL, CUR_CMND ; save a copy CMP D_STLINE, 0 ; 0 means DO update screen JNE >L1 MOV AH, ATTR12 ; REV 3.00 MOV DI, 24*160 + 26 MOV ES,SCR_SEG MOV ES:[DI], AX ; Put new command direct to screen L1: MOV CUR_CMND, AL ; and to string field CMP LAST_CMND, BL ; Has the last command changed? JE ADN CMP D_STLINE, 0 JNE >L1 MOV BH, ATTR12 MOV DI,24*160 + 42 MOV ES:[DI],BX ; Put old command L1: MOV LAST_CMND, BL ADN: POP BX,DI XAAA: RET ; PUT_DEVID is called with 2 HEX digits in BX, low in BH and ; high in BL: PUT_DEVID: #IF CARLM CMP CARL,0; DON'T UPDATE IN REMOTE KYBD MODE JNE >L3 #ENDIF PUSH AX CMP D_STLINE,0 JE >L2 ; Rev 3.01 fixed location of stmt below MOV [LAST_DEVID], BX JMP AAB L2: CMP [LAST_DEVID],BX; Don't put if no change JE AAB MOV AH, ATTR12 MOV [LAST_DEVID],BX XCHG AL,BL PUSH DI MOV DI, 24*160 + 56 ; REV 3.00 PUSH DS MOV DS,SCR_SEG MOV [DI],AX INC DI INC DI XCHG AL,BH MOV [DI], AX L1: POP DS POP DI AAB: POP AX L3: RET PUT_CLINE: CMP D_STLINE,0 JNE AAC CMP LAST_CLINE, AL JE AAC MOV LAST_CLINE, AL PUSH DI MOV DI,24*160 + 72; REV 3.00 PUSH DS MOV AH, ATTR12 MOV DS,SCR_SEG CMP [DI],AX JE >L1 MOV [DI], AX L1: POP DS POP DI AAC: RET ; Put the char found in B[ERR_CHAR] to the ERROR field of DEBUG line. PUT_ERCH: #IF CARLM CMP CARL,0; DON'T UPDATE IN REMOTE KYBD MODE JNE >L1 #ENDIF CMP D_STLINE,0 JNE >L1 PUSH AX MOV AH,ATTR12 ; Background attribute MOV AL,ERR_CHAR CMP LAST_EROR, AL JE ADM MOV LAST_EROR, AL PUSH DI MOV DI,24*160 + 86 PUSH DS MOV DS,SCR_SEG MOV [DI], AX POP DS POP DI ADM: POP AX L1: RET ; TOG_STAT - toggles the status of the ERROR status line TOG_STAT: PUSH DX CMP D_STLINE,0 JE ABF SUB DH,DH ; set flag to 0 MOV D_STLINE, DH CALL WS240 ; put up the status line JMP >L1 ABF: MOV DH,0FFh ; make status flag <> 0 MOV D_STLINE, DH CALL CLR_24 ; clear line #24 ; MOV LAST_DEVID,0 ; Flag no DEVID in field L1: POP DX RET REDO_STAT: CMP D_STLINE,0 JE >L1 CALL CLR_24 RET L1: CALL WS240 RET ; A routine to fix a screen that has been trashed by a scroll ; Note, above routines JMP to and return from this routine, so don't ; move it. FIX_SCRN: CMP BLANK, 0 ; in SCREEN BLANKED mode?? JZ > L1 MOV AL, OLD_DST MOV D_STLINE, AL L1: MOV BLANK, 0 MOV ERR_CHAR, ' '; 3.05 CALL PUT_ERCH CALL VID_INIT; TO CLEAR SCREEN CALL DO_MENU CALL REDO_STAT; Fix status line back per choice PSTATUS RUNNG, ATTR9; REV 3.15 ADDED THESE 2 LINES CURSET 01700h RET ; GET_TAIL - A routine which returns the characters ; found in the command tail. A pointer variable, ; TAIL_PT points to the next byte. It must be ; initialized to 081 by the user. The tail byte is ; returned in AL and the pointer is incremented. ; At the end of the tail, 0 is returned and the ; pointer remains at the end. Note: tail starts at ; CS:080. First byte is count. Variable TAIL_CNT ; must be inititlized to value in CS:080. GET_TAIL: PUSH SI MOV AL,TAIL_CNT CMP AL,0 JE >L1 MOV SI, WORD PTR TAIL_PT AND SI,0FFh; Mask off high byte of SI MOV AL,[SI]; Get character INC TAIL_PT; point to next char DEC TAIL_CNT; dec. counter L1: POP SI RET ; GET_TAILS is to get a string from the command tail. It gets bytes from ; the current position of the tail and moves them to [DI]. It returns ; when it encounters a space, 0Dh, or the end of the command tail. ; It doesn't move the space, or 0Dh to the field. It returns with ; DI pointing to the next available byte in the field. ; added rev 4.11 Make sure TAIL_CNT isn't 0 before calling ... GET_TAILS: CALL GET_TAIL CMP AL, ' ' ; space? JE > L1 CMP AL, 0Dh ; CR? JE > L1 MOV [DI], AL ; none of above, so put in field INC DI CMP TAIL_CNT, 0 JNE GET_TAILS ; tail not empty L1: RET ; FLUSH ; Flushes out the type-ahead buffer and also zeroes the command ; tail. FLUSH: PUSH AX,DX MOV AH,0Ch; Flush MOV AL,06h; same as function AH=06 MOV DL,0FFh; get char, if available. (If ZF=0 char is in AL) INT 021h MOV TAIL_CNT,0 POP DX,AX RET ; SUBROUTINES FOR THE ATARI INTERFACE ; GET_TORK gets a char from cmnd tail or from kybd if ; if tail is empty, doesn't write it to the screen. GET_TORK: PUSH BX CALL GET_TAIL CMP AL,0; 0 means end no tail chars available JNE >X1; OK, use char from tail ... else: ; See if we are in REMOTE CONTROL mode, if so return 27 to ; cancel, and set REMOTE to 0 to take out of REMOTE mode. CMP REMOTE,0 JE >L1 MOV AL,27 MOV REMOTE,0 POP BX RET ; Get a character from keyboard: L1: MOV AH,0 INT 016h; Returns char in AL X1: POP BX RET ; was labelled AAH - 3.17 change ; get up gets a char and converts it to uppercase if it's a letter GET_UP: PUSH DI CALL GET_TORK CALL TO_UPPER POP DI RET ; ROUTINES FOR CARL MANGARONI'S INTERFACE CM_LOOP: #IF CARLM ; first, see if PC operator has changed status of caps lock? MOV AH, 02 ; get keyboard flags INT 016h AND AL, 01000000xB; mask all but caps lock status CMP AL, CAPS_STAT JE >L1 ; skip if not changed MOV CAPS_STAT, AL ; becomes new status AND AL, AL ; is it zero (lower case?) JNE >L2 MOV AL, 69 ; for caps/lower key, unshifted JMP >L3 L2: MOV AL, 69 + 128; for caps/lower key, shift depressed L3: CALL SEND_KEY ; Now, get the key waiting L1: ; I'm going to try to flush the keyboard buffer ; by making its tail pointer = its head pointer + 2 ; which should mean it contains only one character. MOV AX, 0040; BIOS DATA SEGMENT PUSH AX POP ES MOV AX, ES:[001A] INC AX INC AX CMP ES:[001C], AX JBE > K1 MOV ES:[001C], AX K1: PUSH DS POP ES MOV AH, 0; get key INT 016h ; MOV AH, 0Ch ; flush keyboard buffer ; MOV AL, 07h ; get keyboard character ; INT 021h ; MOV CUR_KEY, AL AND AL, AL ; 0 means extended (function) key JNE > L5 CALL CONSOLE RET L5: CMP AL, 1 ; control-A same function as F10 JNE >L6 ; because my debugger intercepts F10 and won't JMP CM_OUT ; let me turn off remote kybd mode L6: CMP AL, 128 ; I don't send anything > 128 JA > L5 ; first, put it to the PC's screen: PUSH AX MOV AH, 0Eh ; write char in teletype mode MOV BH, VPAGE INT 010h ; call bios to write char POP AX ; if a CR was sent, send a LF also CMP AL, 13 JNE >L1 PUSH AX MOV AH, 0Eh MOV BH, VPAGE MOV AL, 10 ; linefeed INT 010h POP AX ; Now, translate and send to Atari: L1: ; CMP AL, CUR_KEY ; JNE > L4 ; CMP DLY_YET, 0 ; JNE > L4 QRZ1: ; TICKS 15 ; first time repeat: hold 0.5 sec ; MOV DLY_YET, 0FFh; Only do it once! ;L4:; MOV CUR_KEY, AL MOV BX, C_TABLE; set up to translate XLAT ; gets char at C_TABLE + AL into AL AND AL, AL JE > L5 ; 0 in table means char doesn't translate ; CALL SEND_KEY JMP >L5 ; L5 is label where key processing is finished, now look at joysticks ; L5: RET ; Routine to send a key data byte to the Atari: ; data expected to be in AL register SEND_KEY: MOV DX, PP_OUT1 ; get address of parallel port to DX OUT DX, AL ; put data out parallel port MOV DX, PP_OUT2 MOV AL, 8 ; enable latch 3 (-init low) OUT DX, AL ; TICKS 2 ; wait 2/18ths of a second CALL ONETICK ; CALL ONETICK MOV DX, PP_OUT2 MOV AL, 12 ; reset port control lines OUT DX, AL ; CALL ONETICK RET ; call CONSOLE when a byte is to be sent affecting SYSRES, ; OPTION, SELECT, START, CARTRIDGE, OR POWER. i.e. - any byte ; which goes to latch U2: OR i.e. when an "F" key is pressed CONSOLE: CMP AH, 043h ; F9 toggles joystick mode JNE >L1 CALL JOY_ON RET L1: CMP AH, 044h ; F10 means toggle remote kybd off JNE >L1 CM_OUT: MOV CARL, 0 PSTATUS CM_OFF, ATTR9 TICKS 25 CALL FIX_SCRN RET L1: MOV AL, AH ; this routine entered with code in AH CMP AL, 03Bh ; turn power on? F1 key JNE >L1 CALL PWR_ON RET L1: CMP AL, 03Ch ; Cartridge on; F2 key JNE >L1 CALL CART_O RET L1: CMP AL, 069h ; Cartridge off; Alt-F2 JNE >L1 CALL CART_O RET L1: CMP AL, 068h ; power off; Alt-F1 JNE >L1 CALL PWR_OFF RET L1: CMP AL, 03Fh ; system reset; F5 JNE > L1 CALL SYS_RES RET L1: CMP AL, 040h ; OPTION, F6 JNE >L1 MOV AL, 2 ; OPTION bit CALL OPSLST ; option/select/start RET L1: CMP AL, 041h ; SELECT, F7 JNE >L1 MOV AL, 4 CALL OPSLST RET L1: CMP AL, 042h ; START, F8 JNE >L1 MOV AL, 8 CALL OPSLST L1: RET ; Subroutine to turn Atari power ON PWR_ON: OR A_CTRL, 10000000xB ; turn bit 7 on MOV AL, A_CTRL MOV DX, PP_OUT1 OUT DX, AL MOV BX, 5 ; for about 5 uS delay CALL TIMER_0 ; in TIME.S source code file MOV AL, 14 ; to latch U2 chip data MOV DX, PP_OUT2 OUT DX, AL MOV BX, 10 ; about 10 uS to latch CALL TIMER_0 MOV AL, 12 ; latch back to normal OUT DX, AL RET PWR_OFF: AND A_CTRL, 01111111xB ; turn bit 7 off MOV AL, A_CTRL MOV DX, PP_OUT1 OUT DX, AL MOV BX, 5 CALL TIMER_0 MOV AL, 14 MOV DX, PP_OUT2 OUT DX, AL MOV BX, 10 CALL TIMER_0 MOV AL, 12 OUT DX, AL RET ; CARTRIDGE ON/OFF CONTROL: ; THE F2 & alt-F2 keys will toggle cartridge on/off: CART_O: CMP AL, 03Ch ; turn on? JNE >L1 AND A_CTRL, 255 - 64 ; clear bit 6 3.15 was 256 JMP >L3 L1: OR A_CTRL, 64 ; set bit 6 L3: MOV AL, A_CTRL MOV DX, PP_OUT1 OUT DX, AL MOV BX, 5 CALL TIMER_0 MOV AL, 14 MOV DX, PP_OUT2 OUT DX, AL MOV BX, 10 CALL TIMER_0 MOV AL, 12 OUT DX, AL ; Now, do we need to turn the power off, then on? TEST A_CTRL, 10000000xB ; power on bit set? JZ >L2 ; if already off, don't bother CALL PWR_OFF TICKS 36 ; wait 2 seconds CALL PWR_ON L2: RET ; SYSTEM RESET: SYS_RES: OR A_CTRL, 1 ; bit 0 is system reset MOV AL, A_CTRL MOV DX, PP_OUT1 OUT DX, AL CALL LATCH_U2 TICKS 5 ; hold for about 1/3 second AND A_CTRL, 0FFh - 1 ; clear bit 0 (release system reset) MOV AL, A_CTRL MOV DX, PP_OUT1 OUT DX, AL CALL LATCH_U2 RET ; JOY_ON toggles the joystick monitoring function on and off ; when the F9 key is pressed. JOY_ON: XOR JOY, 0FFh; toggle JOY to opposite state JNZ > L1 PSTATUS JOY_NO, ATTR9 JMP >L2 L1: PSTATUS JOY_YES, ATTR9 L2: TICKS 25 RET SEND_JOY: MOV AL, JOYSTAT ; get joystick status MOV DX, PP_OUT1 ; get address of parallel port to DX OUT DX, AL ; put data out parallel port CALL LATCH_U1 ; latch it RET ; LATCH U2 latches the data onto chip U2 ; it toggles the latch line (-autofd) and holds it for about 14 uS ; then returns it to its resting state. LATCH_U2: PUSH AX, BX, DX MOV DX, PP_OUT2 MOV AL, 14 OUT DX, AL MOV BX, 14 CALL TIMER_0 MOV AL, 12 OUT DX, AL POP DX, BX, AX RET ; LATCH U1 latches the data onto chip U1 ; it toggles the latch line (-strobe) and holds it for about 14 uS ; then returns it to its resting state. ; U1 is the chip that latches the joystick information LATCH_U1: PUSH AX, BX, DX MOV DX, PP_OUT2 MOV AL, 13 OUT DX, AL MOV BX, 14 CALL TIMER_0 MOV AL, 12 OUT DX, AL POP DX, BX, AX RET ; Carl, I'm not making use of the ability to read status of ; power & cartridge at this time because I'm not sure if a set ; bit means "ON" or "OFF" So, I'm checking the stored status of ; the power bit ... ; Routine to control the status of the OPTION/SELECT/STATUS keys ; Currently, they are held for a fixed time, unless the PC operator ; is still depressing a key; else it is held until no function key ; is held. ; This routine is entered with the correct bit for U2 already in ; AL OPSLST: OR A_CTRL, AL ; 3.15 MOV AL, A_CTRL MOV DX, PP_OUT1 OUT DX, AL CALL LATCH_U2 CALL FLUSH ; don't allow buffer fill L7: TICKS 12 ; 2/3 second hold always ; Now, is the user still holding down a function key? MOV AH, 01; get keyboard status INT 016h JZ > L4 ; zero flag means no key waiting AND AL, AL ; 0 means extended (function) key JNZ > L4 CMP AH, 040h ; OPTION? JB >L4 CMP AH, 042h ; START? ; return without clearing if console button still held: JBE >L5 ; now, clear such that no buttons are pressed: L4: AND A_CTRL, 11110001xB ; clear bits of interest MOV AL, A_CTRL MOV DX, PP_OUT1 OUT DX, AL CALL LATCH_U2 L5: RET L2: TEST A_CTRL, 128 ; is power on? JNE >L3 ; jump if it is CALL PWR_OFF TICKS 36 ; 2 second delay CALL PWR_ON L3: MOV DX, PP_OUT1 MOV AL, A_CTRL OUT DX, AL CALL LATCH_U2 RET #ELSEIF 1 RET #ENDIF ; A subroutine to wait for a keypress: WAIT4KEY: MOV AH,0Bh; Check STDIN status (is a keypress ready?) INT 021h CMP AH,0 JE WAIT4KEY; 0 means no char waiting L1: MOV AH,08h; Now, get the char. and throw it away INT 021h CMP AL,0; Extended code? JE L1; If so, get the rest of it RET ; IS_A_KEY checks to see if a key has been pressed, if so, it ; returns it in AL. Carry clear means no key was waiting. ; AX is changed. No registers are saved. IS_A_KEY: L1: MOV AH,1 ; is a key ready for input? INT 016h JZ > L9 ; zero means no key MOV AH,0 ; else, input the character INT 016h STC JC > L2 L9: CLC L2: RET ; ALF - test char. in AL, returns with carry set if ; not alphabetic. Also converts lower case to upper ; and non alpha to ?. ALF: AND AL,11011111xB; Clear bit for uppercase CMP AL,'A'; Carry set if below 'A' JB >L1 CMP AL,'Z' + 1; Carry set if AL>'Z'; rev 4.17 added + 1, failed on ; Z previously CMC; Complement carry flag - it's opposite day! L1: RET ; GET_STR - This subroutine gets a string from the ; user. If ESC is pressed, the carry is set on return. ; The string is stored at [BX] and terminated by 0. ; Enter with BX pointing to buffer start and CX = ; max number of chars. Make buffer big enough to ; hold max chars plus terminating 0 and initialize ; the ending 0 if it is a must. This routine only ; puts in 0s if string length is less than max. GET_STR: MOV DI,0; Index counter to put chars in buffer L0: CALL GET_TORK; WAS K6 CMP AL,08; Backspace? JNE >L1 CMP DI,0; Don't backspace if at start JE L0 DEC DI; Backspace actions INC CX; Note: I'm not preventing screen bkspce. CALL PRINT1 ; backspace just moves cursor left ... MOV AL, ' ' ; so print a space over deleted character CALL PRINT1 ; and then MOV AL, 08 ; move character left again! CALL PRINT1 JMP L0 L1: CMP AL,27; ESC? ESC means cancel function... JNE >L4 MOV [ERROR],AL STC RET L4: CMP AL,' '; Space means end of filename... JE >L1 CMP AL,0Dh; So does return JE >L1 ; REV 3.17: CMP AL, ' '; reject all codes below 020H JB L0 CMP AL, 127 JA L0 ; OK, its just a regular character... MOV [BX+DI],AL; Put it in filespec block, INC DI CALL PRINT1 LOOP L0; Get more if haven't used 54 JMP > L6 ; Now, put zeroes for rest of field. L1: MOV AL,0 L1: MOV [BX+DI],AL INC DI LOOP L1 L6: CLC RET ; LINEFEED PRINTS CR/LF TO THE SCREEN LINEFEED: PRINTL CRLF RET COMMENT\ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ The routines below were adapted/copied from EPROM.S to ³ ³ display sector data in DEBUG style format to the screen. ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ENDOFCOMMENT\ ; ; show the sector data in "DEBUG" style layout ; VIEW_DATA: PUSH BP, DI, SI, AX, BX, DX, CX CALL BLANK_HL ; CALL CLR_SCRN ; CURSET 0500h CALL LINEFEED MOV EP_ADR, 0 MOV SI, 0 ; MOV DX, D_SIZE ; # of bytes to show ; ADD DX, SI ; plus file offset L3: MOV CX, 0100 ; show up to 16 lines at a time L2: MOV AL, [SECBUF+SI] CALL DEBUG INC EP_ADR INC SI DEC DX JE > L1 LOOP L2 ; CALL P_KEY ; CALL TO_UPPER ; CMP AL, 'Q' ; JE > L1 ; JMP L3 ; CALL LINEFEED ; CALL P_KEY L1: POP CX, DX, BX, AX, SI, DI, BP RET ;P_KEY: ; PRINTL SKWAIT, ATTR9 ; CALL WAIT4KEY ; RET ; A ROUTINE TO TEST THE DEBUG ROUTINE: ;CHAR DB 'A' ;TDB: ; CALL BLANK_HL ; MOV EP_ADR, -1 ; MOV CX, 0120h ;L1: INC EP_ADR ; MOV AL, CHAR ; CALL DEBUG ; INC CHAR ; LOOP L1 ; RET ; Fill the DEBUG data line at HLADR with spaces: BLANK_HL: MOV AL, ' ' MOV DI, HLADR MOV CX, E_HL - HLADR PUSH DS POP ES REP STOSB RET ; DEBUG ; ; DEBUG prints out a DEBUG style line of data with this format: ; ; ADDRESS 00 00 00 00 [16 hex bytes] abcdefg [16 ASCII chars] ; On entry, if the lower nybble of EP_ADR is 0Fh the line (HLADR) will ; be printed, HLHX will be updated from EP_ADR. ; ; In every case, AL data will go to the hex and char areas ; DEBUG: PUSH CX,DI,BX,AX MOV AX, EP_ADR; offset into sector of byte TEST AL, 0Fh JNE > L1 MOV CHAR_PT, 0 ; pointer to hex data MOV DI, HLADR ; offset field of line CALL P_HEXWRD ; put address to HLADR field for next line L1: POP AX ; get back data byte PUSH AX CMP AL, 020h ; printable character? JAE > L2 MOV AL, MARKER ; else use marker character L2: MOV BX, EP_ADR ; for pointer AND BX, 0Fh MOV [HLTXT+BX], AL POP AX PUSH AX CALL BYTE2HEX MOV DI, CHAR_PT MOV [HLHX+DI], BX ADD DI, 3 CMP DI, 24 JNE > L3 INC DI ; leave blank space between 1st and 2nd 8 byte fields L3: MOV CHAR_PT, DI MOV AX, EP_ADR AND AL, 0Fh CMP AL, 0Fh JNE > L4 PUSH BP MOV BP, HLADR CALL PRNT_L10 POP BP L4: POP AX,BX,DI,CX RET ; ; A routine to convert the 16 bit binary # in AX to the 4 digit text Hex ; string representing it. DI must point to the destination field. ; This subroutine was made from the HEXTEX macro for the EPROM program. P_HEXWRD: PUSH AX,BX,CX,DI MOV CX,4;; Counter for 4 hex digits ADD DI,3;; LSD first M1: MOV BL,AL AND BL,0Fh CMP BL,0Ah JB >M2 ADD BL,'A'-10 JMP >M3 M2: ADD BL,'0' M3: MOV [DI],BL DEC DI PUSH CX MOV CX,4 SHR AX,CL POP CX LOOP M1 POP DI,CX,BX,AX RET ; This subroutine prints a string terminated in ASCII 10 at current ; cursor position. BP points to the string. It also expands tab ; chars using the PRNT_TAB routine. This routine is to be used when a ; $ char must be printable. Also note that the ASCII 10 does get printed ; so, string can end in 13,10 (CR/LF) PRNT_L10: PUSH DI,AX,BX,BP L0: MOV AH,0Eh;; Write character MOV BH,VPAGE MOV AL,[BP] CMP AL, 9 ; TAB CHAR? JNE >L2 CALL PRNT_TAB JMP >L3 L2: INT 010h CMP AL, 10 ; linefeed was sent? JE > L1 ; then quit L3: INC BP JMP L0 L1: POP BP,BX,AX,DI RET