From: MagerValp on
>>>>> "M" == MagerValp <MagerValp(a)cling.gu.se> writes:

M> 19+1 bytes per line gives 36 lines of data. The same method can be
M> used with base-64 of course, giving 30 lines of data. What would
M> people prefer though?

My bad, base-64 requires quotes around the data, so you only get 30
characters per line. So, 33 vs 36 lines. Readability is more important
than a measly 3-line advantage.

--
___ . . . . . + . . o
_|___|_ + . + . + . Per Olofsson, arkadspelare
o-o . . . o + MagerValp(a)cling.gu.se
- + + . http://www.cling.gu.se/~cl3polof/
From: Wolfgang Moser on
Hi Per,

MagerValp schrieb:
>>>>>> "WM" == Wolfgang Moser <wnhp(a)d81.de.invalid> writes:
>
> WM> Which bit depth comes with the C64's floating point format
> WM> regarding the base (anything but exponent and sign)?
>
> IIRC, 8-bit exponent, 1-bit sign, and 31-bit mantissa. Plenty of
> precision there.

More than enough.

> How about something like this:

? you saw my posting from midnight, didn't you?

> readline:
> read a$
> if a$="end" then end
> v=0 : s=0 : c=0
> for i=1 to len(a$)
> q=asc(mid$(a$,i,1)) : gosub conv32
> v=v*32+q : s=s+5

You may want to do the "if" first, so that
the last n bits with n>8 automatically remain
within v and no extra check for loop exiting
is needed.

> if s<7 goto nextchar

You surely want to extract a byte, when 8 or
more bits got collected, so if vote for: "s<8"

> q=v and 255 : v=v/256 : s=s-8

Hmmmm.... at first, "v=int(v/256)" seems to
be a good idea to get rid of the unneded
fractional part. And it prevents a possible
"?illegal quantity error" as a test case
just showed to me. Maybe a "(v/256) and 15"
does the same and further reduces to a
non-float number.

Left shifting and inserting at the right with
"v=v*32+q" from above and then again extracting
from the right side would require some weird
bit permutations in the data line encoder. But
in fact it reduces type-in size.

> if i=len(a$) goto checksum

This check could be omitted as said above.

> poke a,q : a=a+1 : c=c+q
> goto nextchar
>
> checksum:
> if c<>q then print "checksum error" : end

With the checksum there're surely some
improvents possible I did not think about in
depth. With 31 characters per data line and
each car storing 5 bits, you get out 18 bytes
and 11 additional bits usable for checksums.

Or 19 bytes plus 3 checksum bits. Maybe that
one is enough checksum info??? My loop
reordering needs to be undone then.

> nextchar:
> next
> goto readline
>
> (Hmm, I should write a simple basic preprocessor, so you can write
> line number-less code like this)

:-) Along with Tok64 integrated to produce
true BASIC files for testing and cbmconvert
for creating a D64...

> 19+1 bytes per line gives 36 lines of data. The same method can be
> used with base-64 of course, giving 30 lines of data. What would
> people prefer though?

As you said later, the 5-Bit scheme seems to be
extraordinary type-in efficient.
This must be no argument against Leif's
observations as long as we don't start measuring
groups of people trying to type-in programs after
one or another scheme.


Womo


From: MagerValp on
>>>>> "WM" == Wolfgang Moser <wnhp(a)d81.de.invalid> writes:

MV> How about something like this:

WM> ? you saw my posting from midnight, didn't you?

Yes, I just haven't had time to sit down at a C64 and play with it.

MV> readline:
MV> read a$
MV> if a$="end" then end
MV> v=0 : s=0 : c=0
MV> for i=1 to len(a$)
MV> q=asc(mid$(a$,i,1)) : gosub conv32
MV> v=v*32+q : s=s+5

WM> You may want to do the "if" first, so that the last n bits with
WM> n>8 automatically remain within v and no extra check for loop
WM> exiting is needed.

Mmm, good point.

MV> if s<7 goto nextchar

WM> You surely want to extract a byte, when 8 or more bits got
WM> collected, so if vote for: "s<8"

Right, tpyo :)

MV> q=v and 255 : v=v/256 : s=s-8

WM> Hmmmm.... at first, "v=int(v/256)" seems to
WM> be a good idea to get rid of the unneded
WM> fractional part.

Yup, whups.

WM> Left shifting and inserting at the right with "v=v*32+q" from
WM> above and then again extracting from the right side would require
WM> some weird bit permutations in the data line encoder. But in fact
WM> it reduces type-in size.

Yeah, it should be fairly simple to add.

MV> poke a,q : a=a+1 : c=c+q
MV> goto nextchar
MV> checksum:
MV> if c<>q then print "checksum error" : end

WM> With the checksum there're surely some improvents possible I did
WM> not think about in depth. With 31 characters per data line and
WM> each car storing 5 bits, you get out 18 bytes and 11 additional
WM> bits usable for checksums.

You can fit 32 characters per line:

0123456789012345678901234567890123456789

99 data01234567890123456789012345678901

19+1 bytes seems like the best option.

MV> (Hmm, I should write a simple basic preprocessor, so you can write
MV> line number-less code like this)

WM> :-) Along with Tok64 integrated to produce true BASIC files for
WM> testing and cbmconvert for creating a D64...

I've been using petcat -w2. How does that compare to Tok64?

--
___ . . . . . + . . o
_|___|_ + . + . + . Per Olofsson, arkadspelare
o-o . . . o + MagerValp(a)cling.gu.se
- + + . http://www.cling.gu.se/~cl3polof/
From: Wolfgang Moser on
Hello Per,

I got some fun writing the encoder ;-)

MagerValp schrieb:
> WM> You may want to do the "if" first, so that the last n bits with
> WM> n>8 automatically remain within v and no extra check for loop
> WM> exiting is needed.
>
> Mmm, good point.

Well, I know vote for using a 3-bit checksum only and
then this exchange is not needed.

> WM> Left shifting and inserting at the right with "v=v*32+q" from
> WM> above and then again extracting from the right side would require
> WM> some weird bit permutations in the data line encoder. But in fact
> WM> it reduces type-in size.
>
> Yeah, it should be fairly simple to add.

I know did it upside/down, back-to-front and it seems
to work.

> WM> With the checksum there're surely some improvents possible I did
> WM> not think about in depth. With 31 characters per data line and
> WM> each car storing 5 bits, you get out 18 bytes and 11 additional
> WM> bits usable for checksums.
>
> You can fit 32 characters per line:
>
> 0123456789012345678901234567890123456789
>
> 99 data01234567890123456789012345678901
>
> 19+1 bytes seems like the best option.

Hmmm, it smells like this decreases type-in efficiency
again, since the letter after the data is somewhat
difficult to read.
Therefore I vote for only using 31 chars. But with
using a 3-bit checksum only, we don't lose a single
decoded raw byte.

> I've been using petcat -w2. How does that compare to Tok64?

Well, although I knew of it, I didn't recognized it
yesterday when I "just" needed such a thing. petcat
is a lot more mighty then Tok64. The latter one even
does not know how to handle long filenames.


Do you like Java-5 ? Then the following encoder
routine is a little present (as well as the decoder
done for validating reasons). I changed the character
mapping a bit, because "2" was too similar to "Z".
Therefore I reintegrated "V" into the mapping, which
is different enough from "W".


Womo

======snip/snap=====

/*
* (C) 2006, Wolfgang Moser, created on 18.10.2006
*/

/**
* <p>
* base64 style encoding system, but with 5 Bits instead
* of 6 Bits per encoded character. So only the chars
* A..T, V..Z and 3..9
* are used effectively. There are three equivalencies
* to eliminate misinterpretations:
* 0 = O, 1 = I, 2 = Z
* </p>
* <p>
* Each encoded line with 31 chars each furthermore
* contains 3 bits for line checksumming.
* </p>
*
* @author <a href="http://wmsr.de">Wolfgang Moser</a>
*
* @version $Id: typeincdc.java 1 2006-10-18 20:46:23Z wmsr $
* @version $HeadURL:
https://svnrepo/Eclipse/C64typein/src/typeincdc.java $
*/
public class typeincdc {
final static String sccsid = "@(#)$Id: typeincdc.java 1 2006-10-18
20:46:23Z wmsr $\\\n";

private static byte inpb[] = new byte[19];
private static char encb[] = new char[31];
private static byte decb[] = new byte[19];

public static void main(String[] args)
{
System.out.print("Test array prefilled with: [");
for(int i=0; i<inpb.length; ++i)
{
inpb[i] = (byte)(Math.random()*256);
System.out.print("" + inpb[i] + ',');
}
System.out.println("]");

encode();
System.out.println("Encoded array filled with: " + String.valueOf(encb));
decode();

System.out.print("Redecoded array filled with: [");
for(byte t : decb)
{
System.out.print("" + t + ',');
}
System.out.println("]");

// test the checksum on repeated encodings and decodings
for(int i=0;i<65536;++i)
{
for(int j=0; j<inpb.length; ++j)
{
inpb[j] = (byte)(Math.random()*256);
}
encode();
if(! decode())
{
System.err.println("Checksum error on run: " + i);
}
}

}

private static void encode()
{
short reg = 0; byte s;
// calc checksum
for(byte t : inpb) reg += t;

// limit checksum to three bits
reg &= 7;
s = 3;

// System.out.println("Checksum: reg="+reg);

// encode with the last byte beginning
for(int i=inpb.length-1, j=encb.length-1; i>=0; --i)
{
reg <<= 8;
reg |= 255 & inpb[i];
s += 8;

while(s>=5)
{
encb[j--] = enmap(reg);
reg >>>= 5;
s -= 5;
}
}
}
/*
private static char enmap_old(short b)
{
String map = "ABCDEFGH1JKLMN0PQRSTWXYZ23456789";
// String map = "abcdefgh1jklmn0pqrstwxyz23456789"; // Z == 2

return map.charAt(b&31);
}
*/
private static char enmap(short b)
{
// String map = "ABCDEFGH1JKLMN0PQRSTVWXY23456789";
String map = "ABCDEFGHIJKLMNOPQRSTVWXYZ3456789";

return map.charAt(b&31);
}

private static boolean decode()
{
short reg = 0; byte s = 0; byte ck = 0;

int j=0;
for(char t : encb)
{
reg <<= 5;
reg |= demap(t); // no negatives expected here
s += 5;

if(s<8) continue;
decb[j++] = (byte)reg;
ck += reg;
ck &= 7;

reg >>>= 8;
s -= 8;
}

// System.out.println("Checksum: ck="+ck+", reg="+reg);

return ck == reg;
}
/*
private static byte demap_old(char c)
{
if(c>'Z') c-=('a'-'A'); // map [a-z] to [A-Z]

if(c=='0') c='O';
if(c=='1') c='I';
if(c=='V') c='U';
if(c>='W') c-=2; // map wxyz to uvwx
if(c<'A') c+=('Y'-'2'); // map 23456789 to yz[\]^_'

return (byte)((c-'A')&31);
}
*/
private static byte demap(char c)
{
if(c>'Z') c-=('a'-'A'); // map [a-z] to [A-Z]

if(c=='0') c='O';
if(c=='1') c='I';
if(c>='V') c-=1; // map vwxy to uvwx and z to y
if(c<'A') c+=('Y'-'2'); // map 23456789 to yz[\]^_'

return (byte)((c-'A')&31);
}
}
From: MagerValp on
>>>>> "WM" == Wolfgang Moser <wnhp(a)d81.de.invalid> writes:

WM> Hmmm, it smells like this decreases type-in efficiency again,
WM> since the letter after the data is somewhat difficult to read.
WM> Therefore I vote for only using 31 chars. But with using a 3-bit
WM> checksum only, we don't lose a single decoded raw byte.

3-bit checksum just won't do though. Way too easy to get a typo that
isn't caught, like an 8 instead of a 0.

WM> Do you like Java-5 ?

Actually, no :P

WM> Then the following encoder routine is a little present (as well as
WM> the decoder done for validating reasons). I changed the character
WM> mapping a bit, because "2" was too similar to "Z". Therefore I
WM> reintegrated "V" into the mapping, which is different enough from
WM> "W".

Ah, good point.

--
___ . . . . . + . . o
_|___|_ + . + . + . Per Olofsson, arkadspelare
o-o . . . o + MagerValp(a)cling.gu.se
- + + . http://www.cling.gu.se/~cl3polof/