It's not 100% complete yet, but I made a two-stage BASIC loader
<https://github.com/hackerb9/co2do/blob/main/co2do> that includes a little
8085 routine <https://github.com/hackerb9/co2do/blob/main/decode.asm> for
speed. You just run ./co2do FOO.CO and it'll create a FOO.DO that can load
speedily.

I took John Hogerhuis's advice to put the machine language in a BASIC
string and call it from there, which helped a lot with portability as I
don't need to have a per machine table of free spaces in RAM. Speed is
great on my Tandy 200. I don't have a Model 100, but when I simulate it in
Virtual T, it seems to take about 14 seconds to tokenize the BASIC. The
time to decode the bytes and load it into RAM is a fraction of a second, so
I'd say the overall speed is about 15 seconds. You can try loading the
resulting .DO file
<https://raw.githubusercontent.com/hackerb9/co2do/refs/heads/main/testfiles/ALTERN.DO>
on a M100 or T102 to see for yourself. (I recommend using it with `RUN
"COM:88N1E"`).

My co2do <https://github.com/hackerb9/co2do/blob/main/co2do> program is
usable now, but incomplete in a few ways:

   - It does not handle the serial transfer itself, so the program is still
   reliant on the speed of the BASIC LOAD/RUN commands.
   - It doesn't run at all on the NEC PC-8201/8300 machines as I haven't
   implemented VARPTR yet.
   - It also hasn't been size optimized at all yet.
   - It needs better memory error warnings and documentation.
   - It should be shipped as a single file instead of having a separate ASM
   file.

—b9

On Thu, Mar 5, 2026 at 9:21 PM Brian K. White <[email protected]> wrote:

>
> It works all on one line after all!
> It doesn't make the file any shorter, actually a couple bytes larger
> because "ELSE:" is longer than "\r2"
> But it did get about 1 second faster.
>
>
> 0READT:CLEAR2,T:DEFINTI,O,C,V,L:DEFSNGA,K,S,T,X,E:DEFSTRB,M,D,N:READT,L,X,K,N,O,M:E=T+L-1:A=T:S=0:C=0:CLS:PRINT"Installing
>
> "N
> 1PRINT@20
> ,CINT((L-(E-A))/L*100)"%":READD:FORI=1TOLEN(D):B=MID$(D,I,1):IFB=MTHENC=O:NEXT:ELSEV=ASC(B)-C:POKEA,V:C=0:A=A+1:S=S+V:NEXT:IFA<=ETHEN1
> 2PRINT:IFS<>KTHENPRINT"Bad Checksum":END
> 3CALLX
> 4DATA59346,3614,59346,454932,"ALTERN.CO",64,"!"
>
>
> On 3/4/26 07:11, Brian K. White wrote:
> >
> > I've gotten co2ba.sh about as good as I think I'm going to get it for
> > now.
> >
> > It generates a larger block of loader code, which also runs slower,
> > but the file is somewhat smaller and that ends up making the total job
> > take about the same time with a 3.6k sample input co file.
> >
> >
> > The sample file used for these tests and comparisons is
> > ALTERN.CO manually reconstituted from
> >
> https://github.com/LivingM100SIG/Living_M100SIG/blob/main/M100SIG/Lib-07-UTILITIES/ALTERN.100
> >
> >
> >
> > My previous loader code looks like this:
> > (extra blank lines to help reading after email wraps the long lines):
> >
> > -----------
> > 0CLEAR0,59346:A=59346:S=0:N$="ALTERN.CO":CLS:?"Installing "N$" ..";
> >
> >
> 1D$="":READD$:FORI=1TOLEN(D$)STEP2:B=(ASC(MID$(D$,I,1))-97)*16+ASC(MID$(D$,I+1,1))-97:POKEA,B:A=A+1:S=S+B:NEXT:?".";:IFA<62960THEN1
>
> >
> >
> > 2IFS<>454932THEN?"Bad Checksum":END
> >
> > 3CALL59346
> >
> > 4DATAmndmpfmndbeccklppfolcbim...
> > -----------
> >
> >
> >
> >
> >
> > With the new scheme I'm down to this
> >
> > -----------
> >
> 0READT:CLEAR2,T:DEFINTI,O,C,V,L:DEFSNGA,K,S,T,X,E:DEFSTRB,M,D,N:READT,L,X,K,N,O,M:E=T+L-1:A=T:S=0:C=0:CLS:PRINT"Installing
>
> > "N
> >
> >
> > 1PRINT@20,CINT((L-(E-A))/L*100)"%":READD:FORI=1TOLEN(D):B=MID$(D,I,1):IFB=MTHENC=O:NEXT
>
> >
> >
> >
> > 2V=ASC(B)-C:POKEA,V:C=0:A=A+1:S=S+V:NEXT:IFA<=ETHEN1
> >
> >
> > 3PRINT:IFS<>KTHENPRINT"Bad Checksum":END
> >
> >
> > 4PRINT"Done. Please type: NEW":SAVEMN,T,E,X
> >
> >
> > 5DATA59346,3614,59346,454932,"ALTERN.CO",64,"!"
> >
> > 6DATA"Í<õÍ1B*¿õë!aŒ!DÍ õ|µÊêç...
> > -----------
> >
> >
> > Part of the size difference is some apples/oranges differences that
> > make it not a direct comparison. The two could be more similar than
> > this if I wanted. Previously I just had the generator write the co
> > header variables directly in the code instead of having a header data
> > line, while in the new one I'm doing it all from a data line, because
> > I like that the loader code then is self contained & portable. You
> > could copy the loader block and stick it on top of some other paylod
> > and it would work.
> >
> > And another part is I made a real percent-done display on the new one
> > because it doesn't cost any run time, just a few more bytes of file
> > size. It only runs once per data line and outside of the inner loop.
> >
> > The defint/defsng etc making line 0 longer also makes it run several
> > seconds faster.
> >
> > I actually have an even slightly shorter version just by using the
> > range syntax for the DEF*
> > DEFINTA-E:DEFSNGF-K:DEFSTRL-O
> > vs
> > DEFINTI,O,C,V,L:DEFSNGA,K,S,T,X,E:DEFSTRB,M,D,N
> > but it makes the code just about unreadable since the letters lose all
> > meaning.
> >
> > The notable points:
> >
> > no goto in the inner loop, just next.
> > saved a line and also made it so that the generator script doesn't
> > have any forward references, so it can just increment line numbers
> > without having to hard code like a GOTO3 on line 1 etc.
> >
> > Instead of
> > O=64 C=0 ... IFB=MTHENC=1  ... V=ASC(B)-(O*C)
> > (on every byte set a decode flag to 0 or 1, then multiply the encoding
> > offset by the on/off flag to enable/disable the offset)
> >
> > Just
> > O=64 C=0 ... IFB=MTHENC=O  ... V=ASC(B)-C
> > (instead of setting the encode flag to 0 or 1, just set it to 0 or the
> > actual offset value, then just subtract it directly without the
> > multiplication step. Always subtract, sometimes it's 0, sometimes its 64.
> > As far as I can tell, 0, 1, and 64 are all the same int and the same
> > work to process as long as the variables are declared to the same type.
> >
> > Already mentioned all variables from data, can-nable loader code etc.
> >
> > If the top address is the very first data value, you can read it, use
> > it to clear, and then just read it again to still have it after the
> > clear without wasting much space or cpu, and without needing the
> > generator script to write the value twice in duplicate assignments
> > before & after the clear.
> >
> > Already mentioned the fancy percent-done progress.
> >
> > The generator script has config options so you can change the behavior
> > at run-time by env variables.
> >
> > So you can change the starting line number, the line number increment,
> > the length of the data lines, the encoding mark character, the
> > encoding offset value.
> >
> > I have the generator script now counting all the bytes in the output
> > line when building data lines and deciding when to start a new line,
> > so now every line fills to the specified max length as much as
> > possible even though the size of the data varies because of the varied
> > encoding.
> >
> > All in all, the new way generates a smaller file, but the loader code
> > runs slower, and it ends up taking almost exactly the same total time
> > to load. The smaller file size is a win though, and the total time is
> > actually *slightly* in favor of the new way.
> >
> > The new scheme is conceptually simple but it takes 2 lines of code and
> > includes an IF branch where the old way the entire loop is on a single
> > line and the the same math ops happen for every byte, no branching.
> >
> > I read that one optimization is to move initialization/setup code to
> > the end instead of the top, and use goto or gosub to jump to it and
> > back, and have your tight loop as close to the top as possible.
> > Something about BASIC searching from the start of the file repeatedly?
> > Well I tried that and it made no difference in my run times. I tried
> > both goto and gosub.
> >
> > For now I kept the old script in the repo as co2ba_old.sh since it's
> > output is probably still useful being all pure low ascii printable text.
> >
> > Converting the same input:
> > ALTERN.CO 3620 bytes
> >
> > old:
> > 7749 bytes
> > xfer time: 1:05
> > load time: 2:04
> > total: 3:09
> >
> > new:
> > 5334 bytes
> > xfer time: 0:45
> > load time: 2:23
> > total: 3:07
> >
> > https://github.com/bkw777/dl2/blob/master/co2ba.md
> > https://github.com/bkw777/dl2/blob/master/co2ba.sh
> >
> >
> > Anyway, thanks again for the idea Steve!
> >
>
> --
> bkw
>
>
>

Reply via email to