Tuesday, 30 March 2021

Guest Post from Bitshifter: Fixing the Oldest and Nastiest Bug in Commodore BASIC

We again are able to enjoy another guest-post from Bitshifter, as he fixes and enhances the C65 ROMs for use on the MEGA65:

---  

The probably oldest and nastiest bug in Commodore BASIC

A huge part of working on the ROM for the MEGA65, which contains the resident part of the operating system and BASIC interpreter, is Debugging. Not counting the character sets, the source code, written in 45GS02 assembler, has about 30000 lines, separated into the modules kernel, editor, DOS, BASIC and graphics.

The debugging is necessary mainly for two reasons:
1) Programmers, developers, software engineers are humans.
2) A source code, that is not your own, is full of traps, side effects and assumptions, that one is not aware of.
Of course my own code is full of traps and side effects too, but I know them (at least for the next few months).

While working on the ROM, fixing Commodore bugs, optimising code to get free space for extensions and introducing new features (and sometimes new bugs), I write often some hundred lines of assembly code and make changes on existing code. Sometimes these changes seem to work perfectly, some result in crashes and freezes, because of errors and some only seem to work fine in my own test, but fail if a developer named „ubik“ demonstrates situations, which the code cannot handle.

Well, I’ll not tell a long story, how I debug, but come directly to the bug mentioned in the title. I tracked his existence down to BASIC 2.0 as used in the VIC-20, C64 and the early PET/CBM series and it seems, that it was never detected, documented or fixed.

It is related to temporary strings, the stack of descriptors for temporary strings, that has a size of 3, and the so called „garbage collection“, which in reality doesn’t collect garbage, but does a defragmentation of string storage.

Let’s look at an example:

10 V1 = 12345: V2 = 6789

20 A$ = RIGHT$(MID$(STR$(V1),2)) + RIGHT$(MID$(STR$(V2),2))


and let’s look into string memory, after the execution of these two statements:



The interpreter needed 6 temporary strings, these are the strings, which are followed by the two byte „garbage“ word in magenta, to create the resulting permanent string, marked here with the „back link“ word in yellow.


Each time, where a string is modified or new assigned, it gets a new allocation in string memory and the old string is flagged as „garbage“ by replacing its back link, which points to the string descriptor, by the garbage word, which is the length of the string, followed by $ff (The high byte $ff can never appear as part of a back link, because the highest address in string memory is $F6FF, therefore it is safe, to use this value as flag).


In programs with much string activity, the occupied string space, which grows from top ($f6ff) to bottom (top of array space), will be filled very fast and if there is no more space left for creating a new string, the call of the defragmentation routine is triggered. This starts at top of screen memory and copies all strings, which do not carry the garbage flag, to adjacent addresses, skipping the garbage strings. Doing this it is necessary, to update the string pointers of the descriptors. That’s the purpose of the backlink: After copying a string to the new address the back link is used to find the descriptor, and the two pointer bytes of the descriptor get the new address. Te descriptor can reside in scalar space, e.g. for a variable like AB$, or in array space, e.g. XY$(I,J) or it can be a temporary descriptor on the descriptor stack in the zero page. And this is, where the bug lurks.

The descriptor stack is 9 bytes long in the zero page and has therefore room for 3 descriptors. Additionally we have a stackpointer, which has four valid values for 0,1,2 or 3 descriptors in use. And we have a LASTPT called variable, which points to the last temporary descriptor, which was used to allocate a string. This is an optimisation tool. When a string is no more needed and it is the last string, that was allocated, the pointer to the used string memory can be updated by the length (plus 2 for the back link) instead of just flagging the string as garbage. This method can slow down the speed of filling the string memory somewhat and let’s the defragmentation happen less often.

This LASTPT is initialised at the execution start, alas only the high byte!




The low byte therefore has the value, that was either initialised at power up or has the value from a previous use. This use can for example be the loading of a program, because this involves string handling for the filename and therefore the use of the descriptor stack.


So it can happen, that the routine, that pops a value from the descriptor stack compares the current pointer with LASTPT, sees equality and decides not to flag the string as garbage, but to update the pointer to free string memory instead. This is an error, if the value of LASTPT is from a previous usage and was not set in the current statement. Alas, it will have no consequences in 99.9 % of the cases, because at the end of a statement all temporary descriptors are freed anyway.

The bug can drive mischief if following conditions meet:


1) A program with heavy usage of strings, which triggers the garbage collection / defragmentation frequently.


2) Statements with complex string operations, which need more than one temporary descriptor.


Then a really rare event can happen:

The garbage collection is triggered in the middle of a complex string formula with temporary descriptors on the stack. The garbage collection is aware of temporary descriptors and copies their strings too and updates the descriptors, but if one of the descriptors freed his string due to a false LASTPT comparison, his string is outside of the garbage collection area and will not be updated. And this causes strange things to be happen. The descripror has now a pointer, that does not point to a valid string. So the whole system of links and back links is corrupt. To make the bug hunting more interesting, this corrupt pointer often does no obvious harm until the next garbage collection, or the collection after it, but each will make the error worse, until back links appear in screen memory or strings dissappear or the computer freezes.


And all this because the setting of LASTPNT was not done with:

STA LASTPT

STA LASTPT+1


instead the first part, setting the low byte, was forgotten.

BTW, the highy byte is always zero, because the descriptor stack resides in the zero page, so this usage of the high byte is redundant.

I found this bug in all versions of Commodore BASIC, that I investigated, VIC-20, C64, C128, C65, MEGA65.

But it needed the „11 BASIC“ preprocessor/compiler of UBIK, to let the bug appear.

And it was very difficult to detect, because only huge programs with heavy string activity could activate it.


So the old programmer’s talk is true:

You can only find the penultimate error in a program!
There is always the ultimate error, that remained undetected.


Tuesday, 16 March 2021

Fixing initial problems discovered by DevKit owners

We now have 100 DevKits in the hands of their new owners, or very much on the way in the post. One of the purposes of this is to help us find and shake down bugs in the MEGA65... which have indeed started to flow in. So here is a summary of what we have fixed, and also some new things that have been implemented.

(Most of this was written several weeks ago, but I have had a busy patch returning to work, and getting ready to teach, so the draft has sat here for a while, almost finished. So I'm finally squeezing this out now that I have surfaced briefly for air.)

1. VIC-IV Raster Re-Write Buffer & Full-Colour Text Mode Bugs

There were several bugs identified in the VIC-IV's full-colour text mode and Raster Re-write Buffer (RRB) logic, which I have fixed.  

This includes using colour $FF in Full-Colour Text Mode, which now correctly uses the colour from colour RAM. If the VIC-IV has extended attributes mode set, then the colour is only 4-bit, but you have the VIC-III extended attributes, such as blink and underline available. If extended attribute mode is not set, then you instead have all 8 bits of colour RAM to select any colour from the palette.

2. Floppy Drive Was Not Working

People also reported that the internal floppy drive wasn't working:  First, when you configure it to be used, it seems to still use the SD card. Second, when you do select it from the freeze menu, it gives drive not ready or hangs when trying to read disks.

So to investigate, I have gone back to an earlier bitstream that is known to work with the internal drive.  I wanted to start here, firstly to make sure that the internal drive in my R3 system works.  Anton tested and found that commit 989d598 on the 138-hdmi-audio-27mhz branch was the last working commit for the internal floppy.

The only challenge right now, is I can't easily find any of the 1581-formatted disks I know I have hanging around the place.  I have found one little cache of disks, but the first disk I tried has the directory track erased, probably from a couple of years ago when there was a bug that had the write enable line set instead of cleared. So I can't easily test loading from that disk.  The second disk I found has the same problem.

Now, as I went through the disks, I used the magnetic flux histogram display to see when I had disks with valid data. Doing this, I made the chance discovery that HD disks are reading fine, just with the expected 1/2 distance between the flux inversions.  So I tried setting the floppy bitrate to double the DD rate to match the HD rate, and voila, I was able to read sectors from a PC formatted 1.44MB floppy disk (or is it an FD2000 disk? I don't have a PC to confirm). Either way, reading data from HD disks works.  A lovely side-discovery, but not particularly helpful to my current challenge. Also, we don't yet have an HD aware DOS for the MEGA65.

So back to my little cache of disks, and it looks like I don't have any that have valid directory tracks.  And as I don't have an old DOS PC hanging around, nor do we have write support on the MEGA65 floppy controller yet, I don't have a great way to debug this as easily as I would like.  I can at least test that the latest bitstream version shows the same behaviour, though.

Ok, so I have loaded the latest bitstream, and the first thing I notice, is that it doesn't seem to be enabling the floppy motor.  Well, the DOS doesn't, but if I write the correct value to $D080, the motor does go.  Nonetheless, a curious thing.  Okay, when I try to use the floppy test programme to display the histogram data, the motor doesn't start.  But if I clear $D080 and then write $60 to it again to start the motor and select the drive, it does start, and I start getting sectors being read. Once the motor is going, the disks read.  

So this is good progress: The problem is most likely that the motor gets stopped for some reason, or the motor start signal is otherwise ignored. 

Next challenge is that my oscilloscope is 700km away, so I can't probe the floppy pins to see if the drive thinks it should stop because of some invalid combination of signals, or whether the VHDL has some change in it that stops the motor.  I know that the drives can stop themselves, because I accidentally discovered this when toggling the /DENSITY select line, and noticed the motor stops until you release the /MOTOR and /SELECTA lines, and then assert them.

Around the time of the commit that corresponds to when this problem started, I plumbed the "drive B" control signals onto the floppy interface. So I am suspecting that this might be all interelated somehow. But again, the drive activates and spins when I write $60 to $D080.  So there must be some funny sequence in the that the DOS in the ROM does, that is upsetting things. Again, not sure if this relates to other signals on the floppy interface being twiddled and upsetting the drive, or if it is being cancelled by some internal logic in the floppy controller.

Yup -- that's the problem: The ROM toggles bit 2 to work around some bug in the real C65's floppy controller. The MEGA65's floppy controller has a different bug that causes the currently selected drive to sometimes not be considered, instead using the previously selected drive.  This combined to cause the MEGA65 to think that the ROM DOS was de-selecting the drive when it was actually selecting it.  The fix required changing only a couple of lines.

3. Floppy/SD Card Select Was Not Working In MEGA65 Configure Utility

The other problem with the floppy, was that selecting to use the internal drive in the MEGA65 Configure programme from the utility menu has no effect: It always uses the SD card. But configuring it until next reset using the freeze menu does work.  Here I suspect the problem is that we are setting the wrong register bits in the hypervisor when it applies the settings, as the drive selection logic did change a while back... Except that it all looks like its correct: Byte four of the config sector gets $01 when set to use the real drive.  The code in the Hypervisor stores that into $D6A1, and it seems that nothing else touches that register... except mounting D81 disk images.  That's almost certainly the problem: We need to NOT mount D81 disk images if we have set $D6A1 to use the internal drive.

4. ASW Instruction Did Not Set Carry Flag

Totally unrelated, someone else also discovered a bug in the ASW instruction, where bit 15 of the operand was not being copied into the C flag.

5. Q-Family Instructions Would Mess Up Following Instructions

On the topic of CPU bugs, we also discovered that the Q family of instructions that use the A,X,Y and Z registers together as a virtual 32-bit register were causing trouble: The flag to write 32-bits of data was not being cleared in these instructions, so all following normal instructions would keep writing multiple bytes, until a single-cycle instruction was encountered. Needless to say this caused various forms of hilarity when a couple of developers tried to use the Q instructions.  A big thank you has to go to mdf200 for working out various clues as to the cause of this problem, including realising that single-cycle instructions were implicated. 

6. Freeze Menu Bugs

Then we had some bugs with the freeze menu not resetting certain VIC-IV registers, resulting in a garbled freeze menu display. 

7. 16-Colour Sprite Mode Glitches Fixed

16-colour sprites had a problem where transparent pixels were only transparent if there were no other sprites behind them. If there was another sprite behind, then Weird Things(tm) would happen.

8. MEGA65 Defaults to PAL if no valid configuration sector is found

Previously it would default to NTSC for better monitor compatibility, but the MEGA65 Configure routine would show that it was set to the default setting of PAL.  This inconsistency was very confusing, and has now been fixed through the introduction of default-to-PAL, and a once-only on-boarding screen that appears in NTSC to allow users to select their preferred video mode.

The Freeze Menu now follows the choice of PAL or NTSC, instead of always being NTSC, which avoids the annoying "resyncing monitor" behaviour that would previously occur. 

9. Fix the use of alternate palettes in Full-Colour Text Mode (FCM)

The logic for switching palettes was fault, and has been fixed.

10. Audio DMA can now interrupt normal DMA operations

This makes it possible to use the DMAgic controller while play DMA-based audio, without causing problems for the audio playback.

New Features

There were also a few small improvements:

1. You can now trigger raster interrupts based on the horizontal raster beam position. Should be handy for horizontal sprite multiplexing.

2. The colour RAM contents is now used in 16-colour text mode (where each pixel is represented by a nybl, and the characters are thus 16 pixels wide) to provide the upper four bits of the colour of each pixel, with the nybl from the character data providing the lower four bits. 

3. The Raster-Rewrite Buffer (RRB) now provides a mechanism to do smooth vertical positioning of characters by setting the trim-pixel values during a GOTOX token. Those bits instead get read as a a Y offset for Full-Colour Mode characters, effectively adding 8 x value to the address. This removes the single annoying limitation that the RRB suffered previously, in terms of using it to display moving sprite-like objects.

4. Various improvements to the MEGA65 Configure programme.

5. Bitplanes can now use memory other than in banks 0 and 1, although they must all still reside in the same 128KB region, that must be aligned on a 128KB boundary. This is to allow a modified BASIC 10 ROM to support 256 colour screens while still having close to 128KB of RAM available for BASIC programmes and variables.

6. The Raster-Rewrite Buffer (RRB) now supports more effective controls for placing sprites in front of, behind, or between layers of graphics rendered using the RRB.

7. The MEGA65 now has an option to enable "CRT scanline emulation" via bit 5 of $D054. The on-boarding process now asks users if they would like this enabled. The result feels much more like using an original C65:

8. The dip-switches on the main board can now be read from the MEGA65. They are connected to the MAX10 FPGA, not the main FPGA.  This was a bit of work to get happening.  My wandering notes as I went through this process follow.

We have only 3 lines to connect the two FPGAs for normal communications.  One of those by default is used to communicate the reset button status from the MAX10 to the main FPGA (like the dipswitches, it too is connected to the MAX10).   That said, we can do a bit of skull-duggery to use it as a 3rd communications line.  

In theory, we can also use the FPGA_DONE pin of the main FPGA to communicate to the MAX10 FPGA. I had wanted to do this, but for some reason, I don't seem to be able to control it, even though I have put the right stuff into the VHDL to do so.  This is a bummer, because with four lines, I could do a nice high-speed link between the two FPGAs with TX, RX, CLOCK and SYNC.  This would allow low-latency control of the 12-pin J21 header (also connected to the MAX10), as well as reading the dip switches.  The reason we need to provide clock information, is that the clock speed of the MAX10 when using its internal oscillator is quite unstable: It can be anywhere between 55MHz and 116MHz according to the data-sheet. This means that a simple UART won't work, because the apparent baud rate will vary by a factor of two -- and UARTs would have to be much slower, anyway.

So we have just three lines. We could still do an SPI-like protocol, as at least that way we can still get higher speed.  But we don't need a lot of the complexity of SPI.  But having an explicit clock will make it much easier to do, so we probably can't avoid using one of the three lines for that.  We can at a small cost add a sync mechanism into the clock. As we know some reasonable bounds for the difference in clocks of the two FPGAs, we can create a mechanism where the clock from the Xilinx FPGA is used to drive the receiver logic, but then also be separately be monitored by some logic clocked by the MAX10's internal clock to detect if the clock doesn't tick for a certain period of time, that it signals a sync.

As not everyone will have an Arrow programmer on hand to update their MAX10 bitstream, I will also implement a backward compatibility check, where we check for the old behaviour of the reset signal from the MAX10 FPGA.  

So we have things working with the new MAX10 programme and new bitstreams, including the reset button, and reading the MAX10 programme version.  However, if we use an old bitstream with the new MAX10 programme, it gets held in reset. So we need a solution for that. 

In the MAX10 code, the line previously called FPGA_RESET_N, i.e., and active-low reset out signal from the MAX10 to the main FPGA, is now the XILINX_SYNC output from the main FPGA into the MAX10. That is, its direction has reversed, which makes backward compatibility a bit of a pain to achieve.  We are now also using XILINX_TX (transmit from main FPGA into the MAX10) and XILINX_RX (transmit from the MAX10 into the main FPGA).  Thus the better way to have this protocol, would be to swap the XILINX_SYNC and XILINX_RX lines, so that when an old main FPGA bitstream meets a new MAX10 programme, the MAX10 is still sending on the line that the main FPGA expects to see the reset signal.  Thus if we don't see the clock signal from the Xilinx FPGA, the MAX10 programme can go back to the old behaviour of having the FPGA_RESET_N signal (which will now be the XILINX_RX signal) follow the state of the reset button.

So the three pairs of signals we have between the Xilinx and MAX10 FPGAs are, together with their signal names from the current bitstream builds for each, that have the old reset button protocol working with old MEGA65 bitstreams:

Xilinx K16 (MAX10_RX) -> MAX10 L11 (XILINX_SYNC)

Xilinx L16 (RESET_FROM_MAX10) -> MAX10 K11 (XILINX_TX)

Xilinx M13 (MAX10_TX) -> MAX10 J9 (XILINX_RX)


The XILINX_RX signal on the MAX10 must be correct, because this is the pin on which the old reset button protocol operates, and we know that this is working.

So this means we probably have the MAX10 L11 and K11 signals switched. So we should have it instead like this:

Xilinx K16 (MAX10_RX) -> MAX10 K11 (XILINX_TX)

Xilinx L16 (RESET_FROM_MAX10) -> MAX10 L11 (XILINX_SYNC)

Xilinx M13 (MAX10_TX) -> MAX10 J9 (XILINX_RX)

Swapping those at least gets the protocol running again, based on the MAX10's LEDs. However, neither the reset button nor the MAX10 version data is visible on the MEGA65 core, so something must still be messed up.

So it looks like we should instead switch K16 and M13 on the MEGA65 side, because the max10_rx and max10_tx signals are actually backwardly labelled. 

Indeed, fixing that fixed it, and it now works as expected. So that one's done, now, too.

Next stop was to make it possible to enable/disable digital audio on the digital video output.  This is because some DVI monitors don't display a picture if HDMI-style audio is provided. So we have disabled this by default.



Wednesday, 3 February 2021

Guest post from Bit Shifter: Improving the C65 ROMs

Today's post is from Bit Shifter, who is working on improving the original C65 ROMs. Best if I just let him explain...

The C65 ROM: Pick up the thread after 30 years. 


 

I watched the MEGA65 project very early and wondered, if it would ever happen, that this machine would see the light of day. But I got the impression, that this is a promising project and offered my assistance. I was accepted and wrote the User’s Guide chapter on BASIC 10, mainly using information from C128 manuals, preliminary C65 documentation and experimenting with the XEMU emulator from Gábor Lénárt. Soon I found out that the existing ROM images that were available thanks to Bo Zimmerman, were in a preliminary state. There were unimplemented commands and functions, bugs inherited from the BASIC 7 of the Commodore 128, which was obviously used as base for the BASIC 10, and a graphics library that was about 80% completed. Also there were ROM images for different types of hardware, programmed while hardware changes in the development of the C65 happened, like the DMA controller or the floppy controller.


Then there was the day, when I got a MEGA65 prototype loaned from the MEGA65 team and I could really program this machine. Soon I found out, that the existing firmware, that was loaded as ROM image from the SD card, could barely be used beyond using some simple programs and demos. The C64 mode was fine, but I wanted to use the power of the MEGA65. This could be done in machine language, so I wrote my first MEGA65 program, a Z-interpreter for playing stories of the legendary Infocom archive, like Zork, The Hitchhiker’s Guide To The Galaxy, The Leather Goddesses Of Phobos and many more. This worked out very well and I turned my attention back to the incomplete BASIC interpreter. I knew, there was the open ROM project, which promised to deliver an advanced BASIC interpreter, but the time schedule was such, that I didn’t want to wait. So I self assigned the job of finishing the BASIC interpreter to myself. My motivation was not to just finish the interpreter for the C65. I found it more challenging to unleash the power of the MEGA65 and decided to use the new features of the MEGA65, which could in many cases overcome the insufficiency of the C65. The task can be described like:

1) Fix bugs 

2) Finish incomplete code

3) Implement planned, but missing commands and features

4) Change the memory map, to take advantage of the RAM capacity of the MEGA65

5) Exchange awkward code, that was necessary due to a bad bank switching design

6) Optimise existing code: faster and shorter alogrithms

7) Use the hardware multiplication and divison unit of the MEGA65

8) Implement convenient features, like the DOS wedge

It would be nearly impossible to work on these tasks without the original source codes as a starting point, but thanks to Bo Zimmerman, who probably hosts the largest arvchive of CBM related technical information, ROM images and software, I could find the necessary source files of Dennis Jarvis, one of the former C65 developers.

Looking at the source, I saw the next obstacle: They were written in an assembler format, that none of the currently used assemblers could understand. Some of the issues were:

1) No different mnemonics for short and long branches, the assembler has to figure out

2) Local label of the form nn$, which can be reused after each normal label

3) Octal constants are prefixed with @, not the usual & as in other assemblers 

4) Use of 65GS02 mnemonics, which were not 65C02 compatible and unknown to many assemblers

5) Different form of pseudo-ops for many data declarations

After some research I found out, that the sources were 1991 assembled, using the BSO (Boston Systems Office) assembler, which was a cross assembler, running on a DEC-VAX with the operating system VMS. This assembler (and the hardware) isn’t available anymore.

Fortunately I had written my own 6502/65C02 assembler some years ago, in order to write programs for a variety of 6502 powered retro computer. So I enhanced the assembler, to support all features of the MEGA65 CPU 45GS02, which includes all of the C65 CPU, but added even more instructions and address modes. Then I introduced a compatibilty mode, which could handle all of the particularities of the BSO assembler. (Funny that I had named my assembler BSA many years ago)

Fortunately the old source archives included besides the source files, the list files, that were the result of the assembler run too and these included the object code in form of hex numbers.

So I could test my assembler by assembling the old source files and comparing the result with the listings. This helped to iron out all issues and finally the output of the BSA was bit identical to the object code, extracted from the list files of the BSO from 1991.

After all these preparations I could finally start to continue the development of the BASIC interpreter and the graphics library by using my self built toolchain. So far I did following changes or implementations:

1) Memory usage


C65: bank 0: 0000-1fff : 8K : system and basic internal variables, zero page, stack, buffers, etc.

C65: bank 1: 0000-1fff : 8K : DOS variables and buffers

C65: bank 0: 2000-7fff : 24K : BASIC program text

C65: bank 1: 2000-7fff : 24K : BASIC variables

C65: bank 0: 8000-ffff : 32K : graphics RAM

C65: bank 1: 8000-f7ff: 30K : graphics RAM

C65: bank 1: f800-ffff: 2K : colour/attributes RAM

MEGA65: bank 0: 0000-1fff : 8K : system and basic internal variables, zero page, stack, buffers

MEGA65: bank 1: 0000-1fff : 8K : DOS variables and buffers

MEGA65: bank 0: 2000-ffff : 56K : BASIC program text

MEGA65: bank 1: 2000-f7ff : 54K : BASIC variables

MEGA65: bank 4: 0000-ffff : 64K : graphics RAM

MEGA65: bank 5: 0000-ffff: 64K : graphics RAM

MEGA65: bank 1: f800-ffff: 2K : colour/attributes RAM

Summarising:

The C65 had 24K free for program and variables each

It could use at maximum one 320 x 200 screen with 7 bitplanes (128 colours) or a

640 x 400 screen with 2 bitplanes (4 colours)

The MEGA65 with the new memory map can use 56K for BASIC program and 54K for variables and use 128K for graphics, enough for a hires screen 640 x 400 with 4 bitplanes (16 colours) or two 320 x 200 screens with 8 bitplanes (256) colours.

2) BUG fix


There was a bug in BASIC 10 inherited from the BASIC 7 of the Commodre 128:

Imagine following code snippet:

100 IF A=1 THEN PRINT "A=1": ELSE BEGIN

110 PRINT "A # 1":BEND: PRINT "SEE"

Executed on a C128 or C65 this code will print the text "SEE" only, if the ELSE branch is executed, but will be ignored, if the TRUE branch is taken. So it’s clear, that the PRINT "SEE" should be executed in any case, because it’s outside the IF-THEN-ELSE statement.

This one was easy to fix.

3) Code optimisation

Then there were so many code parts, especially in the graphics library, that were unnecessary long. I could reduce the code size of the graphics library already from 12K to 9K by using loops and tables to replace long linear and repetitive code sequences. The new won space may be used for enhancements.

4) Bank access

The C65 has an awkward memory management. It can combine many different 8K segments from ROM and RAM, but there is no easy way for a program running in a bank, to access data from a different bank. The solution for the C65 was, to use DMA transfer. So even for fetching a single byte from another bank, for example getting the next character from the BASIC source, it was necessary to build a 12 byte long list describing the desired DMA transfer, trigger the DMA controller and then reading the byte. What a tremendous effort to retrieve just one byte.

The MEGA65 has here a brilliant and easy to use solution: An address mode, that uses 4 zero page bytes to construct an effective 28 bit address, which is sufficient to access the complete 256 MB address space of the MEGA65. So you can uses instructions like:

LDA [ZP],Z STA [ZP],Z CMP [ZP],Z etc. to access any address in the MEGA65.
Replacing some of the DMA calling codes with the 32 bit indirect access already increased the execution speed of BASIC by more than 30%.

5) Hardware multiplication and division

The MEGA65 has an easy to use hardware math unit.

A mulitiplier performs a 32 x 32 bit multiplicazion in just 1 cycle.

A division unit performs a 32 / 32 bit divison in 16 cycles.

So far the multiplier is used to speed up the floating point multiplication in using the hardware to multiply the mantissas of both factors. This increased the speed by a factor of more than 2.2.

6) Convience Enhancments

Finally I made my dream from the C64 days come true and make the BASIC more convenient by implementing very small features, which I like nevertheless much.

How often did it happen, that one hits return, while the cursor is on the line with the READY. Prompt and see the ?OUT OF DATA ERROR, because the interpreter tries to read data for the variable Y. Now you can hit RETURN on the READY. line and nothing happens.

Also the DOS wedge, using the shortcuts @ / ← $ for disk command, load, store and directory is implemented now.

The line numbers can now use the full 16 bit range from 0 to 65535.

Lines can be indented with spaces, which are not swallowed by the interpreter.

And there is much more to come.

Finally it’s interesting to read in the old sources.

You find gems like [….] is an asshole (I’ll not repeat the name here).

Or: OH-OH I programmed a recursion, Dr. Ja-Ja warned me about this.

In fact, that is one of the code pieces which have to be fixed.

Nesting BEGIN … BEND compound statements is dangerous and can crash the machine.

Or the funny code, where a 16 x 16 bit multiplication is called, in order to multiply an index with 1.5, which can be done with only 4 simple instructions instead.

So far my text on working on the MEGA65 kernel and BASIC software.

The text became longer, than expected, I hope, I didn’t bore you, but if you read this sentence, you read it probably completely.

Best wishes,

Bit Shifter



Tuesday, 5 January 2021

ZX-Spectrum on the MEGA65

From the beginning, it was our hope and intention that the MEGA65 would be able to run multiple cores, allowing it to be many different computers and consoles.  This is why we built the whole Flash Menu framework, that allows a user to select which core to load when powering up by holding down the SCROLL LOCK key when powering on, like this:

 

We already have an Amiga core being ported, although it is not finished, while we work out some issues with our HyperRAM controller.  But in the meantime, Sy2002 has managed to largely port a Spectrum core from the ZX-Uno project, as you can read below.  So this is a really nice achievement, as it means that you can run the two main camps of 8-bit  systems on the MEGA65: The Commodore 64/65 and now the ZX Spectrum family -- all with our really nice keyboard and case for a very authentic experience.

We are still working on the bootstrap ROM, but it already gives you the ability to select which exact model you wish to operate as:

The ZX-UNO is designed to run mainly as Sinclair ZX Spectrum machines (48K/128K/+2a)

with DivMMC support (MMC/SD/SDHC storage), ULA+ (multi-color, high resolution graphics),

turbo sound (double AY chip), among other things.

 

The ZX-UNO hardware, software, logo and concept have been created by the ZX-UNO TEAM

(Superfo, AVillena, McLeod, Quest, Hark0) and released under Creative Commons Attribution-

ShareAlike Licence.

 

So thanks to their hard work, you can already have a lot of Spectrummy fun with a MEGA65, as the following images show:






 



The ZX-UNO being completely open source matches the spirit of the MEGA65 perfectly!


Saturday, 12 December 2020

Announcing the MEGA65 Developer Support Programme

Howdy folks! We thought it was time to (very slightly) formalise our MEGA65 Developer Supporter Programme (M65DSP).  We have already been informally finding solutions to help people get access to MEGA65 development hardware, for folks who don't have an official DevKit.  We now want to make it clear that we are keen to support folks who would like to develop software, games, tools, documentation, promotion or other goodies for the MEGA65 platform.


What are the eligibility requirements for the MEGA65 Developer Support Programme?

Unlike some developer programmes, we don't require you to have a promissory letter to the value of US$4.7M, a private island or a double-degree in rocket science and underwater basket weaving! All you need to do is to have a clear idea of what you intend to do or to create, and explain that to us.

To be clear: If you can't afford any hardware, this is not necessarily an impediment. We have some R2 PCBs, Nexys4 development boards and other bits an pieces that we can potentially make available.  But if you are able to afford your own development hardware, that will make it easier for us to support more developers, and thus help even more cool goodies come out for the MEGA65 sooner.

I'm convinced. So where and how do I sign up?

You have several options:

1. Carry your One Ring of Windows 98SE Installation (CD or DVD) to the summit of Mount Doom and throw it into the Schicksals Kluft, and await pickup by the first cooperative oversized avian.

2. However, recognising the difficulty of definitively locating Mount Doom on modern maps, you may instead simply fill out the contact form on the MEGA65 website, explaining that you would like to be considered for the MEGA65 Developer Support Programme, and what you would like to make for the MEGA65 (or if you prefer, volunteering to work on whatever we think is most needed at the time).

3. Attempt to convince an existing DevKit owner to temporarily or permanently part with their MEGA65 DevKit in return for some object of mystical value*.

4. Move house to live conveniently near to a known MEGA65, and dig a secret tunnel that allows you to access the MEGA65 when its owner is sleeping.  Be sure to mend and polish the shoes of the owner, so that they think it's just fairies, and don't become suspicious.

5.  Enrol in a PhD programme related to the MEGA65 or MEGAphone, and maybe even get paid to do awesome 8-bit goodness for three years.  In this post-COVID world, it probably isn't even necessary to move to Adelaide to do this (although we have basically eliminated COVID, and have awesome beaches and stuff that we are all free to use again). In case you think I am joking about this, I'm not: There are opportunities to study the education of students in CS using 8-bit systems, the development of resilient and secure communications systems around the MEGAphone hand-held, including hybrid space-terrestrial mesh networks, FPGA-based cryptography and all sorts of other fun and interesting things.

* We cannot guarantee success of this method.  We recommend MEGA65 owners verify the actual value and function of such mystical value before accepting a trade. The origin of any Palantíri should be subjected to particularly thorough scrutiny.

I'm not convinced, yet. What should I do?

Hmm.... Look closely at this watch swing on it's chain... Closer... Deeper...

Tuesday, 1 December 2020

DevKits are appearing around the world!

 It has been a sheer delight the past few days, as people have begun receiving and assembling their MEGA65 DevKits, and even started to create things using them!

In case you missed the action, there are now several first impressions / assembly videos up on youtube:








That first one is from Shallan, who does regular twitch feeds, including writing C64 games -- and now that he has a MEGA65 DevKit, on coding for the MEGA65.  He has already made his own 256-colour image loader, and started working on using the MEGA65's Raster Rewrite Buffer (RRB) to do a thousand hardware drawn 256-colour moving bullets over the top of a 256-colour background, and using only about 10% of the CPU to do it. You can see what a busy 320x200 screen with 1,000+ blobs looks like here:

 

You can hardly even see the background.  This is just one of many uses of the Raster Rewrite buffer -- so expect to hear a lot more of "RRB" being thrown around.

So hop onto Shallan's live twitch feeds or playlist of videos he posts after for the low-down on how to make the MEGA65 do amazing things.

There is also plenty of action elsewhere. For example, there is a CSDB C64 sprite graphics competition, offering a MEGA65 DevKit as a prize, thanks to the generosity of the community!

Anyway, we are just so happy that people are having a great time with the MEGA65, and re-experiencing that joy of Christmas 1982 of receiving their first C64 (or VIC-20 or other home computer), and then diving in to explore the machine, knowing that they were entering exciting and uncharted territory.  

One great point of satisfaction for everyone involved, is how amazingly nice the keyboards have turned out.  We put a huge amount of effort into making the best possible keyboard for the MEGA65 -- from Cherry MX mechanical keys to the double-shot top and front-marked key caps and space bar long enough to land a fully laden A380. And so it has been sheer delight to see people fall in love with the keyboard, and experience sitting down at a device that _is_ a brand new 8-bit era computer for the first time in decades.

I am sure that there will be lots more interesting videos and material coming out, as people get their DevKits setup, and start tinkering.  We hope you enjoy the journey as much as we are!