; SIO2PC ; ; A communications program for linking an 8 bit Atari computer ; to a PC Compatible computer via the Atari's SIO connector ; and the PC's serial port. ; CONVERTING TO QUICK-ASSEMBLER VERSION ; February 18, 1990 ; (first version begun on A86 assembler) ; ; last session 01/03/92 ; again trying A86: 01/19/92 ; ; NOTICE: WHEN USING A86, JUMPS TO LOCALS WITHOUT THE ">" SYMBOL ; FOR "FORWARD" ARE SUPPOSED TO GO BACKWARDS. I HAVE NOTED THAT ; IF THE SAME LABEL IMMEDIATELY FOLLOWS A BACKWARD JUMP, IT WILL GO ; FORWARD ANYWAY. USE A DIFFERENT (UNIQUE TO THE AREA) LOCAL NAME ; IN THIS CASE: COMMENT\ EXAMPLE: L1: NOP ; START LOCAL PROC NOP NOP CMP AL, STUFF JE L1 ; This will foul up and go forward L1: NOP ; because this adjacent label confuses A86 ; so, make the first L1 be L2 instead and save ; much debugging!!!!! ENDOFCOMMENT\ ; ; this section of the code contains the "main loop," plus ; a few routines which didn't really fit the description of ; the other files; some Interrupt 023 and 024 routines and ; the QUIT routine, plus the stack and end of program label. ; ; The files necessary to assemble the complete SIO2PC other than ; this one are: ; ; TEXT.S; PORTS.S; NUMBERS.S; DISKS.S; PRINTER.S; DIR_SUBS.S ; BUSCMNDS.S; SCREEN.S; TIME.S; MACROS.S ; ; I assemble SIO2PC with the following batch file: ; ; A86 MACROS.S SIOTEXT.S PORTS.S NUMBERS.S TIME.S SCREEN.S PRINTER.S ; BUSCMNDS.S DIR_SUBS.S DISKS.S SIO2PC.S TO SIO2PC.COM ; ; ; ***************************************************************** ; * NOTICE to persons in possession of this source code: * ; * * ; * All commercial rights are reserved by the Author. * ; * * ; * If you make changes or improvements, please contact me so I * ; * can consider updating the original. If you make changes and * ; * distribute the program to others: Leave my sign off message, * ; * add a revision # or note to the effect that the program has * ; * been modified, put your own name and address after mine in * ; * the sign off message. * ; * * ; * Thanks, Nick Kennedy, 300 South Vancouver, Russellville, AR * ; * 72801, 501-967-3843 * ; ***************************************************************** ; NOTE: See QA guide pg 79 for instructions for creating a COM file ; Program execution begins at label "INIT:" ; VERSION 1.01 USES DEFAULT PORT ADDRESSES IF NECESSARY ; VERSION 1.02 CURED SEVERAL BUGS, INCLUDING NO FORMAT IN 2.5 MODE ; VERSION 1.03 CHANGED STD TIME DLY ROUTINE TO TIMER_0 ; VERSION 1.04 WILL ALLOW ENTRY OF PORT ADDRESSES MANUALLY ; VERSION 1.05 CHANGES THE SIO INTERFACE PROTOCOL, ADDS MYVEC8 ; timer 0 redirection to replace JIFFY. Also now programs ; UART directly, not using BIOS. Added loopback test and LCR ; read diagnostic. Added programming of timer 0. Made routine ; getting filespec pad out RFSPEC with 0's. Removed bad write ; to wrong segment in REG_INIT. Shipped 4/24/90. ; VERSION 1.06 STARTED USING NOTES WINDOW. Worked on loopback test. ; Added option "R" to allow restoring screen. Added file ; transfer, Atari to PC, routine FILE2PC. Changed enable/disable ; on RTS line to be when SIO2PC addressed/not addressed. ; ; VERSION 1.07 MADE SOME CHANGES TO WRITE_DISK. I had function 03 but ; should have been 03Eh to close file. Added the get directory ; function to Options. Changed program end to DOS function 4Ch. ; The program now asks if you really want to quit when a ramdisk ; has been written to but not saved. The PRINTHRU function has ; been started, but is not yet functioning. ; VERSION 1.08 PRINT_THRU MODE is working. ; ; VERSION 1.09 Added strip hi bit capability to PRINT_THRU ; ; VERSION 2.00 Allows deletion of ramdisks, making ram re-useable ; ; VERSION 2.1 Adds function to remote control program to send ; ramdisk information to REMOTE.OBJ on Atari. Routine added ; is called RMT_READ ; ; VERSION 2.2 will disable the data out line immediately after ; receiving DEVID if not an SIO2PC device. This is in hopes of curing ; the interference problem encountered by Joe Woyak and Rolf Beyer. ; VERSION 2.3 gets rid of the CTS line check completely. It also adds ; the lock RTS switch. It gets rid of the OPTIONS menu and puts all ; menu items on the same screen. Therefore, some menu choices are ; now addressed by different letters. Also, this revision adds another ; option for PRINT_THRU, allowing the printer data to be sent to ; a file. ; VERSION 2.4 Changed directory to show 4 files per line instead of ; 2, now max of 100 per page. Also change method of printing from ; PRINTL macro to DOS function 40 because file name could contain ; $. Added print functions for original 40 col Atari printer. Sends ; 29 or 20 chars to printer instead of 40. Also, printer STATUS ; routine now gets actual status from printer and sends 'E' to ; Atari if bad. ; This version also redirected the vectors for INT 024h AND INT 023h ; CRITICAL ERROR and BREAK vectors to prevent exit of program ; without ending timer interrupt routine. Added "SHAREWARE" message ; at end of program. ; Rev 2.5: Adding user command "A" to adjust timing values. Allows ; user to set critical time delays used in the bus data transfers, ; to try to iron out differences between different systems. This ; addition is menu choice "A" and adds the TIMING menu. ; ; Rev. 2.6: Rewrote PRINTER routine to more closely emulate 850 ; interface. Moved timer values to front of program and added ; ASCII flags so user can use DEBUG to change program. 12/30/90 ; ; Rev. 2.7: Changing PRINT_THRU routine so it will check for a ; disk full error and notify user, and terminate PRINT_THRU ; process. ; Rev 2.8: Fixed a bug in PRINT_THRU introduced by 2.7 in which ; converting EOL's would lock up the PC if the EOL were found to ; be byte # 40. Also changed so consequtive EOL's no longer put ; spaces between CR/LF's after conversion. Also fixed so ESCAPE ; key also restores the menu. ; ; Rev 2.9: Added "disk full" error trapping for routines which ; write to disk, especially PRINT_THRU and FILE2PC. (Write ramdisk ; already had error trapping.) ; ; Rev. 2.10: Added location and error codes to PRINTER routine ; for better error trapping. Also added a timing value to the ; timings menu for output to the printer. ; ; Rev. 2.11: Added a byte count to sign off message to help users ; discover virus infection. ; ; Rev. 2.12: Adding routine to allow extracting directory info ; from Atari disk image files. This was completed for Atari DOS and ; compatibles only. I also put in the start of the required ; recursive routines to dig out MYDOS subdirectories, but did not ; complete it in revision 2.12 ; ; Rev. 3.0: This revision will allow reading directly from a ; physical disk file, without using a ramdisk intermediary. The intent ; is to allow disk image files of unlimited size. Begun 11/10/91 ; This rev. will move MACROS to a file MACRO.ASM and INCLUDE them. ; ; Rev. 3.01: Fixed PUT_SECNO so it doesn't unless cmnd is P, W, or R. ; Added JMP RED1 after CALL GET_CONFIG. Previously, it went to U13 ; which updated the status line, taking too much time. In READ_DSK, ; added the line to change DSK_FLAGS when the LOAD_OPT is /N. ; Now the "don't format physical disk" option does work. On ; the QUICKA version, I changed the IF NOT ONECHIP to IFE ONECHIP ; after I realized that NOT does an EOR, so a non zero number still ; ends up non zero unless it were all 1's to start with. This had ; been causing major problems with the ONECHIP version. Changed the ; CUSTOM message to say 65535 sectors max instead of 16535. Fixed the ; number of characters to be input for disk size from 5 to 6 because ; the CR counts as one. Previously, one could only go with 4 digits ; maximum. Corrected the math which converted the number of sectors ; to the size in paragraphs. There was an error for LARGE disks ; because I was failing to left shift the high word for each "times 2" ; operation. Fixed the PUT_DEVID routine, because it wouldn't - in ; some cases. ; Rev. 3.02: Found data out line wasn't always getting disabled. Put ; a CALL DISABLE at front of RED1 in hopes of curing this. It seems to ; have worked. ; ; Rev. 3.03: Added CRC check and file size check for virus protection. ; Added routines V_CHECK, GET_CRC, DO_CRC, INC_CRC ; Changed FILE2PC so it would write the whole file (forgot to save ; X before using LDA ICBLL,X to load remaining bytes) ; ; REV 3.04: changed directory logic so separator is '.' for normal ; file and '*' for subdirectory, per original intent. I also added ; SPARTADOS compatibility for the directory extraction function. ; Disk image files ending in 'S' are now treated as SPARTADOS images ; and the directory is expanded, including sub-directories! I moved ; the directory functions to the SIOSUBS file. ; ; REV 3.05: did some tweaks on the main loop and think I got rid of ; at least one bug there. Added a group of size choices for ; SPARTADOS to the CREATE disk option. Moved the density selection ; to a sub function of CREATE. Added the "simulated disk" option ; Menu choice "I" to allow direct access to a PC file. ; ; REV 3.06: did away with the ONECHIP flag. Now there are variables ; REV_FLAG and TX1A. TX1A is copied from REV_FLAG at startup. If TX1A ; is 'i', the system will respond as necessary for the ONECHIP design. ; It does this by toggling the zero flag after comparisons involving ; the RI bit of the MSR. REV_FLAG can be found easily by DEBUG near ; the program's start. Also, a new option under the "A" submenu ; allows changing it during program execution. ; Changed the way the system responds to framing errors on the serial ; bus when High Speed has been in use. Now, it toggles from hi to lo ; or lo to hi whenever a framing error is read during a command frame ; providing a '?' get high speed index has been read as indicated by ; a 'Y' in the EVER_HI variable. ; ; REV 3.07: Print-thru now offers the option of converting ATASCII ; tabs (07Fh) to standard ascii tabs (09h). ; REV 3.08: First correction makes the FIX OLD DISK command accept ; upper or lower case 'Y'; Main improvement adds the DOS SHELL "H" ; command. Also added the capability of the program to fix its internal ; CRC if the user chooses. ; ; REV 3.09 ; Fixed the TO_UPPER sub to it only converts lowercase letters, I found ; that installing a PC which had numbers in its filename file as a disk ; caused the numbers to change to graphics symbols. ; REV 3.10 ; Made some changes to the SIMULATED disk: ; Now, if the Atari tries to write this the SIM disk, an error isn't ; returned (just an 'S' to the ERR column of the status line). Instead ; the system "pretends" to write the sector. Also, the SIMULATED disk's ; status is no longer "locked" or "in use" as shown by the status ; byte in the directory sector. The sim. disk now reports data sectors ; as 401 thru 700, then repeats, instead of just using sector #100 for ; all sectors. Also, no error is returned for requesting the wrong ; sector number. I also added the /B (boot disk) option to the Install ; PC disk feature, but haven't tested it. ; ; REV 3.11: BOOT disk option for SIM disk tested, added message to ; notify user how to install ; NOTE: I had a 3.12, but that was just Carl M's remote interface ; I've decided to withdraw back to 3.11 ... ; 3.12: I had something wrong with the extract directory function for ; SPARTADOS, which is fixed. Something to do with local labels. Also ; added an ESC bailout to the directory function. ; 3.13: doubled some printer timeout numbers due to a user complaint. I'm ; not sure yet if it helped ... ; 3.14: I found that simulated disk access had slowed down. It turned out ; that I had used "T1" as a local code label in two places, causing the ; addresses to supersede the word value T1 had as a bus timing variable!! ; Fixed by changing T1 code labels to L1s. ; 3.15: Added screen blank via B key. Not shown on menu. ; 3.16: Trying to fix a bug which causes an INT 024 hardware error on ; startup. It seems to be caused by the drive # stored at CUR_DRIVE, see ; subs. GET_DRIVE and GET_DIR. Note that DOS sometimes uses A = 0, and ; other times uses different method of drive designation. ; 4.00: Added the 1050-2-PC routines for direct connection to a disk drive ; using different hardware. 4.01 was a minor enhancement ; 4.02: Worked on the 1050-2-PC routines in preparation for shipping first ; two units. Added retry on error to the disk copy routine; and bail-out ; via ESCAPE to a couple of routines. Worked with SIM DISK routines some ; seems to be some minor problems. May need more work. ; 4.04: Fixed SEC_ADR in BUSCMNDS.S so sector #0 will no longer be ; accepted. DOS's and user programs shouldn't ask for the invalid ; sector 0, but if they did, on a write, SIO2PC would overwrite program ; space and crash. COMMENT^ REV. 3.17 2/10/94 Bug fixes and enhancements suggested by Terry Chamberlain's letter. Increased the time on several bus timing constants. Changed the editor so the user can backspace normally, but most non- printing characters are outlawed. Changed the routine which gets the number of sectors desired under Create Disk option 5 to use this editor instead of DOS input. Fixed the load option so the /P doesn't seal in - clears it before each subsequent choice. Worked on the direct access disk feature a bit. I had a complete lockup before I changed a few things. Seems to work OK now. Fixed the SPARTADOS extract directory. It had degraded to the point that it didn't show all files and never extracted subdirectories. Changed the DOS SHELL routine so it gets the COMSPEC path name from the environment string instead of assuming C:\COMMAND.COM. Made many changes to the 6/More sub-option under Create Disk. Mostly I got rid of the 28 sector/track choices and added 26 sector/track. I also change Create option 3 from 143K to 133K because 1050 enhanced is actually 1040 sectors, not 1120 as I had thought. REV 3.18: Changed the TIMER_0 routine. It formerly tried to keep track of counts in the timer chip's timer 0 "on the fly." I've come to believe that the rollover from 0 to 65535 has never been adequately addressed, so now my routine programs the counter to a known initial count (0 or effectively, 2 to 16th), and watches for it to decrement to the desired count. Also, I discovered that timer_0 normally runs in mode 3, not mode 2 as I had thought. More importantly, I found that in mode 3 the counter counts down by TWOS! This explains why the timing seemed to be twice as fast as I calculated. Each count actually represents 420 nanoseconds, not 840 as I had thought! REV 3.19: Good Grief!! The improvement I made in TIMER_0 above causes WRITE and PUT actions to sputter along and stop at random. I couldn't figure out why, so I put TIMER_0 back the way it was. OK, at 3.19 and 1/2, I finally figured out that a JA branch opcode should have been a JB! So I'm back to the new improved version, which is working OK, tested for read, write, format, and FILE2PC. REV 4.0: I added the 1050-2-PC functions and decided to go up to the next integer revision numbers. Currently, read 720 sectors, read 1040 sectors and read user defined block of sectors is working. REV 4.05: Added a bunch of new features to 1050-2-PC. Format, emulate bad sectors debug style screen of sector data, etc. REV 4.06: Took out the DO_TIME crude timing routine. It finally caught up with me on fast PENTIUM PC's. Replaced with the timer_0 interrupt routine counting down. It was only used in the PUT1 and PUT1A routines anyway. REV 4.07: Took a couple of bugs out of how 1050-2-PC sends bad sector status. Added MT-550 to empty a 16550 buffer and called it once per init of COM port and once per pass thru the main loop (no command frame in progress). Changed VID_INIT so it puts the screen in mode 3 instead of mode 2. Mode two caused weirdness such as a 43 line screen on following programs. Also in CON_COM, put the 16550 in the character (not the FIFO) mode. Haven't tested this on a real 16550, but it didn't mess up anything on my 486 or 286. REV 4.09: Added diagnostic routines. Added the A, G menu on SIO2PC and DIAGS.OBJ for the Atari. 12/3/95 Rev 4.10: I discovered that adding some time to T7 (time between UART accesses) completely cured the halting behavior I see on my '486. I started with 000A (4.5 us) but went to 0005 and it worked too. Settled on 0008. 12/4/95 Also, fixed a bug where the MCR wasn't being initialized. This isn't usually a problem, but some computers apparently come up with LOOPBACK turned ON!! Changed TIMER_0 routine so it actually uses timer #2. This is because a routine using VARBL was repeatedly calling TIMER_0, and therefore, it couldn't timer out and decrement VARBL. I changed the programming of the BAUD rate from a 16 bit out to two 8 bit outs with delay between, because I'm not sure I trust that 16 bit out. Added a "hidden" menu function M, which is temporary to allow setting the MCR's lower 4 bits. 4.11 - Remove menu function M; DELETE function wasn't checking for SIM DISK and closing file if so. Fixed. Fixed some other file handle open/close problems. Removed CALL RESETDTA from DOS dir function - it messed up drop down dir which expected my DTA to be in force 4.12 - Fixed problem with multiple disk loads from command line, added some more delays between IN's and OUT's, fixed double backslash in path when in root directory. After DOS directory or DOS Shell, file selector box didn't work - fixed that. Some other problems with file selector box - error in page down function fixed and error caused by bad path couldn't be corrected - fixed it. 4.13 - Fixed an error causing lockup when at the bottom of the file selector list and pressing a key not resulting in a matching file. Also, fixed the feature that puts the simulated directory sector name in the simulated directory. Made the space bar work the same as [TYPE SPEC] in the file selector box. 4.14 - In 1050-2-PC, fixed "press any Key" prompt so it doesn't happen if there are still chars in the command tail. Also made a change so extended characters in the drop down dir box don't do a bogus search!! 4.15 - Fixed formatting error in 1050-2-PC: CMND was being change by STATUS call after having been set up with format command code. Also added the BEEP functions and beeps now occur when errors are encountered in 1050-2-PC sector I/O. 9/96 4.16 - Added low click for read sector and high click for write sector 4.17 - 1/20/97 - fixed ALF routine in 6SCREEN.S so it doesn't fail on 'Z' 4.17 - 8/26/98 - fixed the fact that for large numbers of files in a dir, the selector box would load the wrong file. This was due to an 8 bit multiply MUL BL instead of 16 bit MUL BX in TAKE_IT in DIR_SUBS.S 4.18, 4.19 - 10/5/98 Fixed some stuff I don't even remember well--Oh! ; I moved the sending of the C (complete) to the end of the routine in ; either PUTSEC or GETSEC. Also made the Timings menu show that T7 = ; 8 as it has been since rev. 4.10 ENDOFCOMMENT^ COMMENT" This program is intended to allow the PC to interface with an 8 bit Atari computer, via the PC's RS232 port and the Atari's serial interface. In this implementation, the PC will emulate an Atari disk drive. The Atari will not require any special software whatsoever, and can actually boot from the PC. " C_INFO1 EQU 1200h ; cursor position for info line1 C_INFO2 EQU 1300h C_INFO3 EQU 1400h ; THE PROGRAM BEGINS EXECUTION HERE: ; USER INTERFACE: ; This section of the program puts up a menu screen and gets ; configuration information from the user or from the command ; tail. INIT: CLI MOV AX, OFFSET MY_STACK; Lower the stack pointer ADD AX,0FFh MOV SP,AX STI CALL VID_INIT CALL GET_SCRN ; Get the screen segment into SCR_SEG ; and set COLOR flag CMP COLOR, 0 JNE >L1 CALL DO_MONO ; set all attributes to 07 for mono L1: CALL INEXTS ; init next sector pointer. CALL ZSTARS ; Zero STARS to show no Rdisks yet CALL PUT_SIZE ; fill in ASCII size for sign off msg MOV AL,DS:[80h] ; Get command tail length MOV TAIL_CNT, AL; and init counter with it. MOV AL,081h ; Init tail pointer for GET_TAIL MOV TAIL_PT, AL MOV LOCK_RTS,0 ; RTS not locked on. CALL PRG_T0 MOV CRITIC,0 ; Flag no critical error CALL SET_NEW24 ; Set new INT 024 handler CALL SET_NEW23 ; Set new INT 023 handler CALL SETUPV8 ; Redirect INT 08 for my routine MYVEC8 CALL V_CHECK ; Check CRC and file length for virus 3.03 ; Init for directory and path functions: ; 4.10 - since I'm going use to timer #2, I need to turn off sound: MOV DX,061h ; TTL control port IN AL,DX ; CALL ACC_DLY ; 4.12 CALL ONE_TIK OR AL, 1 ; must gate ON for counter 2 to receive input AND AL, 0FFh - 8 ; turn bit 3 off to kill sound OUT DX,AL CALL ACC_DLY ; 4.12 ; REV 3.16: CHANGE ORDER OF NEXT TWO CALLS, BECAUSE GET_DIR USES ; THE CUR_DRIVE # GOTTEN BY GET_DRIVE ... ; 3.16 also changed GET_DIR: see DIR_SUBS.S CALL GET_DRIVE; Store drive # @ CUR_DRIVE MOV AL,B[CUR_DRIVE] ADD AL,'A'; Change drive # to drive letter, 0 = A. MOV [OLDRIVE],AL MOV [NEWDRIVE], AL CALL GET_DIR; Store path at OLDPATH SMOVE OLDPATH, NEWPATH, 64 ;; 4.11 initializes New = Old path FIND_BYTE NEWPATH, 0, 64 ;; find end of string and add \ CMP B[DI-2], '\' ; already got \ ? 4.11c JE > C1 MOV B[DI-1], '\' ; as preface to adding search spec C1: CALL CONCPATH ; add default *.* to search spec CALL GETDTA; Save address of current DTA set by DOS. CALL SETDTA ; added here by 4.11 ; Initialize parallel port addresses for Carl M.'s interface: #IF CARLM PP_INI: MOV AX, 0040h; BIOS DATA AREA PUSH AX POP ES MOV AX, ES:[08] ; parallel port LPT1 address CMP AX, 0 ; if no address, use default JE > L1 MOV PP_OUT1, AX INC AX MOV PP_IN, AX INC AX MOV PP_OUT2, AX L1: PUSH CS POP ES #ENDIF ; Initialize DOS SHELL data (rev 3.08) PUSH CS POP AX MOV PBS1, AX MOV PBS2, AX MOV CTS, AX ; NOTE: THE QUICKASSEMBLER VERSION CALLS PUT_SIZE HERE; I THINK ; A86 VERSION DOESN'T NEED IT?? (FOR VIRUS MESSAGE) MOV B[ACOMN],'?' ; Rev. 2.7 - if program is restarted, MOV AX,'xx' ; get these fields and flag back to MOV WORD PTR CMTXT,AX ; default values MOV WORD PTR [CMTXT+2],AX MOV CONFIGD,0 CALL CLR_SCRN CALL DO_MENU CALL PUT_RAM; REV 3.04 CALL WS240 ; Set up status line CMP B[REV_FLAG], 'i' ; REV 3.20 JNE > L1 CALL RTS_UP ; command line high for 1050-2-PC L1: PSTATUS PRMT_COM, ATTR9 CALL COM_SET JNC SETUP; No carry = no error CMP CONFIGD, 0; If already configured, disregard error JE L1; Else, demand a port #! MOV AL,' '; Start with "no input" ; SETUP ; A routine which gets characters from the command tail ; or from the user (kybd) and sets up the program as ; directed. It continues to look for input until Run or ; Quit command is received. Returns with Q or R in AL ; 10/30/89: SETUP will now be in-line, not a subroutine. SETUP: ; PUSH AX ; MOV AL, 'H' ; CALL PUT_LOC ; POP AX AND AL,11011111xB; convert to uppercase MOV CCRUD, AL ; save user's menu choice MOV XCRUD, AL ; Now, check for valid command and call routine if good: CMP AL,'S'; Set COM port #? JNE >L2 MOV DH, 20; Line # CALL C_LINE PRINTL CHPN PSTATUS PRMT_COM, ATTR9 CALL COM_SET CALL CLR_ALL JMP XI1 ; Go get more config info L2: CMP AL,'A' ; Adjust timings, rev. 2.5 JNE >L1 CALL CLR_SCRN CALL TIMING ; in file TIME.S CALL FIX_SCRN JMP XI1 L1: CMP AL,'L'; Load ramdisk from real disk? JNE >L3 CALL READ_DSK CALL CLR_ALL ; clear info and status lines CALL SU_DSKHDR JMP XI1 ; Rev 1.08 moved R from options to main menu L3: CMP AL, 'R'; Restore screen/menu JNE >L1 CALL FIX_SCRN JMP XI1 L1: CMP AL,27; ESCAPE? REV 2.8: ESCAPE FIXES SCREEN JNE >L4 ; CALL CLICK_ME this was just for test CALL FIX_SCRN JMP XI1 L4: CMP AL,'C'; Create ramdisk? JE >D3 JMP NEAR DD2 D3: MOV CCRUD, 'C'; assume single density: 3.06 PSTATUS D_OR_S, ATTR9 ; REV 3.05; put density choice here CALL GET_TORK AND AL, 11011111xb CMP AL, 'S' JE >F1 CMP AL, 'D' JNE L1 MOV CCRUD, 'Z'; "Z" tells other routines double density F1: MOV DH, 20; Info line #1 CALL C_LINE PRINTL CRAMD; Tell what's happening PSTATUS PRMT_DSK, ATTR9 CALL CRUD CALL CLR_ALL JMP XI1 DD2: CMP AL, 'I'; 3.06 JNE >L1 CALL INST_PC CALL CLR_ALL JMP XI1 L1: CMP AL, 'W' JNE >L5 CALL WRITE_DISK CALL CLR_ALL JMP XI1 L5: CMP AL,'X' JNE U8 CALL XCHANGE CALL CLR_ALL JMP XI1 U8: CMP AL,'T'; Toggle status line usage JNE >L1 CALL TOG_STAT JMP XI1 L1: CMP AL,'Q' JNE >N1 JMP GDOS; Quit if 'Q' N1: CMP AL,'U' JNE >L1 PSTATUS PRMT_DSK, ATTR9 CALL GET_DISKNO CMP ERROR,27 JE N1 CMP ERROR,'N' JE N1; Don't need to delete if it doesn't exist CALL DELETE JMP XI1 L1: CMP AL,'E'; Enter port address manually JNE >L6 CALL MAN_PORT JMP XI1 L6: CMP AL,'D'; Print directory JNE >L1 CALL DODIR CALL FIX_SCRN JMP XI1 L1: CMP AL,'K'; Lock Data Out Line (RTS) on (toggle) JNE >L7 CALL LOCK_IT JMP XI1 L7: CMP AL,'P'; PRINT_THRU mode JNE >L1; CHANGE TO >L1 WHEN OPTION 'A' READY *** 2.2*** CALL PRINT_THRU JMP XI1 L1: CMP AL, 'J'; Jmp to ultra speed (toggle) JNE >S8; 3.08 CALL TOG_SPEED JMP XI1 S8: CMP AL, 'Z' ; toggle sound ON/OFF (4.16) JNE > L8 CALL SNDONOFF JMP XI1 L8: CMP AL, 'H' ; 3.08 - exit to DOS SHELL JNE > L1 CALL TO_DOS JMP XI1 L1: CMP AL, 'B' JNE > L9 CALL BLANKIT ; blank the screen JMP XI1 L9: ; CMP AL, 'M' ; change MCR bits - 4.10 - 4.11 removes ; JNE XI1 ; CALL EXP_MCR ; change bits 0 - 3 of MCR ; Are there any characters in command tail? ; If not, fall thru and run program XI1: CALL GET_TAIL CMP AL,0 JE > U13 ; 4.10 added > symbol for forward. Needed?? JMP SETUP ; Wait for the Atari COMMAND line to go low. (Connected to RI on port) U13: CMP BLANK, 0 JNE RED1 ; if BLANK non-0, don't print to screen PSTATUS RUNNG, ATTR9 CURSET 01700h RED1: ; MOV AL, 'G' ; CALL PUT_LOC CALL DISABLE ; REV 3.02 - RTS wasn't getting disabled! MOV DX, MSR ; Read modem status register IN AL,DX ; Read to reset TERI CALL ACC_DLY ; 4.10 CALL CK_LINES NCMND: #IF CARLM ; joystick support for CARL's interface CMP JOY, 0 JZ > L1 MOV JOYSTAT, 0 ; initialize MOV AH, 084h ; joystick support function XOR DX, DX ; read switch settings INT 015h JC > L1 ; carry set means error AND AL, 00110000xB ; b4&3 are stick A button statuses JE > L2 ; jump if no button pressed MOV JOYSTAT, 16; set bit 4 L2: MOV AH, 084h MOV DX, 1 ; now read stick position INT 015h JC > L1 CMP BX, 50 ; < 50 means UP JA > L3 OR JOYSTAT, 1 ; set UP bit JMP > L4 L3: CMP BX, 150 ; > 150 means DOWN JB > L4 OR JOYSTAT, 2 L4: CMP AX, 50; < 50 means LEFT JA > L5 OR JOYSTAT, 4 JMP > L6 L5: CMP AX, 150 JB > L6 OR JOYSTAT, 8 L6: CALL SEND_JOY #ENDIF ; MOV AL, 'N' ; CALL PUT_LOC L1: CALL MT_550 ; 4.07 - keep the 16550 empty when no cmnd going MOV AH,1 ; is a key ready for input? INT 016h JNZ > L9 ; 3.14 + ... fix long jmp, was JZ XR1 JMP XR1 ; zero means no key ready L9: #IF CARLM CMP CARL, 0 ; in remote keyboard mode? JE >L1 ; CARL = 0 means not in remote mode CALL CM_LOOP JMP XR1 ; see if SIO bus active #ENDIF L1: MOV AH,0 ; else, input the character INT 016h CMP AL,27 ; ESCAPE pressed? JNE >L1 CMP FTSTATS,0 JE >L1 ; If 0, not in File transfer mode MOV FTSTATS,1 ; Else, flag that ESC has been pressed MOV B[F2P_STAT+3],0FFh; And make next status tell Atari L1: #IF CARLM TEST AL, AL ; check for function key (Carl) JNE >L2 CMP AH, 044h ; F10 key pressed? JNE >L3 MOV CARL, 0FFh ; turn remote kybd mode on CALL CLR_SCRN CURSET 0500h PRINTLA CM_ON, ATTR9 TICKS 36 JMP NCMND JMP > L2 L3: CMP AH, 043h ; F9 key for joystick monitoring JNE > L2 CALL JOY_ON ; toggle ON/OFF JMP U13 #ENDIF L2: JMP SETUP ; Note: when bit 6 of MSR = 0, this means that the RI input is ; logic 1; or command line is HIGH (TTL 1) or, RS-232 line is at ; -10 volts: all mean the same thing. With the ONECHIP design ; the line status is same at PC as at Atari. With the old design ; the RI line is inverse on PC due to inversion on board. XR1: MOV DX, MSR IN AL,DX ; Make sure it was for real... CALL ACC_DLY ; 4.12 CALL CK_LINES AND AL,01000000xB ; This time checking actual RI bit... LAHF ; 3.06 - complement ZF if ONECHIP. AH <- FLAGS CMP [REV_FLAG], 'i' JNE >L1 XOR AH, 01000000Xb; complement ZF L1: SAHF; FLAGS <- AH JE >A1 ; 3.12 cure long jump JMP NCMND A1: ; MOV AL, 'I' ; Update debug info ; CALL PUT_LOC ; Clear the breech by reading a byte from the receive register ; 4.10 removed clearing of DLAB - already clear ; MOV DX, LCR ; Clear DLAB to 0 ; IN AL,DX ; CALL ACC_DLY ; AND AL,01111111xB ; OUT DX,AL ; CALL ACC_DLY ; MOV DX, BAUD ; Read the register IN AL,DX; Throw away this byte... CALL ACC_DLY ; First, clear any error bits from LSR: (REV 3.01) MOV DX, LSR IN AL, DX CALL ACC_DLY ; ; Now read characters from the port. Command frame is 5 bytes long. ; First, get 4, computing checksum... ; First, a routine to time out if no data forthcoming in 55 to ; 110 mSec. ; MOV AL, 'T' ; CALL PUT_LOC MOV VARBL,10; 3.06 L2: MOV DX, LSR IN AL,DX ; First see if a byte is ready CALL ACC_DLY CMP EVER_HI, 'Y' JNE >N1 TEST AL, 8 ; Framing error? JE >N1 CALL CAN_CFB ; Cancel frame JMP RED1 N1: AND AL,1 JNZ >L1 ; branch if byte waiting... CMP VARBL,0 JE AAZ ; loop until timed out... REV 3.06 MOV DX, MSR ; 3.05 IN AL, DX CALL CK_LINES AND AL, 01000000XB LAHF CMP [REV_FLAG], 'i' JNE >L3 XOR AH, 01000000xB L3: SAHF JE L2 ; JNE MEANS CMND LINE IS HIGH JNE PUT_F ; JE MEANS CMND LINE IS LOW AAZ: CMP EVER_HI, 'Y' JNE PUT_F CALL CAN_CFB PUT_F: MOV ERR_CHAR, 'f' CALL PUT_ERCH JMP RED1 ; else abort attempt to get cmnd frame L1: CALL GET1; Get DEVID JC AAZ MOV DEVID,AL ; First, see if we are the device being addressed, if not, just ; ignore the command frame received. CALL SET_BP ; sets BP, NC if good device and VALID <> 0 JNC G3MORE ; I'm still going to get the rest of the frame, cause I want to ; update the STATUS line for the user's info. (Unless bad CKSUM) ; As of REV 3.06: if the speed has been EVER_HI, a framing error ; will cause toggle of speed and cancel of CFB G3MORE: ; MOV AL, '3' ; CALL PUT_LOC MOV CX,3 MOV BL,DEVID GET3: CMP EVER_HI, 'Y'; REV 3.01 for ultra speed JNE >L1 MOV DX, LSR IN AL, DX CALL ACC_DLY TEST AL, 8 ; Framing error? JE >L1 ; No error CALL CAN_CFB ; Cancel frame JMP RED1 L1: CALL GET1 JC AAZ ; carry set means timed out in GET1 MOV SI,CX MOV [CFCKSM+SI],AL ; Store the command frame bytes CLC ; do checksum math ADC BL,AL ADC BL,0 LOOP GET3 ; Now get checksum and store it... CALL GET1 JC AAZ MOV CFCKSM, AL CMP BL, CFCKSM JNE AAZ ; Abort the whole thing if bad CKSUM ; 3.05 moved block below. was after checking cmnd line raised: MOV AL, DEVID; Device ID from cmnd frame, 31 - 34 CALL BYTE2HEX CALL PUT_DEVID CALL PUT_COM ; REV 3.00: This call formerly followed CALL PUT_SECNO CMP VALID,0 ; the JNE >L1 below JNE ABA JMP RED1 ; At this point, we have successfully read a command frame. Now, wait ; for the computer to raise the command line: ABA: MOV VARBL, 2; 4.08 - did use BX in a crude counter for timeout ; MOV AL, 'n' ; CALL PUT_LOC B1: CMP VARBL, 0 JNE >L1 ; timed out, cmnd line didn't go high MOV ERR_CHAR, 'q' CALL PUT_ERCH JMP RED1 L1: MOV DX, MSR IN AL,DX CALL ACC_DLY ; 4.12 CALL CK_LINES AND AL,01000000xB LAHF ; 3.06 - complement ZF if ONECHIP. AH <- FLAGS CMP [REV_FLAG], 'i' JNE >L4 XOR AH, 01000000xb; complement ZF L4: SAHF; FLAGS <- AH JE B1 ; Now, disk does exist so put starting segment for this ; disk into the DVSEG variable ; MOV AL, 'Y' ; CALL PUT_LOC CALL ENABLE MOV CX, [STARS+BP] MOV DVSEG, CX ; Device #40h is the printer CMP DEVID,040h JNE >N2 ; was ADK CMP [PRINTHRU],0; 0 Means no PRINT_THRU mode JE >L1 CALL PRINTER L1: JMP RED1 ; this shouldn't be possible at this point N2: CMP DEVID,03Ah; File transfer to PC file? label was ADK JNE >L2 CALL FILE2PC JMP RED1 L2: CMP B[WRITTN+BP], 'S'; simulated disk (PC file)? JNE >N1 CALL SIM_IO JMP RED1 N1: MOV AL,[CMND] CMP AL,'R' ; read JNE >N3 CMP DEVID, 039h JE >O1 CALL GETSEC JMP RED1 O1: CALL RMT_READ JMP RED1 N3: CMP AL,'P' ; put JNE >P1 CALL PUTSEC JMP RED1 P1: CMP AL,'W' ; write JNE >N4 CMP DEVID, 039h JE >Q1 CALL PUTSEC JMP RED1 Q1: CALL ATTOPC JMP XI1 ; process command N4: CMP AL,'S' ; status JNE >R1 CALL STATUS JMP RED1 R1: CMP AL,'!' ; format JNE >S1 CALL FORMAT JMP RED1 S1: CMP AL,022h ; format in 1055 1.5 density (h = REV 1.02) JNE >L1 CALL FORMAT JMP RED1 L1: TEST B[DSK_FLAGS+BP],2; bit 1 set means don't respond to N or O JNE AEA CMP AL, 'N' ; send config. information to Atari JNE >U1 CALL SEND_CONFG JMP RED1 U1: CMP AL, 'O' ; receive config. info JNE AEA CALL GET_CONFG JMP RED1 AEA: CMP AL, '?'; HI SPEED: 3.01 JNE >V1 CALL SPEED_UP JMP RED1 JMP U13 ; U13 restores the status line; 3.07 TOOK OUT ; following for invalid command: V1: MOV AL,'N' ; send NAK byte: CALL PUT1 MOV ERR_CHAR, 'e'; Update status line CALL PUT_ERCH JMP RED1 GDOS: ; The following lines are REV 1.07 change to check if Ramdisks ; have been changed and ask the user if he is sure he wants to ; quit without saving them: MOV CX,4; Check 4 ramdisks for written or not? MOV BP,0 L1: CMP B[WRITTN+BP],'W' JE WARNW ADD BP,BLOCK_SIZE LOOP L1 JMP >L1 WARNW: PSTATUS QUITW?, ATTR10 CALL GET_TORK AND AL,11011111xB ; Uppercase CMP AL,'Q' JE >L1 JMP XI1; Return to main loop without quiting. ; now close any physical disk files: REV 3.00 L1: MOV CX,4 MOV BP,0 Q1: CMP B[WRITTN+BP], 'F' JNE >L1 PUSH CX CALL REL_DEL ; close the disk files POP CX L1: ADD BP, BLOCK_SIZE LOOP Q1 L1: CALL DO_TITLE CALL DISABLE; get SIO2PC off line when program isn't on. CALL CLOSPFIL; Close printer file, if any ; **** WARNING: DON'T USE THE "TICKS" FUNCTION AFTER THE FIXV8 CALL*** CALL FIXV8; Put INT 08 vector back like it was ; REV 4.11 - return to original drive and path CALL RES_DRIVE CALL RES_PATH ; REV 1.07: USE INT 021h/4Ch instead of INT 020h to terminate MOV AL,0; Return code MOV AH,4Ch; DOS terminate function INT 021h ; A routine to redirect INT 024h to my handler: SET_NEW24: MOV AL,024h; Int number MOV AH,025h; Set INT vector function MOV DX,OFFSET NEWV24; DS:DX points to new handler INT 021h RET ; Interrupt routine for INT 024h, critical error routine NEWV24: ; Note, don't save AX, it carries msg PUSH DS,ES,BX,CX,DX PUSH CS POP DS STI; Allow interrupts to happen MOV AX,DI CALL BYTE2HEX; Convert error code to ASCII digits in BX MOV CRIT_STAT,BX CALL CLR_ALL CALL CLR_24 PSTATUS SCRITIC, ATTR10 RECRITIC: PRINTL SCRITIC2 ; Get a character from keyboard: MOV AH,0 INT 016h; Returns char in AL AND AL,11011111xB; Convert to uppercase CMP AL,'I'; Ignore critical error and proceed... JNE >L1 MOV CRITIC,0FFh; Critic means critical error ignored CALL FIX_SCRN ADD SP,16; First get rid of my 5 plus INT 24 ret. adr. POP AX,BX,CX,DX,SI; Then restore others, see Prog. Ref. POP DI,BP,DS,ES; page 74 ; Also, I want to return with carry set: PUSH BX MOV BX,SP OR WORD PTR [BX+6],1; Carry flag is at bit 0 POP BX IRET L1: CMP AL,'R' JNE >L1 CALL FIX_SCRN MOV AL,1; tells DOS to retry JMP CRIRET L1: CMP AL,'E' JNE RECRITIC; if choice not in range... ; If decision is to exit program, the interrupt vector for INT 08 ; must be fixed because the handler's memory area is not protected CALL CLOSEV8; Fixes without calling DOS MOV AL,2; Tell DOS to end program CRIRET: POP DX,CX,BX,ES,DS IRET ; A routine to handle the BREAK and CTRL-C interrupts: NEWV23: PUSH DS ; My routine just sets a flag to tell PUSH CS ; main program that ctrl-C has been pressed POP DS MOV CTRL_C,0FFh POP DS IRET ; A routine to redirect the BREAK interrupt (INT 023h) to ; my NEWV23 handler... SET_NEW23: MOV AH,025h MOV AL,023h MOV DX,OFFSET NEWV23 INT 021h RET ;**************** INTERRUPT ROUTINES ******************************* ; A routine to get and save the interrupt vectors for IRQ 3 & 4 INT_SAVE: PUSH ES,BX,AX MOV AL,0Bh; INT for COM2&4, IRQ #3 MOV AH,035h; Get int function INT 021h; Call DOS MOV INT_B,BX; Interrupt vector returned in ES:BX MOV BX,ES MOV [INT_B+2],BX ; Now do the same for interrupt OCh MOV AL,0Ch; INT for COM1&3, IRQ #4 MOV AH,035h INT 021h MOV INT_C,BX MOV BX,ES MOV [INT_C+2],BX POP AX,BX,ES RET ; Add subroutines for DOS SHELL function (rev 3.08) ; TO_DOS is the function called from the menu, which manages the ; DOS SHELL entry & exit TO_DOS: CALL GET_SPEC ; 3.17 - get comspec from env. string ... MOV AX, DS ; Get current segment DEC AX ; point to memory control block MOV ES, AX MOV BL, ES:[00] CMP BL, 05Ah ; Means last block in chain JE >L1 PSTATUS NOT_LAST, ATTR11 TICKS 48 RET L1: CALL CLR_SCRN PRINTL TYPE_EXIT CALL FREE_MEM CMP FLAG_BM, 0 JNE >L2 ; skip DOSSHELL if error in releasing memory CALL DOSSHELL ; rebuild memory block to show last block (offset 0 = 5Ah) and memory ; owned equals that amount saved before freeing memory: L2: MOV AX, DS DEC AX MOV ES, AX MOV AL, 05Ah MOV ES:[00], AL MOV AX, MEM_ALLOC MOV ES:[03], AX PUSH CS POP ES L3: CALL FIX_SCRN RET ; A function to release all but required memory to DOS: ; COMMENT\ Please note that there were difficulties freeing and getting back memory. A .COM file has all memory assigned to it. Before I exit to DOS, I use function 4Ah to change the allocation for SIO2PC to just that used by the program plus the amount used by ramdisks. The problem is that this causes DOS to create new memory control blocks ABOVE my memory. Then, when I go back to SIO2PC, I may overwrite these control blocks. Even if I tell DOS I want all the original memory back, it leaves the control blocks back up there. The solution is to trick DOS by restoring the control block ahead of SIO2PC to what was originally shown when I return. It's especially critical that the initial code show that this is the last block in the chain, so DOS doesn't go hunting for more blocks higher up in memory. Control blocks look like this: FLAG DB 04D ; if not last block - 05A if last block PCID DW xxxx ; PSP segment address (process ID) SIZE DW xxxx ; # of paragraphs allocated SPARES DB (11 unused bytes) Note that this control block is in the paragraph just ahead of the process controlled. So, for SIO2PC, just take the value of CS and subtract 1, then the control block is at offset 0 of the resulting segment. You can follow UP the chain like this (first you need a MEM type utility to find the lowest control block, I don't know how to do it.): If you have the segment address of a control block, add SIZE + 1 to it and that is the segment address of the new block. The location of SIZE is defined above. When you look at the new segment address (offset 0000) you will see a 4Dh ('M') if the chain continues, or a 5Ah ('Z') if this is the last block. ENDOFCOMMENT\ FREE_MEM: ; First, store SIO2PC memory block information: MOV AX, CS DEC AX ; point to segment of memory block MOV ES, AX MOV AX, ES:[03] ; # of paragraphs allocated MOV MEM_ALLOC, AX PUSH CS POP ES MOV FLAG_BM, 0 ; assume no error PUSH CS POP ES MOV BX, NEXTS ; top of memory in use, in paragraphs MOV AX, ES ; ES = CS = bottom of memory in use SUB BX, AX ; yields total memory needed by SIO2PC MOV AH, 04Ah ; modify memory allocation INT 021h JNC >L1 L1_2: PSTATUS BAD_MEMAL, ATTR9 ADD AL, '0' CALL PRINT1 CALL WAIT4KEY MOV FLAG_BM, 0FFh ; Flag memory error L1: RET ; A subroutine which executes COMMAND.COM (DOS SHELL): ; NOTE: ALL REGISTERS DESTROYED EXCEPT SEGMENT REGS DOSSHELL: CALL FIXV8 ; turn off my timer interrupt MOV AH, 04Bh MOV AL, 00; execute program (for load overlay; AL = 3) PUSH CS POP ES MOV DS, ES MOV DX, SHELLSPEC MOV BX, PAR_BLOCK MOV DI, SS MOV STORE_SS, DI MOV STORE_SP, SP INT 021h CLI ; inhibit interrupts MOV SS, CS:[STORE_SS] MOV SP, CS:[STORE_SP] PUSH CS POP DI MOV DS, DI MOV ES, DI STI JNC >L1 ; branch if no error L1_1: PSTATUS BAD_SHELL, ATTR9 CALL WAIT4KEY L1: CALL SETUPV8 ; put timer interrupt back CALL SETDTA ; 4.11d adds this ... RET ; Function to search the environment string for COMSPEC= ; and copy the COMSPEC pathname if found ... GET_SPEC: MOV ES, W[02C]; W[02C] is the segment of env. string MOV SI, -1 ; pointer into env. string L1: MOV CX, 8 ; length of CSTRING MOV BX, -1 ; L2: INC BX INC SI MOV AL, ES:B[SI] CMP AL, 0 ; word 0 is end of env. string JE >L3 L4: CMP AL, B[CSTRING+BX] JNE L1 ; reset to start of CSTRING, count = 8 LOOPE L2 ; at this point, all 8 have been found, ES[SI] points to "=" MOV BX, 0 MOV CX, 60; allow up to 60 char pathname L6: MOV AL, ES:B[SI+1] MOV B[SHELLSPEC+BX], AL CMP AL, 0 JE >L5 INC BX INC SI LOOP L6 L3: CMP ES:B[SI+1], 0 ; double 0 is end of string JNE L4 ; if no find by 0000, drop thru to return ... L5: RET ; Make room for my stack: MY_STACK: DB 32 DUP ('STACK ') XEND_PROG: ; LABEL END OF PROGRAM CODE NEXT_SEG: ; ramdisk area can begin here FINI: NOP