Page 2 of 3


Posted: 10 May 2020, 11:06
by marcelk
at67 wrote:
10 May 2020, 10:03

marcelk wrote:
10 May 2020, 08:56
I'm still scratching my head about the different behaviour of Boing on ROM v5a. How many channels does it expect to be active, 1 or 4?
It expects all 4 channels to be active, I'll get 5a into my ROM switcher and test it out on real hardware. I don't seem to have any Boing audio issues on 5a in the emulator, which is a little concerning.
I don't have 64K hardware at home, but I used dkholf's gtrun to test on my macbook. That one uses the loader/babelfish protocol on the IN port and Loader itself to pump files into memory. (Quite similar to Phil's javascript emulator). I believe yours does it in a somewhat different way. If so, that can explain differences.

My theory is that if Boing incorrectly starts with just 1 channel, that channel will be updated 4 times as often and sound 2 octaves higher. But the sample XOUT frequency doesn't change, because that is still every 4 scanlines. This might cause the aliasing effects that I hear. So for some reason it starts with 4 channels in ROM v4, but with 1 channel in ROM v5a. That's the hypothesis at least...


Posted: 10 May 2020, 16:06
by at67
It seems to me your theory is correct, everything is playing two octaves higher, i.e. on one channel at 4 times the sample rate on real hardware with both ROM's dev and 5a installed.

To throw another spanner in the works, it's not just Boing doing it, but ALL the .gbas examples with audio in them.

And now for the entire toolbox, even all my old .vasm/.gasm vCPU audio code is doing it as well, (on real hardware with the either of the above ROM's); so even Tetronis does it when uploading, but not when running from the menu.

And for that extra little kick, the GCL MIDI examples that I wrote don't exhibit this issue when running on real hardware. Is the Python code doing some extra magic when uploading to the Gigatron?

In my loader code that talks to real hardware, I am doing what I have always done which is simply:

Code: Select all

        sendCommandToGiga('R', line, true);
        sendCommandToGiga('L', line, true);
        sendCommandToGiga('U', line, true);
And then sending the actual segments as per the spec.

But when I upload GCL code to real hardware I do the following first:

Code: Select all

std::string command = "python3 -B Core/ -s interface.json \"" + filepath + "\" \"" + gclPath + "\"";


Posted: 10 May 2020, 17:06
by at67
After some more experiments, (I wrote the simplest gtBASIC and vCPU programs that I could, they both just print the value contained at address 0x0021).

Printing the contents of address 0x0021 for the following ROMs, gives:

Code: Select all

ROMv4:	0x3B
ROMv5a:	0x40
DEV:	0xF8
Something is resetting the lowest order 3 bits of channelMask, which is causing the audio issue for everything I have written except the GCL stuff.
I can't find it anywhere in any of my vCPU or GBAS samples and if it was my code, wouldn't it be doing it for ROMv4 as well? I am scratching my head over this one.

Adding this code to the start of Boing, (or any of the audio examples), bandaids the problem, but is obviously not a real solution.

Code: Select all

poke &h21, peek(&h21) OR 3


Posted: 10 May 2020, 17:45
by marcelk
I expect both v4 and v5a Loaders clear the channelMask bits. It seems that ROM v5a just doesn't turn them back on in all cases when safe, while ROM v4 does. I'll see if I can fix it in dev.rom first. Please don't try to workaround it for ROM v5a, it's not worth it.

Edit: a fix is now in dev.rom. It works in emulation but it isn't tested on real hardware yet.


Posted: 12 May 2020, 03:49
by at67
marcelk wrote:
10 May 2020, 17:45
a fix is now in dev.rom. It works in emulation but it isn't tested on real hardware yet.
I just tested 'dev.rom' on real hardware, it works perfectly now, cheers.

Ver 0.9.4B, (Beta):

- added 'romType' checking code to the initialisation phase of the gtBASIC runtime and a pixel blinker error handler.
- added '_codeRomType_' pragma that lets the programmer specify the minimum ROM to link the runtime against and the minimum ROM to check for during runtime initialisation, e.g.

Code: Select all

 ' possible targets are ROMv1, ROMv2, ROMv3, ROMv4, ROMv5a, (not case sensitive)
_codeRomType_ ROMv3
- linking against v3 or higher gives you new/faster graphics routines, fonts and sprites.
- linking against v5a or higher gives you CALLI calls and jumps which can substantially decrease code size and increase code speed, (depending on how fragmented your code is).


Posted: 18 May 2020, 15:07
by at67
Ver 0.9.6B, (Beta):

- Added a bunch of transcendental functions to the vASM assembler and BASIC compiler expression handlers.
- Added multi dimensional arrays for 16it integers, (up to 3 dimensions).
- Added the ASM and ENDASM keywords to the BASIC compiler, you can now easily embed vASM code in BASIC code.
- Added a simple example that shows how to inject vASM code into BASIC using the ASM and ENDASM keywords; 'Notes.gbas" in the audio examples directory.
- Added the DOWNTO keyword to the FOR NEXT syntax, this allows more opportunities for optimisations and better control to the user.
- Removed the auto step logic from FOR NEXT loops and gave explicit control to the user through DOWNTO.
- Fixed the LEN keyword to work for all types, including multi-dimensional arrays and gave it the '#' shortcut, e.g. size = #testStr$.
- Changed the STRCMP function to just CMP.

- Added the 'DEF FN <name>(<param1, param2....<paramN>) = <function>' command to the BASIC compiler, call the function with <name>(<params>). Any params missing from the function definition will be assumed to be globals.
- Added the 'ADDR(<array name>, <indexK>, <indexJ>, <indexI>)' function to the BASIC complier, that returns the address of individual elements of an array of 1 to 3 dimensions; use it when needing to peek/deek and poke/doke an array efficiently.
- Added the 'STR$()' function to the BASIC compiler, that converts integers to strings.
- Added the 'SGN()' function to the BASIC compiler, that returns the sign of an integer.
- Added the 'VAL()' function to the BASIC compiler, that converts strings to integers, (strings not containing numerics will return 0).
- Refactored the function name handling code, now there is much less of a chance of having name collisions between functions and variables.


Posted: 22 May 2020, 11:33
by at67
Ver 0.9.7B, (Beta):

- Added a time module with the following commands, 'TIME$', 'GET("TIME_H")', 'GET("TIME_M")', 'GET("TIME_S")', 'GET("TIMER"),
'SET("TIME_MODE")', 'SET("TIME_EPOCH")', 'SET("TIME_H")', 'SET("TIME_M")', 'SET("TIME_S")', 'SET("TIMER")' and more.
- Added the INIT command to the BASIC compiler, this command allows you to easily time slice or VBlank interrupt up to three
daisy chained routines TIME, MIDI and USER_PROC; (USER_PROC may be written in BASIC or vASM code, but it is highly suggested
to use vASM).
- Added the 'TICK' command to the BASIC compiler, this command is a general purpose version of MIDI PLAY, it is used to 'tick'
along time sliced modules, (TIME and MIDI), when your loop does not call any runtime routines, (it's only used for ROMv1 to ROMv4).
- Added proper VBlank interrupt handling for ROMv5a and higher, (using the INIT command).
- Added the 'RET' command to the BASIC compiler, this is used in place of 'RETURN" when the programmer does not desire the
embedded 'POP'; e.g. VBlank interrupt, vASM code, etc.
- Created a time.gbas sample that shows how to use the new TIME commands for ROMv1 to ROMv4.
- Created a vblank.gbas example that shows how to use VBlank interrupts with the TIME, MIDI and USER_PROC modules.
- Added two new versions of clock.gbas, clock2 uses the TIME module, clock3 uses the TIME module and VBlank interrupts as
well as having bonus sound.
- Changed all system variables to now contain underscores, e.g. 'SERIALRAW' is now 'SERIAL_RAW', etc; (this won't happen again!)
- Fixed some emulator issues with VIDEO_TOP and other system variables not being reset when fast loading.


Posted: 24 May 2020, 15:16
by at67
Ver 0.9.8B, (Beta):

- Added better handling of critical runtime routines to the BASIC compiler, so that they are loaded only when needed, (saves approx. 100 bytes per .GT1 file).
- Added string arrays, to the BASIC compiler, (1 dim only, 2 if you count the string itself), but the syntax is 1 dim only, e.g. DIM a$(10) makes an array of 11 strings. The ability to create CONST string arrays is not a thing, yet.
- Added the 'DATA', 'READ' and 'RESTORE' commands to the BASIC compiler; it supports int16 and string variables. Reading past the end of the data will NOT cause the read index to reset; so you will crash!.
- RESTORE has an optional index parameter so that you can restore to anywhere in the data list, (but no bounds checking, so it can crash).
- Added a simple shortcut for IF THEN GOTO <number> flow control, the GOTO is now optional.

P.S. I haven't received much in the way of bug reports or feedback, (i.e. zero); which must mean the code is bug free and I'm going to spend some time cranking out a few games and putting the compiler through it's paces.

*Edit* Reading past the end of data in a DATA stream WILL crash. I was using a zero terminator, but obviously that means you can't use zero as valid data, (I have no idea what I was thinking at the time when I wrote the code, but it's fixed now).


Posted: 25 May 2020, 07:23
by walter
I hope that will inspire others to also make some games!


Posted: 30 May 2020, 06:40
by at67
walter wrote:
25 May 2020, 07:23
I hope that will inspire others to also make some games!
Yeah that would be awesome.

Maybe this video will provide a little bit of inspiration for others:

If anyone is interested I might start a new thread that logs some of the tips, tricks, optimisations and hair follicle thinning scenarios that present themselves.

P.S. This work was/is inspired by Marcel's original Gobbler documentation found here: ... bbler.xlsx