ATR Copy Center#
SPL source code:#
# ATR Copy Center
# 2008-2013 Carsten Strotmann
# 2013/08/18
const bl $20 ( blank )
const rd $40
const wr $80
const ddevic $300
const dunit $301
const dcmnd $302
const dstats $303
const dbuf $304
const dtimlo $306
const dbyt $308
const daux $30A
const memtop $2E5 ( last free memory location )
const memlo $2E7 ( first free memory location )
const appmhi $0E
var percom 12
var drvstat 17
var buf $100
var dpath $100
var secbuf 2
var bufbase 2
var bufsize 2
var bufend 2
var secbuforg 2
var hsbase 2
var hss2u 2
var hsdrive 2
var siov 2
var siolen 2
var tracks 2
var secpertrack 2
var errorcode 1
var devid 1
var devnm 1
var bytsec 2
var sectors 2
var sector 2
var autoinc 1
var side 1
var i 2
var fcount 2
var cdigit 2
var sidetgl 2
var cnt 2
var debugflg 1
str stfilen "\FILE0000.ATR"
str sterror " Error"
str stwhile "while"
str streading "reading"
str stwriting "writing"
str stsector "Sector"
str stcreating "creating"
str stmounting "mounting"
str stremoving "removing"
str statr "ATR"
str stsingle "single"
str stmedium "medium"
str stdouble "double"
str stauto "Auto"
str stincrement "increment"
str stpress "press"
str stkey "key"
str stdrive "Drive"
str ststatus "status"
str sttimeout "Timeout"
str stwd2793 "WD2798"
str stsrc "Src"
str stdest "(D3:) Dst"
str stdensity "Density"
str stdigit "Digit"
str ston "On "
str stoff "Off"
str stmake "make"
str stmount "mount"
str stcopy "Copy"
str stread "Read "
str stwrite "Write"
str stzeros0 "00000"
str stzeros1 "00000"
str stzeros2 "00000"
str stcompleted "completed"
str stsuccessfully "successfully"
str stunsuccessful "unsuccessfully"
str stcenter "Center"
str stdots "..."
str sttracks "Tracks"
str ststep "Step"
str strate "Rate"
str stsectrack "Sec/Track"
str stsides "Sides"
str stbytessec "Bytes/Sec"
str stencoding "Encoding"
str stside "Side"
str sthelpmsg "[H] for help"
str stnextcpy "[space] to start next copy"
str sthighspeed "high speed"
str stnormalspeed "normal speed"
: debug
dup 20 20 at "debug:" disp dup .$ " " disp " " disp .
;
: debugk
dup 20 20 at "debug:" disp dup .$ " " disp " " disp . key drop
;
: dispspace
disp space
;
: init ( -- )
0 debugflg c!
$44 devid c!
1 devnm c!
$80 bytsec !
18 secpertrack
720 sectors !
1 autoinc c!
0 side c!
0 fcount !
4 cdigit !
end@ secbuf !
$E459 hss2u !
$E459 hsdrive !
$E459 siov !
end@ appmhi !
;
: lcls ( y -- )
crsoff 0 at 156 emit ;
: insline ( y -- )
0 at 157 emit ;
: clearline ( y -- )
39 i ! {
dup i at 31 emit
i --
i @ 0 = if break then
}
drop
;
: rcls ( pos lines -- )
i ! {
dup lcls
i --
i @ 0 = if break then
}
drop
;
: line ( y -- )
40 * $58 @ + 40 $52 fill ;
: colon ( -- )
$3A emit ;
data bittable
$01 $02 $04 $08
$10 $20 $40 $80
end
: bits ( n -- bm )
bittable + c@ ;
code scopy
[ ldy #5 ]
[ jmp sc1 ]
end
code sc1
[ lda stzeros1,y ]
[ clc ]
[ adc #1 ]
[ sta stzeros1,y ]
[ cmp #$3A ]
[ bne sc2 ]
[ lda #$30 ]
[ sta stzeros1,y ]
[ dey ]
[ bne sc1 ]
[ jmp sc2 ]
end
code sc2
[ rts ]
end
: sio ( -- rc )
siov @ call
dstats c@
;
: secbuffetch ( -- )
secbuf @ ;
: clearbuf
buf $FF $FF fill
0 buf c!
0 buf $7F + c!
;
: buf1 ( -- addr )
buf 1+ ;
: preparesio
$31 ddevic c!
devnm c@ dunit c!
7 dtimlo c!
0 daux !
;
: writecmd
wr dstats c!
sio
;
: readcmd
rd dstats c!
sio
;
: getstatus ( -- rc )
preparesio
$53 dcmnd c!
drvstat dbuf !
4 dbyt !
readcmd
;
: getsiolen ( n -- l )
preparesio
$68 dcmnd c!
dunit c!
secbuf @ dbuf !
2 dbyt !
readcmd drop
secbuf @ @
dup siolen !
;
: gethssio ( addr n -- )
dup getsiolen dbyt !
preparesio
dunit c!
$69 dcmnd c!
dup dbuf ! daux !
$40 dtimlo c!
readcmd
;
: gets2usio ( -- )
appmhi @ 3 gethssio
1 = if
appmhi @ hss2u !
siolen @ appmhi +!
then
;
: getdrvsio ( -- )
hsbase @ appmhi !
appmhi @ devnm @ gethssio
1 = if
appmhi @ hsdrive !
siolen @ appmhi +!
then
gets2usio
;
: cprint ( addr -- )
c@ u. ;
: cprintplus ( addr n -- )
+ cprint ;
: printstatus
stdrive disp
ststatus disp colon drvstat cprint
" " disp stwd2793 disp colon drvstat 3 cprintplus cr
sttimeout disp colon drvstat 2 cprintplus
;
: mdquery ( tests for medium density )
getstatus drop drvstat c@ $80 and
dup 0 > if
1040 sectors !
$80 bytsec !
26 secpertrack !
then ;
: clearpercom
percom 12 0 fill ;
: getsectors ( -- sec )
percom c@ percom 2 + @ >< *
;
: getpercom ( -- rc )
clearpercom preparesio
$4E dcmnd c!
percom dbuf !
12 dbyt !
readcmd getsectors sectors !
;
: printpercom ( -- )
sttracks disp colon percom cprint
cr ststep disp strate disp colon percom 1 cprintplus
cr stsectrack disp colon percom 2+ @ >< u.
cr stsides disp colon percom 4 cprintplus
cr stencoding disp colon percom 5 cprintplus
cr stbytessec disp colon percom 6 + @ >< u.
cr stdrive disp ston disp colon percom 8 cprintplus
cr stsector disp colon getsectors u.
;
# sio2usb code
: temp2dpath
stfilen dpath strcpy
;
: dpath2buf
dpath buf strcpy
;
: s2ucmd
$71 ddevic c! 0 dunit c! $80 dbyt !
;
: s2ucmdp
ddevic c@ $71 =
;
: gets2ustatus
preparesio s2ucmd
17 dbyt !
drvstat dbuf !
0 dcmnd c! # get U status info
readcmd
;
: makeatr
clearbuf dpath2buf
preparesio s2ucmd
sectors @ dup >< daux !
$FFFF = if 1 daux ! then
bytsec @ $100 = if
daux c@ $80 or daux c!
else
daux c@ $7F and daux c!
then
$07 dcmnd c! buf dbuf !
$c8 dtimlo c! writecmd
;
: rmatr
clearbuf dpath2buf
preparesio s2ucmd
$09 dcmnd c!
$00 daux !
buf dbuf !
$c8 dtimlo c!
writecmd
;
: mountatr
clearbuf dpath2buf
preparesio s2ucmd
$BB daux c!
$05 dcmnd c!
buf dbuf !
$c8 dtimlo c!
writecmd
;
: seccmd ( i cmd -- rc )
preparesio dcmnd c!
dup 4 < if $80 else bytsec @ then dbyt !
daux ! secbuf @ dbuf !
;
: readsec ( i -- )
$52 seccmd devnm @ dunit c! readcmd
;
: writesec ( i -- )
$50 seccmd 3 dunit c! writecmd
;
code fullquery ( checks if sector buffer is empty )
[ lda secbuf ]
[ sta ta ]
[ lda secbuf+1 ]
[ sta ta+1 ]
[ ldy #0 ]
[ tya ]
end
code fq1
[ ora (ta),y ]
[ iny ]
[ cpy bytsec ]
[ bne fq1 ]
[ jmp push0a ]
end
# user interface code
: clearfcount
0 fcount !
;
: toggleautoinc
1 autoinc ctoggle
clearfcount
;
: qclearfcount ( n -- )
fcount @ swap > if clearfcount then
;
: printfile
cdigit @ 1 = if 9 qclearfcount then
cdigit @ 2 = if 99 qclearfcount then
cdigit @ 3 = if 999 qclearfcount then
cdigit @ 4 = if 9999 qclearfcount then
fcount @ >outbuf
cdigit @ i ! {
$30 ( ASCII 0 ) dpath dup c@ + 3 sidetgl @ + i @ + - c!
i -- i @ 0 = if break then
}
$A1 ( source = outbuf+1 )
dpath dup c@ + $A0 c@ 3 sidetgl @ + + - ( dest )
$A0 c@ cmove
;
: nextfile
cdigit @ if
fcount ++
printfile
then
;
: prevfile
cdigit @ if
fcount --
fcount @ $FFFF = if 9999 fcount ! then
printfile
then
;
: nextside
1 side ctoggle
side @ if 65 else 66 then dpath dup c@ + 4 - c!
;
: toggleside
1 sidetgl ctoggle
sidetgl @ if nextside then
;
: printinfo
$00 sectors !
$80 bytsec !
18 secpertrack !
stdensity disp colon mdquery 0 >
if stmedium disp
else
getpercom
percom 2+ @ >< tracks !
percom 6 + @ 1 = if
stdouble disp $100 bytsec !
else
stsingle disp
then
then
space stsector disp
$73 emit colon
sectors @ u. space space
;
: printsource
5 2 at stsrc disp colon $44 emit
devnm c@ $30 + emit colon
space printinfo
;
: printdestination
crsoff 7 2 at stdest disp colon dpath disp " " disp
;
: printautoinc
crsoff 9 2 at stauto disp stincrement disp colon
autoinc @ if ston else stoff then disp
9 20 at stdigit disp colon
autoinc @ if cdigit @ else 0 then u.
9 30 at stside disp colon
sidetgl @ if ston else stoff then disp
;
: incdigit
cdigit ++
cdigit @ 5 = if
0 autoinc c!
0 cdigit !
else
1 autoinc c!
then
;
: invertcursor ( i -- )
dup dpath + c@ $80 xor
swap dpath + c! printdestination
;
: inccursor
i @ dpath c@ < if i ++ then
;
: deccursor
i @ 1 > if i -- then
;
: newname
1 i !
{
i @ invertcursor
key
i @ invertcursor
dup 47 = if drop 92 then ( transpose / to \ )
dup $27 = if break then ( ESC )
dup $9B = if break then ( RETURN )
dup 42 = if inccursor then ( cursor right )
dup 43 = if deccursor then ( cursor left )
dup 157 = if dpath c@ 30 < if
i @ dpath + dup 1+ dpath c@ i @ - 1+ cmove> ( INSERT )
bl i @ dpath + c!
dpath c@ 1+ dpath c! ( dpath c++ )
then then
( dup $2F $59 within )
dup $2C > if dup $5D < if dup dpath i @ + c! inccursor then then ( ALPHANUMERICAL )
dup 126 = if dpath c@ i @ - 0 > if ( DELETE )
i @ dpath + dup 1+ swap dpath c@ i @ - cmove
dpath c@ 1- dpath c! ( dpath c-- )
then then
125 = if 1 dpath c! 47 dpath 1+ c! then ( CLEAR )
}
drop
;
: beep
$FD emit
;
: clserr
19 lcls 19 lcls 19 lcls 19 lcls
;
: errorwaitkey
beep key drop clserr
;
: errorhead
20 1 at sterror dispspace dstats c@ u. space
;
: prints2ustatus
21 2 at gets2ustatus "Sio2USB:" disp drvstat 15 + c@ dup u. $2F emit $24 emit dup .$ space
22 2 at
dup $2E = if "Illegal characters in filename" disp then
dup $32 = if "USB device is not mounted" disp then
dup $34 = if "ATR filename not allowed" disp then
dup $35 = if "Directory not found" disp then
dup $37 = if "Filename already exists, overwrite?" disp then
dup $38 = if "Not enough free memory on storage" disp then
dup $39 = if "No free root directory entry found" disp then
drop
;
: printerr
errorhead
stwhile dispspace dispspace stsector dispspace
s2ucmdp if
prints2ustatus
then key drop
;
: readerr
streading printerr
;
: writeerr
stwriting printerr
;
: makeerr
errorhead
stwhile dispspace stcreating dispspace statr dispspace
prints2ustatus
beep key clserr
;
: rmerr
errorhead
stwhile dispspace stremoving dispspace statr dispspace
prints2ustatus
beep key clserr
;
: mounterr
errorhead
stwhile dispspace stmounting dispspace statr dispspace
prints2ustatus errorwaitkey
;
: resetcounter
stzeros0 stzeros1 strcpy
;
: checkhighspeed ( addr -- )
@ $E459 = 0if sthighspeed else stnormalspeed then disp
;
: setsecbufbase
appmhi @ $FF00 and $400 + bufbase !
$7000 bufbase @ - bufsize !
bufbase @ bufsize @ + bufend !
$7000 appmhi !
$7000 hsbase !
;
: readbuffer
hsdrive @ siov !
bufbase @ secbuf !
stzeros1 stzeros2 strcpy
sector @ i ! {
i ++
scopy 19 15 at stzeros1 disp debugflg @ if space secbuf @ .$ then # key drop
i @ readsec errorcode c!
bytsec @ secbuf +!
sectors @ i @ = if break then # last sector
bufend @ secbuf @ = if break then # buffer full?
errorcode c@ $7F > if break then # error during read?
}
;
: writebuffer
hss2u @ siov !
bufbase @ secbuf !
stzeros2 stzeros1 strcpy
sector @ i ! {
i ++
scopy
fullquery 0 = 0if
19 15 at stzeros1 disp debugflg @ if space secbuf @ .$ then # key drop
i @ writesec errorcode c!
then
bytsec @ secbuf +!
sectors @ i @ = if break then # last sector
bufend @ secbuf @ = if break then # buffer full?
errorcode c@ $7F > if break then # error during write?
}
i @ sector !
;
: copy
11 12 rcls
printsource
19 2 at stmake dispspace statr disp stdots disp
makeatr 1 > if
makeerr $59 = 0if
exit
else
clserr
19 2 at "removing" dispspace statr disp stdots disp
rmatr 1 > if rmerr exit then
makeatr 1 > if makeerr exit then
then
then
19 2 at stmount dispspace statr disp stdots disp
mountatr 1 > if mounterr exit then
19 8 at stsector dispspace stzeros1 disp
15 2 at "Drive " disp devnm c@ $30 + emit space hsdrive checkhighspeed
debugflg @ if space hsdrive @ .$ then
16 2 at "SIO2USB " disp hss2u checkhighspeed
debugflg @ if space hss2u @ .$ then
debugflg @ if
12 2 at "Buffersize:" dispspace bufsize @ .$
13 2 at "Bufend:" dispspace bufend @ .$
14 2 at "APPMHI:" dispspace appmhi @ .$
then
bufbase @ secbuf !
resetcounter
1 errorcode !
0 sector !
{
19 2 at stread disp
readbuffer errorcode c@ 1 > if readerr then
errorcode c@ $80 < if
19 2 at stwrite disp
writebuffer errorcode c@ 1 > if writeerr then
then
sectors @ sector @ = if break then
errorcode c@ $7F > if break then
}
$E459 siov ! ( reset to original SIOV )
clserr stcopy dispspace
errorcode c@ $80 < if stsuccessfully else stunsuccessful then dispspace
stcompleted dispspace cr cr stnextcpy dispspace
autoinc @ if
sidetgl @ if
side @ if nextside else nextside nextfile then
else
nextfile
then
printdestination
then
;
: status
11 12 rcls
getstatus drop 11 2 at printstatus
getpercom drop 14 2 at printpercom
;
: type ( caddr u -- )
{
swap dup c@ emit 1+ swap 1-
dup 0 = if drop drop break then
}
;
: printdirentry
cnt @ 11 +
dup 20 > if 10 - 22 else 2 then at
$10 * bufbase @ +
dup @ 0 = if drop exit then
dup @ $80 and if drop exit then
cnt ++
dup @ $20 and if $2A emit else space then space
( 1+ dup @ .$ space ) ( Length )
( 2+ dup @ .$ space ) ( Start Sector )
5 + dup 8 type ( Filename )
$2e emit ( . )
8 + 3 type cr ( Extender )
;
: showdirectory
11 12 rcls
0 cnt !
bufbase @ secbuf !
360 sector !
{
1 sector +!
sector @ readsec drop
0 i !
{
cnt @ 22 = if 22 2 at " press key" disp key drop 0 cnt ! 11 12 rcls then
i @ printdirentry
i ++
i @ $40 = if break then
}
sector @ 368 = if break then
}
22 2 at " press key" disp key drop
;
: ver
"1.2 SIO2USB" disp
;
: banner
cls
$90 $2C6 c! crsoff
statr disp stcopy disp stcenter disp
" (c) 2013 C. Strotmann" disp cr
"Version " disp ver
printsource 4 line
printdestination 6 line
printautoinc 8 line
10 line
1 24 at sthelpmsg disp
;
: help
11 12 rcls
12 2 at "1-9 : select source and query disk" disp
13 2 at " / : edit ATR filename" disp
14 2 at " A : toggle autoincrement" disp
15 2 at " + : increment digits" disp
16 2 at " B : enable/disable diskside A/B" disp
17 2 at " N/P : inc-/decrement number" disp
18 2 at " X : toggle diskside A/B" disp
19 2 at " S : print status" disp
20 2 at " D : print DOS 2.x directory" disp
21 2 at " Q : quit program" disp
22 0 at " [SPACE] copy source disk to ATR" disp
;
: acc
setsecbufbase
1 devnm c! getdrvsio
temp2dpath banner help
{
crsoff key crsoff
dup $30 > if
dup $3A < if
dup $30 - devnm c! printsource getdrvsio
then
then
dup $4E = if nextfile printdestination then
dup $50 = if prevfile printdestination then
dup $48 = if help then
dup $20 = if copy then
dup $3F = if help then
dup $54 = if temp2dpath then
( dup $44 = if newpath 0 fcount ! 7 clearline printdestination then )
dup $2F = if newname 0 fcount ! printdestination then
dup $41 = if toggleautoinc printautoinc then
dup $42 = if toggleside printautoinc printdestination then
dup $2B = if incdigit printautoinc then
dup $53 = if status then
dup $44 = if showdirectory help then
dup $58 = if sidetgl @ if nextside printdestination then then
dup $51 = if exit then
dup $7D ( CLEAR ) = if banner then
dup $3F = if debugflg ctoggle 1 38 at debugflg @ if $44 else $20 then emit then
drop
}
cls crson
;
: main
init
acc
bye
;