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!
After some effort, we now have basic shape drawing working in MacDraw. One fun part of this was implementing FixDiv, which uses the binary long division algorithm like the original one on Mac. MacDraw uses this routine excessively to handle document grid sizing and coordination of all shapes drawn on the canvas.
There was also a minor bug in MenuSelect causing zero item selections in MacDraw’s custom menus, but after a quick fix we can now also use them.
Contrary to many other applications, MacDraw uses a different approach to implementing custom menus – instead of providing a MDEF and assigning it to the menu using the menu definition proc ID in resource, it has its MDEF code as part of the program, and creates a fake handle which it assigns to the menu manually. Because of this, we had to tweak the memory manager handle operations to silently fail on such handles, and instead return the proper memAZErr (-113) in D0/MemErr.
Still no text drawing though, and there’s minor tweaking required for line drawing, but it’s looking promising at the moment.
Until this day we’ve been keeping this project blog private, but we were told that there might be other people who might be interested in reading about the news and progression of our little project.
For this purpose, we’ve now moved to this new public domain, and also uploaded the private videos on YouTube for public viewing
If there’s anybody who’s interested following this project, please let us know by following this blog and/or the YouTube channel. This way we will know if we should post news about our progress in the future too.
Although we could make Indy launch already a while ago, for some reason we did not get any graphics to display. However, after Pukka fixed some more CPU bugs (including ror.l instruction), we suddenly got everything appear on the screen:
Interestingly, the game uses Sound Driver to play intro music, *but* after intro completes, it switches to Sound Manager. As we don’t have yet Sound Manager implementation, we added some empty stubs that just return error for the caller, and it seems Indy is happy with that as we can now proceed in the game all the way until getting stuck on quests 🙂
At this point we also noticed that we had accidentally handled the Style parameter of TextFace as 8-bit value instead of 16-bits as we should have, so the style calls had not been working until now that we fixed it. Indy uses these styles to adjust appearance of text on the UI buttons:
Here’s also a short video of the intro (with audio), and few first minutes of the gameplay:
As a lot of the test games were already showing menu bars, we decided to finally implement the menu selection support at this point. In Toolbox, this is done by the “MenuSelect” call, which handles everything needed for selecting the menu item, including:
Using MBDF to save/restore menu background, highlighting titles, and drawing menu frame
Using MDEF to draw menu items and choose items
Returning the selected menu/item to calling application
After a some coding, we got this:
At this point, we have only the basic menu selection support (no support for hierarchical menus yet, scrolling long menus vertically, or popup menus), but it’s enough to handle most of the basic cases.
With track and station building working, we could now also attempt adding trains to run on those tracks. Although we already had one List Manager dummy routine for the Train Roster window, the train creation screen needed a lot of more routines to make it work. This included implementing the following:
LAddRow (and LAddColumn for future use on the side)
It took some time, but we were now able to successfully select and add cars from the car list to the train. Please mind the missing scrollbar, CDEF 1 is still unfinished 🙂
These List Manager routines will also be useful in the future, not only for the Train Roster window in Railroad Tycoon, but also for the Standard File Dialogs which will also make use of them in the file list.
Time for some QuickDraw updates! Perhaps surprisingly, we already had at this point two cases which required Arc drawing: Dark Castle help screen (the “jump” arcs), and Railroad Tycoon signal circles. As the arc drawing is closely related to circle drawing, we had to just handle the arc begin/end angles and using them to control circle scanline rasterization, we had those cases working:
Another set of features in QuickDraw which we needed to implement at this point were the CalcMask and CopyMask routines. It appears that Glider 2 uses those to draw sprites:
…and Railroad Tycoon also uses those to calculate masks and draw everything dynamic on the map (tracks, stations, bridges, and lighthouses). A nice side feature of CalcMask is that it shares basic algorithm with SeedFill call, so with just adjusting a few values we could add support for that trap too. Hopefully we can soon run MacPaint or SuperPaint to test it…
Interestingly, the documentation on CopyMask has conflicting information between Inside Macintosh editions: The later books (IM: Imaging With QuickDraw) indicate that CopyMask scales image to destination rectangle, similar to CopyBits, but older IM:IV describes the correct “Classic” QuickDraw behaviour that it does *not* scale the image.
One of our favourite games, Apache Strike, is now partially working. The game has a weird way of checking machine memory by writing/reading value beyond RAM space, which had just to be handled with special case to not raise a page mapping error from virtual memory system. The music (it’s using Sound Driver) is working OK, and main menu is shown properly:
However, some unresolved CPU bug seems to be causing the 3D rendering to fail, with only vertical lines appearing on the screen. Also controls don’t work yet, but it might be because we don’t yet completely support moving the mouse location by writing to low memory cursor globals from applications.
Here’s a short video with just the main menu and the music playing in background:
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
After we got the Railroad Tycoon main menu to work, we were able to proceed all the way until map generation. This part of the code uses Pack4 (FP68K) dispatcher to run some certain floating-point operations, so we had to implement the following SANE operations:
The tricky part was, that SANE operates on 80-bit extended floating-point numbers, but modern CPUs use only 32- and 64-bit floating point numbers. Following the conventions Apple used in the SANE implementation for PowerPC, we convert the 80-bit extended numbers into 64-bit “double” values for calculation, and convert them to required destination format (depending on operation, usually the 80-bit extended) again.
I’m however not sure if the 80-bit conversion is correctly implemented at the moment, but it seems to work for now, as after adding these couple operations, we immediately got the map generator to pass through successfully: