PC <> ZX

ZXNet echo conference «zxnet.pc»

From Kirill Frolov To Max Melnikov 4 March 2001

Press RESET immediately, Max! 04 Mar 01 00:07, Max Melnikov wrote to All: MM> We need programs for PC and SPECA to throw files between them MM> (via the printer port or some other way). MacroModem (MMD) on Spectrum. Better 4.51 and above. Something on the pussy compatible. The link must first be made with wires. There are several options: 1. Masovsky via a parallel port using 4 signals. 2. Mine is via a parallel port, 16 wires. Fast but with problems. 3. Mine is through software emulation of a serial port on a spec. 4. Like option 3, but in a cartoon according to the Kondratiev scheme. 5. Connecting the sound blaster to the tape input of the Spectrum. Options 1, 2 and 3 worked in MMD. The first and second require specialized software on the PC and have major compatibility problems... In the first version, CPS=~1500 in MMD, in the second the speeds can be enormous, but it was almost impossible to add the software, so CPS worked very floating from 1300 to 4000. In reality, up to 16-32Kb/sec is possible. Third option IMHO is the best (if you do not take into account the 4th one which was not tested). The spec needs a source supply +12 and -12 volts, 2 TTL inputs with diodes plus to the common wire, 2 TTL output and microcircuit converter MC1489 (or 1488 - I don’t remember). On pussy only free serial port.Software port emulation on the spec works at a speed of 38400 bps. Regarding low CPS, I can say that a significant part of the brakes comes from MMD itself - that's why You shouldn’t chase speed if you plan to use MMD. A first two options I don’t recommend it, although they are extremely simple - there will be problems with the software later it will be easy immeasurably since the options are very non-standard. And the speed is not much different serial port are different. And if there is a turbo mode, then you can emulate the 57600 software problem-free (you can do it without turbo, but buggy). With multichay you can immediately 115200 which gives 11.5kb/sec. In general about parallel It's better to forget the port. From software for PC there is: for option 1, Masovskaya link program for dos. Under second special fossil for DOS (BBS worked!) and MMD-compatible program x-modem. For the third option under DOS the same x-modem program as for the second option and any fossil under serial port. It is written for Linux... For the fourth on PC you also need x-modem program, and on the spec there is a multimedia driver for MMD. Or you can transfer files via Melon Z-modem. For the fifth option there are some bourgeois programs, but the speed there is 1500 bit/sec -- they They just emulate a tape recorder. Connection diagram for 3 (or 4) connection options: Spec: Direction: Pisyuk: GND <------------> GNDTXD --> RXD RXD <--TXD not all software will work. On the Scorpion computer There's no need to solder anything at all... these signals are already there. RTS --> CTS bytes are lost during SOFTWARE There will be NO port emulation. CTS <-- RTS didn't get lost by accident. Why the hell not necessary. Branded ZX-Spectrum has these 4 signals on Interface-1. DSR <-- DTR DTR --> DCD without any fossils and unnecessary software on the PC. WHEN CONNECTING, BE SURE TO CONNECT THE COMPUTER CASES WITH A SEPARATE BY WIRE! FOR EXAMPLE, PLUG ALL COMPUTER EQUIPMENT INTO A COMMON EXTENSION CORD 'PILOT' TYPE. Or connect when everything is unplugged. Otherwise maybe BURN EVERYTHING CONNECTED TO BOTH COMPUTERS (TV from Spectrum, Spectrum, pisyuk, ethernet that leads to a neighbor, a neighbor’s computer...) By the way, in the first (MAS) connection option there is an optical denouement. You can also make optical isolation on the serial port, like in MIDI. But II decided that I don’t mind the pussy, but the Spectrum is oak, what will happen to him...

From Aleksandr Majorov To Max Melnikov 6 March 2001

Hello Max! 05 Mar 01 16:55, Max Melnikov -> Aleksandr Majorov: [skipped] AM>> MMD of any series with a special modem driver, small AM>> will a wire for the PC and a rope with 5 wires work? :) MM> Suitable, as long as you solder as little as possible in the sinter... I did everything under Scorp... And it was necessary to solder the current wiring, and also the optical coupler just in case. For Scorp - two wires to the Kempston joystick, two wires to the printer output. Hy and general. And if there is an optocoupler, then another +5. There are four wires on the PC in LPT, common. Well, if there is an optocoupler, then you need to pull another +5 somehow from the PC ;) I took the keyboard out through the socket :) If you are not Scorpio, then you will have to change the addresses and bits in the MMD driver... Alexand

From Kirill Frolov To Aleksandr Majorov 11 March 2001

Press RESET immediately, Aleksandr! 11 Mar 01 02:33, Aleksandr Majorov wrote to Kirill Frolov: KF>> Don't do that. From my own experience I say - twice later KF>> redone. AM> You are not like other people :-)) AM> Who else did it - they didn’t seem to complain... At first I used your program. But she worked poorly or not at all worked in Windows what is called in the background. Then I made my own link. Everything was fine but in OS/2 it stopped the entire system! And when I installed Linux, then DOS programs There was nothing they could do to help me. And just write a module for the kernel like this (!!!) for support I didn’t really want a link via LPT. I did it fine via RS232. Works WITH ANY COMPUTER, ON ANY OS. KF>> And in the end I came to the connection via a regular serial KF>> port. AM> And many more wires between computers. A heap - at least 3, preferably 4. This is together with the common wire. KF>> All this homemade stuff works extremely unreliably AM> Hmm, how long have I been using this link? ...more than a year? AM> I went on business trips for weeks - everything worked without problems.But when your link works, the whole system SLOWS. And the processor gets hot. KF>> and only under DOS and Windows, AM> What is worth it to me - that’s why I did it ;-))))) And you wouldn’t be able to do it so easily for something other than dos. You would have to read several tens of megabytes of documentation and the same amount of raw materials. Your link and mine on LPT and in dosemu work but 100% loading and everything slows down.

From Kirill Frolov To All 13 March 2001

Press RESET immediately, All! 04 Mar 01 22:30, Valerij Kozhevnikoff wrote to Max Melnikov: MM>> We need programs for PC and SPECA to throw files between them MM>> (via the printer port or some other way). VK> There is such a thing and a lot of it. Kirill Frolov and Alexander Majorov are their authors, and VK> not only. I want it myself, but I only have something that spits out the contents VK> disk in AY. Sources for PC and ZX can be found here. Well, since raw materials are used here, I’ll throw them in too. HO! There’s no need to point your finger at the program and say that I’m lame—I know it myself. There is a bug when displaying file names. Maybe someone can fix it... You can compile in TURBO PASCAL or freeware TMT PASCAL. Doesn't seem to compile in Free-Pascal. Works only in DOS (Windows, OS/2). The program works through the FOSSIL serial port driver. Via I don’t remember which port and how, by default it seems to be through the first (zero). Fossil It could be anything, including the link program. === Cut === {{$define DEBUG} {$define BETA} {$M 65520, 0, 655360} {$V+,T+,P+,X+,I-,F-,Q-,S+} {$D-,L-,R-,Y-} {$ifdef BETA} {$D+,L+,R+,Y+} {$endif} uses dos, crt, {windos,} strings, objects; const _VERSION:string[16]='XMD ver 2.1'+ {$ifdef BETA} 'beta'; {$else} 'full'; {$endif}const _XMODEMERROR=1; _PARAMERROR=2; _FOSSILERROR=3; _BADVIDEO=4; _IOERROR=5; _LOGBUFSIZE=8192; _UPDATETIME=10; _TIMERINT=$1C; type wordptr=^word; const Cfg:record CheckSnow,DirectVideo:boolean; LongNames:boolean; LogName:string; FossPort:word; end=(CheckSnow:false;DirectVideo:false;LongNames:false;LogName:';FossPort:0); var StdOut: text; {$ifdef DEBUG} var xlog : text; {$endif} procedure Log(s:string); forward; {------------------------- DISPLAY VARIABLES -----------------------------} {type DirStr=string; type NameStr=string; type ExtStr=string;} var filenum : byte ; {file number global} filepath : DirStr ; {send file path / receive path [79]} filename : NameStr ; {file name [8]} fileext : ExtStr ; {file extension ' or '.???' [4]} fsize : longint ; {file size, HOBETA if RX} transfered : longint ; {bytes transfered of file} filetime : longint ; {вpемя начала пеpедачи файла} attempts : byte ; {число попыток 10..0} CPS : longint ; {CPS текущего файла} files : byte ; {files to send / received} totalsize: longint ; {bytes transfered global} errors : longint ; {errors global} starttime: longint ; {time programm started}{--------------------------------------- COMMON FUNCTIONS ------------------------------} function HexWord(a:word):string; const HexDigit:array[0..$F] of char = '0123456789ABCDEF'; var i:byte; begin HexWord[0]:=#4; for i:=4 downto 1 do begin HexWord[i]:=HexDigit[a mod $10]; a:=a div $10; end; end; function str2dig(a:byte):string; var s:string[2]; begin Str(a:2,s); if s[1]=' ' then s[1]:='0'; str2dig:=s; end; procedure WrStd(s:string); begin WriteLn(StdOut,s); end; Function SubTime (oldtime : longint) : longint; forward; procedure UpdateGlobalInfo; forward; procedure UpdateFileInfo; forward; {---------------------------- X-MODEM -----------------------------------} const RxTime = 3 ; {time during which nothing happens must be accepted} {1/18 of seconds} RxTimeSend = 40 ; {Max. pause between received blocks} TxTime = 150 {75} ; {timeout for transmitter} XTimeOut = 40 ; {X-modem timeout (for receiver?)} BreakTime = 3 ; {delay when sending BREAK} MaxAttempt = 10 ; {maximum number of attempts} BlockSize = 256 ; {block size} BuffSize = 16384 ; {buffer size for file} { --- Constants for the FOSSIL driver ---} const RxNotEmpty=$0100 ; TxEmpty=$4000 ; FossRead = $0200 ; { FossWrite = $0100 ;}FossStatus = $0300 ; FossInit = $0400 ; FossPurgeRx = $0A00 ; FossPurgeTx = $0900 ; FossWrite2 = $0B00 ; FossBlockWrite = $1900 ; FossGetInfo = $1B00 ; type FossInfo = record StrSize : word ; Version : byte ; RevLevel : byte ; ID : Pointer ; InputSize : word ; InputAvail : word ; OutputSize : word ; OutputAvail : word ; ScreenWidth : byte ; ScreenHeigh : byte ; BaudRateMask : byte ; end ; type FI = ^FossInfo ; {--- Константы X-modem из MMD ---} const SOH_ = $01 ; {Start of every X-Modem Block} ACK_ = $06 ; {Block acknowledge} CRC_ = $43 ; {Request block, CRC mode} NAK_ = $15 ; {Block NOT acnowledged} EOT_ = $04 ; {End of Text (file)} SYNC_= $16 ; {MMD command receipt aknowledge} CAN_ = $18 ; {BREAK signal} ERR_ = $17 ; {ERROR prefix} EOF_ = $1A ; {EOF char} COM_ = $1B ; {MMD command prefix} EOB_ = $20 ; {MMD End Of Batch char} errDisk = 10 ; {ошибка диска} errEndFiles = 2 ; {конец пеpедачи} {--- Пеpеменные и константы для pаботы ---} type xmodetype = (undefined, send, recv) ; type fnc = set of char ; const fchar: fnc = ['!

From Kirill Frolov To All 13 March 2001

Press RESET immediately, All! 04 Mar 01 22:30, Valerij Kozhevnikoff wrote to Max Melnikov: VK> There is such a thing and a lot of it. Kirill Frolov and Alexander Majorov are their authors, and VK> not only. I want it myself, but I only have something that spits out the contents VK> disk in AY. Sources for PC and ZX can be found here. And now I’m throwing raw fossils for a link via LPT. Useful for remodeling BUT YOU SHOULD NOT DO THIS!!! Two files. First one first. === Cut === IDEAL P486 MODEL TINY VER EQU "0.0 alpha" _TEST = 0 PUBLIC StDCD, Baud PUBLIC StRxTx PUBLIC RxBot, RxRead, RxWrite, RxTop PUBLIC TxBot, TxRead, TxWrite, TxTop PUBLIC _TxEmpty, _TxNotFull, _RxNotEmpty, _RxOverrun EXTRN LinkInit, LinkDeinit, IntLink CODESEG STARTUPCODE ORG 100h IF_TEST ELSE jmp Install lea dx, LogoTxt mov ah, 9 int 21h lea dx, ASCII_ID mov ah, 9 int 21h mov cl, [80h] mov ch, 0 or cx, cx jz @@noparam mov bx, 81h @@cmp: mov ax, [bx] inc bx cmp al, ' ' jnz @@xparam loop @@cmp jmp @@noparam @@xparam: cmp al, '0' jc @@noparam cmp al, '8' jnc @@noparam sub al, '0' mov ah, 0 mov [FossPort], ax jmp CheckInst @@noparam: lea dx, @@nopartxt mov ah, 9 int 21h mov ax, 4c01h int 21h ; EXIT @@nopartxt db 13,10,"No Port specified.",13,10 db "USAGE: zxfos ",13,10,"$" CheckInst: mov cx, 19 ; fossil driver info structure size mov ax, cs mov es, ax lea di, TopMemory mov dx, [FossPort] mov ah,1bh int 14h ; GetDriverInfo cmp ax,8 jc Install ; driver not installed mov ax, cs mov ds, ax mov es, [word TopMemory+4] ; ASCII ID 4-byte pointer mov di, [word TopMemory+6] lea si, ASCII_ID mov cx, ASCII_ID_Length jnz Install ; DIFFERENT ASCII STRINGS -> not installed ; Driver already installed on specified port lea dx, @@alreadytxt mov ah, 9 int 21h mov ax, 4c00h int 21h ; EXIT @@alreadytxt: db 13,10 db "Fossil Driver already installed on specified port." db 13,10,"$" LogoTxt db 13,10 db "----------------------------------------------------------------" db 13,10,"$" ENDIF Install: lea ax, TopMemory ; set buffers mov [TxBot], ax mov [TxWrite], ax mov [TxRead], ax add ax, [TxSize] mov [TxTop], ax mov [RxBot], ax mov [RxWrite], ax mov [RxRead], ax add ax, [RxSize] mov [RxTop], ax ; buffers empty call near LinkInit ; link initialization jc @@failinit call near LinkDeinit mov ax, cs mov [ID_seg], ax ; ASCII_ID segment xchg ah, al bswap eax ; set user function (80..C0) address lea ax, JMPOLDINT14 mov cx, 40h lea bx, UFADDR @@fill1: mov [bx], eax add bx, 4 loop @@fill1 mov ax, 3514h ; save old and set new int14 vector int 21h mov [word OldInt14], bx mov [word OldInt14+2], es mov ax, 2514h lea dx, INT14 int 21h IF _TEST mov ah, 4 mov dx, 00ffh int 14h mov ah, 4 mov dx, 0 int 14h mov ah, 1bh mov cx, 100h sub sp, cx ; Get driver info mov di, sp push cx push ss pop es mov dx, 0 int 14h pop cx add sp, cx ;@@keyloop: mov ah, 01 ; int 21h ; jmp @@ttyexit @@fossloop: mov ah, 03h mov dx, 0 int 14h test ah, _RxNotEmpty jz @@reltime mov ah, 02h mov dx, 0 int 14h mov ah, 0bh mov dx, 0 int 14h jmp @@chkkey @@reltime: hlt @@chkkey: mov ah, 0dh int 14h inc ax jz @@fossloop jmp @@ttyexit ;-- TERMINAL --- @@ttyloop: mov ah, 03h mov dx, 0 int 14h test ah, _RxNotEmpty jz @@ttykeyb mov ah, 02h int 14h ; mov cx, 1 ; mov ax, cs ; mov es, ax ; mov di, offset @@al_ ; mov dx, 0 ; mov ah, 18h ; int 14h ; mov al, [@@al_] mov ah, 15h int 14h @@ttykeyb: mov ah, 0dh int 14h inc ax jz @@ttyloop mov ah, 0eh int 14h cmp al, 1bh jz @@ttyexit @@send: mov ah, 0bh mov [@@al_], al mov dx, 0 int 14h dec ax ; mov [@@al_], al ; mov cx, 1 ; mov ax, cs ; mov es, ax ; mov di, offset @@al_ ; mov dx, 0 ; mov ah, 19h ; int 14h ; dec ax jnz @@ttybeep mov al, [@@al_] mov ah, 15h int 14h jmp @@ttyloop @@ttybeep: mov ax, 1507h int 14h jmp @@ttyloop @@ttyexit: jmp DeInstall @@al_ db 0 ELSE lea dx, @@installtxt mov ah, 9 int 21h mov dx, [RxTop] add dx, 200h ; 100h ror dx, 4 test dx, 0f000h jz @@noadd inc dx @@noadd: and dx, 0fffh ; MAX 0fff0h bytes ! mov ax, 3100h ; Terminate and stay Resident int 21h ENDIF @@failinit: mov ax, 4c01h int 21h ; EXIT @@installtxt db 13,10,"Fossil Driver installed.",13,10,"$" DeInstall: call near LinkDeinit mov ax, [word OldInt14] mov ds, [word OldInt14+2] mov ax, 2514h int 21h ; restore old INT14 mov ax, 4c00h int 21h ; EXIT ;---------------------------------------------------------------------------- ;***************** DATA SEGMENT ******************************** ;---------------------------------------------------------------------------- include "zxfos.inc" InitFlg db 0 ; 1 if need Init Video. DriverInfo dw DriverInfo_Length FSpec db 5 FRev db 5 ID_ofs dw offset ASCII_ID ID_seg dw ? RxSize dw 512 ;2048 ; default value RxFree dw ? TxSize dw 512 ;2048 ; too ^^ TxFree dw ? Width db ? Height db ? Baud db 11100011b ; 8N1 DriverInfo_Length = ($-DriverInfo) ASCII_ID db "Fr0lOFF ZXLINK fossil driver (C) ver.",VER,0dh,0ah db "Compiled at ", ??date, " ", ??time db 0,"$" ASCII_ID_Length = ($-ASCII_ID) ;FossPort dw ? ;Status equ word StDCD ;StDCD db 08h ;StRxTx db _TxEmpty + _TxNotFull ;RxBot dw ? ;RxTop dw ? ;TxBot dw ? ;TxTop dw ? ;TxRead dw ? ;TxWrite dw ? ;RxRead dw ? ;RxWrite dw ? ;; StackFrame _ES equ [word bp+12h] _DS equ [word bp+10h] _AX equ [word bp+0eh] _CX equ [word bp+0ch] _DX equ [word bp+0ah] _BX equ [word bp+8] _SP equ [word bp+6] _BP equ [word bp+4] _SI equ [word bp+2] _DI equ [word bp+0] _AL equ [byte bp+0eh] _AH equ [byte bp+0fh] _CL equ [byte bp+0ch] _CH equ [byte bp+0dh] _DL equ [byte bp+0ah] _DH equ [byte bp+0bh] _BL equ [byte bp+08h] _BH equ [byte bp+09h] ;---------------------------------------------------------------------------- ;********************* INT 14 HANDLE ************************************** ;---------------------------------------------------------------------------- PROC INT14 push es push ds pusha ; ax,cx,dx,bx,sp,bp,si,di mov bp,sp mov cx,cs ; set DS=ES=CS mov ds,cx mov es,cx cmp ah, 4 jz @@spec ; special INIT / DEINIT. cmp ah, 5 jz @@spec cmp ah, 7 ; check for valid PORT jz @@run cmp ah, 0dh jc @@check cmp ah, 0fh jc @@run cmp ah, 11h jc @@check cmp ah, 14h jc @@run jz @@check cmp ah, 18h jc @@run cmp ah, 1ch jnc @@run jmp @@check @@spec: cmp dx, 00ffh jz @@run ; "SPECIAL PORT" @@check: cmp dx, 8000h org $-2 FossPort dw 0 jnz @@cont ; INVALID PORT -> CALL PREVIOUS INT14 @@run: cmp ah, 1ch ; BASIC (00..1Bh) funtions jc @@runbasic cmp ah, 80h ; USER 80h..BFh functions jnc @@runuser cmp ah, 7eh ; EXTENDED 7Eh, 7Fh -- install/remove user function jc @@cont ; 1ch..7dh not supported movzx bx,ah ; start EXTENDED functions add bx,bx jmp [bx+EFADDR] @@runbasic: movzx bx,ah ; start BASIC function add bx,bx jmp [bx+FADDR] @@runuser: cmp ah,0c0h ; start USER function jnc @@cont ; not supported movzx bx,ah add bx,bx jmp [bx+UFADDR] @@cont: popa pop ds pop es JMPOLDINT14: db 0eah ; jump far to old INT14 OldInt14: dd 0 ENDP PROC Exit popa pop ds pop es iret ENDP ;---------------------------------------------------------------------------- ;***************** FOSSIL FUNCTIONS JMP TABLE **************************** ;---------------------------------------------------------------------------- FADDR dw SetBaud dw TxChar dw RxChar dw StatusRq dw InitDriv dw Deinit dw DTRctrl dw TimerParam dw FlushTx dw PurgeTx dw PurgeRx dw TxNoWait dw PeekAhead dw PeekKeyb dw ReadKeyb dw FlowCtrl dw CtrlKcheck dw SetCursor dw ReadCursor dw WriteANSI dw WatchDog dw WriteChar dw HookTimerInt dw Reboot dw ReadBlock dw WriteBlock dw SendBreak dw GetDrivInfo EFADDR dw InstallUser dw RemoveUser ;---------------------------------------------------------------------------- ;***************** FOSSIL BASIC FUNCTIONS ******************************** ;---------------------------------------------------------------------------- PROC SetBaud ; AX=BAUD RATE DX=PORT -> AX=STATUS jmp StatusRq ENDP ;---------------------------------------------------------------------------- PROC TxChar ; AL=CHAR DX=PORT -> AX=Status ; Wait if buffer id full @@wait: test [StRxTx], _TxNotFull jnz @@ready sti hlt jmp @@wait @@ready: cli mov al, _AL call PutByte jmp StatusRq ENDP ;---------------------------------------------------------------------------- PROC RxChar ; DX=PORT -> AH=0 AL=CHAR ; Wait if buffer is empty @@wait: test [StRxTx], _RxNotEmpty jnz @@ready sti hlt jmp @@wait @@ready: cli mov bx, 8000h org $-2 RxRead dw 0 mov al, [bx] inc bx cmp bx, 8000h org $-2 RxTop dw 0 jc @@nover mov bx, 8000h org $-2 RxBot dw 0 @@nover: cmp bx, 8000h org $-2 RxWrite dw 0 jnz @@nempty and [StRxTx], not _RxNotEmpty @@nempty: and [StRxTx], not _RxOverrun mov [RxRead], bx mov ah, 0 mov _AX, ax jmp Exit ENDP ;---------------------------------------------------------------------------- PROC StatusRq ; DX=PORT -> AX=Status ; ; AH: bit: 6 =1 : Output is empty ; 5 =1 : Output is NOT full ; 1 =1 : Input OVERRUN ; 0 =1 : Input NOT EMPTY ; ; AL: bit: 7 =1 : CARRIER DETECT ; 3 =1 : Always =1, newer 0 ! mov ax, 0 org $-2 StDCD db 08h StRxTx db _TxEmpty + _TxNotFull Status equ word StDCD mov _AX, ax jmp Exit ENDP ;---------------------------------------------------------------------------- PROC InitDriv ; DX=PORT -> AX=1954H BL=Max.Funct. BH=Rev.Level ; DTR raised ; ; if DX=00FF then any initialization needed to make keyboard ; and display available for FOSSIL use should be performed. ; bx=4F50h signals that ES:CX points to a flag byte in the ; application that the driver should increment when its ; keyboard routines detect a CTRL-C ; cmp _DX, 00ffh jnz @@init ; Not SPECIAL mov [InitFlg], 1 jmp @@end @@init: mov [StRxTx], _TxEmpty + _TxNotFull mov ax, [RxBot] mov [RxWrite], ax mov [RxRead], ax mov ax, [TxBot] mov [TxWrite], ax mov [TxRead], ax ; purge buffers test [InitFlg], 0ffh jz @@cont ; video and keyboard initialization mov ax, 0003h int 10h ; set video mode 3 @@clkey: mov ah, 1 int 16h jz @@cont ; keyb. buffer empty mov ah, 0 int 16h jmp @@clkey @@cont: call near LinkInit @@end: mov _AX, 1954h mov _BX, 051bh jmp Exit ENDP ;---------------------------------------------------------------------------- PROC Deinit ; DX=PORT -> none ; ; if dx=00FFh then the initialization that was performed when ; FOSSIL function 04h (INIT) with DX=00FFh should be undone ; cmp _DX, 00ffh jnz @@cont ; Not SPECIAL mov [InitFlg], 0 jmp Exit @@cont: ;;; call near LinkDeinit ; ??? jmp Exit ENDP ;---------------------------------------------------------------------------- PROC DTRctrl ; AL=1 raise /0 lower DTR DX=PORT -> AL=DTR 1=true 0=false test _AL, 1 jnz @@raise call near LinkDeinit mov _AL, 0 jmp Exit @@raise: call near LinkInit mov ax, 1 sbb ax, 0 mov _AL, al jmp Exit ENDP ;---------------------------------------------------------------------------- PROC TimerParam ; none -> AL=timer tick interrupt AH=ticks/second DX=mS/tick mov _AX, 1c12h ; INT 1CH, 18 ticks / second mov _DX, 56 ; 55.555[5] jmp Exit ENDP ;---------------------------------------------------------------------------- PROC FlushTx ; DX=PORT -> none ; Wait until buffer is empty @@wait: test [StRxTx], _TxEmpty jnz @@ready sti hlt jmp @@wait @@ready: jmp Exit ENDP ;---------------------------------------------------------------------------- PROC PurgeTx ; DX=PORT -> none ; Exit immendiatelly or [StRxTx], _TxEmpty + _TxNotFull mov ax, [TxBot] mov [TxRead], ax mov [TxWrite], ax jmp Exit ENDP ;---------------------------------------------------------------------------- PROC PurgeRx ; DX=PORT -> none ; Exit immendiatelly and [StRxTx], not (_RxOverrun + _RxNotEmpty) mov ax, RxBot mov [RxRead], ax mov [RxWrite], ax jmp Exit ENDP ;---------------------------------------------------------------------------- PROC TxNoWait ;DX=PORT AL=CHAR -> AX=1 char sent AX=0 not sent (buffer full) test [StRxTx], _TxNotFull jnz @@ready xor ax,ax jmp @@exit @@ready: mov al, _AL call PutByte mov ax, 1 @@exit: mov _AX, ax jmp Exit ENDP ;---------------------------------------------------------------------------- PROC PeekAhead ; DX=PORT -> AH=0 AL=CHAR if available / AX=FFFFh if not test [StRxTx], _RxNotEmpty jnz @@ready mov ax,0ffffh jmp @@exit @@ready: mov bx, [RxRead] mov al, [bx] mov ah,0 @@exit: mov _AX, ax jmp Exit ENDP ;---------------------------------------------------------------------------- PROC PeekKeyb ; none -> AX=CHAR if available / AX=FFFFh of not mov ah,11h ; get keyb status int 16h jnz @@exit ; character available in keyb. buffer AX=SCANCODE mov ax,0ffffh ; no char available @@exit: mov _AX, ax jmp Exit ENDP ;---------------------------------------------------------------------------- PROC ReadKeyb ; none -> AX=CHAR ; Wait if not available mov ah,10h ; get keyb scan code / wait if not available int 16h mov _AX, ax jmp Exit ENDP ;---------------------------------------------------------------------------- PROC FlowCtrl ; DX=PORT AL=Flow ctrl bit mask -> none ; AL bits: ; 0 =1 : enables remote XON/XOFF (contrl FOSSIL tx) ; 1 =1 : RTS/CTS for FOSSIL<->MODEM ; 3 =1 : enables fossil XON/XOFF (control REMOTE tx) jmp Exit ENDP ;---------------------------------------------------------------------------- PROC CtrlKcheck ; DX=PORT AL=flag byte -> ; -> AX=1 Ctrl-C(-K) detected sinse last call, esle AX=0 ; AL bits: ; 0 =1 : enable/disable CTRL-C(-K) check ; 1 =1 : stop transmitter ; =0 : release previous stop mov _AX, 0 ; fake jmp Exit ENDP ;---------------------------------------------------------------------------- PROC SetCursor ; DH=ROW DL=COL -> none mov dx, _DX mov ah, 02h xor bx, bx int 10h jmp Exit ENDP ;---------------------------------------------------------------------------- PROC ReadCursor ; none -> DH=ROW DL=COL mov ah,03h xor bx,bx int 10h mov _DX, dx jmp Exit ENDP ;---------------------------------------------------------------------------- PROC WriteANSI ; AL=CHAR -> none ; not re-entrant, DOS funct. may be used mov ah,02h mov dl, _AL int 21h ; ANSI.SYS required jmp Exit ENDP ;---------------------------------------------------------------------------- PROC WatchDog ; AL=1 enable AL=0 disable watchdog DX=PORT -> none ; FOSSIL will force the system to reboot if CARRIER DETECT ; on specified port drops while watchdog is on. ; Is not nessesary for port to be active (funct. 04) ; for this function to be used. jmp Exit ENDP ;---------------------------------------------------------------------------- PROC WriteChar ; AL=CHAR -> none ; this function must be re-entrant ! mov al, _AL mov ah, 0eh xor bx, bx int 10h jmp Exit ENDP ;---------------------------------------------------------------------------- PROC HookTimerInt ; AL=1 set AL=0 remove, ES:DX=ADDRESS -> ; -> AX=0 if ok, AX=FFFFh if unsuccessful mov _AX, 0ffffh ; not released jmp Exit ENDP ;---------------------------------------------------------------------------- PROC Reboot ; AL=0 cold AH=1 warm boot -> never returns db 0eah ; jump far dd 0ffff0000h ; reboot ENDP ;---------------------------------------------------------------------------- PROC ReadBlock ; CX=MAXIMUM SIZE ES:DI=USER BUFFFER PTR DX=PORT -> ; -> AX=CHARS ACTUALLY REMOVED ; not wait if no char avail. xor bx, bx ; counter test [StRxTx], _RxNotEmpty jz @@nempty ; no data in buffer mov cx, _CX ; max SIZE in application or cx, cx jz @@nempty mov es, _ES mov di, _DI ; dest. ES:DI mov si, [RxRead] ; source DS:SI mov ax, [RxWrite] ; if (RxWrite > RxRead) sub ax, si ; then { move (ax) or move (cx) ?} jnc @@moveax ; mov ax, [RxTop] ; if (RxTop-RxRead > _CX) sub ax, si ; then { move (cx) } cmp ax, cx ; jnc @@movecx ; mov cx, ax ; else move (RxTop-RxRead) add bx, cx ; add to counter rep movsb ; mov cx, _CX ; bytes left = _CX - (RxTop-RxRead) sub cx, ax ; mov si, [RxBot] ; buffer left = RxWrite - RxBot mov ax, [RxWrite] ; sub ax, si ; @@moveax: cmp ax, cx ; if bytes_left < buffer_left jnc @@movecx ; then move (bytes_left) mov cx, ax ; else move (buffer_left) @@movecx: add bx, cx ; add to counter rep movsb mov [RxRead], si and [StRxTx], not _RxOverrun cmp si,[RxWrite] jnz @@nempty and [StRxTx], not _RxNotEmpty @@nempty: mov _AX, bx ; return data jmp Exit ENDP ;---------------------------------------------------------------------------- PROC WriteBlock ; CX=COUNT ES:DI=USER BUFFER PTR DX=PORT -> ; -> AX=CHARS ACTUALLY REMOVED ; xor bx, bx ; counter bytes removed test [StRxTx], _TxNotFull jz @@nfull ; tx buffer is full mov cx, _CX ; bytes MAX. or cx, cx jz @@nfull mov ds, _ES mov si, _DI ; source -> DS:SI mov ax, cs mov es, ax mov di, cs:[TxWrite] ; dest. -> ES:DI mov ax, cs:[TxRead] ; if TxWrite < TxRead sub ax, di ; then { move (ax) or move (cx) ? } ja @@moveax ; mov ax, cs:[TxTop] ; if TxTop-TxWrite >= BytesMax (_CX) sub ax, di ; then move _CX bytes cmp ax, cx ; jnc @@movecx ; mov cx, ax ; else move (TxTop-TxWrite) bytes add bx, cx ; add to counter rep movsb ; and move it mov cx, _CX ; then BytesLeft := _CX - (TxTop-TxWrite) sub cx, ax ; mov di, cs:[TxBot] ; if (TxRead-TxBot) > BytesLeft mov ax, cs:[TxRead] ; then move (BytesLeft) bytes sub ax, di ; @@moveax: cmp ax, cx ; if ax >= cx then move (cx) jnc @@movecx ; else move (ax) mov cx,ax ; else move (TxRead-TxBot) bytes @@movecx: add bx, cx ; add to counter rep movsb ; and move it mov ax,cs mov ds,ax mov [TxWrite], di and [StRxTx], not _TxEmpty cmp di, [TxRead] jnz @@nfull and [StRxTx], not _TxNotFull @@nfull: mov _AX, bx ; return data call near IntLink jmp Exit ENDP ;---------------------------------------------------------------------------- PROC SendBreak ; AL=1 start AL=0 stop sending BREAK DX=PORT -> none jmp Exit ENDP ;---------------------------------------------------------------------------- PROC GetDrivInfo ; CX=BUFFER SIZE ES:DI=ADDRESS DX=PORT -> ; -> AX=BYTES TRANSFERED ACTUALLY ; 0 (word) = Structure size ; 2 (byte) = FOSSIL spec version ; 3 (byte) = Driver rev level ; 4 (dwrd) = Pointer to ASCII ID ; 8 (word) = Input buffer size ; 0A (word) = Bytes avail (input) ; 0C (word) = Output buffer size ; 0E (word) = Bytes avail (output) ; 10 (byte) = Screen width, chars ; 11 (byte) = Screen height, chars ; 12 (byte) = Baud rate mask ; (See call 00h) mov ah, 0fh int 10h ; Get video mode mov [Width], ah mov [Height], 25 xor ax, ax test [StRxTx], _RxNotEmpty jz @@rxadd mov ax, [RxWrite] sub ax, [RxRead] jnc @@rxfree @@rxadd: add ax, [RxSize] @@rxfree: mov [RxFree], ax xor ax, ax test [StRxTx], _TxEmpty jnz @@txadd mov ax, [TxWrite] sub ax, [TxRead] jnc @@txfree @@txadd: add ax, [TxSize] @@txfree: mov [TxFree], ax mov si, offset DriverInfo mov es, _ES mov di, _DI mov cx, _CX mov ax, [DriverInfo] cmp ax, cx jnc @@movecx mov cx, ax @@movecx: mov _AX, cx rep movsb jmp Exit ENDP ;---------------------------------------------------------------------------- ; ************** FOSSIL EXTENDED FUNCTIONS ******************************** ;---------------------------------------------------------------------------- PROC InstallUser ; AL=code ES:DX=address -> ; AX=1954H BL=code (same as AL) BH=1 if ok else BH=0 xor ax,ax mov al, _AL mov _BX, ax mov _AX, 1954h jmp Exit ENDP ;---------------------------------------------------------------------------- PROC RemoveUser ; AL=code ES:DX=address -> ; AX=1954h BL=code (same as AL) BH=1 if ok, else BH=0 ; if ES:DX not same as address in JMP table error occurs. xor ax,ax mov al, _AL mov _BX, ax mov _AX, 1954h jmp Exit ENDP ;---------------------------------------------------------------------------- ;******************** Common Subrutines ******************************** ;---------------------------------------------------------------------------- ; PROC PutByte ; AL=Byte, tx buffer not full. mov bx, 8000h org $-2 TxWrite dw 0 mov[bx], al inc bx cmp bx, 8000h org $-2 TxTop dw jc @@never mov bx, 8000h org $-2 TxBot dw @@nover : cmp bx , 8000h org $-2 TxRead dw jnz @@exit and [ StRxTx ] , not _TxNotFull @@exit : and [ StRxTx ] , not _TxEmpty mov [ TxWrite ] , bx call near IntLink ret ENDP ;--------------------------------------------------------------------------------------------- ;***************** UNDEFINED DATA SEGMENT ***************************** ;--------------------------------------------------------------------------------------------- UDATASEG UFADDR dd 40h dup(?) ; USER DEFINED FUNCTION ADDRESSES ;; STACK 400h TopMemory = $ END === Cut === To the rest of the world in this category: === Cut === ;--------------------------------------------------------------------------------------------- ;***************** ZX-LINK Send and Receive procedures ******************* ;--------------------------------------------------------------------------------------------- ; IDEAL P486 TINY MODEL _LOOPBACK = 0 EXTRN StRxTx, StDCD EXTRN RxBot, RxTop, RxRead, RxWrite EXTRN TxBot, TxTop, TxRead, TxWrite include "zxfos.inc"PUBLIC LinkInit, LinkDeinit, IntLink ; DS=CS! _PE equ 20h ; direction change 0=receive 1=send _ACK equ 40h ; interrupt request _ERROR equ 08h ; reversed / DCD _AUTO equ 02h ; invert acknowledge _SLCT equ 08h ; return direction 1=receive _IRQ equ 10h ; enable interrupts _DIR equ 20h ; direction set 1=receive DATASEG LptInt db 07h LptPort dw 378h LptActive db 0 UDATASEG RxBlockProc dd ? OldIntVec dd ? CODESEG ;=============================================================================== ; Initialization and configuration. The output flag is cf=1 if there are errors. ; PROC LinkInit ; setting up an LPT port test [LptActive], 1 jnz @@exit mov [byte LptActive], 1 mov ax, [word LptInt] call Int2PIC pusha; a new interrupt vector is installed mov ah, 35h int 21h mov [word OldIntVec], bx mov [word OldIntVec+2], es mov ah, 25h mov dx, offset LptIntProc int 21h popa not cx cli in al, (dx) ; interrupt enable in PIC and al, ch out (dx), al stimov dx, [LptPort] ; enabling interrupts in the port inc dx inc dx mov al, _SLCT or _IRQ or _DIR out (dx), al mov [byte StRxTx], _TxEmpty or _TxNotFull mov ax, [TxBot] mov [TxRead], ax mov [TxWrite], ax @@exit: clc ret ENDP ;================================================================================ ; Shutdown ; PROC LinkDeinit mov ax, [word LptInt] call Int2PIC push ax cli ; disabling interrupts in PIC in al, (dx) or al, ch out (dx), al sti pop ax push ds ; restoring the interrupt vector mov dx, [word OldIntVec] mov ds, [word OldIntVec+2] mov ah, 25h int 21h pop ds mov dx, [LptPort] ; disabling LPT port add dx, 402h mov al, 34h; ECP set to ps/2 out (dx), al sub dx, 400h mov al, 2bh ; off... out (dx), al mov [byte LptActive], 0 ret ENDP ; INPUT: AL=hardware interrupt number. ; OUTPUT: DX=address PIC+1, AL=vector for DOS, CH=mask for PIC. PROC Int2PIC NEARmov right, 9pm add ax, 8 cmp al, 10h jc @@pic20 mov right, 0a1h add ax, 60h @@pic20: mov cx, ax and cx, 7 mov ch, 1 shl ch, cl ret ENDP ;======================================================================================== ; PROC IntLink ret ENDP ;========================================================================================== ; Обpаботка пpеpываний от поpта ; PROC LptIntProc FAR pusha ; ax,cx,dx,bx,sp,bp,si,di push right mov ax, cs mov ds, ax mov right, [LptPort] inc right in al