Skip to content

Commit

Permalink
add co2ba.sh
Browse files Browse the repository at this point in the history
  • Loading branch information
bkw777 committed Feb 20, 2023
1 parent 5d24907 commit aa05322
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 1 deletion.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,10 @@ install: $(APP_NAME) $(CLIENT_LOADERS) $(LIB_OTHER) $(DOCS)
done
mkdir -p $(PREFIX)/bin
install $(INSTALLOWNER) -m 0755 $(APP_NAME) $(PREFIX)/bin/$(APP_NAME)
install $(INSTALLOWNER) -m 0755 co2ba.sh $(PREFIX)/bin/co2ba

uninstall:
rm -rf $(APP_LIB_DIR) $(APP_DOC_DIR) $(PREFIX)/bin/$(APP_NAME)
rm -rf $(APP_LIB_DIR) $(APP_DOC_DIR) $(PREFIX)/bin/$(APP_NAME) $(PREFIX)/bin/co2ba

clean:
rm -f $(APP_NAME)
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,5 +185,11 @@ or you can confuse someone...
$ ROOT_LABEL='C:\' PARENT_LABEL='UP:' dl
```

## co2ba.sh
Also included is a bash script to read a binary .CO file and output an ascii BASIC loader .DO file,
which may then be used with the bootstrap function to re-create the original binary .CO file on the portable.
All KC-85 platform machines are supported including TRS-80 Model 100, TANDY 102 & 200, Kyotronic KC-85, Olivetti M10, NEC PC-8201 & PC-8300.
See [co2ba](co2ba.md)

## OS Compatibility
Tested on Linux, Macos, [FreeBSD](ref/freebsd.md), and [Windows](ref/cygwin.md).
25 changes: 25 additions & 0 deletions co2ba.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# co2ba.sh

Reads a binary .CO file and generates an ascii BASIC loader .DO file

The general usage is
```co2ba FILE.CO [action] [comment] > FILE.DO```

**FILE.CO** is the input binary .CO filename that you want to bootstrap onto the portable.

**action** is what the loader should do with the .CO after it's done re-creating it on the portable:
call - Immediately execute - for TANDY, Kyotronic, Olivetti
exec - Immediately execute - for NEC
savem - Save FILE.CO - for TANDY, Kyotronic, Olivetti
bsave - Save FILE.CO - for NEC
Otherwise if the option is not given, or any other value than these, the loader will only print a message showing the Top, End, and Exec addresses of the loaded binary.

**comment** is an optional custom replacement text for the first half of the line #0 comment.
By default a basic comment giving the name of the .CO file is generated.
The 2nd half of the line always has co2ba.sh itself and the date it was run to generate the loader.
You can use this to give more info about the payload than just the filename.

**FILE.DO** is the output ascii BASIC .DO filename.

For example, to generate TSLOAD.200
```co2ba TSLOAD.CO savem "TSLOAD for TANDY 200 - Travelling Software" >TSLOAD.200```
62 changes: 62 additions & 0 deletions co2ba.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/bin/bash
# Read a .CO file and generate a BASIC loader
# Brian K. White <[email protected]>

CO_IN="$1" ;shift
ACTION="${1^^}" ;shift
COMMENT="$@"

CO="${CO_IN##*/}" ;CO="${CO:0:6}.CO"
BYTES_PER_DATA_LINE=120
typeset -ra h=({a..p}) # hex data output alphabet

typeset -i i t b c SUM TOP END EXE LEN LINE
typeset -a d=()

abrt () { printf '%s: Usage\n%s IN.CO [call|exec|savem|bsave] ["comment..."] > OUT.DO\n%s\n' "$0" "${0##*/}" "$@" >&2 ;exit 1 ; }

# read a binary file into to global int array d[]
ftoi () {
[[ -r "$1" ]] || abrt "Can't read \"$1\""
local -i i= ;local x= LANG=C ;d=()
while IFS= read -d '' -r -n 1 x ;do printf -v d[i++] '%u' "'$x" ;done < $1
}

###############################################################################

# help
[[ "${CO_IN}" ]] || abrt

# read the .CO file into d[]
ftoi "$CO_IN"

# parse & discard the .CO header
((TOP=${d[1]}*256+${d[0]}))
((LEN=${d[3]}*256+${d[2]}))
((END=TOP+LEN-1))
((EXE=${d[5]}*256+${d[4]}))
d=(${d[*]:6})
((LEN==${#d[*]})) || abrt "Corrupt .CO file\nheader declares LEN=$LEN\nfile has ${#d[*]} bytes after header"
SUM= ;for ((i=0;i<LEN;i++)) { ((SUM+=${d[i]})) ; }

# BASIC loader
LINE=0
printf '%u%c%s - loader: co2ba.sh [email protected] %(%F)T \r' $LINE "'" "${COMMENT:-$CO}" -1
printf '%uCLEAR256,%u:A=%u:S=0:N$="%s":CLS:?"Loading "N$" installer...";\r' $((LINE++)) $TOP $TOP "$CO"
printf '%uD$="":READD$:FORI=1TOLEN(D$)STEP2:B=(ASC(MID$(D$,I,1))-%u)*16+ASC(MID$(D$,I+1,1))-%u:POKEA,B:A=A+1:S=S+B:NEXT:?".";:IFA<%uTHEN%u\r' $LINE "'${h[0]}" "'${h[0]}" $((END+1)) $((LINE++))
printf '%uIFS<>%uTHEN?"Bad Checksum":END\r' $((LINE++)) $SUM

# action after loading
case "$ACTION" in
CALL|EXEC) printf '%uCLS:%s%u\r' $((LINE++)) $ACTION $EXE ;;
SAVEM|BSAVE) printf '%uCLS:?"Saving "N$:%sN$,%u,%u,%u\r' $((LINE++)) $ACTION $TOP $END $EXE ;;
*) printf '%uCLS:?"Loaded:":?"top %u":?"end %u":?"exe %u"\r' $((LINE++)) $TOP $END $EXE ;;
esac

# DATA lines
c= ;for ((i=0;i<LEN;i++)) {
((c++)) || printf '%uDATA' $((LINE++))
printf '%c%c' ${h[${d[i]}/16]} ${h[${d[i]}%16]}
((c<BYTES_PER_DATA_LINE)) || { c=0 ;printf '\r' ; }
}
((c)) && printf '\r'

0 comments on commit aa05322

Please sign in to comment.