The past few weeks have mostly gone to improving performance of the runtime environment. Although all the apps have been running smoothly without any issues, there was not much focus on improving the actual CPU usage of the host system.
Unlike hardware-based emulators such as Mini vMac, where everything including applications, ROM, and system software run on 68K, in M.A.C.E. there is distinct separation of execution between 68K based code, and the Toolbox code written in native C. This creates some minor issues with managing performance, as especially in regards of early software – QuickDraw routines would be much slower on real 68000 hardware, and thus games depending on certain 68000 execution speed would experience certain slowdown of using those QuickDraw (and other Toolbox) routines.
However, in M.A.C.E., the native code always runs at full speed, and those expectations break down as experienced in Stunt Copter, Zero Gravity, Harrier Strike Mission II, Brickles among some other applications. To mitigate this, there is an artificial slowdown that the emulator can optionally enable delay throttle in GetNextEvent, which we have so far used to make most of the aforementioned applications usable.
68K emulation throttle
Pukka added an experimental throttle to the 68K emulator, which attempts to slow down applications which do for example busy-looping and polling of TickCount to perform timing. In the old non-multithreading MacOS, this kind of timing was pretty common especially in games that required precise control on the CPU resources. This should in future help CPU usage in programs heavy on 68K code in game loops, such as Dark Castle and Apache Strike. This however does not help the cases which rely a lot on Toolbox, such as the applications which benefit of the GetNextEvent delay throttle.
SystemTask and execution yielding in Toolbox routines
As some may remember, when Apple transitioned from Mac OS 9 to X, one way to yield execution was to add SystemTask calls to blocking loops (in cases where WaitNextEvent would not be desirable). As the Toolbox in M.A.C.E. is completely implemented in C, we have the power to choose yielding strategy ourself, and for that we are experimenting at the moment with very small delays of 1 millisecond on each call to SystemTask, and any other busy-looping toolbox routines, which include:
- MenuSelect and PopUpMenuSelect
- TrackControl and DragControl
- DragTheRgn (affecting DragGrayRgn and DragWindow), GrowWindow and TrackBox
- Delay (it had earlier implementation used by the GetNextEvent hack, but was implemented in a rather stupid way which ended up as a busy-loop on host CPU…)
- File Manager synchronous command queueing
- Device Manager synchronous command execution, and driver close
Video rendering and dirty-rectangle detection
Another optimization feature was the addition of detection of video memory “dirty rectangles”, which define which areas of video memory have changed, so that only those would need to be drawn to the screen. This optimization is being experimented especially to improve the future fullscreen and pixeldouble modes (which are not yet enabled due to requiring still some work), and depending on the machine and application, there is varying degree of performance improvement, but not very much (which is to be expected as the 512×342 screen with 1-bit colors does not require a lot of the CPU in regards of pixel format expansion and SDL surface updates).
With these changes, we got CPU usage of 100% to drop to around 7-10% on a Mid-2010 Mac Pro, and 9-12% on 2015 MacBook Pro of the currently bundled applications. Of course, some test applications we are experimenting with still require further work to gain these benefits, but this should help at least keep those fans more quiet on MacBook computers 🙂
We have also updated the test application bundles with these new optimizations in the downloads section on this blog.
Hierarhical menus and PopUpMenuSelect
In addition to performance optimizations, we also finally added the hierarhical menu and popup menu support which was for a long time waited to make especially Railroad Tycoon way more playable.
There was a bit of tweaking, bug fixing, polishing, more bug fixing and tweaking to get those two features to work, but now they appear to work exactly like on a real Mac (timing, positioning, mouse tracking behaviour, screen buffer saving, etc). Sadly we don’t have yet any bundled test applications to demonstrate this, but at least the applications we are using internally all work perfectly.
These are again another major features which gets us closer to the “general classic replacement” release, although there is still lot of work needed to get us there. The progress is however very promising at current pace.
Full list of changes since last post
2019-09-05 01:47:24 +0300 • Add dirty rectangle visualization to debug build 2019-09-05 00:35:24 +0300 • Update runtime version in cmake script 2019-09-04 12:44:03 +0300 • Fix offset of minimum-intersection dirty-rectangle 2019-09-04 03:38:02 +0300 • Finally fix that darn StretchBits… 2019-09-04 03:14:55 +0300 • Improved, faster dirty rectangles with bit-o-magic 2019-09-03 22:35:25 +0300 • Implement GetItemIcon and SetItemIcon traps 2019-09-03 22:21:14 +0300 • Add pixel-double support also to windowed mode 2019-09-03 22:20:11 +0300 • Fix uninitialized mouse loc in PopUpMenuSelect 2019-09-03 01:27:55 +0300 • Implement prototype dirty-rectangle video renderer 2019-09-02 22:42:44 +0300 • Add EnvRunBackgroundTasksReleaseCPULockWithYield 2019-09-02 20:43:19 +0300 • Fix hit-testing of hierarchical menus in MBDF 2019-08-30 22:31:02 +0300 • Fix mouse button check in relative mouse mode 2019-08-30 03:13:25 +0300 • Update trap list XLS/CSV 2019-08-30 03:06:21 +0300 • Implement basic non-styled TEPaste 2019-08-30 02:56:58 +0300 • Fix two masking bugs in CopyMask 2019-08-30 02:07:25 +0300 • Implement pic opcodes 0x1A & 0x1B (RGBColor fg/bg) 2019-08-30 02:04:08 +0300 • Fix popup menu crash 2019-08-30 01:13:42 +0300 • Initial fullscreen (and pixel-double) support 2019-08-28 22:25:51 +0300 • Enable delay hack in Brickles test app 2019-08-28 22:25:34 +0300 • Add execution yield for 1ms to SystemTask 2019-08-28 21:54:36 +0300 • Fix the earlier video update limiter adjustment 2019-08-28 13:31:18 +0300 • Experimental change to lower CPU usage, has issues 2019-08-27 23:54:36 +0300 • usleep logic to m68k helper 2019-08-27 05:04:18 +0300 • First proto of PopupMenuSelect, has bugs 2019-08-27 00:32:21 +0300 • Merge branch 'master' of 2019-08-27 00:32:17 +0300 • Also handle shortcut keys for submenus in _MenuKey 2019-08-26 21:46:33 +0300 • Merge branch 'master' of 2019-08-26 21:45:28 +0300 • revert unwanted modification 2019-08-26 17:02:42 +0300 • Fix left-hand side hierarchical menu handling 2019-08-26 03:13:36 +0300 • Fix icon alignment in default MDEF 0 item drawing 2019-08-26 02:30:48 +0300 • Merge branch 'master' of 2019-08-26 02:30:42 +0300 • Add "bermuda triangle" to hierarchical menus 2019-08-25 20:36:24 +0300 • move pc increment away from instructions + some optimizations 2019-08-24 23:38:22 +0300 • Update instructions.c 2019-08-24 23:17:34 +0300 • some optimizations and ea macros 2019-08-24 15:33:05 +0300 • Improve hierarchical menu tracking 2019-08-24 01:12:35 +0300 • Fix GetItemMark/Cmd/Style result byteswap bug 2019-08-23 19:41:36 +0300 • Fix drawing of hierarchical menu items 2019-08-23 04:36:38 +0300 • Merge branch 'master' of 2019-08-23 04:35:57 +0300 • First rough proto of hierarhical menu support 2019-08-22 21:51:52 +0300 • fix cmpm instruction with FAST_ADDRESSING 2019-08-21 00:30:28 +0300 • Add cmake config for Brickles, which was missing 2019-08-20 02:31:00 +0300 • Use rb fallback in NFSOpenFileHook is r+b fails