Most of the past couple weeks have again been a bit quiet due to busy time at the daytime job, but there are a couple improvements which are worthy of creating an update in this development diary:
Notarized macOS downloads
The set of (macOS) app bundles on the downloads page have finally been notarized, after Toni enrolled again in (& paid for) the Apple developer program for one year required to do it. So, there won’t be any longer any trouble with the scary warnings on the recent macOS versions.
The downside is, that the default notarized applications require macOS 10.9, but we’ve left the old, unsigned application bundles for Mac OS X 10.6+ compatibility, for now.
There are not much functional differences between the most recent notarized applications and the previous builds, as most of the recent progress has been on improving color compatibility, and other features in applications not currently part of the set of the downloadable app bundles.
Escape Velocity map “works” now
After a couple days of debugging, the code crashing Escape Velocity when opening the map was isolated. However, curiously it would appear there might be a bug in Escape Velocity causing the issue; in map, the game keeps track of four data structures of 10 bytes each (which I assume may contain coordinates for at least the nebula and asteroid field pictures), but in the map drawing code it accidentally accesses a fifth element in the array, which will contain random data at end of the allocated memory area. I briefly tested this part on a real Mac running Mac OS 9 – and it exhibited the same behaviour, but luckily SectRect intersected the offending corrupted coordinates, before running CopyBits, which would crash on negative source rectangle size; in M.A.C.E. as a workaround the StdBits (which CopyBits uses) was reinforced to ignore negative transfer sizes, which appears to be invalid operation on the QuickDraw on real Macs.
There were also a couple other minor fixes:
MakeFSSpec did not populate the FSSpec fields correctly for non-existing file, which was required behaviour when using it to create FSSpecs for creating new files with FSpCreate
The “search & replace” mode in _Munger trap did not work correctly; The mission list was using this to replace “<DST>” with destination name, but in the case the search string was not found, it would keep appending it in the end of string infinitely
StandardGetFile selector in Std File Package was missing typeList pointer, causing the “Open pilot” dialog to not display any files
We recently also tested Thexder on M.A.C.E., which seems to be working quite well in both “classic” monochrome mode (with audio), and in the color mode. The controls are also quite responsive, although having played previously the DOS version it took a short bit of learning to play with the numpad controls, where vertical and horizontal movement keys are combined, as holding down multiple arrow keys is disabled in the Mac version, perhaps to avoid conflicting with the use of space bar as fire button.
This game is quite rare in the sense that it is the only game which we know that uses 2-bit (four-color) mode in the color version; this however works as a perfect test case for the 2-bit display mode testing and debugging. Interestingly, the monochrome version of the game seems to have some bugs (such as enemies not following player horizontally in the same way as in color version, and also some walls destructible by lasers seem to not work correctly). But as these bugs appear also on real Macs and minivmac, it seems that at least the emulation is working as intended.
Palette fix for Loony Labyrinth
As mentioned in the previous post, Loony Labyrinth was having some color corruption problems, which seemed to only affect the playfield. After a quick evening of debugging, it appeared that as the game used custom palette for intro screens, it was trying to reset color table back to default using RestoreDeviceClut selector of PaletteDispatch, which contained some code which was left previously as unimplemented to-do task. With a quick implementation to release the palette links from the GDevice, and doing a reallocation of color entries to restore original palette, the playfield now appears and displays as it should:
Also, to celebrate this in combination with the physics fixes from earlier this month, here’s a video of how well the game’s own AI is able to play the game in the demo mode:
Although this does not fix Marathon’s color table issue, we luckily we have identified the problem with that game, and will be fixing it before next week. More about that in the next update!
Full list of changes since last post
2020-09-29 03:12:46 +0300 • Finalize (mostly) RestoreDeviceClut implementation 2020-09-29 02:13:02 +0300 • Fix PortList allocation & add PortList debug tool 2020-09-27 03:26:40 +0300 • Fix missing typeList in StandardGetFile 2020-09-27 02:56:59 +0300 • Fix "search&replace" mode in _Munger trap 2020-09-27 02:19:43 +0300 • Implement FSpSetFInfo for HighLevelFSDispatch 2020-09-27 02:17:32 +0300 • Add dummy empty NewAlias and NewAliasMinimal 2020-09-27 02:15:44 +0300 • Populate properly fnfErr result case in MakeFSSpec 2020-09-22 11:09:13 +0300 • Merge branch 'master' of 2020-09-22 11:09:08 +0300 • Minor tweak in colorQD detection in CDEF 63 2020-09-22 02:06:41 +0300 • Fix warnings causing errors on the new Xcode 2020-09-21 03:26:21 +0300 • Fix StretchBits crashing on negative srcRect width 2020-09-21 03:24:14 +0300 • Fix ADF filenames starting with % to map correctly 2020-09-21 03:23:00 +0300 • Add OrbQuest test application JSON config to cmake 2020-09-10 13:22:57 +0300 • Fix vfs file dependency command in cmake 2020-09-10 11:57:35 +0300 • Tweak Thexder JSON config 2020-09-10 11:57:03 +0300 • Pixel-doubling support for 4-bit (16-color) mode 2020-09-10 11:56:35 +0300 • Pixel-doubling support for 2-bit (4-color) mode 2020-09-10 04:13:30 +0300 • Fix cmake to allow again unsigned apps in OSX 10.6 2020-09-10 03:19:58 +0300 • Also return success code for decoding opOpColor… 2020-09-10 03:18:11 +0300 • Add Thexder test app to cmake json configs 2020-09-10 03:17:43 +0300 • Implement opOpColor in PICT playback
A lot of has happened past week, perhaps thanks to the summer finally starting to be over, and us having more time for the project again. Here’s a breakdown of most important advances made last week:
Fixed the DIVU.W overflow calculation
A long-time bug in unsigned 16-bit division instruction was finally found, and fixed by Pukka! We accidentally calculated overflow using signed 32767 limit, while it should have been unsigned 65535. This immediately fixed highly noticeable glitches in two of the test applications, Vette! and Test Drive II: The Duel (both ironically of same racing simulation genre):
Before the fix, Test Drive II had noticeable warping and glitching in the road near the bottom, and the polygons in Vette! had sometimes incorrect tangents, causing them to get messy depending on the angle of polygon edge.
This also fixed the “Divide overflow” bug occurring in SoftPC, which was weirdly happening on certain times of day, which does indicate that some calculation related to the computer clock time was failing because of the incorrectly signaled overflow. Now SoftPC works quite reliably.
Bitfield instruction fixes
One recently added test application, Prince of Persia 2, used a lot of the bitfield instructions for the SHAP resource drawing on the screen (apparently RLE/LZ decoding), which originally had a really messy artifacts:
But after fixing the instructions, the levels finally looks as they should:
Time Manager fixes
Besides the bitfield instructions, Prince of Persia 2 also uses Time Manager heavily for timing, and that surfaced a couple nasty bugs in the code, which were fixed.
There are still so oddities to investigate, for example the intro sequence does not advance past second screen yet, and the death and level completion delays do not trigger during the gameplay.
Sadly these fixes do not (yet) fix the one special case in Speedometer, where Dhrystone test does not work properly because of some issues that may be related to Time Manager (it starts the same timer twice, and stops it before test, so it never runs).
Keyboard handling threading bug
There was also a nasty bug in keyboard handling, which had rather surprisingly managed to stay hidden for a quite long time; Basically, the SDL2 key events that were handled by the keyboard code on main thread had chance to accidentally modify data structures and especially the A0 register, while 68K was running in VBL interrupt handler, causing in some rare cases the A0 register value to get corrupted; This caused a lot of crashes in Prince of Persia 2, and is most likely the cause of a very rare crash in Wolfenstein 3D. The offending part code was made thread-safe, which fixed this particular crash completely.
Sound in SoftPC
This was a very minor fix, but still worth mentioning; the reason for why there was no sound in SoftPC was caused by the fact that the application was setting the sound driver volume from the SPVolCtl low memory global, which had been set to zero on startup. By improving the PRAM simulation to populate all low memory PRAM values with sensible default values, the sound works now nicely in SoftPC!
Dark Castle “_Random” bug
As Pukka guessed last Christmas, the reason for buggy behaviour of robots, and some other minor glitches, in Dark Castle was indeed related to calling of the “_Random” trap! Of the last weekend was spent on searching the bug in other places at first, such as robot behaviour code, until we noticed something strange.
In Apple documentation, and all references known to us, the QuickDraw random number generator is defined simply as a Pascal type function with the following signature (in IM: Mathematical and Logical Utilities, 3-51):
pascal short Random (void);
Which means, that the function takes no arguments, and returns a 16-bit signed integer on stack. But, however, the way Dark Castle used was rather odd:
This screenshot of ResEdit showing disassembly of the part of Dark Castle code calling _Random shows, that it actually ignores the result value at offset 000B60 by discarding it off stack! And later looking at the code, it was actually using value in D0 instead…so, a quick look at System 7 _Random trap handler gives some insight to this:
Here actually it is visible, that on real Macs, the trap trashes a number of registers, and has the side-effect of leaving result value in the D0 register (being a toolbox trap, the trap dispatcher does not clean up any of the registers, unlike it does for some of registers after calling OS traps).
So, to fix Dark Castle, we added extra code to set up the D0 register as the game expected it, and everything started to work perfectly.
Some other progress from these changes
A couple other test applications seemed to benefit of these changes too, although they still need a bit of work to make sense: Loony Labyrinth now loads correctly after bitfield instructions were fixed (and physics in it also work correctly after the DIVU.W fix), and Marathon now actually runs and is playable with the Time Manager fixes:
Interestingly both of these games still seem to suffer from having colors completely messed up, but besides this glitch, they appear to be playable and run quite nicely.
And to celebrate getting SoftPC finally to work properly, I recorded this short video of M.A.C.E. running SoftPC running David Murray’s (The 8-bit Guy) Planet X-3:
2020-09-09 23:29:07 +0300 • Merge branch 'master' of
2020-09-09 23:28:59 +0300 • Update CMake scripts to support Apple notarization
2020-09-09 21:14:01 +0300 • add missing addressing fixes
2020-09-09 20:32:11 +0300 • memory addressing fixes
2020-09-09 20:26:50 +0300 • Fix compilation error in QDColorStretchBits.c
2020-09-09 20:00:29 +0300 • Fix some warnings in StretchBits color blitters
2020-09-09 19:59:57 +0300 • Fix some warnings in CodeResourceWDEF1
2020-09-09 19:26:58 +0300 • Fix return value in C_PlotCIconHandle
2020-09-09 19:18:10 +0300 • Merge branch 'master' of
2020-09-09 19:16:59 +0300 • fixes for bitfield and divuw instructions
2020-09-07 04:23:28 +0300 • Tweak more Dark Castle CMake JSON configs
2020-09-07 00:04:11 +0300 • Simulate PRAM (SysParam) to make SoftPC sound work
2020-09-06 23:04:58 +0300 • Update MACE version in CMake config
2020-09-06 13:14:44 +0300 • Color pixeldouble & (disabled) CRT simulation
2020-09-06 03:45:52 +0300 • Update trap generator XLS file
2020-09-06 03:44:13 +0300 • Tweak Dark Castle JSON config settings
2020-09-06 01:52:48 +0300 • Hack Random result value in D0 to fix Dark Castle
2020-09-05 03:54:17 +0300 • Get correct tmCount in RmvTime for non-first tasks
2020-09-03 02:16:54 +0300 • Fix the conversion of positive count in PrimeTime
2020-09-02 19:30:04 +0300 • Fix threading issue with keyboard input module
2020-09-02 19:28:30 +0300 • Don't crash on purged handles in GetHandleSize
2020-09-02 19:27:42 +0300 • Fix a lot of Time Manager bugs & clean up the code
2020-09-02 19:23:45 +0300 • Fix typing of region handle to CMDoDrawControls
2020-08-31 23:01:40 +0300 • A simplified MakeFSSpec implementation, for POP2
2020-08-31 04:17:44 +0300 • Add missing EqualRect change in EmuUtils.h
2020-08-31 04:16:59 +0300 • Fix GetCCursor crash when ResLoad was FALSE
2020-08-31 04:16:08 +0300 • Add dummy SCSIDispatch for Loony Labyrinth
2020-08-30 21:32:44 +0300 • Add Prince of Persia 2 to test app JSON configs
2020-08-03 01:45:10 +0300 • Make NewGWorld's rowBytes to work w/ Color VETTE!
2020-08-01 20:08:42 +0300 • Record PICT2 opHiliteColor, opOpColor &opDefHilite
2020-08-01 19:45:53 +0300 • Record HiliteBit as opHiliteMode in PICT2 format
As we estimated previously, the progress has been a bit slow during the summer months, with so many things to do in “real life”. But there have been a few things here and there that have been tweaked in the moments, when there has been a moment of time. Here’s a brief breakdown of the key things that have been changed:
In attempt to get some picky color games to work (such as Warlords 2, Warcraft and A/10 attack), a number of hacks have been added:
A number of placeholder gestalt functions, with dummy values to allow the games to pass startup tests (for example, Warlords 2 appears to not start unless the system tells it supports truetype fonts…)
Some help manager’s Pack14 selectors, such as querying balloon help mode and setting the balloon help mode
A number of process manager selectors in OSDispatch, which seem to be used by some apps to check if it is in foreground in multitasking environment
More dummy placeholders for Apple Events. There was not yet time to research futher, but I’m guessing some of the apps are expecting kAEOpenApplication (‘oapp’) event at startup to proceed correctly. The apple events will most likely be implemented parallel to better process manager support later, so that any dependencies with EPPC can be verified)
subPin mode for the awesome looking alpha-blended shadows in Warlord’s 2 windows
More work is still needed to make the above games work, assumedly the lack of AppleEvents right now is blocking a number of them from working.
Eric’s Ultimate Solitaire Sampler also required implementing (& fixing) some things:
Some color blitter updates (blend and srcBic transfer mode improvements, and other minor improvements). The game uses these to do nice blending effects on the highlighted cards, including blending the card “slots” with background. These appear now to draw exactly like on real Mac.
‘PICT’ opOrigin opcode was fixed, if a picture would have a non-zero origin, the fact that V and H values were swapped would cause it to be drawn at a wrong location
One of the most important changes was finally fixing the SANE’s Extended 80-bit to 64-bit double encoding/decoding bugs. The basic exponent/fraction conversion was already fixed over one year ago, but the special cases were completely broken (such as NaN, Inf and zero values). Also, clamping the exponent/fraction values when doing conversion to lower bit size was broken, instead of actually getting clamped these values would wrap around…not good! Most notable result of these fixes is that Speedometer now displays properly zero (0) as the initial score instead of 2.0.
Below are some screenshots of this awesome-looking card game:
There are still a couple issues left to fix, most notably the game complains about missing resources on each startup, even though it still succeeds to open. And as the sound manager implementation for the color version environment is still unfinished, there are no sounds yet. But mostly, the game works quite well, and is very playable, as you can see from the number of games and time played statistics screenshot above 🙂
At the moment, Toni is working on getting the picture recording to work in color mode (PICT2 support), which is required to get some editors to work properly in ResEdit, and Pukka is researching the full extension word format of 68020 emulation, which when will allow a large number of new color applications to work.
Full list of changes since last post
2020-07-31 22:06:34 +0300 • More work on PICT2 recording (pixpats in-progress) 2020-07-21 05:29:26 +0300 • Support grafProcs' putPicProc for StdPutPic 2020-07-21 05:01:31 +0300 • Implement CopyPixPat trap 2020-07-16 22:41:09 +0300 • Initialize pnMode correctly in OpenPicture 2020-07-16 22:40:40 +0300 • Fix PICT verb recorder bugs (pnSize & swap pnMode) 2020-07-16 05:13:03 +0300 • Make StdComment recording version 2 compatible 2020-07-14 05:47:44 +0300 • OpenCPicture & ColorQD OpenPicture abstraction 2020-07-08 05:31:55 +0300 • Tweak Float64 to Float80 conversion (denorm exp) 2020-07-07 14:34:46 +0300 • Other Float80 special cases; NaN, denormals, infs 2020-07-04 20:35:08 +0300 • Handle zero special case @ 80-bit float conversion 2020-07-04 12:28:21 +0300 • Fix mixed up H and V delta values in opOrigin 2020-07-04 12:26:43 +0300 • Add non-colorizing stretch blitter for srcBic mode 2020-07-04 04:05:17 +0300 • Fix opOrigin picture opcode 2020-07-04 02:35:44 +0300 • Fix missing alignment shift of arithmetic blitters 2020-07-03 14:39:58 +0300 • Implement FSUBS for SANE's FP68K dispatcher 2020-07-03 14:34:15 +0300 • Improve direct color support in stretch blitter 2020-06-28 01:38:25 +0300 • Add indexed region blitter for "blend" (0x20) mode 2020-06-28 01:36:23 +0300 • Add Eric's Ultimate Solitaire Sample test app 2020-06-22 02:45:59 +0300 • Fix inverted handling of TE record's active flag 2020-06-22 02:44:50 +0300 • Add AE and ProcMgr control configs to environment 2020-06-14 04:58:58 +0300 • Add Prince of Destruction test app to cmake JSON 2020-06-13 21:42:12 +0300 • Add missing procNotFound define to MacErrors.h 2020-06-13 21:41:27 +0300 • Add A10 Attack! Demo test app to cmake json config 2020-06-13 19:13:46 +0300 • Add dummy GetNextProcess 2020-06-13 19:13:10 +0300 • Add some missing data types & enums to Processes.h 2020-06-12 04:08:43 +0300 • Add dummy InitEditionPack & EditionManager module 2020-06-12 03:56:06 +0300 • Add dummy RestoreDeviceClut selector 2020-06-12 03:44:33 +0300 • Properly fix the previously disabled optimization 2020-06-12 00:10:50 +0300 • Add dummy AESetInteractionAllowed Pack8 selector 2020-06-11 17:48:36 +0300 • Fix InvalMenuBar to really work (Warlords 2 menus) 2020-06-10 20:57:41 +0300 • Disable a buggy copybits colorization optimization 2020-06-10 19:09:03 +0300 • subPin mode color region blitter (WarLords 2 demo) 2020-06-10 19:08:15 +0300 • Fix invCT pointer in color mapping (skip header) 2020-06-10 13:59:56 +0300 • Fix WDCB allocation: list size is bytes, not count 2020-06-10 05:57:31 +0300 • Dummy HMIsBalloon & HMSetBalloons for Pack14 2020-06-10 05:51:30 +0300 • GetCurrentProcess, GetProcessFromLayer, SameProc.. 2020-06-10 05:29:24 +0300 • Implement AECreateDesc in Pack8 (AppleEvents) 2020-06-10 05:28:23 +0300 • Add MacAppleEvents.h (+move old stuff from Events) 2020-06-10 05:27:17 +0300 • Tweak trap generator to allow "result" param name 2020-06-10 04:49:08 +0300 • Add dummy OSDispatch & GetProcessInformation 2020-06-10 04:17:52 +0300 • Fake gestaltLaunchControl flag for Warlords 2 2020-06-10 03:52:44 +0300 • Fix script mgr gestalt functions (emIntlGlobals) 2020-06-10 02:35:00 +0300 • Add 'a/ux', 'edtn', 'help', 'pop!', 'font', 'stdf' 2020-06-10 01:23:22 +0300 • Add dummy AEInteractWithUser selector for Pack8 2020-06-10 01:14:16 +0300 • Add 'kbd', 'hdwr', 'evnt' and 'os ' gestalt funcs
Since the last update, there has been progress on many features, but especially on the following ones to highlight:
The GWorld routines are practical utility functions for easy creation and handling of off-screen color ports, relieving the developer from a lot of mundane tasks for allocating the memory structures and house-keeping them. In the old “classic” QuickDraw, the developers were forced to do all this by themselves, but on other hand, the old-style QuickDraw had a lot less complexity and fewer data structures. The color QD requires maintenance of PixMap structures, and possibly “fake” GDevice handles with unique color tables and inverse color lookup tables, etc. The routines which color version were implemented this time were (* indicates ones that previously existed for “classic” QD’s GWorld wrappers):
The games which benefitted most of the new GWorld routines were Wolfenstein 3D, SimCity 2000 and Civilization. It is also possible other games are utilizing them, but these were the ones first encountered in the test suite:
Another new feature added in the color QuickDraw are the PixPat patterns. As old QuickDraw only allowed 1-bit monochrome patterns, these PixPats have much more flexibility allowing multi-color patterns and also higher resolutions (most commonly seen as powers-of-two from 8 to 64 pixels, and up to 256 colors, although the PixPat data supports also “direct” pixel data).
The interesting feature of these “pixel patterns” is the fact that they actually use regular PixMap data as the pattern storage, so that a lot of internal routines for PixMap manipulation were directly helpful in the implementation of the color patterns. The most code needed for pixpat-specific drawing were the conversion to target depth (using the shader PixMap translators), and handling the special pattern modes in blitters, with repetition of pattern with variable-size dimensions.
The first games requiring use of PixPats were Glider 4.0 and Siege of Darkwood – but as a nice side effect, we now also have support for using color patterns on the desktop!
There were also many other minor improvements, some of which include:
Finally a proper region-clipped color blitter (was on TODO list for a long time…)
32-bit PICT pixel data support, needed for Escape Velocity
CopyBits & ScrollRect, for Civilization and SimCity 2000 map scrolling
A bunch of new blitter modes
Partial resouce read support for SimCity 2000
Abstracted resource loading as a magic “CheckLoad” vector, to make AutoDoubler-compressed applications work (the one we encountered was the color version of Lemmings)
MANY bug fixes and other improvements (complete list of everything at the end of this post)
Since the the last post, we have two new videos of test applications running in color mode. First is Glider 4.0, which seems to now be playable, benefitting especially from the most recent transparent arithmetic transfer mode support:
Also, here’s video of Wolfenstein 3D running (the lag is from QT video capture, game itself runs quite smoothly):
And of course as Sound Manager is not yet implemented, there is no audio in either videos.
Status of some of the color test applications
There are also some other games which are starting to get more functional in color mode, here’s a brief update on where they’re at right now:
Most of these games run nicely, but there are some common issues still to be resolved:
Menu drawing still need to be updated to support color mode properly
List Manager does not yet handle hilite mode properly
Scroll Bars are still rendered as monochrome versions only
Standard File dialogs have still issues with color mode (folder popup menu, hilite mode, etc)
No sound yet because of incomplete Sound Manager implementation
Horizontal stretching for pixmap data is not yet implemented (although vertical stretching is), so horizontally scaled text/images do not yet appear properly
A lot of missing blitter modes (they will be written as needed in the first pass, but will be generalized and optimized later so that all cases will be properly covered)
There are also a couple cases with application-specific problems:
Maelstrom is playable & smooth, but gets stuck at end of level screen probably because of missing Sound Manager Implementation
Civilization has a rare bug where inverse color tables appear to break down after playing the game for some time
SimCity 2000 has a palette manager bug where a couple of palette entries go to wrong slots, causing a couple specific colors to not display properly (mostly visible in the title screen, and “Dispatch Firefighters” map sprite)
Escape Velocity gets to main menu, but crashes due to some unresolved 68k cpu emulation bugs which Pukka is investigating
The status page will be updated in the coming weeks to reflect this new status.
Full list of changes since last post
2020-04-07 00:38:42 +0300 • Add pixpat patOr mode for color rectangle blitter
2020-04-07 00:31:42 +0300 • Add srcBic support to color rectangle blitter
2020-04-07 00:30:52 +0300 • Fix outline/shadow text style in color text render
2020-04-06 21:29:15 +0300 • Do 68K VM stack guard magic check for native fra..
2020-04-06 01:07:31 +0300 • Set bg color in SetWinColor, fix Siege of Darkwood
2020-04-06 00:39:03 +0300 • Fix crash when decoding pixpats from PICT resource
2020-04-05 23:10:26 +0300 • Fix GetPalette bitmasking (missing window redraws)
2020-04-05 05:21:26 +0300 • Indexed transparent arithmetic region renderer
2020-04-05 04:39:00 +0300 • Indexed transparent arithmetic rectangle renderer
2020-04-05 03:22:26 +0300 • Indexed transparent arithmetic scanline renderer
2020-04-04 16:53:34 +0300 • Clean up old commented-out legacy code
2020-04-04 16:52:27 +0300 • Handle undefined EnvDefaultColorDepth case
2020-04-04 16:51:21 +0300 • Handle arithmetic mode setup for color mapping
2020-04-01 22:24:46 +0300 • Update test desktop background pattern
2020-04-01 03:01:26 +0300 • Color desktop ppat (forced on for now for testing)
2020-04-01 02:47:14 +0300 • Fix 8x8 pixpat expansion
2020-04-01 01:59:00 +0300 • Implement (mostly) pixpat conversion & rendering
2020-04-01 01:57:35 +0300 • Separate pixel translation from stretch blitter
2020-04-01 01:43:46 +0300 • Clear CGrafPort refs to pixpat in DisposePixPat
2020-03-30 16:59:25 +0300 • Add (partial) FillCRect/Oval/Arc/Rgn/Poly
2020-03-30 16:00:04 +0300 • Add EnvDefaultColorDepth for app-specific default
2020-03-30 15:32:31 +0300 • Fix region masking bug of diagonal Line/LineTo
2020-03-30 15:30:07 +0300 • Fix ErasePoly (typo from copy-paste)
2020-03-30 11:53:03 +0300 • Fix right-to-left color rectblit & right-edge mask
2020-03-30 04:57:07 +0300 • Add srcXor mode for non-colorizing stretch blitter
2020-03-30 04:54:25 +0300 • Color QD version of polygon operations
2020-03-30 04:47:10 +0300 • Add region-clipped color blitter & fix LOT of bugs
2020-03-30 04:44:10 +0300 • Fix invalid masking in srcCopy in translating blit
2020-03-30 01:18:15 +0300 • Fix iteration of region 3-only non-rect case
2020-03-28 21:53:06 +0200 • Fix inverted hilite flag check in colorized WDEF 0
2020-03-27 21:39:58 +0200 • Fix TextEdit locals saved forecolor overlap bug
2020-03-27 20:45:13 +0200 • Add color support also to WDEF 0 zoom box drawing
2020-03-27 19:34:27 +0200 • Add color support to WDEF 0 growbox drawing
2020-03-27 16:36:51 +0200 • Add (partial) color QD support for ScrollRect
2020-03-27 15:18:16 +0200 • Add Loony Labyrinth test app to CMake JSON configs
2020-03-27 15:17:43 +0200 • Implement SaveFore/Back & RestoreFore/Back
2020-03-27 02:46:11 +0200 • Fix (again) AnimatePalette
2020-03-27 01:36:19 +0200 • Set default palette in GetNewWindow/GetNewCWindow
2020-03-26 23:12:07 +0200 • Implement ReadPartialResource in ResourceDispatch
2020-03-26 22:26:03 +0200 • Fix HCreateResFile (dirID mishandled)
2020-03-26 21:02:04 +0200 • Improve StdText CGrafPort/GWorld compatibility
2020-03-26 21:00:46 +0200 • Fix CloseResFile stack frame mismatch
2020-03-26 20:11:11 +0200 • Implement SetPixelsState and AllowPurgePixels
2020-03-26 19:54:40 +0200 • Implement GetPixelsState selector in QDExtensions
2020-03-26 19:46:06 +0200 • Implement SetGWorld selector in QDExtensions
2020-03-26 19:33:15 +0200 • Implement GetGWorldPixMap selector in QDExtensions
2020-03-26 19:16:17 +0200 • Implement GetGWorld in QDExtensions
2020-03-26 19:12:42 +0200 • Implement Palette2CTab
2020-03-26 18:45:36 +0200 • Add SimCity 2000 test app to CMake JSON configs
2020-03-26 17:24:03 +0200 • CopyBits improvements (fix Escape Velocity crash)
2020-03-26 02:59:02 +0200 • Add 32-bit to indexed color conversion to blitter
2020-03-26 02:57:00 +0200 • Fix rgb PICT data unpack for rowBytes > 250
2020-03-26 02:56:00 +0200 • Implement DisposeCIcon
2020-03-25 22:09:57 +0200 • Support 'PICT' packType=4 RGB data (run-packed)
2020-03-25 20:45:05 +0200 • Start collision check from current link, not next
2020-03-25 19:08:43 +0200 • Fix color blitter for <=32bit wide transfers
2020-03-25 18:35:49 +0200 • Conditionalize Paletter Manager debug log output
2020-03-25 18:34:59 +0200 • Handle collisions in inverse color table lookup
2020-03-25 14:08:12 +0200 • Validate input in SetEntries & clear cached fonts
2020-03-25 03:01:34 +0200 • Fix UInt16/SInt16 RGB delta bug in palette update
2020-03-25 01:13:22 +0200 • Add missing A6 setup for the CheckLoad wrapper
2020-03-25 01:05:40 +0200 • Add secret "CheckLoad" hook (AutoDoubler support)
2020-03-25 00:57:35 +0200 • Add color Lemmings JSON to CMake test apps configs
2020-03-24 22:34:47 +0200 • Clamp cursor hotspot between [0, 15]
2020-03-24 22:34:15 +0200 • Fix color CopyBits thePort/dstBits comparison bug
2020-03-24 19:55:58 +0200 • Extract color QD rect blitter to own module
2020-03-24 19:30:09 +0200 • Implement DisposeGDevice (used in DisposeGWorld)
2020-03-24 14:47:56 +0200 • Implement color QD version of ClosePort
2020-03-24 04:24:57 +0200 • Unreserve palette entry when cleared (single GD)
2020-03-24 04:23:41 +0200 • Set MemErr to noErr in ReservMem on success
2020-03-24 02:35:37 +0200 • Fix negative dstLeft corruption @ B/W stretch blit
2020-03-23 21:01:59 +0200 • Implement DeleteMCEntries
2020-03-23 20:50:33 +0200 • Paint window (and invalidate) on ActivatePalette
2020-03-23 20:49:14 +0200 • Draw desktop pattern for PaintOne(nil) case
2020-03-23 20:44:03 +0200 • Fix AnimatePalette for srcIndex > 0 cases
2020-03-23 01:41:36 +0200 • Fix GetCatInfo bug by previous fix (non-WDCB case)
2020-03-23 01:27:40 +0200 • Minor menu color entry manipulation tweaks
2020-03-23 01:25:58 +0200 • Fix monochrome QD compilation error
2020-03-22 23:36:53 +0200 • Implement SetEntryColor
2020-03-22 23:24:53 +0200 • Implement GetPalette trap for Palette Manager
2020-03-22 22:09:37 +0200 • Extract PaletteDispatch routines to own C module
2020-03-22 21:42:58 +0200 • Add Ultimate Doom test app to JSON configs
2020-03-22 21:42:24 +0200 • Add CTabChanged and (partial) DisposeGWorld
2020-03-22 07:33:06 +0200 • Give more CPU time for 68020+ mode
2020-03-22 06:46:10 +0200 • Fix buffer size bug in NewGWorld w/ pixelDepth = 0
2020-03-22 03:55:04 +0200 • Implement FCMPS in FP68K (SANE) for Wolf3D
2020-03-22 03:42:46 +0200 • Improve bits opcode (9x) for non-indexed support
2020-03-22 03:37:10 +0200 • Implement NoPurgePixels selector
2020-03-22 03:36:45 +0200 • Fix unassigned pmBounds.left bug in NewGWorld
2020-03-22 02:23:21 +0200 • Implement color QD version of NewGWorld
2020-03-22 02:22:18 +0200 • Resolve WDCB to DirID in GetCatInfo ioFDirIndex>1
2020-03-21 18:50:18 +0200 • Add 'qdrw' Gestalt selector (Quickdraw features)
2020-03-21 04:44:26 +0200 • Fix pixpat opcodes in DrawPicture
2020-03-21 04:42:32 +0200 • Implement unpacked pixmap data load in DrawPicture
2020-03-21 04:40:28 +0200 • Fix CloseWD crash (ignore ioNamePtr)
2020-03-21 03:43:35 +0200 • Implement CopyPixMap
2020-03-21 02:26:20 +0200 • Fix GetPenState bug (caused gray fills everywhere)
2020-03-21 01:33:43 +0200 • Implement color QD version of ScrnBitMap
2020-03-21 01:20:54 +0200 • Hack tmp SoundBase to make Glider 4 happy in color
2020-03-21 01:19:08 +0200 • Implement color CopyMask (untested!)
2020-03-21 01:17:37 +0200 • Fix missing argument deref in color pat conversion
2020-03-21 01:16:34 +0200 • Add 'vm ' Gestalt selector (returns 0 for no VM)
2020-03-21 01:14:12 +0200 • Add HWPriv & dummy FlushData/FlushInstructionCache
2020-03-20 19:18:33 +0200 • Fix colorQD highlight bug of radio/checkbox button
2020-03-20 19:09:02 +0200 • Implement grayishTextOr mode for StdText
2020-03-20 19:07:55 +0200 • Implement GetGray selector for PaletteDispatch
2020-03-20 19:06:06 +0200 • Tweak signature of rgb delta calculation to UInt16
2020-03-20 18:20:45 +0200 • Implement patBic mode in pattern rect blitter
2020-03-20 06:22:31 +0200 • Fix StdGetPic, handle byteCount as unsigned UInt16
2020-03-20 06:20:48 +0200 • Implement GetPixBaseAddr selector in QDExtensions
2020-03-20 05:27:15 +0200 • Fix masking bug in color stretch blitter
2020-03-20 03:38:11 +0200 • Add a bunch empty dummy SoundDispatch placeholders
2020-03-20 02:57:14 +0200 • Implement QDError trap
2020-03-20 02:54:26 +0200 • Implement FSpOpenResFile and FSpCreateResFile
2020-03-20 02:52:57 +0200 • Implement HCreateResFile
2020-03-20 02:29:20 +0200 • Add semi-dummy ResolveAliasFile selector
2020-03-20 02:08:52 +0200 • Add Escape Velocity test app to cmake configs
2020-03-20 02:08:30 +0200 • Add missing file from previous commit
2020-03-20 02:08:18 +0200 • Add Pack12 & Fix2SmallFract+SmallFract2Fix+RGB2HSL
2020-03-20 00:06:06 +0200 • Fix signature of SwapMMUMode
2020-03-19 23:25:45 +0200 • Fix text styling buffer overflow in color QD
2020-03-19 23:22:36 +0200 • Apply kernMax in color font renderer
2020-03-19 19:18:59 +0200 • Update & re-seed GDevice pmTable in SetEntries too
2020-03-19 16:01:13 +0200 • 4-bit debug palette view
2020-03-19 16:00:59 +0200 • Implement SetPortPix trap
2020-03-19 01:26:06 +0200 • Add fake SwapMMUMode trap
2020-03-19 01:24:19 +0200 • Add dummy 'snd ' Gestalt selector
2020-03-19 01:23:39 +0200 • Dummy SoundDispatch (& dummy SndPlayDoubleBuffer)
2020-03-19 00:40:09 +0200 • Add Maelstrom test app to cmake configs
2020-03-19 00:39:47 +0200 • Dispose auxCtlRec also in DisposeControl trap
2020-03-19 00:29:57 +0200 • Fix 'cctb' ID=0 bug
2020-03-19 00:15:34 +0200 • Implement ProtectEntry and ReserveEntry traps
2020-03-18 23:53:47 +0200 • Fix RS stack frame mismatch in FrameRect
2020-03-18 23:53:10 +0200 • Implement TestDeviceAttribute & SetDeviceAttribute
2020-03-18 23:44:13 +0200 • Implement GetCWMgrPort trap
It is now two years since we started this project, and so far the progress is looking promising. At this point, it is good to take a brief overall look at where we are right now… so far, we have a lot of phase #1 goals accomplished:
Good enough 68000 emulation to run majority of games designed to use that CPU.
Majority of “classic” QuickDraw traps implemented to allow black & white games which needs them to work. Also hardware-level VIA page-swapping support for double-buffered games such as Dark Castle and Continuum.
Complete “.Sound” driver functionality, including ~99% coverage of low-level sound hardware emulation to allow games such as Dark Castle, Tetris and Pirates! to have working sound.
External file system emulation with HFS metadata support abstracted to ADF files, with almost all read/write operations tested working (except delete/rename, which have so far been rarely needed)
Basically implemented most of toolbox calls needed to, get out of the 87 test applications, 78 to work in at least somewhat usable way, and 43 to function near-perfectly.
Ability to run (or try running) the test applications/games as native OSX application bundles (and now with Windows support, also as windows EXE files), with full mouse/keyboard support, fullscreen/windowed and pixel-double support. Sound also mostly works but the SDL buffering needs some tweaking especially on windows…
As the toolbox is quite large, and there is a large number of traps/selectors which are rarely needed, and have not been encountered in the applications we have been testing vigorously. These APIs are still unimplemented, but they will be eventually added to the emulation. However, because these missing phase #1 features have such minor impact on most test applications, we also have started to work on some phase #2 features which are not only beneficial for a lot of current test suite, but which also will allow a huge number of new applications to be added to our tests:
68020/030/040 emulation, which Pukka has already done a lot of progress on.
Color QuickDraw support, which was started after Christmas (more about that later in this post – very important for getting color games to work!)
Some preliminary progress on System 7.x APIs (FSSpec calls, Folder Manager, Time Manager, Script Manager, etc.).
Because of the fact that as we are implementing new features in a parallel fashion, we don’t have any fixed schedule for milestones. But realistically we expect to get a lot progress on the color support during the spring, which is the biggest bottleneck for getting much larger test application coverage. The downside of this is, however, that a “generic” emulator release will get delayed, because we want it to be as complete as possible, so that you won’t have to suffer from the incomplete features until we get everything polished. You can always follow the test application coverage (and overall progress) on our status page at https://mace.software/status/.
Color QuickDraw progress & first color game (somewhat) playable: KYE!
Since the previous post, majority of work as focused on getting source-mode blitting to work within the color hardware and Color QD API emulation. One of the easiest test cases for that purpose is a fun game called KYE, which was one of personal favorites of Toni on his LC II in early 90’s. The reason why this particular game is nicely suited for this early-stage testing is the fact that it uses mostly just PlotCIcon to draw all of its “sprite” graphics. Thanks to this, we did not have to work on a huge number of different calls at once, but were able to focus on getting that single call working. That way we could get something visible progress on the screen, instead of the invisible “under-the-hood” type of progress which has more impact on the long term.
For curiosity, below is a set of screenshots taken during the PlotCIcon development, which shows how the bugs were squished one by one until the rendering was finally okay:
Here’s a screenshot of latest stage of PlotCIcon functionality in KYE:
As you can see in the screenshot, icon rendering is working nicely, but text rendering is still completely missing. We also updated the WDEF 0 to have most of color support, so it uses now shading from the default ‘wctb’, leading to authentic System 7-style look and feel. Because of early stage of implementation, the color blitter has right now following limitations:
Blitter only works on “indexed” targets (1-8 bit pixmaps), i.e. not on “direct” (16/32-bit) screens
Only supports indexed sources too
Only simple srcCopy and srcOr modes supported (non-colorized)
No stretching support yet (only 1:1 scaling)
No arithmetic modes yet
Focus at this stage is on accuracy – that is, getting the output results to look exactly same as on the original, “real” Color QD – so performance is far from optimal for now. Leaves a lot of space for blitter optimization in future though…
Probably a lot of other use cases which I can’t recall right now…
Below is also a short video of level 2 gameplay:
Anniversary bonus! PT-109 gameplay video
To celebrate the two-year anniversary, we also recorded 90 minutes of PT-109 gameplay to show the current state of that game’s compatibility with M.A.C.E. below:
This video shows what to expect when we get the “generic” emulator released some day in the future. For now, we can only share the video of this awesome game as it is sadly copyrighted – but we have a bunch of freely available games at our downloads page at https://mace.software/files for both Mac OS X and Windows 64-bit.
If you are interested in keeping up with our progress (now that we start the third year with full speed) you can follow this blog, or one or more of the following:
One of the major features of phase #2, as we originally wrote in the milestone and phase plan two years ago, is adding support for Color QuickDraw emulation. Even though a lot of APIs considered part of phase #1 are still incomplete, the application compatibility and overall progress of project appears good enough to justify starting the work on that particular feature at this point. Nevertheless, all missing phase #1 features will be worked on simultaneously as they come up when testing the applications.
Adding color support will eventually allow us to test a huge number of new applications and games, and it will also allow trying out the existing ones in color modes. Especially games from the early 1990s have very good support for multiple color depths, so it should be interesting (for example, Civilization’s support for 1-bit and 256 colors, Railroad Tycoon’s 1-bit and 16 color support, Glider’s 16-color art, etc…)
First steps: The slot-based architecture
Originally Apple’s Mac II lineup had a quite different architecture from the old “classic”-type compact macs, which also reflects on how Color QuickDraw operates. Instead of dividing the memory space into four regions as in “classic” Macs (4mb RAM, 4mb ROM, 4mb I/O and 4mb VIA space), the slot-based models (in original 24-bit model) divide memory into 1mb “slots”, which are more dynamically assigned. For example, IM:Memory 3-6 describes the following model (in 24-bit mode):
0x900000-0xEFFFFF: Nubus slot addresses
That particular model fits quite well with the currently implemented 24-bit memory manager, so we use that as a starting point for Color QuickDraw machine emulation. It also allows us to partially emulate slow manager APIs (as slot numbers $9 through $E match their address space as on real Macs), and allows possibility for emulating multiple screen using multiple “virtual” slot manager cards, one for each screen. The drawback of this, though, is that only one megabyte is assigned for each video device in 24-bit mode, which limits usable VRAM to that 1 megabyte. What this practically means, is that these are the approximately maximum supported “standard” resolutions for each color depth:
1-bit (black & white): 3840 x 2160 (4K)
2-bit (4-color): 2560 x 1440 (QHD)
4-bit (16-color): 1920 x 1080 (FHD)
8-bit (256-color): 1280 x 720 (HD)
16-bit (32K colors): 832 x 624 (Mac 16″)
32-bit (16.7M colors): 512 x 384 (Mac 12″)
Of course, when we later someday add 32-bit memory manager support, we will have 256 megabytes per video device, and can get rid of this limitation.
The slot driver
One key component between the “virtual” slot-based video device emulation, and the Color QuickDraw, is the device driver for the slot device. In our case, we added the .Display_Video_MACE_FB driver (following Apple’s naming convention for slot drivers), which is used by QuickDraw’s and Color Manager to control video modes, color table, etc.
On real Macs slot manager would be responsible for iterating parsing sRsrc:s and other slot-specific data structures, but we forego those hardware-specific details and address the native video device data (currently SDL) through our platform-abstraction interface.
The DRVR calls are still important to implement properly, as they were quite standard on real Macs, and there might be apps using them directly, even though well-behaving apps should always use GDevice, Color Manager and Color QuickDraw API calls.
Platform abstraction for color video
As we already had prepared for adding color support when starting the project two years ago, most of the support for it existed already in the platform abstraction layer. There were a couple tweaks needed, but most work was just adding the output renderers for each of the new color depths (originally there was only 1-bit blitter, as it was the only color depth supported on classic Macs). This also included adding the color lookup tables in the pipeline, so that we are ready for Palette Manager when we get to the point of implementing it.
As there may exist any number of screens, with any resolution and various color depths, Color QuickDraw added the concept of GDevices. Each GDevice represents one screen/video card attached to the system, with its own screen buffer, color & gamma tables, etc.
Color QuickDraw allows drawing to all of these devices at once using the standard toolbox API, doing all the color conversion and addressing for the user. This is what we need to implement next also in our emulator.
One key component of Color QuickDraw is Color Manager, which is responsible for managing the color tables for each GDevice. What this means, that it creates and manages the inverse color lookup tables (which are used to map RGB colors to indexed colors), and handles those lookups. It also keeps track of seed values for color tables, which are used to determine when color tables have changed, which is important especially if a previously expanded pattern is drawn after a new color table has been activated. For now, we implemented a very basic ITable generation for allowing RGBColors to work on indexed color modes.
Inverse color-lookup table
As meantioned above, one key feature of Color Manager is the generation and management of ITab data structures, which are used to map RGB Colors back into color table indices in indexed video modes (2-, 4- and 8-bit depths). The generator is run in MakeITable trap handler, which takes handle of color table, handle of output inverse table, and desired channel resolution as arguments.
The inverse table is actually a RGB cube, where the cube’s channel size is defined by the number of bits given as the resolution; so for example resolution of 4bits gives 2^4 = 16, and the entire RGB cube would take 16x16x16 bytes which is 4096 bytes, or 4K of memory. As in three-dimensional XYZ space, RGB cube can be thought of in the same way; Each R, G, B coordinate are used to locate index in the cube’s 3-dimensional table.
When Color QuickDraw wants to get for example, index of RGB color #E39EA0, Color Manager would convert first the RGB components into cube’s resolution range (in this case, result would be (14, 9, 10]), and use those values of index the ITab data to get the value.
When the cube is generated by MakeITable, it is initially empty, but is given the seed values from the source color table; each seed value is the color lookup table index, placed at the RGB coordinate which it specifies. After this, the seed values are progressively iterated, so that each value “spreads” into adjacent RGB cube slots in any of the six axis directions (+R/-R, +G/-G, +B/-B). This is repeated as long until there are no longer any unfilled slots left in the RGB cube. This is familiar method from basic pathfinding, and some maze generation algorithms, and ensures that each RGB cube slot contains the index of color lookup table which is the closest available approximation for that particular RGB color.
PixMaps (and PixPats)
As BitMaps only supported 1-bit graphics, Apple added PixMap in Color QuickDraw to allow representing graphics of any bit depth using a standard data structure. Additionally, the GDevices use PixMap to represent the VRAM buffers, and PixPat (multi-color patterns) structure also uses PixMap as storage for the pattern data. And they also are by default implemented as Handles, which means they can be moved in the heap during compaction to prevent memory fragmentation (but require locking in certain cases).
The first step: Using legacy GrafPorts with Color QuickDraw
As Color QuickDraw has a lot of layers to provide backwards-compatibility for older applications, the first step was to start from the most basic one, legacy GrafPort support. As the very first call done to QuickDraw is to gray out the screen at startup, we focused on getting the most basic case for FillRect working at first. With adding support for pattern expansion to any pixel depth, and adding new srcCopy blitters, we got this fist monochrome output result after a couple weeks of coding:
When emulating the old-style GrafPorts, of of their interesting features to simulate was support for the 8 old-style QuickDraw colors (which map mostly to the colors used in ImageWriter printers with CMYK ribbon). With proper color mapping, and a couple days of banging the head against desk, we ended up with this result:
Second step: CGrafPort support
As mentioned earlier, the old-style GrafPorts were limited to only displaying those 8 colors, so to get the full range of RGB colors displayed, we had to add a proper CGrafPort support. This included implementing OpenCPort and InitCPort, and initialization of all related data structures. For example, all patterns in CGrafPorts are PixPat patterns, so we had to do a Pattern-to-PixPat conversion.
Most importantly, the fgColor/bkColor no longer represented the old-style color constants, but instead needed to be mapped to bit-depth specific index (on indexed device modes) or pixel value (on direct device modes). To control these colors, we implemented the RGBForeColor/RGBBackColor traps, which map the RGB values to the mode-specific values.
After a couple of days of more hard work, we now have the RGB colors working in CGrafPorts:
There is still A LOT of things to do before we can get much beyond simple rectangles on the screen, but the tasks should get easier as we go along. A lot of the routines (such as color mapping) can probably be shared as-is with most of other Color QuickDraw APIs. Some of the tasks next up are:
Adding region masking variant to the color blitter
Adding other pattern modes beyond patCopy
Adding source transfer modes (only patCopy done at the time of writing this)
Color versions of the special horizontal single-scanline blitters
A lot of other stuff
Full list of changes since last post
2020-01-31 18:02:57 +0200 • Basic support for "oldPat" PixPats in CGrafPorts 2020-01-31 16:35:14 +0200 • Implement InvertColor (default gdCompProc only!!!) 2020-01-31 13:47:55 +0200 • Some progress on CGrafPort colormapping & bugfixes 2020-01-30 02:10:42 +0200 • Add ColorQD Fore/BackColor & RGBFore/BackColor 2020-01-30 01:25:49 +0200 • Init default ColorQD PixPat patterns in InitCPort 2020-01-29 20:06:33 +0200 • Implement NewPixMap and NewPixPat 2020-01-29 01:42:41 +0200 • Initialize WMgrCPort (color port) in InitWindows 2020-01-29 01:41:59 +0200 • Implement OpenCPort and (mostly) InitCPort 2020-01-29 00:48:03 +0200 • Implement GetPixPat and GetCCursor colorQD traps 2020-01-28 22:12:56 +0200 • Implement DisposePixPat trap handler in color QD 2020-01-28 01:46:18 +0200 • Fix non-default colored patterns in 1-bit mode 2020-01-28 01:11:02 +0200 • ColorQD compatible GlobalToLocal/LocalToGlobal 2020-01-27 20:22:27 +0200 • Fix palette alignment issue in 8- and 15-bit modes 2020-01-27 20:20:38 +0200 • 15-bit (thousands of colors) SDL rendering support 2020-01-27 20:20:04 +0200 • 2-bit SDL output rendering support 2020-01-27 20:19:27 +0200 • Disable grayscale flag for now, test&fix it later 2020-01-27 20:18:37 +0200 • Fix last palette entry missing (zero-based count) 2020-01-27 13:33:46 +0200 • Add support for direct colors in color mapping 2020-01-27 13:26:34 +0200 • Set GDevice's gdType properly at initialization 2020-01-27 10:38:45 +0200 • GDev CLUT setup & rendering (first colors output!) 2020-01-27 09:44:47 +0200 • ColorQD ForeColor/BackColor in old-style GrafPorts 2020-01-27 09:43:56 +0200 • Fix initialization of QDColors low-mem global 2020-01-27 04:59:25 +0200 • Use Color2Index in color mapping for correct color 2020-01-27 04:56:41 +0200 • Set GDevice's gdResPref in the InitGDevice handler 2020-01-27 04:39:29 +0200 • Color2Index proto (no hidden color handling yet) 2020-01-27 04:36:27 +0200 • Fix the one-entry off "black-most black" index bug 2020-01-27 04:11:57 +0200 • Finish the first proto of MakeITable 2020-01-27 03:19:38 +0200 • Remove unneeded mitq resource from build 2020-01-27 03:18:51 +0200 • "Plant" seeds for the ITab generator from the clut 2020-01-26 00:24:21 +0200 • Start work on MakeITable 2020-01-26 00:23:50 +0200 • Tweak pattern blitters, preparing 8-bit support 2020-01-26 00:22:14 +0200 • Dummy Color2Index stub, prep use in colormapping 2020-01-25 17:05:21 +0200 • Hack 4- and 8-bit (16 & 256-color) output support 2020-01-25 17:01:45 +0200 • Fix old-type pattern to 8-bit conversion 2020-01-25 16:55:25 +0200 • Fix mask calculation for non-1-bit rectangle blits 2020-01-25 02:21:23 +0200 • First simple non-region FillRect case for ColorQD 2020-01-25 02:20:38 +0200 • Block attempting to post events before InitEvents 2020-01-25 02:19:04 +0200 • Fix the "dummy buffer" string RSAlloc overflow 2020-01-24 02:35:50 +0200 • Some progress on color blitter rectangle culling 2020-01-24 02:34:20 +0200 • Add QDErr low-mem global 2020-01-24 00:05:55 +0200 • Do CQD old 1-bit pattern to b&w GrafPort expansion 2020-01-23 00:18:35 +0200 • First CQD color mapping pass for old-type GrafPort 2020-01-22 17:53:29 +0200 • A bit of work on the color QD color mapping 2020-01-21 01:32:09 +0200 • Implement portBits to PixMap conversion to colorQD 2020-01-21 01:30:38 +0200 • Init lot of lowmem globals for default videodevice 2020-01-21 01:27:42 +0200 • Fix byteswap bug on device depth in CVGetVidParams 2020-01-20 15:02:02 +0200 • Refactor QD a bit in preparation of color support 2020-01-20 02:34:13 +0200 • Disable for now dirtyrect optimization in color QD 2020-01-20 02:22:37 +0200 • ColorQD versions of InitPort and OpenPort 2020-01-20 01:33:36 +0200 • Save LastMode/-Fore/-Back/-Depth in FMSwapFont 2020-01-20 01:32:29 +0200 • Fix two indexing bugs in ColorVideoInitOneSlot 2020-01-20 01:30:00 +0200 • Implement most of InitGDevice trap for color QD 2020-01-20 01:28:50 +0200 • Add empty stub for MakeITable trap 2020-01-19 23:29:53 +0200 • Add GetDeviceList trap 2020-01-19 20:37:49 +0200 • Add grayscale flag to video devices 2020-01-19 14:36:11 +0200 • Fill in GDevice's VPBlock from color video driver 2020-01-19 14:35:34 +0200 • Fill in DCE slot info in Open call for slot device 2020-01-19 05:03:02 +0200 • Add one more missing ROM clut resource 2020-01-19 05:02:32 +0200 • Add DisposePixMap, New/InitGDevice, GetNextDevice 2020-01-19 04:59:55 +0200 • Use cmake source_group TREE to clean up projects 2020-01-19 04:59:08 +0200 • Add MacVideo header 2020-01-18 23:54:18 +0200 • A couple more CQD resources (gama, mitq, cluts) 2020-01-18 05:51:16 +0200 • Add unit table debug dump tool to device manager 2020-01-18 05:50:37 +0200 • Add "virtual" slot DRVR installation support 2020-01-18 04:29:39 +0200 • Tweak video driver name & fix default slot amount 2020-01-18 04:26:22 +0200 • Implement DoVBLTask trap (untested) 2020-01-17 17:27:46 +0200 • Add SlotManager module + slot queue initialization 2020-01-17 01:52:09 +0200 • Implement color version of InitGraf 2020-01-17 01:28:37 +0200 • Add GetCTSeed/GetCTable/DisposeCTable to ColorMgr 2020-01-17 01:18:38 +0200 • Add TableSeed and HiliteRGB low-mem globals 2020-01-17 01:17:59 +0200 • Add default 'clut' tables to color ROM resources 2020-01-16 01:50:16 +0200 • Clean up linker errors for missing color QD stubs 2020-01-16 01:43:16 +0200 • Add setup of menubar 'mctb' color table (untested) 2020-01-16 01:35:33 +0200 • Empty stubs for GetCIcon, PlotCIcon & DisposeCIcon 2020-01-16 01:27:38 +0200 • GDevices module & GetMainDevice/GetMaxDevice stubs 2020-01-16 01:20:13 +0200 • Add empty stub for _ActivatePalette 2020-01-16 01:15:39 +0200 • Empty stubs for Delete/SetMCEntries & InitPalettes 2020-01-16 01:06:12 +0200 • Tweak ClassicSound to not fail colorQD compilation 2020-01-16 00:56:30 +0200 • Tweak some CMake configs for color-only apps 2020-01-16 00:55:31 +0200 • Refactor VBL code out of VIA + add slot# to video 2020-01-15 02:52:16 +0200 • Improve compilation of QDExtensions with color QD 2020-01-15 02:41:14 +0200 • Improve Menu Manager color QD compatibility 2020-01-15 02:40:40 +0200 • FMSwapFont color QD tweaks & LastSPExtra type fix 2020-01-15 02:36:37 +0200 • Fix ClassicSound compile error w/o Sound driver 2020-01-15 00:49:29 +0200 • Separate Mono & Color fake roms + add 32-mode flag 2020-01-15 00:47:24 +0200 • Add the DRVR 120 (.Display_Video_MACE) to fake rom 2020-01-15 00:45:59 +0200 • Add color video initialization call to boot code 2020-01-15 00:44:02 +0200 • Add stub for the color video driver 2020-01-15 00:42:54 +0200 • Add symbol name to binary-to-C converter
Recently, somebody was asking on Emaculation forums, what would happen if Apple’s Finder would be attempted to run in M.A.C.E.? That was an interesting question, which motivated us to try it out.
Mac System Software architecture
To think about what would make Finder work, let’s consider the classic Mac system software as an architecture consisting of roughly three layers (in real Macs):
ROM: Most of Toolbox APIs, ROM resources and stage 0 boot loader.
System: Patches to ROM, extensions, system zone, the so-called “kernel” of old MacOS.
Finder: The “desktop metaphor” front-end running as a regular Mac application.
This categorization is very naïve, does not consider details such as role of hard drive drivers in boot process, etc. Additionally, M.A.C.E. combines roles of ROM and System as a single entity implemented in native code.
The interesting part to highlight is how Finder is basically “just another” application running on the System, and was even replaced by alternate startup applications on the old Macs (such as MiniFinder, MultiFinder, or other applications using the “Set Startup” option). As such, especially on System 6.x and older, the undocumented dependencies between System and Finder might be few in number, if any.
The first run
So, the question was, what would happen if we would try to run it? Well, we got this far on the first attempt, and with a couple minor fixes to progress further:
So, almost there. What we needed was a couple new (missing) routines and some fixes:
Fixed the 0x16 and 0x17 csCodes for .NativeFS driver, which return the logical/physical ICN# data for the volume icon (as seen on the desktop). We actually had that icon already one year ago, but this was the first time anything wanted to access it. 🙂
Added working directory indexing to GetWDInfo, which Finder uses to close all open working directories, presumably left open by misbehaving applications under System 6.x.
Fixed a buffer overflow bug in GetVolInfo (in volume name).
Implemented File locking APIs, which Finder wants to use to maintain the Desktop file.
Getting to the desktop
After a long and tedious session of debugging, it was discovered that due to a stupid bug in GetWDInfo Finder was crashing upon attempting to enumerate volumes. After that fix, we got nice Finder desktop, and a lot of functionality already working:
Operating on the Finder windows added need to implement a couple other missing traps, although as dummy versions for now (SetCatInfo and SetVolInfo, which Finder attempts to use to write metadata about modifications done in the spatial finder windows, icons, etc). Some points:
Finder and system icons appear as documents, but that might be because those don’t yet exist in the System file. Not sure about that yet.
It’s nice to see how a Finder 6.1.8 from Apple’s real System 6.0.7 behaves nicely even though M.A.C.E. System declares being version 7.0. 🙂
For some reason, doing “Get Info” on our Hard Drive turns our custom icon returned by the .NativeFS DRVR to a generic floppy icon.
It’s interesting how Finder considers at the moment our custom Hard Drive as “AppleTalk” device, but that might be because we’re hooking into the ExtFS file manager hooks which *I think* were used by AppleTalk in the real System 6.x. Just another thing which needs more investigation.
The modification and creation dates shown in “Get Info” (and list-style finder windows) use International Utilities date & time formatting functions, which are still placeholders. And as such, they only display mostly the numeric value of date-time instead of the proper, human-readable format.
Making the Desktop file work
At this point, we didn’t yet get the proper application and document icons to appear, so we did a bit more debugging on what was happening with the Desktop file – which Finder uses to keep track of known application creator & types, file comments, etc. It turned out, that we accidentally had all the “hasBundle” (0x2000) bits turned off in applications, which is why they were not detected by Finder.
As this issue was fixed, Finder started to process the applications properly, and quickly needed a some improvements to Resource Manager APIs. Mostly, it wanted to use UniqueID to allocate unique IDs for resources inside the Desktop file’s resource fork (to avoid conflicts). After that, updating Desktop file seems to work quite nicely, resulting in some fancy icons now appearing in the Finder under M.A.C.E.:
For now, running the real Finder remains as a curiosity, but nevertheless works as a great test case for a various number of Toolbox File Manager APIs which still need work (among some other minor bugs). The summary of the major known issues is:
The launching of programs “almost” works. Everything else appears to be fine, but it suffers from the same issue as previously found out using the “Transfer” command in THINK Pascal: The Font Manager data caches do not clear completely, leaving some dangling handles/pointers to the old application zone, which cause crash on attempting to reference them after the zone has been reinitialized for the new application.
Getting back to Finder (or any shell) is not yet possible, as ExitToShell is still hard-coded to terminate the entire emulator, instead of launching LMGetFinderName() application. Getting this to work would also encourage researching the Emscripten and Process Manager compatibility, as all of those features share a common need for a better in-emulator process management.
SetCatInfo/SetVolInfo are still dummy placeholders, so Finder is trying to use them to update metadata, though it is not yet saved.
Folder creation (_DirCreate), File/Folder deletion (_Delete), renaming (_Rename) are not yet implemented, so attempting those operations on Finder will still fail.
The _Eject trap is not yet implemented (and in any case you will not be able to eject the NativeFS drives).
As previously pointed out, Date & Time formatting does not yet work
The “Rebuild Desktop” operation (though using option + cmd keys at startup) does not yet seem to do the actual rebuild on a “fresh” start (i.e. if Desktop file has been wiped). Additionally, attempting that operation while old Desktop file exist will error out because _Delete is unimplemented, and old file cannot be removed out of the way.
Maybe other issues too, those are just the ones found out in the quick testing.
The “generic” M.A.C.E. environment might benefit of this though, as a replacement shell and/or program launcher, that could be optionally used by the end-user.
Full list of changes since last post
2019-12-12 18:19:41 +0200 • Add UniqueID/…1ID, to allow Desktop file updates 2019-12-12 17:49:18 +0200 • Add Disk Initialization Pack2 to keep Finder happy 2019-12-12 17:46:55 +0200 • Fix byteswap bug in NativeFS _Allocate handler 2019-12-12 15:00:12 +0200 • Add missing NativeFS.c changes for previous commit 2019-12-12 04:34:28 +0200 • Add dummy SetCatInfo and SetVolInfo selectors 2019-12-12 04:02:48 +0200 • Fix GetWDInfo bug (ioVRefNum & ioWDVRefNum mixed) 2019-12-09 02:58:47 +0200 • Fix memFullErr check in SetApplLimit 2019-12-08 06:31:06 +0200 • Fix filename overflow in GetVolInfo NativeFS call 2019-12-08 06:30:06 +0200 • Implemented CloseWD 2019-12-08 06:29:03 +0200 • Add WD indexing to GetWDInfo 2019-12-08 06:27:20 +0200 • Add Finder test app to cmake configs 2019-12-08 06:27:01 +0200 • Implement icon csCodes in NativeFS Control call 2019-12-08 06:25:52 +0200 • Make more macros in memory manager MSVC friendly 2019-12-08 06:25:18 +0200 • Add dummy SetFilLock and RstFilLock 2019-12-08 06:23:36 +0200 • Fix FinderName lowmem global 2019-12-06 23:44:06 +0200 • Add Bash Big Blue to cmake config for testing 2019-12-04 21:21:36 +0200 • Fix QD_LOG to respect debug settings 2019-12-04 20:48:17 +0200 • Add Cairo ShootOut! to cmake config for testing 2019-11-30 02:02:05 +0200 • Fix empty VA_ARGS problem in MaceLog macro 2019-11-29 23:55:30 +0000 • Make SWAP and MIN/MAX macros MSVC compatible 2019-11-29 23:54:08 +0000 • Made vararg ellipsis parameters MSVC compatible 2019-11-29 23:52:21 +0000 • Make Memory Manager return macros MSVC compatible 2019-11-29 23:51:27 +0000 • Make ROMScratch macros MSVC compatible 2019-11-29 23:50:08 +0000 • Move SwapPoint to MacQuickDraw.h to make it inline 2019-11-29 23:48:05 +0000 • Change void* to UInt8* in fake ROM (for MSVC) 2019-11-29 23:46:50 +0000 • Make SANE conversion macros MSVC compatible 2019-11-29 23:33:03 +0000 • Merge branch 'master' of 2019-11-29 23:32:43 +0000 • WinAPI EndianXX_Swap macros 2019-11-30 01:30:54 +0200 • Add UInt128 type to EmuMacTypes.h
Before Macintosh was created, there was a computer architecture called IBM PC. With Intel 8086 processor, it was incompatible with the Motorola 68000 family used in Macintosh computers – and thus, no IBM PC software would work in Macintosh. But there were some really smart people, who created a special application called SoftPC in mid-80’s, which interpreted Intel’s x86 instructions on the fly, and emulated enough PC architecture and BIOS ROM to allow those programs to run on Macintosh. And now, SoftPC finally also works on M.A.C.E.
SoftPC 2.51 architecture
The version of SoftPC we got to run is 2.51, which happened to be compatible with the “Classic”-type 68000 Macintosh computers, one which M.A.C.E. aims to emulate in the Phase 1. That is, it works on 68000 processor, supports the 1-bit “classic” QuickDraw on 512×342 screen, and appears to be compatible with System 6 level Toolbox calls.
The IBM PC architecture which SoftPC 2.51 emulates is IBM XT with 640 kilobytes of RAM, and a CGA monochrome display. It also supports two serial ports (although M.A.C.E. serial port drivers are still unfinished to try them out), a printer port (no printing support for us yet), two hard drives (through disk images), and two physical floppy drives (which we don’t either emulate yet).
The XT memory map
The challenging part of getting SoftPC to work was ingenious way it emulates the PC memory map. As everybody knows, IBM PC has physically 20-bit addressing scheme (through 16-bit segment and offset register pairs, which give 4+16 bits of usable virtual address space, as there is overlap between segments). This 20 bits equals 2^20 = 1048576, or 1 megabyte of address space. What SoftPC does, is that it allocates this entire 1 megabyte area to be linearly accessible throughout the physical Macintosh address space, but it saves memory by allowing this area to have “holes” in it for the non-used areas of the PC memory map. This is basically the layout it creates:
0B8000-0DDFFF: CGA video memory
0F0000-0F4FFF: ROM BIOS #1
0FE000-100000: ROM BIOS #2
The steps it uses to ensure this linear layout is created is quite unique, and a good challenge to test the memory manager implementation:
For starters, the availability of large enough linear memory space is ensured by doing allocation of 1048576+32 bytes of memory using NewPtr. If this fails, it will know that there won’t be enough memory.
The allocated space is shrunk down to the 640K+32 RAM size using SetPtrSize. (The 32 bytes extra is used for aligning the actual addresses inside allocations to 16-byte boundaries for apparently memory access speed optimization on later Macs).
The three other blocks (CGA memory and two ROM areas) are allocated at correct locations using the following algorithm:
The size of “hole” preceding the allocation is calculated. For example, having video memory at B8000 would leave 18000 bytes space between A0000 and B8000.
Two pointers are allocated after each other using NewPtr: one for the hole (using calculated hole size), and the actual memory block (+32 bytes for alignment).
Now this is where the magic happens: If the latter allocated block’s start would not be within alignment range of the required offset (in CGA case B8000) from start of RAM (the 640K block), the size of hole would be decremented with 16 bytes, the two blocks would be disposed, and allocation re-attempted at step 3-2.
After repeating steps 3-2 through 3-3 enough so that required range is reached, the pointer to the allocated hole block is saved, and next one of the three blocks is allocated starting from step 3-1. (It should be noted, that because of a very minor bug in M.A.C.E. memory manager, the allocation size failed to decrease, and this loop would be terminated after 64 attempts, with incorrect block left allocated.)
After all three blocks have been allocated at correct offsets, the holes preceding each of them would be disposed using DisposePtr. This part of process leaves space inside the emulated PC address space, which the Toolbox can use for any regular memory allocations – pointers and handles, even resources. It is not 100% certain, but it may be that SoftPC may optimize performance in such way, that writing to PC address space at these holes might actually even cause native memory to get corrupted, BUT for now we did not try to see if that might happen.
The issue with Memory Manager in step 3-4 was, that as the DisposePtr call on the two blocks actually creates two adjacent “free” blocks, the allocation of new block using NewPtr right after that with only 16 bytes smaller size, would actually not return a physical block with smaller size. This was, because the block allocation routine checks if the space between allocated and next block would be less than minimum allowed block size (for creating new “free” block between allocation and next block), it would actually merge that small bit of space back to the physical allocation. The bug in Memory Manager was, that the when allocating block in free space, it was supposed to always merge the next “free” block after the allocation, and slice the new “free” space from that. A real Mac merges only one extra “free” block after allocation, but in M.A.C.E. for simplicity we fixed this by merging all free space in one run, thus at the same time reducing clutter of having many adjacent free blocks.
With this fix in Memory Manager, SoftPC is now finally able to boot up. Thanks to the Standard File Package implemented earlier this autumn, we could not only configure the hard disk image (C:/), but also set up a “shared” network disk (E:/) through a folder inside emulated Mac file system. This allows easy access of files (and thus DOS applications) from the M.A.C.E. file system, including some games. The shared disk access routines, however, surfaced luckily a couple File Manager bugs, related to the ioNamePtr handling in _GetCatInfo and _GetFileInfo calls, which possibly also improve compatibility of other applications too.
Below are some screenshots of the configuration dialogs of SoftPC (click for larger image):
And here is DIR command output right after booting up:
Also, there was GWBASIC included with the DOS installation, so we can run GWBASIC compatible BASIC programs:
And also some games work nicely. The Monochrome CGA emulation has interesting approach of emulating the 320×200 resolution with 1.5x scaling as 480×300 pixel bitmap display. The four CGA colors are also mapped into distinct vertical stripe patterns, which might also have been used on some old monochrome CGA displays:
Of the two above games, SOPWITH appears to be quite responsive and playable, but ALLEYCAT controls are very laggy. Also Sierra adventure games seem to run:
The Black Cauldron (pictured above) seems to work just fine, although for some reason the function keys were not working, while they did work in GWBASIC earlier (opening of doors with F6, for example). Also, none of the games produced any sound although the SoftPC boot beep works, so it might be that SoftPC may lack actual PC speaker emulation in this particular version (beyond the beep).
Other issue that we also fixed while working on this was a bug in Scrap Manager, which caused the clipboard to misbehave when working in “on-disk” mode (after _UnloadScrap was called). This allows Copy-Paste operations to work nicely in SoftPC, and it also improves clipboard functionality in other applications.
Only remaining issue with SoftPC is that some routine, possibly in SANE and most likely related to converting PC date & time, is causing divide overflow error to popup at random times, which appears to be related to the actual date & time. This needs to be investigated still at later point.
Full list of changes since last post
2019-11-27 00:34:43 +0200 • Fix a Scrap Manager bugs, fixes SoftPC copy+paste
2019-11-26 23:06:55 +0200 • Fix ioDirFlag to be 4 which appears to be correct
2019-11-26 23:06:27 +0200 • Don't crash on invalid zone in Handle validation
2019-11-26 04:01:31 +0200 • Fix register-based 68k->native UPP calls' D0 nuke
2019-11-26 03:57:20 +0200 • Don't overwrite *ioNamePtr if not indexing files
2019-11-22 03:41:15 +0200 • Add FREMS selector to SANE's FP68K dispatcher
2019-11-22 03:40:22 +0200 • Force merge of free blocks at end of BlockFindSize
2019-11-19 22:59:13 +0200 • Fix bug where everything left of a list got erased
2019-11-19 22:55:27 +0200 • Redraw modified cell in LSetCell
2019-11-19 01:42:03 +0200 • Add support 23 new native 68k exception handlers
Since the previous update, focus has been mostly on improving the compatibility and stability of existing test applications through debugging, bug fixes and finishing some partially implemented features. This has so far had mostly effect on Excel, THINK Pascal and Fokker Triplane Flight Simulator:
Microsoft Excel 3.0 progress
Seems that Excel was complaining the out of memory error only because it could not locate the ‘PACK’ 6 resource (IntlUtils package). Adding a ‘PACK’ wrapper resource to System file, in similar fashion to the one which was added earlier for ResEdit as ‘PACK’ ID = 0, allowed this check to pass. After that a couple of new IntlUtils selectors were needed, with a couple file manager tweaks, and now Excel is able to start up successfully (albeit with a alert about not finding Excel, which can be passed).
It seems that a lot of tools and features are already functional, including basic worksheet creation, cell selection/modification, shape drawing, basic formatting etc. However, the most important feature, text input to allow entering data to worksheet cells, still requires TEDispatch to be implemented.
THINK Pascal 4.0 progress
One application which surfaced a lot of bugs and issues was THINK Pascal 4.0, here’s a rough summary of the issues found & ‘fixed’:
Reallocation of resources was not working properly in ChangedResource. Resource Manager did not save & restore active resource entry when measuring space available between current and next resource, which caused the new resource allocation in growth case to end up in wrong resource entry in the map (the next one was reallocated instead of current).
Removing name was attempted even if no name existed, causing resource names to get corrupted
RmveResource was not offsetting the types properly when removing the last instance of a given type.
The internal routine RGetResourceCount was trashing the resource entry pointer in resource manager’s stack state, causing some resources to be skipped altogether in iteration.
SetHandleSize was allowing locked blocks to move during the operation, which was explicitly told in Inside Mac documentation would not happen. This bug caused sometimes locked memory to move, with dereferenced pointers becoming invalid, causing crash during pascal code compilation.
A very rough approximation of MoveHHi was added. It works well enough to allow THINK Pascal to move resources out of the way to not prevent heap fragmentation from growing size of locked handles – but still causes sometimes fragmentation enough to surface this issue. However, this is for now enough to get the projects compile roughtly 2 to 3 times in one session before memory fragmentation kicks in and crashes the compiler.
The resource copy phase of THINK Pascal surfaced a bug in CountResources/GetIndResource, where CurMap was used instead of TopMap (CurMap should only be used when operating on 1-deep versions of the calls, Count1Resources/Get1IndResource). With this fix, the resource file copy phase succeeds.
Using “Transfer” command in THINK Pascal can be used to launch another app – in most cases, the application that was just compiled. However, the application zone teardown was – and still is – largely unfinished, having a number of issues. One that was fixed, was that resource manager attempts to release and purge all font caches with allocations in the application zone, which would be invalid upon launching the new program.
GetScrap trap had a minor issue, in which the case of hDest being nil it would crash, instead of just returning the scrap size as it was supposed to. This fixes the clipboard to (almost) work in THINK Pascal.
Now even a bit more complex programs can be compiled using THINK Pascal, for example one of Toni’s old games from as early as 1998. However, there are still minor glitches in various places:
Sometimes clipboard operation does not work on the first attempt.
Replacing existing application with “Build application” & replace dialog does not yet work because _Delete trap is still unfinished.
Sometimes text editing has very tiny minor selection glitches (when doing “Search again” in source code, where previous hit was selected and visible in area which was scrolled only little up, the old selection is left on when highlighting the new one).
Because resource map compaction is (still) unfinished, each time resources are updated and/or written in resource files, the file size grows indefinitely (by size of modified resource).
Compiling only works a couple times (2-3) on large projects, before heap fragmentation crashes the compiler.
The “Go” option does not yet work, because when running applications inside the THINK Pascal IDE, it does not actually launch a separate applications process for it. Instead, it loads the application “on top” of the pascal IDE, and in order to do this, it wraps a lot of its handlers to toolbox routines, and to do this, it manipulates the trap tables directly. This however assumes the toolbox trap table is located at 0xC00 on mac plus (0x75)-type machine, while it is currently located at 0xE00 (later machines). Because some currently used low memory globals overlap this area in non-compatible ways (for example, cursor device), they need to be adjusted a bit to behave differently on “Classic” type environment (like on real Mac Plus), and other way on later (slot-based / color-QD) environment.
Fokker Triplane Flight Simulator
It seems that the only issue causing Fokker Triplane to freeze upon starting new game was actually the lack of low-level interrupt handler emulation. The game attempted to override system VBL handler by adding its own VBL interrupt handler in the Lvl1DT low memory area containing the list of VIA’s Level 1 interrupt handler table, and as it was never called, caused the lock-up. The VBL, and 1-second timer, have now proper handlers in this low memory area, which is checked upon triggering the emulated VBL interrupt. This also includes the familiar performance optimization, where unpatched handlers skip the MixedMode interface with direct method call. It seems that with this change, the game is now fully playable with sound effects (although not thoroughly tested).
Full list of changes since last post
2019-11-16 04:08:45 +0200 • Lowlevel VIA interrupt handler for Fokker Triplane
2019-11-13 03:50:11 +0200 • Tweak SndNewChannel to not crash ResEdit
2019-11-09 09:03:38 +0200 • Dummy OpenDeny/OpenRDeny (=>paramErr for local FS)
2019-11-09 07:51:53 +0200 • Workaround for mapping wideOpen Rgn in DrawPicture
2019-11-09 07:49:02 +0200 • Move File Manager commands to separate module
2019-11-09 07:47:37 +0200 • Move SoundDriver test code to separate module
2019-11-09 02:29:58 +0200 • Add dummy BitMapRgn trap for aWorm
2019-11-06 05:40:10 +0200 • Respect port clipRgn in CopyBits
2019-11-06 04:31:42 +0200 • Fix edge cases in UnpackBits
2019-11-04 21:32:35 +0200 • If GetScrap argument hDest = nil, return only size
2019-11-04 11:31:38 +0200 • Clear font caches when closing res file w/ fonts
2019-11-04 04:16:41 +0200 • Add IUMagString & improve Transliterate for Excel
2019-11-04 03:09:38 +0200 • Fix Count…/GetIndResource to begin at TopMap
2019-11-04 02:15:21 +0200 • Add memLockedErr enum missing from previous commit
2019-11-04 02:14:56 +0200 • (HACK) MoveHHi added - works, but not as in specs!
2019-11-04 02:12:08 +0200 • Fix SetHandleSize for locked blocks (don't move)
2019-11-04 02:06:36 +0200 • Fix tail check in the zone check
2019-11-04 02:04:53 +0200 • Fix name allocation in AddResource
2019-11-04 02:03:14 +0200 • StdFile: No "New folder" button in old dialogs
2019-11-03 05:53:37 +0200 • More verbose heapcheck & optional free space debug
2019-11-02 18:13:37 +0200 • Fix possible TextEdit calibration memory move bug
2019-11-02 17:40:30 +0200 • Fix resource map validation for maps with no names
2019-11-01 17:55:35 +0200 • Add dummy cstr2dec and pstr2dec selectors in Pack7
2019-11-01 17:54:15 +0200 • Don't trash ResourceEntry ptr in RGetResourceCount
2019-11-01 02:30:02 +0200 • Dummy IUMagWString & Transliterate(Text) for Excel
2019-11-01 00:43:41 +0200 • Add 'PACK' 3,4,5,6&7 mapping (Excel now starts up)
2019-10-31 21:33:21 +0200 • Resource fork compact placeholder code
2019-10-31 01:01:48 +0200 • Fix RmveResource offset bug at last item of a type
2019-10-30 21:56:35 +0200 • Don't try to remove name if entry doesn't have one
2019-10-30 21:55:55 +0200 • Add map checks to Resource Manager calls for debug
2019-10-30 04:54:54 +0200 • Fix reallocation of resource in ChangedResource
It’s been quite a while since last update, which is due to combination of us being busy real-life jobs, and focusing work on this project on a monolithic feature, which in this case is nothing less than getting the Standard File Package to work!
This is list of the features which the M.A.C.E. Standard File Package emulation is currently capable of:
All 8 selectors for Pack3 (SFPutFile, SFGetFile, SFPPutFile, SFPGetFile, StandardPutFile, StandardGetFile, CustomPutFile, & CustomGetFile). The ones tested are highlighted, but others should work too.
Support for custom file dialogs (with assorted hacks to convert MFS-style dialogs, such as the “Save” dialog in MS-BASIC 2.00, to the new HFS-style format)
Supports both SFReply and StandardFileReply outputs
File listing using List Manager, which displays currently System 6-style SICNs, but with System 7.1+ style spacing (later expandable to use the real icons, when we get Desktop Manager interface)
Path popup menu, visually and functionally like on real System 7.x
Desktop folder support
Focus on selected items (including file list with highlight frame), alterable by mouse or tab key
Most of common SF key shortcuts: Clipboard shortcuts, Cmd+S (Save), Cmd+O (Open), Cmd+N (New folder), Cmd+D (Go to desktop), Cmd+Up (Go to parent), Cmd+Shift+Up (Go to root/desktop), Cmd+Down (Open folder), (Cmd+Left/Right to browse volumes not yet implemented)
Filename field input filtering (prevents “:” from being used in filenames, which is path separator). Also, copy-pasted filenames will be filtered with proper alert messages.
Not yet implemented: sfHookOpenAlias, sfHookGoToAliasTarget, sfHookGoToNextDrive, sfHookGoToPrevDrive, sfHookChangeSelection, sfHookSetActiveOffset
File type filtering supported, both by typeList and FileFilterProc
Although most of the Standard File Package is functional, and usable, there are still some issues left:
Because DirCreate is not yet implemented in NativeFS layer, FindFolder cannot create the Desktop Folder/Trash folders to the file system, thus at least Desktop Folder needs to exist to allow access to “Desktop” level in the SF dialogs. This also prevents “New folder” from actually creating the folders.
Eject button does not yet do anything, as the NativeFS volumes are non-ejectable
There are minor differences to real System 7.x style SF dialogs, for example with certain elements being a few pixels off their intended locations, and popup menu’s width not always expanding
Some custom dialogs don’t yet work exactly as they should, for example THINK Pascal 4.0 “Add files” dialog erases left edge of the applications own custom list located below the SF file list, and for some reason it allows attempts to add folders as source files…
Location of the SF dialog is sometimes not correct (for example, Railroad Tycoon’s “Save game” dialog is partially under the menu bar)
We cannot yet create app bundles for the currently working freeware/shareware applications that use StandardFile, because when sandboxed the bundle file system is read-only, and thus attempting to save anything to it would straight out fail. To work around this, we need to implement certain changes to the way file system in bundled applications is handled, but we are already working on that for the next release
Other improvements made for Standard File
There were a couple features that were implemented as part of Standard File Package implementation, some of which were necessary to make it work
NativeFS AVL tree balancing and iteration support
One important feature was the need for catalog iteration, which is used by Standard File dialogs to enumerate the files in current folder to be displayed in the file list. This allows for example GetCatInfo to use ioFDirIndex in the parameter block to index specific files inside given directory.
Also, this gave a good excuse to finally implement the actual AVL balancing algorithm in the NativeFS file system, which until now had behaved mostly as a dummy binary tree. Below is a screenshot of how the file system structure was changed by the balancing algorithm:
On the right-hand side, is the unbalanced “dummy” binary tree, and on left-hand side is the same file system, when using AVL balancing algorithm to do the insertions. The deepest nodes were reduced from, in this case, from way over 100+ key comparisons into a rough maximum of 10+.
Popup Menu Control
One important feature of the HFS-style Standard File dialogs is the navigation aid provided by the path popup menu. For this, the Popup Menu Control CDEF 63 was implemented. On real Macs, this was originally part of Communications Toolbox, before it was merged to the System 7.x at some point. The Standard File dialogs use only a subset of its features, but foundation for most use cases was built at the same time, so taking it into more common use should be quite easy. As it uses the Menu Manager’s PopUpMenuSelect trap call, the actual menu selection was already there.
One fun and tricky part though was the need to add MDEF “wrapper” for SF popup path menu, to ensure that the opened popup menu would never be narrower than width of the popup control. To do this, the control imitates how the real Macs did this by adding temporarily a MDEF “wrapper”, which injects modified menuWidth value to the menu after it receives a mSizeMsg message from the Menu Manager, thus modifying the resulting popup menu size.
Picture Button Control
The CDEF 61, picture button, was implemented just to allow adding the “New folder” button to the “put” dialogs. It is quite simple, at least in monochrome version, just drawing a PICT resource as content of a regular push button
Dialog Manager improvements
The StdFilter, which is also used by Standard File dialogs, was improved to add features used by it:
Outlining default button with FrameRoundRect
Handle “cancel” item’s shortcut key as escape/cmd+dot
Track cursor to turn it into i-beam over enabled textedit fields
Handle update events for default items
Also, the default shortcut keys (Cmd+X/C/V for Cut/Copy/Paste) were also implemented in DialogSelect trap.
Other news: 68020/68040 support
In other news, Pukka has also been busy adding 68020/68040 support, which includes: