From: Spiro Trikaliotis (ml-cbmhackers_at_trikaliotis.net)
Date: 2009-01-25 14:36:30
Hello,
* On Sat, Jan 24, 2009 at 07:22:23PM +0100 I wrote:
> I just found out something that was not known to me beforehand. Is this
> a known bug?
>
> If issuing a M-R command on the floppy (1540, 1541, 1570, 1571, 1581),
> if the M-R crosses a page boundary, the M-R is stopped early.
>
> That is: If I read from $0500, I can read $100 byte:
>
> "M-R"CHR$(0)CHR$(5)CHR$(0)
>
> However, if I read from $0510, I can read only $F0 byte. If I specify
> more bytes, the floppy aborts the read, after exactly $F0 byte.
>
> Is this known and documented somewhere?
I started some investigation on this. Here is what I found out (for the
154x/157x):
M-R is implemented starting at $CB20. Essentially, it writes the start
address of the bytes to be read into $A5/$A6 - this is the pointer to
the error buffer, which normally points to $02D5. (To be more precise:
The first byte is stored in $85 and later (at $D449) in $0243, and the
pointer at $A5/$A6 points to the next byte, but that's just a minor
detail.)
The end address of where to read is stored at $0249. Note that only the
low byte can be stored, there is no memory available for the high byte!
Later, when sending the data bytes to the computer, the routine at $E909
is used. The pointer is advanced to the next byte at $E992, which
executes a JSR $D3AA.
Here, we have:
.8:d3aa A6 82 LDX $82
.8:d3ac 20 25 D1 JSR $D125
.8:d3af D0 03 BNE $D3B4 Taken for the command channel
.8:d3b4 A5 83 LDA $83 Secondary address (here: $0F)
.8:d3b6 C9 0F CMP #$0F
.8:d3b8 F0 5A BEQ $D414 Yes, it is the command channel, branch taken
.8:d414 20 E8 D4 JSR $D4E8 this routines gets the buffer
pointr of the current character;
low into $94, high into $95. It
returns the low byte in A, too.
For the error channel, the
pointer at $99+2*6/$9A+2*6 is
taken, that is $A5/$A6 (see
above)
.8:d417 C9 D4 CMP #$D4 Compare the low byte with $D4
(the error channel starts at
$02D5; thus, if the pointer is
at $02D4, then a new error
message has to be generated)
.8:d419 D0 18 BNE $D433 No new error message, skip
(Afterwards, the high byte would
have been compared to $02. If it
is different, then the BNE would
be taken to $D433; otherwise, a
CR would be generated.)
.8:d433 20 37 D1 JSR $D137 get the next character from the buffer
.8:d436 85 85 STA $85 remember for output
.8:d438 D0 09 BNE $D443 z=1 (from JSR above) means: End of buffer!
If we reach here, the buffer endedd
.8:d43a A9 D4 LDA #$D4 store $02D4 as new pointer for error channel
.8:d43c 20 C8 D4 JSR $D4C8 first command: STA $99,X. The rest does not interest us here.
.8:d43f A9 02 LDA #$02
.8:d441 95 9A STA $9A,X
.8:d443 A9 88 LDA #$88
.8:d445 85 F7 STA $F7
.8:d447 A5 85 LDA $85 store remembered output byte
.8:d449 8D 43 02 STA $0243 as new byte to send over the IEC bus
.8:d44c 60 RTS
So, the "magic" of finding the EOI condition is in $D137:
.8:d137 20 2F D1 JSR $D12F
.8:d13a B9 44 02 LDA $0244,Y for error channel: LDA $0249 -
that's the calculated end of
transmission, as remarked above
in the description of the M-R
command
.8:d13d F0 12 BEQ $D151 if the transfer ends is at $xx00, branch
.8:d13f A1 99 LDA ($99,X) X is $0C here for the command
channel: Thus, LDA ($A5), gets
the next byte
.8:d141 48 PHA
.8:d142 B5 99 LDA $99,X check if we reached the end of the block
.8:d144 D9 44 02 CMP $0244,Y
.8:d147 D0 04 BNE $D14D no --> then branch
.8:d149 A9 FF LDA #$FF "delete" the low byte
.8:d14b 95 99 STA $99,X
.8:d14d 68 PLA
.8:d14e F6 99 INC $99,X advance to the next character
.8:d150 60 RTS
.8:d151 A1 99 LDA ($99,X) Get the next character
.8:d153 F6 99 INC $99,X advance to the next character
.8:d155 60 RTS
You see something? Yes, the complete routine does not care at all about
the high byte! This makes sense for the error channel and the other
buffers, as the buffers always start at a page boundary. For M-R,
however, this is a restriction. But it gets obvious: M-R cannot cross a
page boundary!
Now, one question remains: Where does the CR at the end of reading the
command channel (error channel) come from? That's why $02D4 is stored
into $A5/$A6 at $D43A-$D441. As already stated, the error buffer starts
at $02D5, one byte later.
At $D417-$D41F, it is tested if the pointer points to $02D4. If this is
the case, $D421-$D423 stores a CR as the output character:
.8:d421 A9 0D LDA #$0D
.8:d423 85 85 STA $85
Thus, in some sense, the CR at the end is not the last read character,
but more the first read character of the next output! Interesting, isn't
it?
There is another interesting fact here: If doing a M-R in the $0200
page, the you cannot read beyond $02D4! That's because of the special
handling of the $02D4 address. Thus, if you want to read the complete
$0200 page, you have to read first $0200-$02D3, then $02D4-$02FF.
For the 1581, the special address is $02CF; thus, here, you have to read
$0200-$02CE, then $02CF-$02FF.
Regards,
Spiro.
--
Spiro R. Trikaliotis http://opencbm.sf.net/
http://www.trikaliotis.net/ http://www.viceteam.org/
Message was sent through the cbm-hackers mailing list
Archive generated by hypermail pre-2.1.8.