CPCWiki forum

General Category => Programming => Topic started by: SagaDS on 12:56, 18 July 25

Title: CPC Basicator - A python tool to create BAS AMSDOS Files from PC Text files
Post by: SagaDS on 12:56, 18 July 25
Hello,

I have created a BASIC tokeniser (and AMSDOS header) for a big BASIC project. I know WinApe can do it by 'typing' a copy/paste text, but it is slow (you have a x10 but you need to switch it ON and OFF) and it can't do several files... With this, I can easily add several BAS files into a DSK file.
It works for me and seem to create identical tokens than my tests with WinApe. Only missing point: no floating point tokeniser... If you know how to create the 5 bytes from a string, feel free to tell me (I have some documentation and a link to the ROM assembly, but I can't figure it out in python).

Link to project (https://jolletx.visualstudio.com/CPCBasicator/_git/CPCBasicator)
Title: Re: CPC Basicator - A python tool to create BAS AMSDOS Files from PC Text files
Post by: McArti0 on 13:03, 18 July 25
https://www.cpcwiki.eu/index.php?title=Technical_information_about_Locomotive_BASIC&mobileaction=toggle_view_desktop#Floating_Point_data_definition
Title: Re: CPC Basicator - A python tool to create BAS AMSDOS Files from PC Text files
Post by: SagaDS on 13:11, 18 July 25
Yes I know this one (I put a link to it in doc directory of project). 
Just not so easy to reprogram (even with readable ASM method).

https://github.com/Bread80/CPC6128-Firmware-Source  look for  REAL_5byte_to_real

Also, my project was not using floating point numbers so no real need for them  :D
Title: Re: CPC Basicator - A python tool to create BAS AMSDOS Files from PC Text files
Post by: McArti0 on 21:35, 19 July 25
@SagaDS

if floatnumber=0 then

exponent=0
mantissa=0

else

exponent =-127
norm= abs(floatnumber)/(2^exponent)
while norm>=1 or norm<0.5
   exponent=exponent+1
norm= abs(floatnumber)/(2^exponent)
wend
if sgn(floatnumber)=1 then norm=norm-0.5
mantissa=int(norm*(2^32))
exponent=exponent+128

endif

4 bytes Little endian mantissa and 1 byte exponent
Title: Re: CPC Basicator - A python tool to create BAS AMSDOS Files from PC Text files
Post by: lightforce6128 on 04:15, 20 July 25
I wrote a small program in Locomotive BASIC to do the conversion. It should not be a problem to convert any part of it to Python or something else.

100 MODE 2 : ZONE 16
110 float!=-123.456
120 PRINT "Number: ",float!
130 PRINT
140 IF float!<>0 THEN GOTO 170
150   PRINT "Special case: Set all bytes to zero."
160   GOTO 350
170 sign=SGN(float!)
180 intDigits=INT(LOG(sign*float!)/LOG(2))
190 exponent=128+intDigits+1
200 mantissa=(sign*float!)/(2^intDigits)
210 PRINT "Sign: ",sign
220 PRINT "Exponent: ",exponent,
230 PRINT "&";RIGHT$("0"+HEX$(exponent),2)
240 mantissa=mantissa-1
250 mantissa=mantissa/2
260 PRINT "Mantissa:"
270 FOR i=1 TO 4
280   mantissa=mantissa*256
290   intPart=INT(mantissa)
300   mantissa=mantissa-intPart
310   IF i=1 AND sign<0 THEN intPart=intPart+128
320   PRINT i;": ",intPart,
330   PRINT "&";RIGHT$("0"+HEX$(intPart),2)
340 NEXT
350 PRINT
360 PRINT "Memory:"
370 FOR i=0 TO 4
380   byte=PEEK(@float!+i)
390   PRINT i;": ",byte,
400   PRINT "&";RIGHT$("0"+HEX$(byte),2)
410 NEXT
420 PRINT

Some explanation:

Finally I have to say that I only did a few tests. There could be some corner cases left where unexpected things happen. Also using a floating point number itself to do the calculations could introduce rounding errors. This effect will be minimized on modern systems that use 64 bits, much more than the needed 32 bits.
Title: Re: CPC Basicator - A python tool to create BAS AMSDOS Files from PC Text files
Post by: GUNHED on 15:11, 20 July 25
This works on every CPC and emulator:

- Load ASCII file (every line begins with an number)
- Save it with SAVE"xzy

Now you got a BASIC program on you disc / cassette
Title: Re: CPC Basicator - A python tool to create BAS AMSDOS Files from PC Text files
Post by: SagaDS on 10:37, 21 July 25
Quote from: GUNHED on 15:11, 20 July 25This works on every CPC and emulator:

- Load ASCII file (every line begins with an number)
- Save it with SAVE"xzy

Now you got a BASIC program on you disc / cassette
There are several ways to generate BASIC files. 
My purpose here was to generate them directly on a DSK produce on PC.
Title: Re: CPC Basicator - A python tool to create BAS AMSDOS Files from PC Text files
Post by: SagaDS on 10:39, 21 July 25
Quote from: McArti0 on 21:35, 19 July 25@SagaDS

if floatnumber=0 then

exponent=0
mantissa=0

else

exponent =-127
norm= abs(floatnumber)/(2^exponent)
while norm>=1 or norm<0.5
  exponent=exponent+1
norm= abs(floatnumber)/(2^exponent)
wend
if sgn(floatnumber)=1 then norm=norm-0.5
mantissa=int(norm*(2^32))
exponent=exponent+128

endif

4 bytes Little endian mantissa and 1 byte exponent
Thanks for proposed algo (@lightforce6128 too).
I will give it a go sometime in future.

Just hope that python will not modify float precision in a way that result won't be the same...
That is why I was looking for a text parser (thus the ROM information) instead of a conversion from float...
Title: Re: CPC Basicator - A python tool to create BAS AMSDOS Files from PC Text files
Post by: McArti0 on 12:18, 21 July 25
You have to calculate with double numbers.
Title: Re: CPC Basicator - A python tool to create BAS AMSDOS Files from PC Text files
Post by: SagaDS on 16:13, 22 July 25
I have implemented algorithm of lightforce6128.

I had to modify one thing when testing with more values in python (was working in BASIC):

        intDigits=int(math.log(sign*floatnumber)/math.log(2))
        if intDigits<0:
            intDigits-=1
        exponent=128+intDigits+1

New version v1.0 pushed.
Title: Re: CPC Basicator - A python tool to create BAS AMSDOS Files from PC Text files
Post by: mv on 17:16, 22 July 25
It took me a while to figure it out in TypeScript. I hope it's correct...

https://github.com/benchmarko/CPCBasicTS/blob/8496dd96ecc1a2585626637fc14b6d23e3c0952f/src/CodeGeneratorToken.ts#L375C1-L394C3

private static floatToByteString(number: number) {
  let mantissa = 0,
    exponent = 0,
    sign = 0;

  if (number !== 0) {
    if (number < 0) {
      sign = 0x80000000;
      number = -number;
    }
    exponent = Math.ceil(Math.log(number) / Math.log(2));
    mantissa = Math.round(number / Math.pow(2, exponent - 32)) & ~0x80000000;
    if (mantissa === 0) {
      exponent += 1;
    }
    exponent += 0x80;
  }
  return CodeGeneratorToken.convInt32ToString(sign + mantissa) + CodeGeneratorToken.convUInt8ToString(exponent);
 }


And the reverse (bytes to number):
https://github.com/benchmarko/CPCBasicTS/blob/8496dd96ecc1a2585626637fc14b6d23e3c0952f/src/BasicTokenizer.ts#L98C1-L114C3
...
Powered by SMFPacks Menu Editor Mod