Today Pukka was busy fixing some CPU bugs, and thanks to that effort, we have a bunch of games working more or less better than previously. One of them is Battle Chess, which appears to be pretty stable with gameplay – and sound – working.
Some of the dialog boxes don’t quite work yet because of unfinished TextEdit stuff, but otherwise it looks good. Other games which saw some degree of process were Prince of Persia, Dark Castle, Beyond Dark Castle, Continuum, and Lemmings. They don’t yet work quite, and we’ve updated the status page to reflect their current situation.
To celebrate this, we recorded one complete Mac. vs Mac. match of Battle Chess below on our YouTube channel, enjoy!
Pukka had been working long on the disassembler, and we were finally able to get first version of it integrated with the emulator. Below is a simple partial disassembly of Tetris audio mixer VBL, executed from Xcode debugger command prompt:
Although the disassembler itself still has some minor quirks to fix, there were some interesting bits we found about the Tetris mixer code in this disassembly:
Unlike Sound Driver, which has 4-channel mixer, Tetris uses a 6-channel mixer
The audio is downsampled from 22256 Hz to 11128 Hz by writing each sampled byte twice (the $7000(A6) at 00030C18 is supposed to be 2(A6) in disassembly)
The division of summed samples by 6 is done by pre-calculated lookup table (which has 6×256 = 1536 entries)
The pitch of channels is controlled by directly writing the fixed-point pitch into mixer code at addi.l instructions from 30BAA to 30BC8
During the Christmas holidays, Pukka was busy fixing 68K emulator bugs (including or.b/w/l and move.m instructions), and we can now play Dark Castle (without sound) at least through a few rooms, until it finally crashes in Shield 3:
And as a bonus, here’s title screen of Beyond Dark Castle:
These few weeks have been mostly bug fixing, and improving things to get the test applications to run further. This includes fixing the OR masking bug in Dark Castle, adding keyboard controls so we can actually move the character, and trying out different things. A lot has improved, but there’s still work to be done. At this point it might be appropriate to document some of the most strange bugs we had so far:
Most of Dark Castle levels load, but Fireball 1 crashes because of a buggy bird sprite.
There’s something wrong in the 68K code Stunt Copter uses to translate mouse movement to copter speed, causing trails to be left on screen after exceeding movement speed. Another issue with Stunt Copter is that it runs way too fast, but after experimentation we formulated a toolbox patch which would allow throttling the speed to make game actually playable.
And although Dark Castle starts to get playable, we still have issue of boulders teleporting around, and character falling through the floor 🙂
One critical part of UI was still missing at this point, the Control Manager. Luckily implementing it was quite simple, as like with Window Manager, a lot of the core functionality depends on QuickDraw to do the difficult things.
With support for Controls, we could now use buttons, like one in the above IconQuest introduction dialog, and the buttons below in Dark Castle main menu using ModalDialog:
The buttons still need titles, checkbox implementation is not complete, and TrackControl is implemented as a immediate return, but that is enough to allow entering The Great Hall in Dark Castle:
With this test case, Pukka identified a bunch of CPU bugs, including lack of BCD (Binary Coded Decimal) support which Dark Castle uses to display the values at bottom of the screen, which will be fixed next.
As one of the main goals is to actually run our favorite games in this emulator, we started now converting some of them into the AppleDouble format, and one of the was the legandary Dark Castle by Silicon Beach Software. It almost worked:
After fixing a bunch of bugs, and adding another bunch of new traps, it actually didn’t take long to get the title screen to appear. However, GetNextEvent was unimplemented at this point, so couldn’t yet proceed past it, and also the animation timing appears to still a bit off. It was nice though to see that the alternate video page switching code appears to work nicely, including also for the first time having 68K code running in VBL service thread! The video below shows this running:
Thanks to the earlier work done on Resource Manager for the “Fake” ROM resources, we already had rudimentary support for accessing resources. As the ROZ resource map was built to have exactly same format like “real” resource maps, the main missing features needed were reading and loading the resource map from resource fork using the recently added File Manager traps, and implementing further file reading operations in LoadResource trap.
And now with ability to load resources, the first thing to logically do is to start work on the Segment Loader. The Launch trap is used to:
Handle launch parameters
Init application one (unless doing a “Chain” launch)
Load jump table from CODE resource ID 0
Set up the A5 world and copy jump table to correct place
Set up 68K state
Jump to application entry point in 68K code
At this point, we can now for the first time start running an actual 68K Mac application, although there were, and still are, a bunch of 68K cpu bugs to fix. At least, now we can test the CPU emulator with actual, real program code!
At this point, Pukka had been working hard to update the 68K emulator to work with the new environment. With 64-bit support, cross-platform standard C and POSIX compatibility as requirements, we had already discussed how to interface the emulator with the virtual memory system.
First integration test
To make a simple test case for the 68K emulator, we created a short 68K assembly program which we wrote manually to the memory using the C code below, and ran the CPU:
Quite simple test, but it not only displayed that the 68K emulator worked, but also that our trap dispatcher was also working as intended! Which meant that the calls from 68K to native C code worked, arguments got translated correctly, return value got transferred to 68K stack and it just…worked!
…Which was a bit ironic, as soon after this we noticed that we forgot to allocate space on stack for the return value of Random trap (0x558F = SUBQ.L #2,A7). The MOVEA._L -1,A0 and MOVE.L A0,-(A7) was supposed to put return address for RTS but somehow it worked! I guess we got lucky this time…