Matrix Brandy BASIC VI for console and SDL1.2: V1.22.8 released

for discussion of bbc basic for windows/sdl, brandy and more
Soruk
Posts: 793
Joined: Mon Jul 09, 2018 11:31 am
Location: Basingstoke, Hampshire
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.7 released

Post by Soruk » Thu Aug 13, 2020 7:07 am

Richard Russell wrote:
Wed Aug 12, 2020 10:48 pm
I'm not sure if this is a bug or a feature, or even if Matrix Brandy's 'virtualising' of MODE 7 to address &7C00 is officially supported (ARM BASIC doesn't do it AFAIK), but there's a difference in how it behaves compared with BeebEm as you can see below. I discovered this when experimenting with MODE 7 sprites for pixelblip:

beebem7c00.png brandy7c00.png
It is supported officially in Matrix Brandy, and you're right, it is not supported in RISC OS. It is noted that the behaviour is different to the BBC Micro, in that &7C00 always refers to the top left character cell even after scrolling, whereas the BBC does clever tricks with the screen memory wrapping to speed up text scrolling.

I see the difference here being that the BBC stores the unshuffled character, Matrix Brandy stores the shuffled character value when the high bit isn't set. I can fix this (not straight away as I'm away on holiday) but the array it's reading holds the values by the screen update code and GET(x,y) so I would rather not change that - most likely I'd shuffle in the read and write memory calls for that address block.
Matrix Brandy BASIC VI (work in progress)

User avatar
Richard Russell
Posts: 1658
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.7 released

Post by Richard Russell » Thu Aug 13, 2020 9:33 am

Soruk wrote:
Thu Aug 13, 2020 7:07 am
Matrix Brandy stores the shuffled character value when the high bit isn't set.
I guessed that's what was happening. I don't do that, because when I originally coded the MODE 7 emulation I was keen for it to behave as closely as possible to the SAA5050 hardware, which means that my memory buffer has to contain the same (7-bit) data as the chip would have expected.

In lieu of MODE 7 address virtualisation I'm thinking of adding a PROC_poke7 and FN_peek7 to my mode7lib library, which would take an address in the &7C00-&7FE7 range, convert it to the equivalent address in my buffer, and access the character there.

Soruk
Posts: 793
Joined: Mon Jul 09, 2018 11:31 am
Location: Basingstoke, Hampshire
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.7 released

Post by Soruk » Thu Aug 13, 2020 9:50 am

Richard Russell wrote:
Thu Aug 13, 2020 9:33 am
Soruk wrote:
Thu Aug 13, 2020 7:07 am
Matrix Brandy stores the shuffled character value when the high bit isn't set.
I guessed that's what was happening. I don't do that, because when I originally coded the MODE 7 emulation I was keen for it to behave as closely as possible to the SAA5050 hardware, which means that my memory buffer has to contain the same (7-bit) data as the chip would have expected.

In lieu of MODE 7 address virtualisation I'm thinking of adding a PROC_poke7 and FN_peek7 to my mode7lib library, which would take an address in the &7C00-&7FE7 range, convert it to the equivalent address in my buffer, and access the character there.
Maybe more cross platform, use it as a wrapper to GET(x,y) and could even be made portable to any MODE7-supporting platform using OSBYTE 135.

I'll look at doing the shuffle in the address virtualisation when I get back. While byte reads and writes will be easy, the separate word, float and string operations will be rather more complicated.... (Float operations in Mode 7 screen memory are rather pointless, but implemented for completeness)
Matrix Brandy BASIC VI (work in progress)

User avatar
Richard Russell
Posts: 1658
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.7 released

Post by Richard Russell » Thu Aug 13, 2020 11:29 am

Soruk wrote:
Thu Aug 13, 2020 9:50 am
Maybe more cross platform, use it as a wrapper to GET(x,y) and could even be made portable to any MODE7-supporting platform using OSBYTE 135.
The shuffling comes into play though: we don't want ?&7C00 or FN_peek(&7C00) to return the same code as GET(0,0) when one of the shuffled characters is there. And one would have to clear the text viewport and restore it afterwards.

It's even messier for the POKE case, because as well as the shuffling one would have to save the current cursor position and text viewport, clear the viewport, move the cursor to the location corresponding to the supplied address (hiding it so the move is invisible), write the character (taking care to ensure that it doesn't cause a scroll - how?), restore the text viewport and cursor position, then show the cursor (but only if it was originally visible)!

Admittedly poking into the buffer has its own problem: when do I update the displayed screen from the buffer? Doing it every time a character is written could be very slow and inefficient. I could hook into the ON TIME interrupt and do a periodic refresh, but what if the calling program is already using that?

Not straightforward!

User avatar
Richard Russell
Posts: 1658
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.7 released

Post by Richard Russell » Mon Aug 31, 2020 6:30 pm

As far as I'm aware, all versions of BBC BASIC which support the SYS statement provide both SYS "string" and SYS number equivalents of every function, where the numeric option is likely to be faster. For example, if I'm reading the documentation correctly, in Matrix Brandy one can use SYS &140000 instead of SYS "Brandy_Version".

The trouble with this is that one has to know the 'magic number' corresponding to each function, and that means searching through documentation (in BBC BASIC for Windows one can use SYS "GetProcAddress" to do this automatically, and in BBC BASIC for SDL 2.0 one can use SYS "SDL_LoadFunction", but these are highly platform-specific).

What I'd ideally like is a cross-platform way of doing this, i.e. some functionality which will take the string name and return the equivalent numeric, which would work in Matrix Brandy and in my BASICs. Is this something you've ever considered? Would you like to propose something (I'm not keen on it being a SYS call itself, because of the problem of finding a name for it that would be appropriate for all platforms)?

Soruk
Posts: 793
Joined: Mon Jul 09, 2018 11:31 am
Location: Basingstoke, Hampshire
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.7 released

Post by Soruk » Mon Aug 31, 2020 8:37 pm

Richard Russell wrote:
Mon Aug 31, 2020 6:30 pm
As far as I'm aware, all versions of BBC BASIC which support the SYS statement provide both SYS "string" and SYS number equivalents of every function, where the numeric option is likely to be faster. For example, if I'm reading the documentation correctly, in Matrix Brandy one can use SYS &140000 instead of SYS "Brandy_Version".

The trouble with this is that one has to know the 'magic number' corresponding to each function, and that means searching through documentation (in BBC BASIC for Windows one can use SYS "GetProcAddress" to do this automatically, and in BBC BASIC for SDL 2.0 one can use SYS "SDL_LoadFunction", but these are highly platform-specific).

What I'd ideally like is a cross-platform way of doing this, i.e. some functionality which will take the string name and return the equivalent numeric, which would work in Matrix Brandy and in my BASICs. Is this something you've ever considered? Would you like to propose something (I'm not keen on it being a SYS call itself, because of the problem of finding a name for it that would be appropriate for all platforms)?
RISC OS (yes, I know...) provides the system call OS_SWINumberFromString, and it is implemented in Matrix Brandy (and intercepted on RISC OS builds to recognise the internal-to-brandy calls). Note the double-comma used, as the system call to look up is sent via the second register (R1 in ARM parlance).

Code: Select all

>SYS "OS_SWINumberFromString",, "OS_Byte" TO A%: PRINT ~A%
         6
>SYS "OS_SWINumberFromString",, "Brandy_Version" TO A%: PRINT ~A%
    140000
>
Where I have implemented RISC OS calls I have kept the same number. The "SWI" name comes from the ARM SWI instruction.
Matrix Brandy BASIC VI (work in progress)

User avatar
Richard Russell
Posts: 1658
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.7 released

Post by Richard Russell » Mon Aug 31, 2020 9:17 pm

Soruk wrote:
Mon Aug 31, 2020 8:37 pm
Note the double-comma used....
ROFL! The principle that API functions return only one value must surely have been well established before RISC OS; how does that translate to C (I think I once knew because I've asked the question before)?

Anyway, it's the mess of having a different way of doing it on each platform that I'm hoping to resolve. Does ARM BASIC or Brandy currently use SYS as a function? If not, can I propose:

Code: Select all

number = SYS(function$)

Soruk
Posts: 793
Joined: Mon Jul 09, 2018 11:31 am
Location: Basingstoke, Hampshire
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.7 released

Post by Soruk » Mon Aug 31, 2020 10:01 pm

Richard Russell wrote:
Mon Aug 31, 2020 9:17 pm
Soruk wrote:
Mon Aug 31, 2020 8:37 pm
Note the double-comma used....
ROFL! The principle that API functions return only one value must surely have been well established before RISC OS; how does that translate to C (I think I once knew because I've asked the question before)?
The C call (quickly referencing how the Brandy code does it for RISC OS) takes a pair of int32 arrays (which can be the same array), which contain the values to be put in the registers, then the second array is populated with the register state afterwards. Strings are sent as pointers to the string. Many SYS calls take multiple parameters, and can return multiple values in the registers.
Richard Russell wrote:
Mon Aug 31, 2020 9:17 pm
Anyway, it's the mess of having a different way of doing it on each platform that I'm hoping to resolve. Does ARM BASIC or Brandy currently use SYS as a function? If not, can I propose:

Code: Select all

number = SYS(function$)
To the best of my knowledge and some quick playing in RPCEmu, no, ARM BASIC does not use SYS as a function. Matrix Brandy certainly does not. Before I get too carried away with attempting to implement this, is this function intended to be an analogue of the OS_SWINumberFromString call, so, for example,

Code: Select all

>PRINT ~SYS("Brandy_Version")
   140000
>
?
Matrix Brandy BASIC VI (work in progress)

User avatar
Richard Russell
Posts: 1658
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.7 released

Post by Richard Russell » Mon Aug 31, 2020 10:44 pm

Soruk wrote:
Mon Aug 31, 2020 10:01 pm
Before I get too carried away with attempting to implement this, is this function intended to be an analogue of the OS_SWINumberFromString call, so, for example,

Code: Select all

>PRINT ~SYS("Brandy_Version")
   140000
>
That's the idea, yes, but don't do anything precipitously; it's only a suggestion at this stage.

As I'm sure you can guess I'm looking at my latest in-browser edition of BBCSDL as a possible use case. It currently doesn't support SYS at all, because WebAssembly (unlike every other ABI I know of) checks function signatures at run time! It will abort if the function you are calling doesn't match the signature that the calling code is using (parameter numbers/types and the return type must agree), which completely breaks the way SYS works in my versions. :(

The only way I could support SYS in WebAssembly is by wrapping every single callable function in a uniform wrapper! Even with a limited repertoire of functions that would be a significant overhead, and of course it would mean I must do my own function-name lookup rather than relying on an OS API to do it (SDL_LoadFunction in the case of SDL 2.0). Hence thinking about how I might expose that name-to-number conversion to the BASIC programmer.

All speculative at this stage, but not having SYS available in the in-browser edition is a limitation I would like to address.

Soruk
Posts: 793
Joined: Mon Jul 09, 2018 11:31 am
Location: Basingstoke, Hampshire
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.7 released

Post by Soruk » Tue Sep 01, 2020 4:42 pm

Richard Russell wrote:
Mon Aug 31, 2020 10:44 pm
Soruk wrote:
Mon Aug 31, 2020 10:01 pm
Before I get too carried away with attempting to implement this, is this function intended to be an analogue of the OS_SWINumberFromString call, so, for example,

Code: Select all

>PRINT ~SYS("Brandy_Version")
   140000
>
That's the idea, yes, but don't do anything precipitously; it's only a suggestion at this stage.
Got it going - on a branch, not merged it into mainline yet...

Code: Select all

[soruk@CentOSvm8 ~]$ tbrandy

Matrix Brandy BASIC VI version 1.22.7 (Linux) 1 Aug 2020

Starting with 4194304 bytes free

>*HELP BASIC

Matrix Brandy BASIC VI version 1.22.7 (Linux) 1 Aug 2020
  Git commit c8381a0 on branch sys_function (Tue Sep 1 14:05:39 2020 +0100)
  Forked from Brandy Basic v1.20.1 (24 Sep 2014)
  Merged Banana Brandy Basic v0.02 (05 Apr 2014)
>PRINT ~SYS("Brandy_Version")
    140000
>_
Matrix Brandy BASIC VI (work in progress)

User avatar
Richard Russell
Posts: 1658
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.7 released

Post by Richard Russell » Tue Sep 01, 2020 5:41 pm

Soruk wrote:
Tue Sep 01, 2020 4:42 pm
Got it going - on a branch, not merged it into mainline yet...
Thanks, but I've had some pushback on this proposal at the discussion group (even Jonathan Harston seems to be against it) so although I still think it's a good idea I may be forced by weight of opinion to abandon it. Sometimes I think it would be nice simply to do what I want...

Aside: Many years ago I sought advice on what PLOT code to allocate to RECTANGLE SWAP ... TO. The obvious choice was 190 (PLOT 189 being RECTANGLE FILL ... TO and PLOT 191 being RECTANGLE ... TO) but a number of respondents pointed out that 190 wasn't strictly 'free' because on Acorn systems it did the same as 189 (or maybe 191, I can't remember which) so I mustn't use it. I dutifully followed suit and allocated a different number, but to this day I regret not having stood my ground!

User avatar
Richard Russell
Posts: 1658
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.7 released

Post by Richard Russell » Fri Sep 04, 2020 10:56 pm

Richard Russell wrote:
Tue Sep 01, 2020 5:41 pm
Thanks, but I've had some pushback on this proposal at the discussion group
I've now had a couple of positive responses to balance the negative (or neutral) ones, so I will plan to go ahead with this extension in my BASICs. It seems that some of the concern stemmed from a worry that adding a SYS function could somehow upset the SYS statement and hence cause compatibility to suffer, but of course the two are entirely independent (despite sharing a keyword) so there shouldn't be any issues.

What does your implementation do if you pass the name of a non-existent function? I'm leaning towards SYS returning zero rather than reporting an error, so that you can use it to test for the existence of a function without the inconvenience of wrapping it in ON ERROR. It may not apply to Matrix Brandy, but in BBCSDL I don't always know whether an API function exists because it can depend on the version of SDL2.

Soruk
Posts: 793
Joined: Mon Jul 09, 2018 11:31 am
Location: Basingstoke, Hampshire
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.7 released

Post by Soruk » Sat Sep 05, 2020 5:12 pm

Richard Russell wrote:
Fri Sep 04, 2020 10:56 pm
Richard Russell wrote:
Tue Sep 01, 2020 5:41 pm
Thanks, but I've had some pushback on this proposal at the discussion group
I've now had a couple of positive responses to balance the negative (or neutral) ones, so I will plan to go ahead with this extension in my BASICs. It seems that some of the concern stemmed from a worry that adding a SYS function could somehow upset the SYS statement and hence cause compatibility to suffer, but of course the two are entirely independent (despite sharing a keyword) so there shouldn't be any issues.

What does your implementation do if you pass the name of a non-existent function? I'm leaning towards SYS returning zero rather than reporting an error, so that you can use it to test for the existence of a function without the inconvenience of wrapping it in ON ERROR. It may not apply to Matrix Brandy, but in BBCSDL I don't always know whether an API function exists because it can depend on the version of SDL2.
At the moment an error "SWI name 'whatever' not known" - but I can get that changed. I'd prefer to return -1 in an error condition as 0 is a valid SYS call in RISC OS - OS_WriteC which is also implemented in Matrix Brandy internally, and on RISC OS builds it would call the OS implementation.
Matrix Brandy BASIC VI (work in progress)

User avatar
Richard Russell
Posts: 1658
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.7 released

Post by Richard Russell » Sat Sep 05, 2020 5:43 pm

Soruk wrote:
Sat Sep 05, 2020 5:12 pm
I'd prefer to return -1 in an error condition as 0 is a valid SYS call in RISC OS - OS_WriteC which is also implemented in Matrix Brandy internally, and on RISC OS builds it would call the OS implementation.
Fair enough. I will still return 0 because that's what the native GetProcAddress (Windows), SDL_LoadFunction (SDL2) and dlsym (Linux) APIs all return for 'non-existent function'. I don't think there can be any circumstances when a BASIC program will be using the new SYS function in a cross-platform fashion, because the function names are themselves OS-specific.

Interestingly, in Emscripten / WebAssembly small numbers are returned (although never zero) so it's more like RISC OS in that respect. For example in Windows:

Code: Select all

>PRINT SYS("SDL_SetHint")
1.4045096E9
>
but in Chrome:

Code: Select all

>PRINT SYS("SDL_SetHint")
       104
>

Soruk
Posts: 793
Joined: Mon Jul 09, 2018 11:31 am
Location: Basingstoke, Hampshire
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.7 released

Post by Soruk » Sat Sep 05, 2020 6:39 pm

Richard Russell wrote:
Sat Sep 05, 2020 5:43 pm
Soruk wrote:
Sat Sep 05, 2020 5:12 pm
I'd prefer to return -1 in an error condition as 0 is a valid SYS call in RISC OS - OS_WriteC which is also implemented in Matrix Brandy internally, and on RISC OS builds it would call the OS implementation.
Fair enough. I will still return 0 because that's what the native GetProcAddress (Windows), SDL_LoadFunction (SDL2) and dlsym (Linux) APIs all return for 'non-existent function'. I don't think there can be any circumstances when a BASIC program will be using the new SYS function in a cross-platform fashion, because the function names are themselves OS-specific.
OK, here we go.

Code: Select all

Matrix Brandy BASIC VI version 1.22.7 (Linux) 1 Aug 2020

Starting with 4194304 bytes free

>PRINT ~SYS("Brandy_Version")
    140000
>PRINT ~SYS("Nonsense_Value") 
  FFFFFFFF
>_
This is still on the branch, not yet merged to mainline. I need to check I haven't broken RISC OS first!

Edit: I may come up with an analogue for calls made via Brandy_dlcall - the look-up is always by name.

Edit 2: After some tweaking, this works on RISC OS too, so merged to mainline. I've kicked off a nightly rebuild.
Matrix Brandy BASIC VI (work in progress)

Soruk
Posts: 793
Joined: Mon Jul 09, 2018 11:31 am
Location: Basingstoke, Hampshire
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.7 released

Post by Soruk » Sun Sep 06, 2020 9:18 pm

Soruk wrote:
Sat Sep 05, 2020 6:39 pm
Edit: I may come up with an analogue for calls made via Brandy_dlcall - the look-up is always by name.
I have now done this, syntax is:

Code: Select all

>SYS "Brandy_dlgetaddr", "symbol" TO addr%%
>SYS "Brandy_dlcalladdr", addr%%, parm1, parm2....TO result%%
To suppress an error if the symbol isn't found, use the X flag: SYS "XBrandy_dlgetaddr", and the result will be -1 if the symbol couldn't be found.
Matrix Brandy BASIC VI (work in progress)

Soruk
Posts: 793
Joined: Mon Jul 09, 2018 11:31 am
Location: Basingstoke, Hampshire
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.7 released

Post by Soruk » Fri Sep 11, 2020 8:50 am

Soruk wrote:
Sun Sep 06, 2020 9:18 pm

Code: Select all

>SYS "Brandy_dlgetaddr", "symbol" TO addr%%
>SYS "Brandy_dlcalladdr", addr%%, parm1, parm2....TO result%%
A quick benchmark tests calling malloc() and free() show that calling it by name is about 20% slower than obtaining the numbers and calling by address (and using the numeric SYS call identifier).
Matrix Brandy BASIC VI (work in progress)

Soruk
Posts: 793
Joined: Mon Jul 09, 2018 11:31 am
Location: Basingstoke, Hampshire
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.8 released

Post by Soruk » Wed Sep 16, 2020 12:24 pm

I've released version 1.22.8 of Matrix Brandy BASIC.

Changes include:
- BASIC: Fix REM behaviour of DEF line.
- BASIC: Implemented SYS() function, somewhat in line with BBCSDL's version. In Matrix Brandy, this calls OS_SWINumberFromString, and also works under RISC OS.
- System: Implement two SYS calls for obtaining the address of a system call (Brandy_dlgetaddr) and to call it (Brandy_dlcalladdr).
- System: Implement OS_SWINumberToString. Note that on RISC OS this does NOT look up the Matrix Brandy internal calls.
- System: Fix bugs in string handling on OPENIN, OPENOUT and OPENUP (CVE-2019-14662 and CVE-2019-14663 reported on upstream Brandy), and a buffer overflow on handling command-line parameters.
- Display: Fix a subtle VDU23,16,1| bug. Thanks to Richard Russell for this.
- Examples: Telstar client updated with ANSItex BBS added.

Downloads including source code and binary builds for Win32, Win64, RISC OS 26-bit and 32-bit are on the Matrix Brandy website, and the git tree is over at Github.
Matrix Brandy BASIC VI (work in progress)

Post Reply

Return to “modern implementations of classic programming languages”