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.