We had this week a rather interesting thing happen by accident, which was rather unusual: While trying out a couple potential test applications with the emulator, we ran into an application which was infected by nVIR A type virus ( https://en.wikipedia.org/wiki/NVIR ). What makes this interesting, is that it apparently was able to infect the System file of that application’s bundle, as we now have near-complete resource write support:
Above is partial output of the System file’s resource map debug dump (and Rezilla screenshot of infected System file), and the ‘nVIR’ and ‘INIT’ resources were actually written into the System file by the virus in infected application – and the system resource map seemed to be (mostly) still functional! I only found this out because a bug in resource writing corrupted Geneva font, causing the infected application to crash. A kind of controversial achievement, having good enough compatibility for even viruses to work in the toolbox emulation…
One of the positive sides of the current per-application bundling of files as isolated file systems, is that the infection never was able to break out of the application bundle. We have also scrubbed through all the disk images and Mac files downloaded we use for development and testing, to make sure there will not be any risk of infection at later time (and run Disinfectant on the source Macs/emulators regularly). These viruses are ancient, but can awake up at any time it seems…
New test application: IAGO
After we got the infection sorted out and everything back to normal, we experimented with a couple of new test applications, and found out that IAGO, which is a public domain game written by David Reed in 1984.
We were able to identify one bug in ROXLI.L instruction, which caused the game timer to not advance correctly. After it was fixed, the game works as smoothly as it does on a (fast) real Macs. It is now also available for testing as application bundle in the downloads section.
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