6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Thu May 09, 2024 1:19 pm

All times are UTC




Post new topic Reply to topic  [ 8 posts ] 
Author Message
PostPosted: Sat Jan 28, 2023 1:36 am 
Offline
User avatar

Joined: Tue Mar 05, 2013 4:31 am
Posts: 1373
I've been reworking various parts of DOS/65 lately. As I've done a fair amount of work on CCM and PEM, the code size has been reduced quite a bit and many of the routines are quicker as well. I did attempt to extend the number of drive letters from the default 8 and found some strange actions.... where drive letters are acting as a phantom to another drive letter. After much testing, I opted to go back to the stock CCM and PEM routines and found the same problems... so more testing has been done and it looks to be a problem in CCM.

Here's what happens:

Do a DIR against drives or simply change the active drive and you don't always get what you think. I also went back to my older 3.03 ROM code and found the same issues.

My system is configured for 8 drives (A - H).

If you do a DIR command against drives I: thru O: you get a PEM error stating Invalid Drive, which is completely normal.

If you do a DIR against drive P: you get a listing from drive A: Also, if you change to drive P: nothing happens to the default drive letter, but references still go to drive A:.

If you change to drive Q: you get drive A:

Starting with drive R: you get drive B: and this pattern repeats for a bit, i.e.:

drive S: shows drive C:
drive T: shows drive D:
drive U: shows drive E:
drive V: shows drive F:
drive W: shows drive G:
drive X: shows drive H:
drive Y: shows drive I: (as invalid)
drive Z: shows drive J: (as invalid)

Thinking I had other problems either in CCM, PEM or SIM, I opted to power up Bill's (Plasmo) CRC65 with his port of DOS/65 V3. It does the same... go figure.

Further testing, I bypassed CCM and just call PEM directly to change the active drive... drive letter in A reg (0= A;, 1=B:, etc.) and X reg set function call of $0E, then jump to $0103 PEM entry. This works correctly, every drive attempted beyond the 8 drives configured show as an invalid drive, and also show the invalid drive letter.... from I: thru Z:. Just for chagrins, I incremented the drive past Z: and still got an invalid drive, but it was drive [: (left square bracket).

Going directly to PEM appears to work correctly, albeit it shows drive letters beyond legitimate ones, but as invalid, which is correct. It's time to start digging into CCM... which appears to be the culprit here!

side thought... as DOS/65 was a rewrite of CP/M to some extent, I'm wondering if CP/M has a similar drive letter issue :roll:

_________________
Regards, KM
https://github.com/floobydust


Top
 Profile  
Reply with quote  
PostPosted: Sat Jan 28, 2023 3:12 am 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 690
Location: North Tejas
CP/M-80 is limited to 16 drives, A..O.


Top
 Profile  
Reply with quote  
PostPosted: Sat Jan 28, 2023 11:53 am 
Offline

Joined: Mon Jan 19, 2004 12:49 pm
Posts: 683
Location: Potsdam, DE
Which suggests... bug-compatibility! Yay!

(Isn't drive 16 P:?)

Neil


Top
 Profile  
Reply with quote  
PostPosted: Sat Jan 28, 2023 12:27 pm 
Offline
User avatar

Joined: Tue Mar 05, 2013 4:31 am
Posts: 1373
I thought so too... (A thru P), but as they say, "Everything's bigger in Texas", but I never suspected the alphabet to have more letters :wink:

_________________
Regards, KM
https://github.com/floobydust


Top
 Profile  
Reply with quote  
PostPosted: Sat Jan 28, 2023 1:45 pm 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 690
Location: North Tejas
You guys are right - the highest drive is P: for a total of 16. Fencepost error...


Top
 Profile  
Reply with quote  
PostPosted: Sat Jan 28, 2023 2:48 pm 
Offline

Joined: Fri Dec 21, 2018 1:05 am
Posts: 1076
Location: Albuquerque NM USA
Probably a bug in converting ASCII letter to number. The code may just mask off the upper 4 bits; if so ! (0x21), 1 (0x31), A (0x41), Q (0x51), a (0x61), q (x71) all map to drive A, and they actually do. Try "dir !:", you'll get drive A directory.

Z80 CP/M does not have that bug, nor CP/M68K
Bill


Top
 Profile  
Reply with quote  
PostPosted: Sat Jan 28, 2023 7:22 pm 
Offline
User avatar

Joined: Tue Mar 05, 2013 4:31 am
Posts: 1373
Yes, there is the masking of the lower 3 bits for the drive, once in CCM and once in PEM. However, PEM and CCM don't always work the same way.

There's also the iostat variable, which uses the upper 4-bits for the user number (0-15) and it uses the lower 3-bits for the drive number (0-7).

CCM uses multiple 8-bit variables for the drive in various routines, as: dfldsk, tmpdsk, dsksav and oldtmp.

PEM uses multiple 8-bit variables to hold the drive number; curdrv, olddrv and drvcmd. There's also a single byte, lginvc, to indicate drive log-in status (1-bit per drive, hence 8 drives supported).

I'm going to look at changing how CCM handles a drive letter being entered to rectify the issue, which can be somewhat confusing and also damaging in the case of erasing a file(s) using an incorrect drive letter (fingercheck).

As PEM only uses drive numbers (0-7), this should be a bit easier to change the basic drive support and eliminate phantom drive letters from being output via the error routine.

It might be worthwhile to add a call to SIM to get the total drive count, but that might get tricky, as the console definition block is specifically located in SIM, hence it should not be moved as it could break other pieces of code that depend on it's location.

_________________
Regards, KM
https://github.com/floobydust


Top
 Profile  
Reply with quote  
PostPosted: Sun Jan 29, 2023 4:28 am 
Offline
User avatar

Joined: Tue Mar 05, 2013 4:31 am
Posts: 1373
I spent some time today and went thru CCM and PEM and made changes to correct this issue.

In CCM, the parse routine was the issue. In short, it takes the first character in the line, masks off the upper 4 bits, then tests the second character for a colon. If the colon is found, it branches to set the tmpdsk variable with the lower 4-bits from the masked value. This works okay provided you never enter a drive letter (or any ascii character) that is not a valid drive. After this, the tmpdsk value is tested for zero, is it is, any drive change is skipped and the default drive is used. If the value is non-zero, one is subtracted and then saved as the selected drive and PEM is called. This is the main issue with drives responding to invalid drive letters, or any ascii character as the upper 4-bits are stripped off.

In PEM, the change drive routine simply masks off the upper 5-bits and uses the lower 3-bits as the drive number. As other programs loaded into the TEA can also access PEM, any drive number passed to PEM will access drives from 0-7 depending on whatever was passed in the A reg to the PEM call.

The fix is two-fold:
- Change how PEM processes the drive number used in the change drive call. Instead of masking for the lower 3-bits, a compare of the maximum drive is done. If the drive number is too high, PEM now issues a drive out of range message and performs a warm boot. Easy enough.

- Change to CCM for the line parse routine. First strip off the high bit to ensure ascii only. Next if it's a drive change (colon character is second), a test and convert lower case to upper case is done. Once completed, a range check from "A" to "H" is done, any character outside of the range is change to the highest drive letter plus 1 (so it's out of range). After that, the upper 4-bits are masked off (now 0-15 is valid) and saved as tmpdsk. Also pretty easy as a fix.

Initial testing has been successful... doing a dir command or attempting to change the deafult drive using upper or lower case works correctly. All drives respond only to their actual drive letter. Any other character is returned as a drive range error.

the CCM code change is:

Code:
;parse command line
prslin   ldx   #0      ;clear index
prsmre   txa         ;save
   pha         ;index
   lda   #0      ;clear temp
   sta   tmpdsk      ;drive flag
   ldy   cnbfpt      ;get buffer pointer
   jsr   skpspc      ;find first non-space
   sty   curpnt      ;save index
   beq   nulchr      ;jump if null
;
;the and instruction below is to strip off ascii bits that are drive letter related!
; by doing so, A - H become %0001 - %1000 (1-8), which can be a real problem...
; if the next character is a semicolon (:). that 4-bit masked value becomes the
; TMPDSK variable, which is spliced into the FCB and becomes the selected drive.
; As a result, any ascii character can be entered and you wind up with a list of
; phantom drive letters, depending on what was entered, alpha or not.
;
; The goal here is to mask off the lower 7 bits for true ascii, then let this
; routine below starting at "drvinp" complete the check for a valid drive letter.
;
   and   #%01111111   ;strip off bit 7 for ascii only
   pha         ;and save to stack
   iny         ;point to next char
   lda   cnstxt,y   ;and get it
   cmp   #':'      ;if it's a colon
   beq   drvinp      ;jump and set drive letter
   pla         ;else clear the stack
   dey         ;backup index
nulchr   lda   dfldsk      ;set automatic
   sta   fcbone,x   ;to default
   bpl   trynme      ;then parse name
;
;at this stage, we get the ascii character back from the stack, which is the
; assumed drive letter. Now we need to range check this and ensure it's within
; the range of a-z or A-Z. First, we'll convert lower case to upper case, then
; check for the proper range. If the character is outside of the range, we can
; simply set it for the acceptable range plus one. This will be caught by the
; PEM routine and flagged as a drive out of range.
;
drvinp   pla         ;get the "drive letter" back
        cmp     #$61            ;check for lower case ascii/control characters
        bcc     ucok            ;if lower, upper case is okay
        sbc     #$20            ;else subtract $20 to convert to upper case
ucok    cmp     #'A'            ;compare for ascii "A" or higher
        bcc     baddrv          ;branch if too low
        cmp     #'I'            ;check for ascii "I" or higher
        bcc     drvok           ;else branch and set drive
baddrv  lda     #'I'            ;get first out of range drive
drvok   and     #%00001111      ;mask off upper 4 bits
   sta   tmpdsk      ;else save to temp disk flag
   sta   fcbone,x   ;and into the fcb
   iny         ;increment past colon, continue parsing
trynme   lda   #8      ;set name count


and the PEM code change is here:

Code:
;change drive
; input:addinp
; returns:none
; alters:all
xchgdr   lda   addinp      ;get inout
        cmp     #8              ;check valid range (0-7)
        bcs     drnger          ;if bad, use error below
   sta   drvcmd      ;and save
chgdrv   lda   drvcmd      ;get input
   cmp   curdrv      ;if same as current
   beq   drvsme      ;do nothing
   sta   curdrv      ;else change current
   jmp   mapdrv      ;then log it in
drvsme   rts
drnger  lda   rngmvc      ;point to
   ldy   rngmvc+1   ;select message
   jsr   sndstr      ;and send it
        jmp   xwboot      ;and abort


Code:
;relocatable vectors
   .byte   $4c
extevc   .word   extexq-1
   .byte   $4c
sltmvc   .word   sltmsg
   .byte   $4c
rngmvc  .word   rngmsg
        .byte   $4c
empdvc   .word   empty
   .byte   $4c
rommvc   .word   romsg
   .byte   $4c
bdsmvc   .word   bdsmsg
   .byte   $4c
pemmvc   .word   pemmsg
   .byte   $4c
dcbevc   .word   dcb
;relocation stopper
   .byte   $ff
;messages
romsg   .byte   " - R/O$"
bdsmsg   .byte   " - BAD SECTOR"
   .byte   cr,lf,"<RET> TO IGNORE -- <OTHER> "
   .byte   "TO ABORT$"
pemmsg   .byte   cr,lf,"PEM ERROR ON $"
sltmsg   .byte   " - INVALID DRIVE$"
rngmsg  .byte   cr,lf,"DRIVE OUT OF RANGE$"


I'm still working on a new RAM based version, but the changes above are to the unmodified code from Richard. Sorry about the bad formating... I'm using the original source code, which uses tab characters and spaces mixed.

_________________
Regards, KM
https://github.com/floobydust


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC


Who is online

Users browsing this forum: Google [Bot] and 10 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: