spotlessmind1975 / ugbasic

An isomorphic BASIC language compiler for retrocomputers
Apache License 2.0
92 stars 16 forks source link

Program crashes C128 #905

Closed mzattera closed 2 days ago

mzattera commented 3 months ago

This code compiles for all targets I tried, including C128. But when executed on C128 it breaks.

image

spotlessmind1975 commented 3 months ago

Hi @mzattera , and thank you for your bug report!

Based on the preliminary analysis of the anomaly found, it is possible to indicate the cause in the exceeding of the available memory, which by overlapping the video space, determines an erratic behavior of the software. While waiting for the automatic optimizations of the occupied space, which are always in progress, it is possible to verify the space occupation of each single line of the program using the Additional Info option of IDE.

image

The objective should be to "streamline" the memory occupation of each line, or by removing certain features that, overall, occupy space. I.e. removing audio support (by omitting the BELL command) will reduce the executable size from from 28,975 bytes to 26,325 bytes. This latter size is able to be run inside the emulator:

image

Thank you again!

mzattera commented 3 months ago

Thanks for the hint!!! Still, isn't >25K a bit too much for this code? I agree it uses FLOAT, and maybe you are not using ROM code for that, but still...is there any other feature you see I use that is bogging down the code?

spotlessmind1975 commented 3 months ago

Hi @mzattera , and thank you for your comments!

The size of the executable code produced depends, almost always, on the presence of duplicate assembly code and also depends on the type of processor used (for example, the MOS 6502 produces less compact code than the MOTOROLA 6809).

Unfortunately, since the compiler is single-pass and has no heap memory and no stack, ugBASIC cannot perform optimizations other than those that can be implemented with a "peephole" approach. Therefore, it is necessary for the programmer to adopt some techniques to improve performance from a spatial point of view.

The least impactful ones make use of pragmas. For example, the default space occupied by dynamic strings can be reduced, using the pragmas DEFINE STRING SPACE and DEFINE STRING COUNT. With these:

 DEFINE STRING SPACE 256
 DEFINE STRING COUNT 32

the space allocated for strings is reduced from 3,072 to 640 bytes.

Or you can use the DEFINE SCREEN MODE UNIQUE pragma, which eliminates those parts of "dead" code that will not be called. Alternatively, or together, you can optimize the code by using, for example, native instructions of the language. In this specific case:

 10 PRINT SPC((TILES WIDTH - 8)/2);"HAMURABI"
 20 PRINT SPC((TILES WIDTH - 18)/2);"CREATIVE COMPUTING"
     PRINT SPC((TILES WIDTH - 22)/2);"MORRISTOWN, NEW JERSEY"

it takes up a total of 1,860 bytes. These three lines can be rewritten using the CENTER command:

 10 CENTER "HAMURABI"
 20 CENTER "CREATIVE COMPUTING"
      CENTER "MORRISTOWN, NEW JERSEY"

This takes up 1,518 bytes, or about 350 bytes less.

Another example. This code:

 533 babies=INT((20.0*acres+store)*c/population/100.0+1.0)

generates a very large code, about 3527 bytes, due to the fact that the compiler is forced to reconstruct the sequence of operations statically (that is: without using the stack), moreover using floats as temporary variables. Without giving up the use of floats, it can be improved by simplifying the expression.

For example, the simple fact of doing sums with integers instead of floats:

 533 babies = INT((20.0*acres+store)*c/population/100.0)+1

leads to 3469 bytes, with a saving of 58 bytes.

I hope these first indications will be useful, but of course I am sure that it is possible to further improve the space occupied. And, of course, with time ugBASIC will produce even more compact code.

mzattera commented 3 months ago

Thanks a lot for the hints!!! You know that one day you will have to write a comprehensive book about ugBASIC, don-t you? 😬

mzattera commented 3 months ago

JFYI, it works on C120 Z80 mode, so the RAM is enough for the game. I appreciate the memory map is different and that will cause issue.

spotlessmind1975 commented 3 months ago

Hi @mzattera and thank you very much for the feedback!

I confirm your observation. The version for the c128 with Z80 works because, in fact, the routines available on this platform are very limited. There is no audio, and the interaction with the video chipset is much more "compact", since it has only two modes (a text and a graphical one).

In general, each target must be taken individually, that is, it can also be very different from each other. Not long ago, for example, the msx1 and the coleco were diametrically opposed as implementations, despite having the same video chipset, only because the interrupt line is connected to a different pin of the CPU!

spotlessmind1975 commented 2 days ago

I'm closing this ticket because it will be addressed by specific tickets, related to memory usage and banking management under Commodore 128.