Closed CityAceE closed 1 month ago
That's not a bug. :)
"|" is a native procedure call, and BASIC has no awareness of C type information or anything like that. It is therefore the programmer's responsibility to pass the right type of parameters, or bad things will happen.
In this case, playmod()
expects a string as its argument. BASIC strings are passed to native procedures as pointers, so what happens above is that the number 1 is interpreted as a pointer to address 1, which is (I guess) not mapped on Windows. The "natural" thing to happen in such a case when running on an operating system as opposed to the bare metal is for the process to be killed.
The (original) philosophy of the BASIC Engine is to give the programmer unhindered access to any and all system resources. What that effectively requires is full access to the entire physical address space. This has been implemented differently on different incarnations:
On ESP8266 that it the natural state of things as it doesn't have any MMU.
On H3 NG (bare metal without hypervisor) I mapped all memory linearly, which essentially had the same effect.
On RX (with Jailhouse hypervisor) this is mostly still true, but some accesses to memory (such as to the interrupt controller and UART) are trapped by the hypervisor. Jailhouse is designed for high-security applications (i.e. the exact opposite of the BASIC Engine use case), and I have not gone all the way in disabling all security measures it implements.
On LT, no explicit measures have been taken to allow memory access from Engine BASIC, so by default access to memory that does not belong to the Engine BASIC process crashes the interpreter. (It will respawn, though.) Since the process runs as root and is able to run native procedures, it is however pretty easy to create a mapping of physical memory into the EB address space and thus access all memory (in addition to being able to load Linux kernel modules, device tree overlays and such things).
On desktop systems (desktop Linux, MacOS, Windows) Engine BASIC is inevitably locked down; we're not in control of those systems, do not have elevated privileges and generally have no idea what the system's properties are, so we cannot allow unlimited access from Engine BASIC. If you access memory you're not supposed to, the operating system will kill the Engine BASIC process.
In theory, one thing that could be done on desktop and LT systems is to catch illegal accesses and return to the BASIC prompt instead of letting the OS reap the process. I am not at all convinced that that is a good idea, though. If something or someone tries to access random unmapped memory it's likely that something has gone wrong before that, potentially modifying Engine BASIC internal memory and leaving the system in an unstable state. The reliable way to deal with that would be to restart EB. Furthermore, handling segfaults from within a userland process is notoriously difficult to get right. In fact, this suggestion
https://feepingcreature.github.io/handling.html
basically looks like the exact thing that would get you flagged as malware by Windows. :)
So the bottom line is: This is a limitation that necessarily comes with running under a general-purpose operating system, and any workarounds are not likely to make things better.
Steps to reproduce:
enginebasic.exe
chdir"playmod
, press Enterrun"loader.bas
, press Enter|playmod 1
, press Enter