;======================================
; pwd_main.s (print working directory)
;======================================

program pwd_main

include library
include prosys
include c64
include 1:diskutils.e

con pathlen=128

word pathptr
word err
word i

byte buffer[256]
byte path[pathlen]
byte cmdbuf[64]
byte partname[16]
byte dev
byte drive
byte column
byte row
byte track
byte sector
byte header ;boolean

;--------------------------------------
; Display usage message.
;--------------------------------------
proc usage

begin

output"#c#cUsage: #s [device]",carg[0]
output"#cdevice is 0:, 1:, or a device number"
output"#c(defaults to 0:,"
output"#c number must be from 8 to 30)"

end

;--------------------------------------
; Parse command-line arguments.
; return: true if arguments are valid,
;         false otherwise
;--------------------------------------
func byte parse
word i
word j
byte b

begin

if ncarg<>1
  dev=c64ddv0 ;use 0:
  return true

;carg[0] is program name
if cmpstr(carg[1],"=","0:")
  dev=c64ddv0
else if cmpstr(carg[1],"=","1:")
  dev=c64ddv1
else
  b=strval(carg[1],#j) ;j must be word
  if (carg[1]+b)@< ;not null-terminator?
    usage
    return false
  if j<8 or j>30
    usage
    return false
  dev=j

return true ;fall-through

end

;--------------------------------------
; Add an element to the path.
; pass: address of sector buffer
; pass: offset to end of path element
;--------------------------------------
proc addpath
arg word buffer
arg word pathend
word bufptr

begin

bufptr=pathend
while m[buffer+bufptr]=$a0
  bufptr=bufptr-1
if bufptr <= pathend-16
  return ;root of sd2iec/uIEC partition
while bufptr > pathend-16
  path[pathptr]=m[buffer+bufptr]
  pathptr=pathptr-1
  bufptr=bufptr-1
path[pathptr]='/'
pathptr=pathptr-1

end

;--------------------------------------
; Get path on a CMD drive.
; pass: Nothing (uses global variables).
;--------------------------------------
proc getcmdpath

begin

err=getdirhead(dev,buffer)
if err
  return

track=buffer[32]
sector=buffer[33]
if track=0 and sector=0 ;root directory
  path[pathptr]='/'
  pathptr=pathptr-1
  path[pathptr]='/'
else
  header=true
  while track<>0 and sector<>0
    if header
      header=false
      addpath buffer,$11
    else
      addpath buffer,$13

    err=readsect(dev,track,sector,buffer)
    if err
      return
    track=buffer[34]
    sector=buffer[35]
    if track=0 and sector=0
      path[pathptr]='/'

end

;--------------------------------------
; Get path on an sd2iec/uIEC drive.
; pass: Nothing (uses global variables).
;--------------------------------------
proc getsdpath
word cdptr
byte first

begin

first=true
while true
  err=getdirhead(dev,buffer)
  if err
    return
  err=sendcmd(dev,"CD_")
  err=readcmd(dev,cmdbuf)
  err=(cmdbuf[0] and $0f)*10
  err=err+(cmdbuf[1] and $0f)
  if err=62 ;file not found
    err=0
    if first ;we started at the root
      path[pathptr]='/'
      pathptr=pathptr-1
      path[pathptr]='/'
      return ;don't have to CD back
    else
      path[pathptr]='/' ;we're at the root
      break
  else if err<>0
    return

  first=false
  addpath buffer,$9d

;now return to original directory
cdptr=pathptr-2
path[cdptr]='C'
path[cdptr+1]='D'
err=sendcmd(dev,path+cdptr)

end

;======================================
; program mainline
;======================================
begin

if not parse
  exit
path[pathlen-1]=0
pathptr=pathlen-2

column=curcol
row=curline
output"#cenumerating drives..."
drvquery
curset column,row ;overwrite message

drive=drives[dev-8]
if drive=0
  output"#cDevice not present!  #c",$0d
  exit
if drive and $80 or (drive=$71 or drive=$72)
  err=getpartinfo(dev,255) ;255=current part.
  if err
    output"#cError #w!             ",err
    exit
  if partinfo[0]<>1
    output"#cNative partitions only!"
    output"#c(this partition: #s)",partdesc(partinfo[0])
    exit
  i=15
  while partinfo[3+i]=$a0
    partname[i]=0
    i=i-1
    if i=65535    ;i is unsigned
      break
  if i<>65535
    repeat
      partname[i]=partinfo[3+i]
      i=i-1
    until i=65535 ;i is unsigned
else
  output"#cCMD or sd2iec/uIEC drives only!"
  output"#c(this drive is a #s)#c",drvdesc(drives[dev-8])
  exit

output"#cgetting path...      "
curset column,row ;overwrite message

if drive and $80 ;CMD drive
  getcmdpath
else
  getsdpath
if err
  output"#cError #w!             ",err
  exit

output"#c                                       "
curset column,row
output"#cdrive #w is a #s",dev,drvdesc(drives[dev-8])
output"#cpartition #w (#s)",partinfo[2],partdesc(partinfo[0])
if partname[0]<>0
  output": #s",partname
output"#c#s#c",path+pathptr,$0d

end
