Tuesday 28 July 2020

MEGA65 Emulator and Tools Live ISO

Snoopy, one of the MEGA65 enthusiasts who frequents forum64 has done some amazing workk, making a live ISO image containing LGB's MEGA65 emulator, the MEGA65 documentation and various other goodies.  You can follow the thread directly here, but for your viewing convenience, and with Snoopy's permission, here's the low-down:

As mentioned and discussed in this thread, I have written some toolscripts, configured them for suitable use and build now a new iso image for USB stick or DVD which let you boot a live system based on Xubuntu for an easy use of xmega65 and xc65 of the Xemu emulator.

Because of potential copyright issues the original C65 ROM is not included in the live system.

The live system offers you after booting the options to load the system ROM file (has to be named MEGA65.ROM) from a connected storage medium (USB stick, SD card, ...) or to download the ROM file from the website 'zimmers.net' and patch it automatically to the latest C65 ROM patch "AH". The patch "AH" fixes some issues of the original ROM (e.g. more free BASIC10 memory and a work around for the "disc change bug"). Because the live system is read only, you have to repeat this procedure after every new start of the live system.


Please note, if you do not load or download the C65 ROM you can use xmega65 only with the included OpenROM from the Mega team.

The live system also includes the "Mega65 book" manual (the version from 18th of July 2020 with 734 pages) which can be updated to the latest available version with the "Update MEGA65 book" icon on the desktop. Because the live system is read only, you have to update the MEGA65 book after every new start if necessary.

Also included are a few disc images (read only, because it's a live system!), which you should copy first to an external USB stick or SD card. So you could use them also for saving data onto it with the emulator. In Xemu you can attach a disc image with a right mouse click.


The Xemu live system offers you a Xubuntu (64bit) system with English system language and four selectable keyboard layouts:

- English (US) (as default)

- German

- Hungarian (greetings to LGB-Z for his great work on the Xemu emulator!)

- Italian (there are some great C65 fans in Italy)

Please note that the Xemu emulator only uses English keyboard layout, regardless which system layout you have chosen.

You start the Xemu emulator with a click on the appropriate icon on the desktop:

'xmega65' for MEGA65 emulation:


'xc65' for C65 emulation:

Also included in the live system are some "everyday" programs like LibreWriter, LibreCalc, Leafpad, Calculator, GHex, Geany, Midnight Commander (MC) and the latest version of Firefox (Firefox 78.0.2 - 64-bit) with the most important bookmarks. :D


Handling of the iso file:

The iso image has to be copied to an USB stick (at least 2 GB big) or burn onto a DVD. That should be no great problem in most cases. To burn a DVD you can use nearly every CD burning program. To copy the iso bootable to a USB stick you can use an image writer tool (e.g. "ISO to USB" for Windows or using "Startup Disk Creator" with Linux/Ubuntu).

After done this, plug the stick into the PC or the laptop and turn it on ... and wait until it's ready. Nearly every computer which can handle 64bit systems and can boot from external stick should be good enough for the live system. I have tested it positive with four different computers (even an old "Samsung NC10 plus" netbook works).


You can also use the iso file within a virtual environment as e.g. Virtualbox. But it will be more or less slower as using a real computer.

Please note that every change you made to the system or any file in the live system will be lost after turning the computer off. You have to copy files and disc images, you wanted permanently save and change, to an external medium (usb stick, SD card, external harddrive, ...) and save the data on them, because the files on the live system are read only.

If you need the system passwords, there are:

user: mega65

password: mega65

root password: mega65

You can read the password infos also by clicking the desktop icon "Read me".

Installation of the live system onto your computer:

If you select "Boot system installer" at the very first boot screen of the iso file, you can install the live system onto your computer. Please follow the instructions shown on the screen.

Please note that my main topic was the live system, so I don't used much time for the installer and possible issues with it. Maybe it works on your computer, maybe not. ;)

Other boot options are:

- "safe graphics mode" (try this if your computer has some graphics trouble with the live system)

- "debug mode" (shows much more details during booting for debugging what's going wrong if something's going wrong)

You can download the iso file "xemu_live_system_20200724.iso" (1,72 GB) via https from this filehoster (mega.nz) link:

xemu_live_system_20200724.iso

Don't blame me for possible slow download speed or other traffic limitations, it's up to the filehoster. :zeig:

If you want to be (nearly) sure, that you have downloaded the correct and original iso file, you can use the md5sum for control. With Windows you can use e.g. the freeware "MD5 Checksum Tool" and in Linux e.g. the shell command md5sum -b xemu_live_system_20200724.iso for it.

The md5sum of the iso file 'xemu_live_system_20200724.iso' is:

4e4c845f21ed9f1ea0e48bab3dcb04c7 *xemu_live_system_20200724.iso

If your downloaded iso file has a different md5checksum, something has gone wrong. :achtung

I have checked the content of the ISO for possible copyright issues to the best of my knowledge. If anyone have legal issues with that live system, please contact me and I will delete the iso file from the filehoster as soon as possible!

To all other guys: Have fun with the Xemu live system!



Friday 17 July 2020

ACME Support for the MEGA65's 45GS02 CPU, Porting HYPPO to ACME

A couple of weeks back, the latest release of ACME added support for the MEGA65's CPU via the m65 CPU type.  This provides 1st-class support for all of the 4510 opcodes, as well as the 45GS02 extended instructions.  So now you can, for example, do:

LDA [zppointer],z

to read any memory address, where the address is stored in the four Zero-Page bytes at zppointer.

Or if you want to load a 32-bit value into A,X,Y and Z at the same time, and add it to another 32-bit value, before putting it back somewhere else, you can do something like:

LDQ $1234
CLC
ADCQ $1238
STQ $123C

There are even a few instructions that support combining the two, e.g., to add some 32-bit values from anywhere in memory, you could do:

LDQ [$12]
CLC
ADCQ [$16]
STQ [$1A]

Note that these instructions are not indexed by the Z register, because the Z register forms part of the virtual "Q" register.

You can of course also use all the new instructions like LDZ, PHX, PHY, PHZ, TAB, BRA etc.

So, now that ACME supports the MEGA65, I spent part of the afternoon porting the MEGA65's Hypervisor programme, HYPPO, from KickAss to ACME.  I like  KickAss and its accomplice, KickC, a lot. But ACME edges it out with its better 1st class support for the MEGA65 CPU extensions, its open-source nature, and that it is written in pure C, and so might be able to be compiled to run natively on the MEGA65 one day.

I was expecting this to be harder than it was.  Mostly it consisted of converting comments from KickAss's Java-style comments to ACME's traditional ; comments, and changing lots of pseudo opcodes, like .byte becomes !8, and .label is not needed. The hardest part was fixing a few constant expressions, to make sure that the instructions still produced ZP instructions.

There isn't really much to show, as HYPPO now works just exactly like it did before.  But since every blog post should have an image in it, here is a random screenshot of the new HYPPO running:


Updated m65dbg tool

One of our volunteers, Gurce, has been working on improving some of the tools we have been building for making development on the MEGA65 easier.


New and improved "m65dbg" tool

In short: the m65dbg tool has now integrated facilities provided by the m65 and mega65_ftp tools.

What are all these tools?

  • m65dbg is a tool I wrote to enhance the remote-debugging experience for the mega65. It builds upon the serial monitor that the MEGA65 provides at the hardware-level.
    If you are not already familiar with the idea of the m65dbg programme,  the following video from a while back walks through its facilities, and how it compares to the serial monitor. But skip down if you would like to know what's new.
     
  • The m65 tool is more of a swiss-army knife Paul has been working on, also making use of the serial monitor under the hood, with nice, unique facilities being added from time to time. My 2 favourite facilities within it are:
    • take a 'screen-shot' of the screen (saved as either ascii or .png)
    • 'remote keyboard' mechanism (letting you remotely type on your mega65 via your pc)
       
  • mega65_ftp is a nice tool to upload/download files directly to/from the sd-card plugged into your mega65, again using the serial monitor under the hood.

 

Why integrate them?

While I was enjoying all of these facilities during my debugging forays, I was tiring of chopping and changing between them. I felt the debugging experience would be enhanced further if all these facilities could be found in one place.

 

Can I see a demonstration of the new m65dbg tool in action?

Yep sure, made a short video of the new facilities in the following video:


 

Ok, I'm sold! Where do I get my hands on this lovely tool?

Right now, it's solely available as source-code on github here:

Happy debugging to you!

Note from Paul: We hope to move all of these tools into the https://github.com/MEGA65/mega65-tools repository over coming weeks, so that there is a one-stop shop for when you want to get started with developing for the MEGA65.



QMTECH Wukong board support and Audio over Digital Video testing

The HDMI-compatible audio drama might finally be coming to an end.
Adam has kindly written an implementation that uses direct FPGA lines instead of the ADV7511 chip, which we have confirmed works on the QMTECH Wukong FPGA board

The Wukong board is quite amazing: It is a complete 100T based FPGA board, that you can buy for less than the price of a single 100T FPGA!  And it has a direct HDMI output interface, which is good for our debugging purposes.

This makes it a much better option than the Numato Mimas A7 board we used previously for this, as that board had only a smaller FPGA that couldn't fit the whole MEGA65 design, so I was limited to testing the HDMI video output. Being able to fit the whole MEGA65 design means that I am able to get a head-start on the changes to the VHDL that I need to make for the MEGA65 R3 PCB, that will also have such a direct HDMI interface.

The starting point was to make a target for the Wukong board in our build environment.  Making new targets really just consists of making three files:

vivado/TARGET_gen.tcl
src/vhdl/TARGET.vhdl
src/vhdl/TARGET.xdc

The first is used to generate the Vivado project files, and is rather boring, being mostly a list of files.  I even started some work on auto-generating those, but for now, it is just hand done.

The second is the top-level VHDL, where we connect all the interfaces of the MEGA65 design to the external hardware pins, and also add any optional pieces that are required, e.g., HyperRAM controllers for boards that have HyperRAM.

The third is the list of FPGA pins and their names.

That's the easy part.  After a day or so of fiddling, I had a bitstream to try.

The next fun part is that on the current revision of the Wukong board, there is no integrated JTAG-over-USB.  This is annoying, as it means that you have to connect an external JTAG programmer to the header. I used the TET0004-02 Arrow programmer that I normally use for programming the keyboard CPLD in the MEGA65, and workout the pin arrangement to connect it up.  Also, the Wukong board has no microSD slot, so I used a PMOD microSD adapter I had laying around.  Then add the USB mini port for the serial-over-USB for the MEGA65's serial monitor interface, and then a 5V power supply, and I had it all going.

That's right, including the HMDI out, we need four different connections to the board to make it work.  They could have easily done the same as the N4DDR board or the TE-0725, and allowed it to be powered over USB, and to do JTAG over USB, so that only USB and HDMI would be required. I've contacted QMTECH about this, and they gave me a nice polite response indicating that they would likely implement at least some of that on their next revision.

Anyway, here is what the spaghetti-monster cable-salad looks like with the current revision, with close-ups of the connectors that are important to get the correct pinout for:





It took a little fiddling to get the pin-out for the microSD right, but that now works nicely. We also get a good stable HDMI image.

What is currently the problem, is that I can't switch it to C64 mode, as the CPU goes off somewhere funny when tries. 

Tracing through, it goes into the DOS ROM to do the normal C65 internal drive DOS setup up.  It's interesting going through that code. It is quite inefficient in places, such as how it initialises buffer memory using tight loops, rather than using the DMAgic controller, for example. The code to extract drive error messages is also quite fascinating in just how long it takes to get such a message out.  Neither is really a problem, except when you are single stepping through the startup trying to find a problem...

Okay, after nearly giving up, I have traced out the otherside of the DOS setup, and got to $FCF5, which is the C64 ZP and low memory setup routine.  While stepping through that, I thought I would just check if the $01 CPU register was set properly to map KERNAL and BASIC.  It looks like it is, but there seems to be something funny going on: The BASIC ROM is not visible at $A000. Rather, I see a slab of $00's.  But it isn't the RAM at $A000 showing through, because if I modify the RAM, it doesn't show up in the ROM area. Nor is it from $1A000 or $3A000. I did make sure that the BASIC ROM data is loaded at $2A000.

Ah, but it could be that it thinks that there is a cartridge... That would indeed be the case, it seems. I had tied the /GAME and /EXROM lines to Z for high-impedance, but in the absence of an actual driving signal, that results in a low rather than high signal when read.  

So I made some changes to the VHDL to fix that, but in the meantime, I thought I would try to use the Hypervisor option to disable cartridges to work around it temporarily and let me get to C64 mode where I could test audio, without having to wait for the new bitstream. That was all going fine, until I started smelling magic smoke.  I still don't know that happened, but I think the JTAG programmer must have rested on something in a way that shorted it out. Anyway, as you can see, the power lead got a bit melty:

Fortunately it didn't let all of the magic smoke out. Its a bit tricky to get it to programme the FPGA now, but it still usually works.

So I was finally able to switch to C64 mode, and load a game that I know makes noise at the intro screen, and confirm that, yes, we now have audio coming out of the HDMI TV I have connected up to it:



The audio sounds nice and clean, if a little quiet.  But we can easily increase the gain in the MEGA65's audio mixer to compensate. 

It's hard to test much more on the Wukong board right now, because I don't have keyboard or joystick inputs hooked up to it. I do have a spare MEGA65 prototype keyboard here, but not a cable to hook it up. And, besides, I don't really need to for testing purposes.

What I will do, though, is make a D81 to be the default disk image, and put an auto-booting version of Commando or maybe our MOD file music player, so that its easier to test other screens.  Then its just a case of flashing the bitstream to the onboard flash memory, and we will have the board all setup for easy testing of different TVs and monitors. 

Probably using the TE0790 JTAG programmer would allow me to flash it from vivado, but after letting magic smoke out of the Arrow one, I'm not that keen on risking the TE0790, since ordering replacement parts in the middle of the Outback takes weeks.  I'll have a think about how I work around that soon.

But the main thing is that we now have an updated HDMI audio test platform, that I can use to test all the TVs around the place up here -- in particular the Sony one, as those are renowned for being picky about the audio framing.

Saturday 11 July 2020

Porting a Wolfenstein-type engine to the MEGA65

This post is about something that I have had in mind for a long time:  A couple of years ago (or possibly more), someone pointed out to me that the DMAgic controller could in theory be used to paint textures, since texture painting really is just a matter of copying a texture onto the screen.  Well, and scaling it appropriately. And dealing with the screen memory layout, so that each successive write goes to the next pixel.  Luckily, its possible to do both using some quite simple tricks.



First, let's look at the pixel writing first.  First up, remember that the MEGA65's VIC-IV has no frame buffer. Rather, just like the C64's VIC-II, the screen is usually made up of 8x8 character cells.  The main difference between bitmap mode and text mode is whether you can choose which cell appears where, or whether they appear in a fixed arrangement.  This is actually a strength of the VIC family of video controllers for a Wolfenstein type engine, where we need to draw vertical stripes of pixels.  Let me explain:

First, lets consider a toy screen with only 4 columns and 4 rows:

ABCD
EFGH
IJKL
MNOP

This is the normal arrangement in bitmap mode, with ascending characters going across the screen.  So to find the address of the next pixel down in a column we have to work out whether we are crossing a character boundary, and if so, add enough to the address to skip the rest of the characters on the row.  But if we use text mode, and put our pixels in the character data, we can arrange the screen differently, striping down the rows instead of across the columns, like this:

AEIM
BFJN
CGKO
DHLP

Now, if we want to advance one pixel down the screen, we always add the same amount, i.e., the number of bytes to skip down one row in a character. On the VIC-II, that is always one byte, as one bit defines each pixel.  However, for a nice looking engine, we would like to have more pixel colours.  So for this engine, I am using the VIC-IV's "full-colour text mode". You can read more about it in the MEGA65 Programmer's Reference Guide, but the bottom line is that each pixel of a character is now represented by a byte instead of a bit. This means a row of character data consisting of 8 pixels now takes 8 bytes instead of 1 byte (8 bits).  So to go from one pixel to the next, we need to tell the DMA controller to add 8 to the address every time when it is generating the address to write to.

That's the writing side. So lets think about the other half: Reading from the texture, and scaling it.  The first observation is that the scaling should be done on the reading side, as we always want to write to each destination pixel exactly once.  Thus the solution is to change how the source address is calculated for each new pixel. 

If the texture is being drawn at 1:1 scale, then its simple: We can just read each successive byte of the texture data, and write it out with our x8 address generation when writing to the screen. 

If the texture needs to appear bigger on the screen than it is in memory, then we need to increment the source address only sometimes, so that the same pixel values get repeated.

Conversely, to draw the texture smaller on the screen than it is in memory, then we need to increment the source address by more than 1 on average, so that we skip some pixels. (Ideally we would calculate some average of the pixel values, but that's too much work for our poor 8-bit machine, and certainly too much to ask the DMA controller to do for us).

Our solution to this problem is to allow the DMA controller to increment either source and/or destination address by between 1/256th of a byte and 255 bytes each time. This way we can skip 8 bytes at a time on the writing side, and quite smoothly scale the texture we are reading on the reading side.  There will be a very small fraction of a pixel error at the end sometimes, but this will be a consistent error, and thus won't be noticeable on screen.

What is best about this, is that we can scale and draw a texture of any resolution at any zoom on any height screen, at a constant time cost of 2 cycles per pixel drawn.  For a 320x200 screen, that means about 128,000 cycles.  Given that the MEGA65 has at least 675,000 cycles per frame in NTSC (or 810,000 in PAL), this means that we could in theory draw the screen at full frame-rate, with some margin to spare. 

This compares very favourably with any other possible method, which presumably would have to involve at least one load and store operation (and probably a lot more), resulting in a cost well north of 9 cycles per pixel drawn.  I saw the difference first-hand when I was porting the engine, as I didn't initially have the DMA painting implemented.  Without the help of DMA, it would take several seconds to draw a single frame, i.e, about 200 PAL frames to draw the screen.  With the DMA painting implemented, I was able to achieve a frame rate of up to 10 frames per second, i.e., about 5 PAL frames to draw each frame.  This means that our DMA method is about 40x faster than without! That's on top of the 40x speed up thanks to the CPU speed. 

So for this particular case, we are able to outperform the C64 by a factor of about 1,600x!  That's the power of custom-chips. Interestingly we are also a lot faster than the best Amiga Wolfenstein-type engines I have found.  This is to be expected because the full-colour text mode effectively gives us a "chunky" video mode -- but with the extra advantage that we can arrange the screen the way we did, so that the striding between addresses is constant, and thus faster than even a PC of the era could achieve.

But we are getting ahead of ourselves here -- we started talking about how to do the texture painting, and are now talking about a complete engine, without me showing you the steps in between...

So let's talk about Wolfenstein type-engines and how they work.  They were the first successful 1st person "3d" engines that allowed the user to look in any direction.  They did this by "casting" light "rays" in various directions, and working out where they hit, and then drawing that thing.  They also had to work out how far away the thing the light ray hit is, so that they could work out how big to draw it, to simulate the impression of distance.  One light ray was cast per column of pixels on the screen, thus the interest in drawing those columns quickly.

The algorithms and optimisations that they make to draw quickly are quite interesting, and there is plenty of information on them out there, as well as example engines.  I tried a couple before settling on one that was designed for fast fixed-point calculation (as compared to floating point), since the MEGA65 doesn't have a floating point math unit.  I then forked it on github, and set about making work on the MEGA65.

Looking back at the commit log, it took less than 4 hours to adapt it to draw a display on the MEGA65, including using the DMA drawing method described above.  It took a further couple of days to fix a few bits and pieces, implement movement around the map using the cursor keys, including bumping into walls and the like.

The sky texture which adds a great feeling of realism and helps to orient the player in terms of which direction they are facing turned out to be super easy to do: Because the sky is "vertical" we can just have a loop texture, and draw it in each column of the screen, down to where the textured wall should appear.  The floor on the other hand is a pain, because in this view, the ground is horizontal, and so drawing it in the same way as the sky looks quire weird when you walk forwards or backwards.  When you stay still it looks pretty good, though.  To help make it look better, I rotate it, but its still not perfect, and there are bugs in the way I am doing it on top of that, where it scrolls in the opposite direction it should when you walk in certain directions.  But its a start.

The keyboard input was quite interesting to get right, as for intuitive movement, I wanted to know whether particular keys were being held down, not just pressed. This meant that the MEGA65's hardware accelerated keyboard scanner was only of limited use, because it doesn't indicate when keys are released.  However it does provide separate access to the keyboard matrix in a convenient way, similar to how the C64 KERNAL scans the keyboard, but in a separate register pair, so that you can scan joysticks and keyboard simultaneously.  As the MEGA65 keyboard is fully diode protected, it is possible to test the state of every single key independently.  Thus I implemented both WASD and cursor key control.  For good measure I also implemented joystick in port 2. I also implemented 1351 or amiga mouse in port 1 to control the direction you point.

As the sample map that the engine I used was a bit boring, I decided to replace it with a random maze generator.  I spent more time on that than intended, until I eventually found a good and complete pseudo-code description that allowed me to implement a working maze generator.  The result is in mazegen.c in the repo.

As I wanted to support mazes of various sizes, I decided to use a slab of memory above 64K to hold the information about each maze cell, and make a routine to look up values from that using the lpeek() function in the MEGA65 libc.  However, I found that the drawing speed of the engine went through the floor from about 10 FPS to about 2 or 3.  This is because checking if a particular block is empty or not occurs right in the heart of the ray casting algorithm.  Thus doing a complicated memory fetch was slowing it down. 

Worse, as CC65 is horribly slow at passing arguments to functions, that fetch was taking even longer.  So I implemented a little bitmap that had just whether a given cell was empty or not in it, and put that at $C000, so that a simple memory read could be used.  I wrapped that in a C Pre-processor macro so that there would be no function calls, and the frame-rate improved quite a bit, up to maybe 6 or 7 frames per second.

Along the way I also changed a few routines that were performing multiplications to use the MEGA65's hardware multiplier.  But the core routines are still in fairly boring C.  I suspect that with some hand-tweaking, it should be possible to make it quite a bit faster than it is now.

Once I had the core engine working, I started thinking about how I would do titles and other text that needs to appear in the game.  I could draw them over the rendered 3D display, but that would cause a lot of problems.  At the moment, because the rendering is so fast, it looks fine to just render from left-to-right continuously, without using double-buffering.  This is great, because I don't have a easily have a spare 64KB of RAM to dedicate to the double buffer (I could ditch the ROM to gain 128KB, but that's a pretty desperate measure).  But its not so good if we want to draw text over the top, as we would have to do a second layer of rendering, which would slow things down, and risk making a glitchy display.

Instead I used one of the VIC-IV features which is the ability to draw on a raster more than once.  That is, we can basically ask the VIC-IV to do in hardware that which would be a pain to do in software.  This works because the VIC-IV has a single raster line buffer into which it renders.  If there is enough raster time, its possible to tell the VIC-IV to go back over the raster, and render some more stuff.  If you set the appropriate flag, any background pixels in the material being drawn over the top are not drawn, effectively keying the new foreground content over the existing material from the first pass of rendering. 

Don't worry if that sounds horribly complicated. Just think about it as a kind of "text sprite": We can put an extra layer (or more!) of text over the top of whatever is being displayed, and have the VIC-IV composite it for us in hardware.

This is the feature that I used to make it possible to put text-based titling over the 3D display. This is used in the intro screen, as can be seen in the video I made of the core of the game that I already have working:


This works by telling the VIC-IV that each line of the screen has 80 characters, the first 40 of which are the ones arranged in the vertical stripes for efficient texture painting.  The 41st is the "GOTO" token that tells the VIC-IV to go back to near the left edge, and start drawing the 42nd to 80th over the top of the first forty.  In reality there are 2 bytes per character, for a total of 160 bytes per line, beause we need to use 16-bit text mode to access this feature (and to have more than 256 characters on the screen, which is needed for the 3D display which uses 1000 different "characters" to make our optimised bitmap layout).

Thus we need to tell the VIC-IV that each line has 160 chars. We do this by writing 160 into $D058, and 0 into $D059 (because there are less than 160 chars per line. We then put 80 into $D05E to tell the VIC-IV to draw 80 characters on each line.  The ability to set these two values independently is necessary for 16-bit text mode.  But it is also powerful for making screens bigger than the display area, that can then be hardware smooth-scrolled.  This would be very useful for making a side-scroller, for example, as the entire map could be setup as a single giant screen, of which only part is visible at a time.

For the curious, the routines with "overlaytext" in their names in main.c have the magic. Basically it is a lot of address calculation to work out where to put a character to make it appear in the right place.  Otherwise, there is the nice routine overlaytext_line_x_position().  This one is interesting, because it makes it simple to set the horizontal position where the compositing of the overlay onto the rasterline will occur.  That is, it can be used as a kind of hardware smooth-scroll on a line-by-line basis.  This is what is used to slide the title screen text off the right hand side when you start the game.

These features are all explained in more detail in the MEGA65 Book at https://github.com/mega65/mega65-user-guide

As well as general VIC-IV and DMA hacking, we needed random numbers for the game. So I wrote routines for generating random numbers.  This includes routines that try to gather thermal entropy from the FPGA to produce true random numbers (although we still have to test that this is reliable).  That process is slow, and sometimes you want reproduceable sequences of numbers, say, for consistently producing the same random maze.  So I also created srand() for seeding a pseudo random number generator, and rand8(), rand16() and rand32() for obtaining 1, 2 or 4 byte random numbers.  Each takes an optional argument that can be used to obtain numbers in a limited range. It works by multiplying the random number by the supplied argument using the hardware multiplier, and returning the upper bytes of the result.  The result is nice and fast.

You might have noticed that in the video the game was started from C64 mode.  Another little piece of work we have done is to create a wrapper programme that can be used to make any C64-mode oriented programme launchable directly from C65 mode or C64 mode. This is interesting in its own right, so I'll blog about it separately when I get a moment. But suffice to say that the current version of MEGA MAZE can be started from either C64 or C65 mode using the same programme.  By naming this AUTOBOOT.C65 on a D81, we can even auto-boot the MEGA65 to run it, if it is on a disk in the floppy drive (or on the D81 image that is mounted by default).

Finally, to get music playing in the game was a bit interesting, because there isn't really space left in the first 64KB of RAM for a SID file. There is fortunately space for an interrupt handler.  So I wrote a tiny little interrupt handler that banks in some of the 2nd 64KB of RAM that contains the SID file, calls the play routine, and then puts everything back before resulting the interrupt handler.  It looks like this:

uint8_t music_irq[27]={
  0xa9,0xc0,      // LDA #$c0
  0xa2,0x11,      // LDX #$11
  0xa0,0x00,      // LDY #$00
  0xa3,0x00,      // LDZ #$00
  0x5c,           // MAP
  0xa9,0x00,      // LDA #$00
  0x20,0x03,0x10, // JSR $1003
  0xa9,0x00,      // LDA #$00
  0xaa,           // TAX
  0xa8,           // TAY
  0x4b,           // TAZ
  0x5c,           // MAP
  0xea,           // NOP
  0xee,0x19,0xd0, // INC $D019 to ack raster interrupt
  0x4c,0x31,0xea // JMP $EA31
};


I put it in a C array like this, because I copy it into place in $0340, rather than trying to have an interrupt handler call a C function, which is known to be messy in CC65.  The routine itself is very simple: First, set the bottom 8KB slab to be banked, and the bank address to be +$1C000.  This causes a SID file stored at $1D000 to be mapped at $1000 (since $1000 + $1C000 = $1D000).  It then calls the play routine for the SID file, and then clears the mapping, acknowledges the raster interrupt, and resumes the normal interrupt handler.

There is a trick, though: This little routine has to also be installed at $1C340, so that when the first MAP instruction executes, the rest of the routine is visible in the new memory mapping.  The routines that handle all this are in music.c of the raycaster repo. Those routines also handle parsing the play routine address out of the SID file, and patching the above handler to use the correct address:

void music_start(void)
{

  asm ("sei");

  play_addr=lpeek(0x1cf8e)<<8;
  play_addr+=lpeek(0x1cf8f);
  music_irq[12]=play_addr&0xff;
  music_irq[13]=play_addr>>8;
 
  music_irq[10]=0x00;
  music_irq[24]=0x4c;

 
  lcopy(music_irq,0x340,63);
  lcopy(music_irq,0x1c340,63);
  // Set IRQ handler to music routine
  POKE(0x0314,0x40);
  POKE(0x0315,0x03);

  // Disable CIA interrupt, and enable raster interrupt
  POKE(0xDC0D,0x7f);
  POKE(0xD012,0xFF);
  POKE(0xD011,0x1B);
  POKE(0xD01A,0x81);
  POKE(0xD019,0x81);
 
  asm ("cli");
}

I realise that this has all been a bit of a whirl-wind tour, rather than deeply worked examples of the various features.  But hopefully it is enough to get you thinking about some of what is possible on the MEGA65, and some example code you can look at, as well as pointers to where it is documented in the https://github.com/mega65/mega65-user-guide repository.


First MEGA65 Commercial Software Announced! Hibernated 2

Just a short post this time, but a very exciting one: The first commercial software title has been announced for the MEGA65!  Hibernated 2 will released on 3.5" disk for the MEGA65:

Both the author and Stefan Vogt and PuddleSoft are enthusiastic supporters of the MEGA65, and thus it our great pleasure to be able to announce them as being the first retro-game house adding support for the MEGA65.  Here's a screenshot from when I was helping to get it running:



What is particularly exciting about this particular release, is that it uses a Z-Machine text adventure engine, Ozmoo, that I ported for the MEGA65 last week.  This means that it is possible to make MEGA65 versions of a large back-library of text adventure games, all enjoying 80 columns and 40MHz CPU speed.  While the 80 columns makes an obvious contribution, the CPU speed is actually super-helpful here, as the Z-Machine is notorious for running slowly on 6502-based systems.  At 40MHz, though, it feels super responsive. 

Just to show how easy it is to use our port of Ozmoo to create versions of existing text adventures, here is a screenshot of The Hitch-Hiker's Guide to the Galaxy:


We are hoping that this will be the first of many official software releases for the MEGA65!

Wednesday 1 July 2020

Built-in Sprite Editor Progress

Just a quick post to report on progress on the integrated sprite editor that we are building as a plug-in to the Freeze Menu.  The reason for doing this is that unlike BASIC 7 on the C128, the C65's BASIC 10 doesn't include a sprite editor.

We have already made this plug-in framework, where the Freeze Menu can call helper programmes for the audio mixer.  So it was really just a case of making the sprite editor itself.

And this is where one of our volunteers Hernán comes in: He has been working on the actual editor.  Together we merged that in as a plug-in to the Freeze menu, and hooked up all the plumbing, so that exiting the sprite editor returns to the freeze menu.  We also jointly implemented simultaneous joystick and mouse support, so that its is super comfortable to use.  To enter the sprite editor, you simply press S from the familiar Freeze Menu.  You then get something like this:



You can then use the keyboard cursor keys to move around, and toggle pixels. You can also see that there is provision for multi-colour sprite modes.   Now, the screenshot tool doesn't currently show sprites, which I only just realised while pasting the screen-shots in. This is annoying, because it means you can't see the sprite pointer in the following, where I have used the mouse to move the cursor and draw:



One of the nice things that has come from this, is that we have made library functions for using the mouse as part of the mega65-libc. Hernán also wrote simple console output library functions for drawing the display.  This means that we have a new set of APIs that are easy for other programmer's to use in their own programmes. When I get the chance, I'll start documenting the library functions to be included in the MEGA65 Book, and likely in a smaller separate MEGA65 Cross Developer's Reference Guide.

Anyway, the editor is now at the point where the hard parts are mostly done. Next steps will be to make it actually edit the sprites from the frozen programme's memory, rather than from in the memory of the sprite editor process.