ugBASIC
Posted: Wed Apr 12, 2023 7:32 pm
I've discovered this cross-compiler today. Seems interesting, I will take a look later.
https://github.com/spotlessmind1975/ugbasic
https://github.com/spotlessmind1975/ugbasic
The community forum for all Sinclair users
https://spectrumcomputing.co.uk/forums/
Surely this is the simplest and fastest way to use ugBASIC in a Windows environment.
With respect to this point, I point out that, in recent days, the installation page has been completely revised, as well as the UBASIC-IDE, and now there is a more "symmetrical" management of the 64-bit and 32-bit versions.+3code wrote: ↑Thu Apr 13, 2023 6:57 pm Edit 2: Now I'm not sure if the 32 bits version I pointed previously is really a 32 bits version, I've downloaded the installer labeled as "32 bits without the .NET" and downloaded the .NET package by my own and something is wrong.
Edit 3: Well, seems only the IDE is 32 bits, the console compiler is 64 bits, sorry.
Yes, I'm aware of the problem. Using the IDE it should be possible to avoid them, but I haven't actually been able to find a general method, or in any case a method compatible with the "open source" nature of the project.. On the other hand, the alternative is to recompile each compiler by hand. This is quite a tedious task on Windows, due to the lack of a standard build environment.
Yes, they are. Actually, using the IDE simplifies the download of the components necessary for compilation but creates a separation between program and repository. I opened an issue on github to keep track of this specific improvement on the IDE, i.e. the ability to download one or more examples directly, so you don't have to search for them on git.
For this example, however, I don't think it works on ZX Spectrum. The reason is simple. The ugBASIC language is an isomorphic language: this means that it puts the programmer in communication with the underlying hardware as much as possible, without abstractions. Which means that if a piece of hardware isn't there, its instructions do nothing. That is, there is no "translation" in some sort of emulated hardware.
I tried but I think the WAIT...MS command works fine. Probably the problem lies rather with horizontal scrolling, which I'm not sure if it works properly. I opened an issue on github just to keep track of the problem.
I believe the output is correct, at least compared to what is explained here. Can you be so kind as to tell me what, in your opinion, the expected output would be? So I can open an issue if that's the case.
No, it doesn't. In ugBASIC, string arrays are structures that are fixed in size but composed of strings whose length is dynamic, just like in standard BASIC. In other words, the elements of the array, in turn, are dynamic strings, ie they occupy the effective space of the string (plus some control bytes). So an array of strings occupies a certain number of fixed bytes, related to the array length, and then occupies as many bytes as the strings are long.
Yes, I confirm that there is something wrong. I opened an issue on github to track the bug. As soon as it is resolved, the fix will be made available directly on the download page.
Yes, generally speaking, the ugBASIC language exposes multiple ways to solve the same problem. It is an approach borrowed from other BASIC languages of the 80s and 90s, and allows to adapt the software to the hardware, and not vice versa, as happens nowadays.
Yes, there is something wrong. I opened an issue to track down the problem.
In the meantime, you can use other commands. If you need to wait for a key just use the WAIT KEY command. If you need to control a specific character (eg "A"), try KEY PRESSED (KEY A). Finally, if you need to wait for a string, try INPUT.
Yes, of course. There are no limits to the use of returns within control structures, even the most intricate ones. Actually, it's best to use EXIT PROC instead of RETURN. It is convenient to use RETURN if you want the procedure to return a value. If, on the other hand, you don't care then it's fine to use EXIT PROC. If it can help you, on this page is present a guide that explains how to use and exit from procedures. I hope it will come in handy!
the problem has been fixed, so you can download again the compiler.
Thank you for the report.
Yeah, IDE exists just for things like that.
In ugBASIC your progam talks directly with the hardware, as much as possible, of course.
In general it should be possible, but IMHO it's not the right approach to use with ugBASIC. Being an isomorphic language, its goal is to give the maximum for a single platform, as did the BASICs of the time. The fact that you can reuse the same source on multiple platforms we can see as a "plus" rather than something necessary. So it's possible to do what you want, but it doesn't necessarily mean that you do it the same way.
If ugBASIC doesn't get there with its primitives, it is still possible to use inline assembly, as well.
As with all BASIC, it is not necessary to declare variables before using them. But when it happens, it is the last that wins over the first. However, the definition does not match where variables are allocated and initialized. This happens, always, at the beginning of the program.
Code: Select all
CLS
DIM a AS BYTE(10)
a(1) = 5
DIM a AS BYTE(10)
a(2) = 10
FOR i = 0 TO 9
PRINT a(i)
NEXT
Code: Select all
DIM a AS BYTE(10)
'''
CLS
a(1) = 5
a(2) = 10
FOR i = LBOUND(a) TO UBOUND(a)
PRINT a(i)
NEXT
Code: Select all
DIM a AS BYTE(10) = #{ 0, 5, 10, 0, 0, 0, 0, 0, 0, 0 }
'''
CLS
FOR i = LBOUND(a) TO UBOUND(a)
PRINT a(i)
NEXT
The SHARED statement causes the variable used within the procedure to be the one defined in the main program, instead of the local one. This means that the space to which it will refer is the original one, allocated and prepared at the beginning of the program. If you declare a variable with the same name as one you have defined as SHARED, the declaration will simply be ignored. For example:
Code: Select all
DIM a AS BYTE(10) = #{ 0, 5, 10, 0, 0, 0, 0, 0, 0, 0 }
'''
PROCEDURE initgame
SHARED a : ' makes main program's "a" visibile to procedure
DIM a AS BYTE(5) : ' this declaration will be ignored
'''
CLS
FOR i = LBOUND(a) TO UBOUND(a)
PRINT a(i)
NEXT
END PROC
initgame[]
I fixed this behaviour in the develop version of the IDE, but the IDE itself is released less frequently than compiler, so you have to have a bit of patience.
a piece of code could help conduct a diagnostic, or maybe if you want you can open a bug on github. In any case, check the limits of the array: in ugBASIC, array are 0 based. So if you do
Code: Select all
DIM a AS STRING(42)
When I change the string in an array it just overwrites memory.DIM marray$(3)
marray$(3)="hi"
PRINT marray$(3)
marray$(2)="this is going to overwrite the previous string in the array"
PRINT marray$(3)
PRINT marray$(3)
PRINT marray$(2)
PRINT marray$(3)
PRINT marray$(3)
PRINT marray$(3)
PRINT marray$(3)
PRINT marray$(3)
The DIM marray$(3) means an array of 3 elements, from marray$(0) to marray$(2). By accessing to the index 3, you are accessing outside of the limits of the array, by overwriting memory in some place, and so disrupting the executable.
By defining DIM marray$(3),you are allocating spaces for 3 dynamic strings, from 0 to 255 characters (under ZX Spectrum). The exact space allocated depends on the size of each string (it is the sum), while the complessive memory allowed by the string subsystem depends on the DEFINE STRING SPACE and DEFINE STRING COUNT commands. By default, on ZX Spectrum, it is allowed to define up to 1024 bytes of strings, with a maximum of 255 separate strings (with about 3.068 bytes of RAM allocated).