From
Kirill Frolov
→
To
All
11 November 1999
Immediately press RESET, All!
Well, I figured out how to issue auxiliary commands
and what glitches there are. You can live without reading register 1F, through
FF readiness is always read.
At the same time I learned that the DX command cannot be given to the VGshka. She then
goes into meditation, INTRQ does not output... We really need D0
immediate interruption.
But as for recording sector readings, it couldn’t be worse. :-(
I found this in TR-DOS:
3F4B 3ED0 LD A, 0xD0
3F4D D31F OUT (0x1F), A
3F4F 78 LD A, B
3F50 E601 AND 0x01
3F52 C2E73E JP NZ, 0x3EE7
3F55 DB3F IN A, (0x3F)
3F57 B7 OR A
3F58 2005 JR NZ, 0x3F5F
3F5A DB5F IN A, (0x5F)
3F5C FE0A CP 0x0A
3F5E C8 RET Z
It turns out that if there is an error when reading sector 10 on track 0
TR-DOS doesn't care about that. Moreover, _PARTY NUMBER IS NOT CHECKED_!
This means that the 10th sector of the very first file on the disk can
be read with an error or not read at all! =%-()
The conclusion is quite logical - 3d13 Mazda. But no turboloaders
there will be no help here, they either ignore errors altogether, since they don’t
can read register 1F, or use this buggy program
in TR-DOS.
But I just wanted to create a read-write programsectors with error detection and without using system variables
TR-DOS. I came to the conclusion that this is simply impossible without reading the register
1F.
We need to fix TR-DOS, this time... It's a terrible glitch. :-(
It will definitely work in iS-DOS on 640kb disks,
in MOA CP/M, in TR-DOS itself, when reading MS-DOS 800kb disks...
Kirill Frolov. [ZX]
From
Ivan Mak
→
To
Kirill Frolov
14 November 1999
Greetings, Kirill!
<01:50> Kirill Frolov write to Ivan Mak:
IM>> However, in both cases TR-DOS is easily replaced with RAM protected from
IM>> records. You can fix it any way you want.
KF> Well then, tell me how this can be done in Petersburg.
Petersburg has a 3FFD port.
Bits 0 and 3 enabled
Bit 0 switches halves of 27010, like two halves of 27512
If bit 3 is one, instead of 27512 (27010) 64Kb of RAM is connected, which
located in 12-15 banks.
12 - EXPANSION
13 - TR-DOS
14 - BASIC128
15 - BASIC48
At zero they are naturally write-protected, but writing is the same as in a regular extension
remains.
Upon reset, 3FFD is reset to 0
And in the latest firmware for Peters (27010) it was done so that you can
the installed "ROM" is reset.
Wow! The Protoss are attacking my Zerlings! It's time to get going. Ivan.
- Divorce the circuit, big and small.. [ Sprinter-II ] [ Forth-CPU ] [ ZX ]
From
Sergey Selev
→
To
Kirill Frolov
17 November 1999
I wish you good health, %t1.
I wish you good health, Kirill.
One day on Thursday, November 11, 1999, Kirill Frolov spoke with All about TR-DOS...
KF> I found this in TR-DOS:
KF> 3F4B 3ED0 LD A, 0xD0
KF> 3F4D D31F OUT (0x1F), A
KF> 3F4F 78 LD A, B
KF> 3F50 E601 AND 0x01
KF> 3F52 C2E73E JP NZ, 0x3EE7
KF> 3F55 DB3F IN A, (0x3F)
KF> 3F57 B7 OR A
KF> 3F58 2005 JR NZ, 0x3F5F
KF> 3F5A DB5F IN A, (0x5F)
KF> 3F5C FE0A CP 0x0A
KF> 3F5E C8 RET Z
KF> It turns out that if there is an error when reading sector 10 on
KF> track 0
KF> TR-DOS doesn't care about that. Moreover, _PARTY NUMBER NOT
KF> CHECKING_ !
KF> And this means that the 10th sector of the very first file is on
KF> disk can
KF> be read with an error or not read at all! =%-()Who taught you to use this subroutine? I myself have long ago
I realized that she is a motherfucker!
KF> The conclusion is quite logical - 3d13 Mazda. But none
KF> turboloaders
KF> won't help here, they either ignore errors altogether, because
KF> not
KF> can read register 1F, or use this buggy
KF> program
KF> in TR-DOS.
What are you doing!!! Have you driven my Turbo Commander v0.xx??? In it
all errors (No disk, Break, Disk error, Read only) are perfectly caught (there
costs Turbo Driver)!!! Syst. subject variables can be saved if desired (12
bytes in total).
KF> But I just wanted to create a program for
KF> read-write
KF> sectors with and without error detection
KF> system variables
KF> TR-DOS. I came to the conclusion that this is simply impossible without
^^^^^^ ^^^^^^^^^^ this is complete nonsense!!!
It looks like you don't know how to program at all.
KF> read register 1F.
I would recommend this:
Use the subroutine at address 10048 (#2740). What and how you work out yourself. But
if it doesn’t reach you, then I’ll have to kill youshow me how to do it. Variables WILL NOT be spoiled!!!
+++*** Bye. Selev Sergey aka Cyber from Cobra Software ***++++
From
Aleksandr Kolotuhin
→
To
All
20 August 2000
·∙.■■■ Hi, everyone! ■■■.∙·
Explain to me, stupid, how to intercept
errors:
1. Disk error
2. No disk
3. Disk is protected
4. Disk is full
Thank you.
Happy All! I came across Aleksandr's message.
[SPECCY] [ZENIT] [BEER!] [GIRLZZZZ] [MY GUITAR]
From
Kirill Frolov
→
To
Aleksandr Kolotuhin
21 August 2000
Press RESET immediately, Aleksandr!
20 Aug 00 02:44, Aleksandr Kolotukhin wrote to All:
AK> Explain to me, stupid, how to intercept
AK> errors:
AK> 1. Disk error
AK> 2. No disk
AK> 3. The disk is protected
AK> 4. Disk is full
Error codes:
Error handling in TR-DOS is implemented very incorrectly, but
it is still possible to distinguish errors if we use two translations
variable: 23610 and 23823.
╔════════════════════╤══════════ ═══════════════════╤═════╤═════╗
║Error message.│Meaning. │23610│23823║
╟────────────────────┼────────── ───────────────────┼─────┼─────╢
║O.K. │Normal completion. │ 255 │ 0 ║
║No file(s) │The required file was not found. │ 255 │ 1 ║
║File exists │The file already exists. │ 255 │ 2 ║
║No space │No disk space. │ 255 │ 3 ║
║Directory full │There is no space in the disk directory. │ 255 │ 4 ║
║Rec OF │Appeal to non-existent │ 255 │ 5 ║
║ │file sector. │ │ ║
║No disc │There is no disc in the drive. │ 26 │ 6 ║
║Disc error │Disk error. There are 3 options - │ 26 │ 7 ║║Trk XX sec XX │anta: R - try again- │ │ ║
║Retry, Abort, Ignore? │ │ ║
║ │of the next sector, A - otka- │ │ ║
║ │to avoid surgery. │ │ ║
║Read only │The disc is write protected. Yes │ 26 │ 7 ║
║Trk XX sec XX │3 options (see above). │ │ ║
║Retry, Abort, Ignore? │ │ │ ║
║Stream opened │The stream to be opened is already busy. │ 25 │ 10 ║
║Not disk file │The closed channel does not belong - │ 255 │ 11 ║
║ │lies TR-DOS. │ │ ║
║Array not found │The required variable is not found- │ 255 │ 14 ║
║ │dena. │ 1 │ 1 ║
║*BREAK* │BREAK key is pressed. │ 20 │ 20 ║
║ │ │ 12 │ 12 ║
║Out of RAM │Not enough RAM│ 3 │ 3 ║
║Disc error │The disk does not belong to TR-DOS. │ 255 │ 0 ║
║Read only │Attempting to record on a 40-track-│ 255 │ * ║
║ │ 80-track disc │ │ ║
║ │disk drive. │ │ ║
║*ERROR* │Other errors, mainly │ 11 │ 12 ║
║ │syntactic. │X │X+1 ║╚════════════════════╧══════════ ═══════════════════╧═════╧═════╝
* - copy of the variable with the drive type,
X - any number.
If the message Retry, Abort, Ignore? installation error codes
are poured when the answer is A.
> There is no need to intercept points 1, 3 and 4, just look at the error code immediately
> after CALL 3D13. Just don't forget to do LD HL,0 : LD (5D0F),HL.
> Point 2 is intercepted in the standard way, through the system
> variable ERR_SP (see Larchenko and Rodionov in the book):
; calling the tr-dos function
trdos:
push hl
ld hl, (err_sp)
ex (sp), hl
push hl
ld hl, basic_error
ex (sp), hl
ld (err_sp), sp
call 3d13h
basic_error:
pop de
pop de
ld (err_sp), de
.... ; checking for an error
System variables TR-DOS 5.04T.
╔═════╤═════╤═══════════════════ ═══════════════════════════════╗
║Address│Length│ Content. ║
╟─────┼─────┼─────────────────── ───────────────────────────────╢
║23734│ 1 │Used if there is INTERFACE-1. If equal to ║
║ │ │244, then the variable area is not transferred, otherwise ║
║ │ │checking 23832. ║
║23735│ 11 │Not used. ║> Pay attention VVV
>
>║23746│ 1 │Contains the RET command. Used to switch - ║
>
> ^^^^^ Look there
║ │ │version of ROM to BASIC. ║
║23747│ 5 │Not used. ║
║23752│ 1 │Drive type A: ║
║ │ │ bit 7=0 - 40-track drive. ║
║ │ │ 1 - 80-track drive. ║
║ │ │ bit 1=0 - single-sided drive. ║
║ │ │ 1 - double-sided disk drive. ║
║ │ │ bit 0=0 - use 80-track drive as║
║ │ │ 40) track. ║
║23753│ 1 │Drive type B. ║
║23754│ 1 │Drive type C. ║
║23755│ 1 │Disk drive type D. ║
║23756│ 1 │Current sector when working with a directory. ║
║23757│ 1 │If not 0, then there will be a delay after positioning-║
║ │ │ka. VG-93 status register before road check -║
║ │ │ki. Bit 7 of the VG-93 status register before reading ║
║ │ │address marker. ║
║23758│ 1 │Flag for operations with sectors. At 0 - reading sectors,║║ │ │at 255 - recording. ║
║23759│ 2 │Address of the working memory area for MOVE, COPY, LIST.║
║ │ │and when processing the record number when outputting to a file ║
║ │ │direct access data. ║
║23761│ 1 │Length of the moved file for MOVE. ║
║23762│ 1 │Array name when writing/loading an array in the form: ║
║ │ │bits 0 - 4 - array name (from "A"=1 to "Z"=26), ║
║ │ │bit 5 - if 0, then the array is numeric, ║
║ │ │bit 6 - if 1, then the array is string, ║
║ │ │bit 7 is always 1. ║
║23761│ 2 │Autostart line number when writing a program to ║
║ │ │basic. ║
║23763│ 2 │Sector counter of the moved file for MOVE. ║
║23764│ 1 │Number of the file to be erased for MOVE. ║
║23765│ 1 │Current sector of the moved file for MOVE. ║
║23766│ 1 │The current track of the moved file for MOVE. Co- ║
║ │ │number of defective sectors during formatting and ║
║ │ │checking the disk. For the string compression routine: ║
║ │ │if 0, then the command is in the program line at║
║ │ │basic, otherwise elsewhere. For subroutine ║
║ │ │file download: if 0, then download address and length ║║ │ │taken from the file descriptor, if 3, then from 23769 and ║
║ │ │23771 respectively, otherwise the download address is taken║
║ │ │from 23769, and the length is from the file descriptor. ║
║23767│ 1 │The current sector of the file to be erased during MOVE. Quantity-║
║ │ │two tracks when determining the type of drive and format- ║
║ │ │matting. ║
║23768│ 1 │The current track of the file to be erased during MOVE. If not
║ │ │0, then the formatted track is not checked. ║
║23767│ 2 │Saves CH_ADD when processing record number in ║
║ │ │sequential access file. Variable address ║
║ │ │string length for the string compression routine. Address║
║ │ │of the old array when loading the array. Secto address -║
║ │ │pa for PEEK and POKE. ║
║23769│ 1 │Relative address of record when processing number ║
║ │ │records in a sequential access file. ║
║23770│ 1 │Number of the block of the arbitrary file to be opened - ║
║ │ │stupid when processing the record number. If equal to 128, ║
║ │ │, then two sides are formatted, otherwise only one.║
║23769│ 2 │Counter of freed sectors for MOVE. Address ║
║ │ │file loading for LOAD, sector number for PEEK and ║
║ │ │POKE. The keyword address for the compression subroutine is ║║ │ │this line. Length of the file to be written when SAVE. ║
║23771│ 1 │The number of the loaded sector of the file block is arbitrary - ║
║ │ │free access when processing the record number. Number ║
║ │ │the first sector of the moved file for MOVE. ║
║23772│ 1 │number of the first track of the moved file for MOVE.║
║23771│ 2 │File length for LOAD. File length to specify in ║
║ │ │directory with SAVE. Stream number for CAT and LIST. ║
║23773│ 8 │The name of the file or disk when formatting. ║
║23781│ │File extension. ║
║23782│ 2 │File download address. Sector table address for ║
║ │ │formatting. ║
║23784│ 2 │File length. Sector table address to check ║
║ │ │paths. ║
║23786│ 1 │File volume in sectors. ║
║23787│ 1 │Number of the first sector of the file. ║
║23788│ 1 │Number of the first track of the file. ║
║23789│ 2 │Download address of the old file for COPY. ║
║23791│ 2 │Length of the old file in bytes for COPY. ║
║23793│ 1 │Length of the old file in sectors for COPY. ║
║23794│ 1 │Number of the first sector of the old file for COPY. ║
║23795│ 1 │Number of the first track of the old file for COPY. ║║23796│ 1 │Number of the current sector for the subroutine ║
║ │ │sector loading/writing. ║
║23797│ │Number of the current track for the subroutine ║
║ │ │sector loading/writing. ║
║23798│ 2 │Disk drive number for the operation (0 - 3). ║
║23800│ 1 │Source drive for COPY. If equal to 255, then at║
║ │ │When outputting to a data file, the buffer is not deleted. ║
║23801│ 1 │Receiver drive for COPY. Drive number at ║
║ │ │output of the directory. Sign of file operation: 0 - ║
║ │ │ - loading, 255 - verification. ║
║23802│ 1 │Drive head movement time A: (8 - 11). ║
║23803│ 1 │Same for drive B:. ║
║23804│ 1 │Same for drive C:. ║
║23805│ 1 │Same for drive D:. ║
║23806│ 1 │Controller command for read/for- ║
║ │ │pis sector. ║
║23807│ 1 │Sector number for the read/write routine ║
║ │ │sector. ║
║23808│ 2 │Sector address for read/write routine ║
║ │ │sector. ║
║23810│ 2 │Saves HL for subroutine call subroutine ║║ │ │from BASIC ROM and 15635. ║
║23812│ 2 │Keeps DE. ║
║23814│ 1 │Number of file descriptor bytes checked when it is ║
║ │ │search. ║
║23815│ 1 │Number of erased files for the erase subroutine - ║
║ │ │ files. ║
║23816│ 1 │The first character of the file name for the erase routine is ║
║ │ │ files. ║
║23817│ 1 │data file type for OPEN# ("R", "W" or "RND"). ║
║23819│ 2 │Not used. ║
║23820│ 1 │Buffer presence flag: 0 - yes, otherwise - no. ║
║23821│ 1 │Number of the current file when copying the entire disk from║
║ │ │two disk drives. ║
║23822│ 1 │State flag of the working memory area. If equal to ║
║ │ │255, then the work area was used. If equal║
║ │ │254, then subroutine 963 ignores errors. ║
║23823│ 1 │TR-DOS error code. When searching for a file with the subroutine ║
║ │ │15635: 255 - file not found, otherwise - file number. ║
║23824│ 1 │Operation flag for the load/verify subroutine
║ │ │file cations: 0 - file operation, 255 - download- ║
║ │ │ka / file sector verification, otherwise - write ║║ │ │sectors of the file. ║
║23825│ 2 │Command line address. ║
║23827│ 2 │Saves the contents of ERR_SP for subprograms
║ │ │gate to BASIC. ║
║23829│ 1 │If 0, then error messages are displayed on the screen - ║
║ │ │kah, otherwise they will not be displayed. ║
║23830│ 1 │Copy of the system register. ║
║23831│ 1 │If equal to 170, then when calling 15612 the screen saver does not ║
║ │ │is displayed, otherwise the splash screen is displayed and checked ║
║ │ │byte at address 23296. If it is equal to 170, then the
║ │ │the “boot” file is launched. ║
║23832│ 1 │Used if there is INTERFACE-1. If not 0, then║
║ │ │memory blocks 45 bytes long are swapped ║
║ │ │addresses 23747 and 23859. ║
║23833│ 1 │Default drive number. ║
║23834│ 2 │Return address from the completion subroutine. ║
║23836│ 2 │Saves SP for routines to return to BASIC. ║
║23838│ 1 │File number when searching for it. ║
║23839│ 1 │Flag for calling TR-DOS. If 0, then the call was ║
║ │ │from machine code, otherwise - from BASIC. First sec-║
║ │ │tor of the file on the destination disk for COPY S. ║║23840│ 1 │First sector of the file on the destination disk for COPY S.║
║23840│ 3 │Saves the first 3 characters of the command line. ║
║23841│ 1 │If not 0, then the first copying pass is in progress, otherwise-║
║ │ │che continuation. ║
║23843│ 1 │Size of available memory in sectors for MOVE and ║
║ │ │COPY. ║
╚═════╧═════╧═══════════════════ ═══════════════════════════════╝
When initializing the system, the following cells are also used:
╔═════╤═════╤═══════════════════ ═══════════════════════════════╗
║Address│Length│ Content. ║
╟─────┼─────┼─────────────────── ───────────────────────────────╢
║23746│ 1 │RET command. Used to call subroutines ║
║ │ │from BASIC ROM. ║
║24320│ 2 │Saves HL for command execution subroutine ║
║ │ │processor in RAM. ║
║24322│ 14 │Not used. ║
║24336│ 3 │Subroutine for moving LDIR memory blocks or ║
║ │ │LDDR. ║
║24339│ 237 │Time stack. ║
╚═════╧═════╧═══════════════════ ═══════════════════════════════╝
Also, when initializing TR-DOS system variables, 20 bytes saddresses 23698 are used to place the verification routine
availability of INTERFACE-1.
> Intercepting messages "What the hell, what the hell, what the hell?" is implemented something like this:
; interception installation
install:
ld hl, 5cc2h
ld (hl), 0c3h
ld hl, your_programm
ld (5cc3h), hl
...
; calling tr-dos functions
trdos:
ld (tempstack), sp
jp 3d13h
; interception
your_program:
ex (sp), hl
push af
ld a, h
cp 0dh
jr nz, return
ld a, l
cp 6bh
jr z, catch
return:
pop af
ex (sp), hl
ret
; caught the NO DISK error or the request No, No, No?
catch:
ld sp, 0
tempstack equ $-2
...
Everything is based on the fact that before displaying the RAI request, tr-dos clears the screen
calling procedure 0d6bh from BASIC.
From
Aleksandr Kolotuhin
→
To
All
14 July 2004
·∙.■■■ Hi, All! ■■■.∙·
And throw at me the procedures for working with a disk drive (reading, writing,
head positioning, etc.) without using tr-dos.
Or tell me the url with documentation.
·∙.■■■ Happy All! ■■■.∙·
From
Kirill Frolov
→
To
Aleksandr Kolotuhin
18 July 2004
Press RESET immediately, Aleksandr Kolotukhin!
On Wed, 14 Jul 04 18:49:47 +0400, Aleksandr Kolotukhin wrote:
AK> Throw at me the procedures for working with the drive (reading, writing,
AK> head positioning, etc.) without using tr-dos.
AK> Or tell me the url with documentation.
TR-DOS as well as Beta-Disk are still required. TR-DOS just for what
procedures are used to provide access to Beta-Disk ports
inaccessible to programs executing in RAM (I mean that when
placed in the TR-DOS ROM, the program should be a little more different).
Should have been used in CP/M. Yes, TR-DOS needs version 5.03
or any compatible. Almost anyone. No special
no requirements.
A code revision is required, as well as bug fixes. List of functions
at first, there is no documentation. If used, I require publication
version used (i.e. corrected...) here and/or in Fido,
in real.speccy or zx.spectrum.
; IY=Drive Parameters Block pointer
global fdreset ; reset controller
global fdstop ; stop all drives
global fready ; check drive ready/not -> CF=0 if ready
global fdindex ; return INDEX state -> CF=0 if active
global fdchange ; -> CF=1 disk changed
global fdpresent ; -> CF=1 drive not present global fdctl ; call it first for new drive!
global fdside ; set side A?0:1
global fdtrack ; set heads to track A -> CF=1 on error
global fdrdsec ; read sector A \n
global fdwrsec ; write sector A |
global fdrdadr ; read address mark > CF=1 on error, A=status bits
global fdrdtrk ; read track | buffer=(HL++)
global fdwrtrk ; write track /
;
; Floppy disk driver for ZX-Spectrum and Beta-Disk interface
; Copyright (C) 1999, Kirill Frolov
*Include floppy.inc
*Include betadisk.inc
rsttime equ 1000
; controller io registers
rgcmd equ 1fh ; write only -- command register
rgstat equ 1fh ; read only -- status register
rgtrk equ 3fh ; track register
rgsec equ 5fh ; sector register
rgdata equ 7fh ; data register
rgctl equ 0ffh ; write only -- external controller register
; command modifiers
cs0 equ 01h ; head moving speed bit 0
cJ0 equ 01h ; interrupt command modifier, see below
ca0 equ 01h ; special sector mark, not used
cs1 equ 02h ; head moving speed bit 1
cJ1 equ 02h
cC equ 02h ; check side (for read/write commands)
cV equ 04h ; read and verify head position (for seek, step and
reset commands)
cE equ 04h ; delay before reading/writing?
cJ2 equ 04h
ch equ 08h ; load head (for seek, step and reset commands)
cS equ 08h ; disk side (for read/write commands, used only if cC=1)
cJ3 equ 08h
cI equ 10h ; modify or not rgtrk, used only for step commands
cm equ 10h ; multisector operation (for read/write sector commands
only)
; command interrupt bits
ci_noi equ 0 ; stop command execution but don't interrupt host
(INTRQ signal)
ci_rdy equ cJ0 ; stop command execution when DRDY is active (drive
ready)
ci_off equ cJ1 ; stop command execution when DRDY is inactive (drive
not ready)
ci_idx equ cJ2 ; stop command execution when INDEX impulse detected
ci_imm equ cJ3 ; stop command execution now and set INTRQ
; commands
creset equ 00 ; reset controller, seek track 0
cseek equ 10 ; seek track in rgdata
cstep equ 20 ; repeat last cfstep or cbstep
cfstep equ 40 ; forward step (from track 0)
cbstep equ 60 ; back step (to track 0)
crdsec equ 80 ; read sector(s)
cwrsec equ 0a0h ; write sector(s)
crdadr equ 0c0h ; read address mark (6 bytes)
crdtrk equ 0e0h ; read whole track with all address marks, etc...
cwrtrk equ 0f0h ; write whole track (format track)
cint equ 0d0h ; interrupt command execution
; status bits
sbusy equ 01h ; 1=controller busy (command executed)
sdrq equ 02h ; 1=data read/write requested
sidx equ 02h ; 1=index impulse
strk0 equ 04h ; 1=heads at track 0
sover equ 04h ; 1=data overrun
scrc equ 08h ; 1=crc failed, sector corrupted
sseek equ 10h ; 1=seek failed
snosec equ 10h ; 1=sector not found
shead equ 20h ; 1=head loaded
serase equ 20h ; 1=special sector mark, not used
swfail equ 20h ; 1=write failed
swprot equ 40h ; 1=write protected disk
sdrdy equ 80h ; 1=drive ready (really it's HEAD/MOTOR signal
indicator)
; control register bits
dd0 equ 01h ; drive number bit 0
dd1 equ 02h ; drive number bit 1
dreset equ 04h ; 0=reset controller
ddrdy equ 08h ; 1=floppy drive ready (emulation of real DRDY signal)
dside equ 10h ; 1=bottom size(0), 0=upper side(1)
dmfm equ 20h ; 1=double density (MFM method), 0=single density (FM) for
8" floppy
; interrupt bits
idrq equ 40h ; 1=active only if data read/write requested
iintrq equ 80h ; 1=active after execution of all commands
trentr equ 3d2fh ; tr-dos entry point
troutc equ 2a53h ; out(c),a
trintr equ 3fcah ; wait for intrq !set C to rgtrk, rgsec or rgdata only!
trread equ 3fd5h ; reading routine address
trwrite equ 3fbah ; writing routine address
trstat equ 2470h ; read status
trssv equ 5d04h ; word
trsst equ 5ccdh ; byte
trshl equ 5d02h ; word
trsjp equ 5cc2h ; byte
trsadr equ 5cc3h ; word
; get STATUS REGISTER in A
fdstat: ld a, (trsjp)
push af
ld hl, (trsadr)
push hl
ld hl, (trssv)
push hl
ld a, (trsst)
push af
ld hl, trsjp
ld (hl), 0c3h ; JP instruction
ld hl, fdstret
ld (trsadr), hl
ld d, (iy+track)
ld hl, trstat
push hl
ld hl, (trshl)
jp trentr
; 2740: in a,(1fh)
; ld (5ccdh),a
; ld e,d
; push de
; ld a,e
; out (7fh),a
; ld a,18h
; call 3d9ah
;
; 3d9a: out (1fh),a
; push hl
; rst 20h
; dw 1f54h
;
; 0020: jp 2f72h
;
; 2f72: ld (5d02h),hl
; ld (5d04h),de
; pop hl
; ld e,(hl)
; inc hl
; ld d,(hl)
; inc hl
; push hl
; ld hl,3d2fh
; push hl
; push de
; ld hl,5cc2h
; push hl
; ld hl,(5d02h)
; ld de,(5d04h)
; ret
fdstret:
; pop hl ; 1f54h
; pop hl ; 3d2fh
; pop hl ; rst 20h ...
; pop hl ; push hl
; pop hl ; call 3d9ah ...
; pop hl ; de
ld hl, 12
add hl, sp
ld sp, hl ; restore stack
ld a, (trsst) ; e = rgstat
ld e,a
pop af
ld (trsst), a
pop hl
ld (trssv), hl
pop hl
ld (trsadr), hl
pop af
ld (trsjp), a
ld a, e
ret
; write command A to COMMAND REGISTER
fdcmd: ld c, rgcmd
; jp fdwreg
; write A to register C
fdwreg: ld hl, troutc
push hl
jp trentr
; write command A to COMMAND REGISTER and wait INTRQ
fdcserv: call fdcmd
ld c, rgtrk
; jp fdwait
; wait for INTRQ !DANGER may never return!
fdwait: ld hl, trintr
push hl
jp trentr
; jump to READ proc. hl=data
fdjpread: ld c, rgdata
push hl
ld hl, trread
ex (sp), hl
jp trentr
; jump to WRITE proc. hl=data
fdjpwrite: ld c, rgdata
push hl
ld hl, trwrite
ex (sp), hl
jp trentr
; reset controller
fdreset: ld c, rgctl
xor a
call fdwreg
ld bc, rsttime
fdres1: dec bc
ld a, b
or c
jr nz, fdres1
call fdctl
call fdcserv
call fdtrack0
xor a
ret
; turn off motor
fdstop: ld a, (iy+track)
ld c, rgdata
call fdwreg
ld a, cseek
ld c, rgcmd
jp fdcserv
; set head to track 0 -> CF=1 on error
fdtrack0: ld a, creset+ch
or (iy+sspeed)
ld c, rgcmd
call fdcserv
call fdstat
ld (iy+track), 0
and strk0
ld a, 0
ret nz ; all ok
scf
ld (iy+track), 0ffh ; reset failed!
ret
; set head to track A -> CF=1 on error
fdtrack: or a
jr z, fdtrack0
ld b, (iy+track)
cp b
ret z
push af
inc b
jr nz, fdtrack_1
call fdtrack0
pop bc
ret c
push bc
fdtrack_1: pop af
ld b, (iy+track)
ld (iy+track), a
ld c, rgdata
call fdwreg
ld a, b
ld c, rgtrk
call fdwreg
ld a, cseek+ch
or (iy+sspeed)
ld c, rgcmd
call fdcserv
xor a
ret
; check if drive ready (HEAD/MOTOR is active?) and start it -> CF=0 if ready
fdready: call fdstat
and sdrdy
ret nz
scf
ret
; return index state -> CF=0 - INDEX
fdindex: call fdstat
and sidx
ret nz
scf
ret
; check if disk changed? CF=1 if changed
fdchange: call fdstat
push af
and sdrdy
jr nz, fdch1
call fdstop ; stop drive if it is inactive
fdch1: pop af
and swprot
xor (iy+chflag)
ret z
xor (iy+chflag)
ld (iy+chflag), a
scf
ret
; check if drive present? CF=1 drive not present
fdpresent: call fdtrack0
ret c
ld a, 1
call fdtrack
call fdstat
and strk0
ret z ; all ok, drive present
ld (iy+track), 0ffh ; no drive!
scf
ret
; set side A
fdside: and 01h
ld (iy+side), a
; jp fdctl
; set control register(s)
fdctl: ld a, (iy+drive)
and dd0+dd1 ; hack... why?
bit bmfm, (iy+dmode)
jr z, fdctl1
or dmfm
fdctl1: bit 0, (iy+side)
jr nz, fdctl2
or dside
fdctl2: or ddrdy+dreset
ld c, rgctl
call fdwreg
ld a, (iy+track) ; 0xff... bug?
ld c, rgtrk
jp fdwreg
; read sector A from current track to (HL++) !DANGER: NO SECTOR SIZE CHECKING!
; return CF=1 if error, A=status bits
fdrdsec: push hl
ld c, rgsec
call fdwreg
bit bcside, (iy+dmode)
ld a, crdsec
jr z, frds1
or cC
bit 0, (iy+side)
jr z, frds1
or cS
frds1: ld c, rgcmd
call fdwreg
pop hl
call fdjpread
jp z, fdtout ; timeout!
call fdstat
and sover+scrc+snosec
ret z ; all ok
jp fderror
; write sector A to current track from (HL++) !WARNING: NO SECTOR SIZE
CHECKING!
; return CF=1 if error, A=error code
fdwrsec: bit brdonl, (iy+dmode)
jr z, fdwrs0
ld a, efdwprot
scf
ret
fdwrs0: push hl
ld c, rgsec
call fdwreg
bit bcside, (iy+dmode)
ld a, crdsec
jr z, fwrs1
or cC
bit 0, (iy+side)
jr z, fwrs1
or cS
fwrs1: ld c, rgcmd
call fdwreg
pop hl
call fdjpwrite
jr z, fdtout ; timeout!
call fdstat
and sover+scrc+snosec+swfail+swprot
ret z ; all ok
jr fderror
; read address mark to (HL++) 6 bytes.
; return CF=1 if error, A=error code
fdrdadr: push hl
ld a, crdadr
ld c, rgcmd
call fdwreg
pop hl
call fdjpread
jr z, fdtout ; timeout!
call fdstat
and sover+scrc
ret z ; all ok
jr fderror
; read track to (HL++) ~7kb max.
; return CF=1 if error, A=error code
fdrdtrk: push hl
ld a, crdtrk
ld c, rgcmd
call fdwreg
pop hl
call fdjpread
jr z, fdtout ; timeout!
call fdstat
and sover
ret z ; all ok
jr fderror
; write track from (HL++) ~7kb max.
; return CF=1 if error, A=error code
fdwrtrk: bit brdonl, (iy+dmode)
jr z, fdwrt0
ld a, efdwprot
scf
ret
fdwrt0: push hl
ld a, cwrtrk
ld c, rgcmd
call fdwreg
pop hl
call fdjpwrite
jr z, fdtout ; timeout!
call fdstat
and sover+swfail+swprot
ret z ; all ok
and 0ffh-swprot
ld a, efdwprot
scf
ret z ; error A=status
jr fderror
; read/write sector/track/addressmark error
fderror: ld c, a
and swprot
ld a, efdwprot
scf
ret nz
ld a, c
and snosec
ld a, efdnosec
scf
ret nz
ld a, c
and scrc
ld a, efdcrc
scf
ret nz
ld a, efdfail
ret
; read/write sector/track/addressmark timeout
fdtout: ld a, cint+ci_imm ; stop command execution
call fdcmd
ld a, creset
or (iy+sspeed) ; stop drive, move heads to track 0
call fdcmd
ld (iy+track), 0ffh
ld a, efdtout ; return error status
scf
ret
end
From
Kirill Frolov
→
To
Kirill Frolov
18 July 2004
Hемедленно нажми на RESET, Kirill Frolov!
On Sun, 18 Jul 2004 09:54:52 +0000 (UTC), Kirill Frolov wrote:
KF> ; IY=Drive Parameters Block pointer
Забыл ещё:
; IY+var -- drive variables (передаётся аргументом ко всем функциям)
drive equ 0 ; physical drive 0..3
sspeed equ 1 ; seek speed 0..3
dmode equ 2 ; mode bits
track equ 3 ; track 0xff = undefined
side equ 4 ; side 0=bottom, 1=top
chflag equ 5 ; write protect status(call fdchange)
changed equ 6 ; 1=disk changed
reservx equ 7 ; reserved
dpbsize equ 8 ; size of drive vars.
; mode masks and bits
mmfm equ 01h ; 1=mfm (*)
bmfm equ 0
mcside equ 02h ; 1=check side (*)
bcside equ 1
mwrdel equ 04h ; 1=write delay (for slow drives)
bwrdel equ 2
mauto equ 08h ; 1=auto disk change
bauto equ 3
mrdonl equ 80h ; 1=readonly (*) -- used in betadisk module
brdonl equ 7
; error codes
efdok equ 0 ; no errors
efdfail equ 1 ; hardware failure
efdwprot equ 2 ; write protect
efdnosec equ 3 ; sector not found
efdcrc equ 4 ; crc error
efdtout equ 5 ; timeout
From
Slavik Tretiak
→
To
All
10 March 2006
Hello, All
remind me how to disable error handling in TR-DOS (i.e. so that it does not respond to
BREAK and if there was a reading error, I read until I was blue in the face).
We did this in our demo (-=AOS=-), but it was a long time ago and I don’t remember how.