The past few weeks have been a bit quiet for us, as we’ve been both busy doing important work and personal life stuff, so we haven’t had as much time recently to spend on this project. We will continue progress soon when each of us gets more spare time, but meanwhile here’s a bit of entertainment for meanwhile:
As mentioned a few weeks ago, the audio output – which previously was not working in MS-BASIC – suddenly started working as Pukka fixed some 68k CPU bugs. At that time, I recorded a short video of the “Music” sample program running with audio included – and as there’s no other news to share at this time, we hope this “filler” video will keep you entertained for the time being!
This previous weekend, while helping Pukka to fix a mysterious coordinate calculation bug in Fool’s Errand intro, I decided to experiment with one weird idea: How about adding support for System Extensions and Control Panels? Therefore, yesterday I added the After Dark ‘cdev’ control panel to MacPaint app’s build settings to be included in the System Folder, and took some time to look what it would take to make it work.
Basically, INITs and cdevs are loaded during the startup by Mac OS by checking a few bits (such as file type, visibility, etc), opening the resource map of each file, and executing the first ‘INIT’ code resource found. At this experimental stage, we don’t yet have full INIT/cdev scanning, but instead have just a hard-coded filename to load INIT code from which works ok enough for this test case.
Our boot-time heap wasn’t quite properly set up yet, as the boot stack was too high, not leaving enough space between MemTop and BufPtr, which on the first attempt of running the INIT caused After Dark’s InitZone call to actually end up at top of the stack, causing all sorts of havoc. Besides that, there were a ton of bugs/improvements:
68k-to-68k trap calls did not work correctly (i.e. calling a trap patched with 68k from 68k code)
InitZone parameter block handling was completely broken from the last year’s trap refactor, so it was fixed
Memory Manager’s Handle validation had not taken into account the case where handle’s “relative handle” field would point to invalid memory location in some “fake” handles (as one in After Dark), for which validation was added
Empty stubs were added for Notification Manager calls to allow After Dark to call them during activation/deactivation of screen saver
Locking of 68k mutex was not done early enough, so After Dark’s VBL handler was making the initial call Launch trap to have invalid register values
After Dark uses grafProcs to call QuickDraw, so one missing case used by it was added (ovalProc for ovals)
After that bunch of minor tweaks, we have now at least After Dark working nicely!
Although the INIT code itself works, there is not yet any UI for displaying cdevs (Control Panels), so modules cannot be configured yet, and thus only the default “Starry Night” built-in module is displayed.
There’s also a short video to demonstrate After Dark running:
Although not very usable feature at the moment, this will definitely allow interesting possibilities in the future, as theoretically we should be able to run applications requiring certain application-specific extensions to be present in the System Folder. This experimenting with After Dark has anyway allowed us to find a number of important bugs (as previously mentioned), and also works as a very good “compatibility” test to see how well our Toolbox API and 68k implementation can handle one very quirky control panel, as it patches a ton of toolbox traps and does a lot of low-level stuff which all appear to be compatible with our emulation.
As mentioned in the previous post about file system write support, one major motivation for experimenting with it this point was the interest about getting HyperCard to work on MACE. So, after we added it a few days ago, and after fixing a few bugs, we already got quite a few default stacks (included with HyperCard) to at least open up and display something! Below is a HyperCard screenshot extravaganza what we can do right now (click on pictures to see full size!!!):
As you can see, there’s a lot of stuff appearing correctly, but also a lot of things still broken and needing work. Cool stuff that works:
Most of cards open up and actually do sensible stuff
Most of drawing tools work (see the mess we made in the Home card!). I think they also share a lot of code with MacPaint tools, as some have same toolbox bugs present in both MacPaint and HyperCard
Stuff that needs a lot of work still:
Corrupted texts appearing here and there around places (such as between months in calendar & weird mess in some lists)
Bunch of error messages popping up here and there
Font setup dialog is not displaying font names correctly as using some still unimplemented selectors at least in List Manager
Cannot get back to Home stack, which apparently does not close correctly and cannot be reopened without restarting entire HyperCard application
HyperCalc stack does not appear to work well at all, all fields are empty and the “help” popup does not appear
File system writing needs improvements, especially to add the Standard File package so we wouldn’t anymore have to use the hard-coded filenames
TextEdit support is not yet complete, so most of text input does not yet work (with the exception of text drawing tool, which like MacPaint does not use TextEdit)
A bunch of other misc bugs here and there
Anyway the current status looks quite promising, and as eventually bugs will get hunted down & features added, the state of this application should improve over time.
This week we reached a major milestone! From the encouragement on the work on HyperCard on 68KMLA forums, we got inspired to attempt tackling one major obstacle that was preventing it from working – file system write support!
As we mentioned earlier last year, when we last fall added the file system API, we did so using abstraction on top of AppleDouble file format. As Mac file system has the special dual nature of being split to data and resource forks, the AppleDouble format helps managing this in the emulated file system. Data fork, as mentioned earlier, is saved directly in its own file, while resource fork is merged with other file metadata in the AppleDouble header file. With this distinction, adding support for writing to data forks was really just trivial mapping of file manager write calls to the data file. Resource fork writing is a bit tricky, but we currently force the AppleDouble headers to keep resource fork as last element in the file, which allows us to offset also write operations from the beginning of resource data, and allows us to expand/shrink file easily, as end of resource fork is the actual end of header file. (One side note, setting EOF of files doesn’t have a standard C file operation, so we’re for now using the POSIX extension “ftruncate” which works at least on Mac OS X, but may lead to portability issues.)
Currently there’s very limited set of features for writing to file system implemented, basically just “Create” and “Write” file manager calls. For example, resource manipulation does not yet work as it will require a number of routines added to the Resource Manager to support it. However, one test application that directly benefited from this new feature was our beloved MacPaint, as it requires two scratch files to be present on startup volume/folder to function. This was nice, as it allowed us to add a few other missing features, such as PackBits (which also benefitted other apps and picture recording).
Although all tools don’t yet work perfectly, most of basic drawing functions are solid enough to not only allow drawing, but the experimental file writing also allows saving of MacPaint files, which appear to be readable by the Preview application in development host system Mac OS X 10.12!
Additionally, many other applications have seen improvements from this, as now we can save Civilization games and continue playing them! (Although Standard File package is still using hard-coded SFReply records).
There’s not much news for the past days, as half of the entire development team has been bedridden by a spring flu, which luckily is improving. However, during this period we did a stress test to hunt a nasty memory corruption bug found in Civilization:
Eventually the memory heap corruption bug was reproduced, and thanks to extensive debug logging, the culprit was a double-release of color table handle in window manager auxiliary window list entry which was not implemented correctly. With additional checks in memory manager handle “handling”, we’re working on fixing this issue and hopefully will catch similar issues faster in the future with the added handle validation code.
Other notable improvements done in the past weeks include:
Near-completed scrollbar (CDEF 1) support
Bug fixes to Control Manager (which was using dereferenced handles after calling routines which move memory, causing random crashes)
List Manager bug fixes (alignment of items, scroll working, and scroll bar support, incorrect bit masking, etc.)
Fixed FCOSX interpreted accidentally as FLOGBX. They both had same selector, but different trap (FP68K vs Elems68K). This allows ZeroGravity to display force indicator correctly, and fixes Test Drive II: The Duel road rendering almost completely.
Other minor fixes & improvements (MapRgn trap implemented, OpenPicture pen hide bug, DeltaPoint byteswap bug, FindDialogItem trap implemented, ScrollRect was not calculating source address correctly in non-clipped downwards scrolling, etc.)
Somehow sound has started to work in Microsoft BASIC, so the “Music” sample app now plays music in BASIC without issues
The past week we’ve been busy working on optimizations on the 68k CPU and various improvements to the toolbox API. One of the improvements has been adding support for Apple’s MacApp MethodDispatch routine, which is used by Object Pascal and C+- (yes, that’s “C plus minus”, Apple’s proprietary C++ version which was briefly out before official C++ came to Mac). Basically, MethodDispatch is the virtual function table dispatcher commonly seen in C++ programs, but instead of being bundled in the application, it is actually implemented by the operating system as a toolbox trap – although with special calling convention, which cannot be called directly through A-line traps, but needs to be invoked through jump from 68k code. It handles selecting the correct implementation for class functions which can be inherited and overridden.
With the new MacApp method dispatching support, we should now be able to try running any MacApp-based applications – one cool such application, which is written in Objective-Pascal, is the first version of Adobe Photoshop:
Most of the dialog boxes appear to display (almost) correctly, although color picker, text input and popup menu support are missing so there’s little that can be done here:
And just to test out how it works, we did a quick “Hello world” drawing using Photoshop drawing tools inside MACE:
Although implementing the method dispatching routine was fairly trivial, some time was taken by other features used by Photoshop, such as crude International Utilities/Script Manager support, PrGlue dispatcher for printing (or as in current case, telling application that printers are not available), proper Gestalt support, and various bug fixes even to some fairly low-level things as handling of empty regions in UnionRgn calls, rewriting the 80-bit “Extended” floating-point format conversion in SANE, etc… A few other test applications did benefit of those additions, but we’ll post more about them later!
Ps. In case you are interested how MacApp-based application code looks like, the original Object Pascal source code for the first Mac Photoshop was at some time ago published as open-source and is available on github: https://github.com/amix/photoshop
After spending a few days fixing bugs/issues, we can now successfully start up Microsoft BASIC 2.10, and run BASIC sample code applications with it. It looks a bunch of stuff is now working:
The BASIC sample apps seem to all be opening up and running the basic code is working fine in the BASIC interpreter.
Sample code listing, formatting and scrolling (by dragging text selection with mouse) appears to be working.
Trace and single-stepping seem to work ok using “Run” menu (and stopping using cmd+period).
The BASIC sample apps seem to be able to draw text and pictures, read files, and create menus, windows and dialogs.
There’s still a few issues to iron out though:
Only binary version of MS BASIC works, decimal version has some issues.
Standard File Package is still unfinished, so opening BASIC applications for testing is done temporarily using hard-coded SFReply records.
TextEdit input does not work yet properly, so for now we can only run existing sample apps. Interestingly, MS BASIC uses custom text input field which appears to do all the text drawing/selection itself without TextEdit, but depends on it for text input. This also prevents “Command” window from being much of use.
SOUND command does not appear to work yet, and there’s no visible signs of attempted calls to .Sound driver or sound hardware, so it needs further investigation. This may be related to sound missing from a few other test applications.
An important feature which was implemented a few days ago is the StretchBits trap. It was actually implemented for the first “Stunt Copter” prototype, but as it’s effects are visible in many places, I felt proper to write a separate blog entry for it just to demonstrate a few cases where it had big impact on the content:
Before implementing StretchBits, calls to it were directed as a placeholder to StdBits, which would show the content partially depending on the context, but causing graphic glitches as can be seen. On the Railroad Tycoon map, the “Map” uses both double-size scaling to draw the map, and half-size scaling for the mini-map on the right hand side. Also, the “New Train” screen uses stretching to scale locomotive PICT resources to fit the List Manager list it uses:
Also the text rendering benefits of this, as text can now be scaled to arbitrary sizes, which is quite important when drawing bitmapped fonts in non-exact resolutions, such as in Missile:
The scaling algorithm has some room for improvement, as it for now only has the generic method for scaling bits one pixel at a time. For now, this seems to be enough to allow working on other missing features.
With help of the new build system, we have now foundation to make porting to other host platforms easier. Currently, Pukka is working on Rasperry Pi port, while I today managed to get the emulator to compile and run on Haiku for the first time!
With the support for multiple application-specific build targets, we could immediately get all the (currently functional) test apps to run. Below is screenshot of a few of them running at the same time:
The sound output took a bit tweaking to get to work, as for some reason Haiku’s SDL2 implementation did not handle unsigned 8-bit audio (native Mac format) so we had to briefly hack in support for converting it to signed 16-bit PCM on the fly. Sadly, modifier keys don’t work yet, and mouse input is broken, but emulation, file system, rendering and sound output appear to be working ok for now.
There’s however still much to do, and ports aren’t yet a priority, so these ports will probably see less action in the near future until we get all the other tasks done.
EDIT: Here’s a short video of first level of Prince of Persia running in MACE on Haiku: