BMOW title
Floppy Emu banner

AVR-GCC Compiler Makes Questionable Code

Most people believe that modern compilers generate better-optimized assembly code than humans, but look at this example from AVR-GCC 5.4.0 with -O2 optimization level:

    7b96:	10 92 34 37 	sts	0x3734, r1	; 0x803734 <tachFlutter>
    7b9a:	e0 e0       	ldi	r30, 0x00	; 0
    7b9c:	f0 e0       	ldi	r31, 0x00	; 0
    7b9e:	a0 91 35 37 	lds	r26, 0x3735	; 0x803735 <driveTachHalfPeriod>
    7ba2:	b0 91 36 37 	lds	r27, 0x3736	; 0x803736 <driveTachHalfPeriod+0x1>
    7ba6:	ae 1b       	sub	r26, r30
    7ba8:	bf 0b       	sbc	r27, r31
    7baa:	b0 93 89 00 	sts	0x0089, r27	; 0x800089 <OCR1AH>
    7bae:	a0 93 88 00 	sts	0x0088, r26	; 0x800088 <OCR1AL>
    7bb2:	10 92 95 00 	sts	0x0095, r1	; 0x800095 <TCNT3H>
    7bb6:	10 92 94 00 	sts	0x0094, r1	; 0x800094 <TCNT3L>
    7bba:	32 2d       	mov	r19, r2
    7bbc:	e0 e0       	ldi	r30, 0x00	; 0
    7bbe:	f0 e0       	ldi	r31, 0x00	; 0
    7bc0:	f0 93 e3 33 	sts	0x33E3, r31	; 0x8033e3 <currentTrackBytePos+0x1>
    7bc4:	e0 93 e2 33 	sts	0x33E2, r30	; 0x8033e2 <currentTrackBytePos>

This is straight-line code with no branching. All registers and memory references are 8-bit. With AVR-GCC, the register r1 always holds the value 0, so the code is doing this: Set tachFlutter to 0, load driveTachHalfPeriod, set OCR1A to driveTachHalfPeriod minus 0, set TCNT3 to 0, set currentTrackBytePos to 0. There’s also a move of r2 to r19, which is used later, and I’m not sure why the compiler located the instruction here. There are at least three glaring inefficiences:

  • the compiler wastes time loading 0 into r30 and r31, when it could have just used r1
  • it does this TWICE, when we know r30 and r31 were already zero after the first time
  • it subtracts a constant 0 from driveTachHalfPeriod

I can maybe understand the subtraction of constant 0, if there’s another code path that jumps to 7ba6 where the value in r30:r31 isn’t 0. But why wouldn’t the compiler make a completely separate path for that, with faster execution speed when the subtracted value is known to be 0, even if the code size is greater? After all this is -O2, not -Os.

It also appears there’s no optimization for setting multi-byte variables like currentTrackBytePos to zero. Instead of just storing r1 twice for the low and high bytes, the compiler first creates an unnamed 16-bit temporary variable in r30:r31 and sets its value to 0, then stores the unnamed variable at currentTrackBytePos.

This whole block of code could easily be rewritten:

    sts	0x3734, r1	; 0x803734 <tachFlutter>
    lds	r26, 0x3736	; 0x803736 <driveTachHalfPeriod+0x1>
    sts	0x0089, r26	; 0x800089 <OCR1AH>
    lds	r26, 0x3735	; 0x803735 <driveTachHalfPeriod>
    sts	0x0088, r26	; 0x800088 <OCR1AL>
    sts	0x0095, r1	; 0x800095 <TCNT3H>
    sts	0x0094, r1	; 0x800094 <TCNT3L>
    mov	r19, r2
    sts	0x33E3, r1	; 0x8033e3 <currentTrackBytePos+0x1>
    sts	0x33E2, r1	; 0x8033e2 <currentTrackBytePos>

This is much shorter, and avoids using r27, r30, and r31, so there are more free registers available for other purposes.

Read 17 comments and join the conversation 

Mysteries of Macintosh High Density MFM Disks

In the classic Macintosh world, 400K and 800K floppy disks use GCR encoding but 1440K disks use MFM encoding. The BMOW Floppy Emu disk emulator has supported 1440K MFM disk emulation for years, and I thought I knew everything about how it worked. Recently I dug into Mac MFM again, while adding support for in-emulator formatting of disk images, and discovered some bad assumptions as well as some critical but undocumented behaviors of the Macintosh-Sony high-density floppy drive – or at least behaviors not documented anywhere that I can see.

I’ll gloss over most of the errors and misunderstandings in my MFM design, but there were many of them. One of the biggest was using the wrong sync byte value in some places: $AA instead of $4E. Fixing this was surprisingly difficult, due to a design practice of repeating a single $A nibble value to create the $AA sync byte, which wouldn’t work for $4E.

 
Index Pulses

The most interesting discoveries were related to how the Mac-Sony HD floppy drive handles index pulses. Yes that’s right, index pulses. If you’re like me, you may have thought that Macintosh floppy disks are all soft-sectored and don’t use index holes. That’s true, the disks don’t have any hard indexing mechanism, but the high density drive does. For every rotation of the disk, the drive’s index signal pulses briefly high.

But where and how can the computer read this index signal? Some readers may know that 3.5 inch Sony floppy drives have 16 internal 1-bit state registers, whose values can be read by the computer by selecting a register using the CA2, CA1, CA0, and SELECT I/O signals. This table is from Inside Macintosh Volume III:

You’ll find very similar tables in a few other sources, like the IWM documentation for Linux on Mac 68000. The Floppy Emu’s 3.5 inch drive emulation is built around this table – it emulates these registers. There are registers for things like motor on, write protection, and step direction… but I don’t see anything about index pulses.

Well, it turns out that this table is only valid for 400K and 800K floppy drives, but I’ll be damned if I can find a good source that documents the differences for other types of drives. Based on some old cryptic notes, and a logic analyzer trace of the disk I/O signals while a Macintosh LC formats a real 1440K floppy, I was able to conclude that the 0111 TACH register is actually an INDEX register for 3.5 inch high density Sony drives operating in HD MFM mode. I think I may have seen documentation of this somewhere in the past, but can’t locate it now. Floppy Emu doesn’t emulate this INDEX behavior at all, and it’s not needed when reading or writing a disk, but it turns out that it’s crucial when formatting a disk.

 
Reading While Writing

While examining the logic analyzer trace from the Macintosh LC as it was formatting a disk, I noticed something else curious. The computer sometimes asserted the write-enable signal for much longer than a single rotation of the disk, which is all that should be needed for a single track. Sometimes it was almost two rotations of the disk. I also noticed an odd pattern reading the RDDATA0 and RDDATA1 registers while writing to the disk. What should the read data even be, in the middle of a write operation? I’d never thought about it before, and don’t know of any software that might attempt to do it. But I noticed there was always a single 0 to 1 transition on RDDATA somewhere in the middle of the write, occurring at different times after the start of the write for each track, but always appearing about 200 ms before the end of writing.

For a very long time, I simply wrote this off as an unimportant detail, but eventually I realized that the step transition on RDDATA while writing is the INDEX pulse. I’ve never seen this behavior documented anywhere, but after reviewing the logic analyzer trace it was undeniable. The computer begins to format a track by writing a continuous string of sync bytes, while simultaneously reading RDDATA0 or RDDATA1. When it sees a low to high transition there, it knows it’s the index pulse, and it begins writing the first sector beginning just after that spot. From there it continues to write all the other sectors, ending the write operation just before the index pulse is due to appear again. Finally it checks the index pulse again, this time by reading the INDEX register the normal way at 0111. If everything checks out OK, then it steps to the next track and repeats the process.

This was my ah-ha moment, when all the pieces suddenly clicked into place and I could understand why the computer was responding differently to the Floppy Emu during formatting than it did to a real drive. Now I need to make additional firmware modifications, and try to get Floppy Emu to emulate this same behavior.

Read 1 comment and join the conversation 

MOOF disk image support for Floppy Emu

Good news! Today’s BMOW Floppy Emu firmware update brings support for the Macintosh MOOF disk image format. MOOF is a new disk image format for 3.5 inch Macintosh floppy disks, designed by John K. Morris, with the goal of capturing all the low-level disk information needed for copy-protected software. It’s the Macintosh equivalent of a WOZ disk image for Apple II computers. With a MOOF, you can use original floppy disks exactly as they came from the publisher, with copy protection still intact, instead of relying on cracked or modified versions. Although media-based copy protection was never as common in the Mac world as it was for Apple IIs, there’s still a good amount of early software from the era of the Mac 128K, 512K, and Plus that’s copy-protected. Most of them are 400K disks, but there are some 800K ones too. Archive.org has a collection of MOOFs at https://archive.org/details/moofaday

 
Understanding MOOF

A regular Macintosh .dsk or .img disk image is a byte-level representation of the logical data contained in a disk. It’s all of the disk’s sector data concatenated together into one big file. It supports normal disk behavior that’s built around a typical ReadSector() and WriteSector() API. For an 800K floppy disk, the .dsk disk image is precisely 800K in size.

A MOOF disk image is a bit-level representation of the disk as it’s physically implemented in the floppy media. It’s everything on the physical disk, including the empty space between sectors, the headers and footers, and GCR 6&2 encoded data or whatever non-standard encoding the developer may have chosen. For a MOOF that’s created using John’s Applesauce hardware, it will also correctly preserve the relative angular positions of adjacent disk tracks, and areas of the disk where there are no bits, both of which are essential for some copy-protection schemes. For an 800K floppy disk, the MOOF image is typically about 1300K in size.

I don’t recommend rushing to re-encode all your Mac disks as MOOF. For the vast majority of disks, this is not only unnecessary, but counterproductive since MOOF images are larger and more difficult to use with common software tools. But for those few Mac disks with embedded media-based protection, a low-level MOOF image is just what’s needed.

 
MOOFing the Floppy Emu

When people asked me about MOOF in the past, I said it was impossible for Floppy Emu to support bit-level 3.5 inch disk images because there wasn’t enough RAM to store a complete track at the bit level. So what kind of black magic makes this possible now?

To make the data fit, the Floppy Emu firmware must depart slightly from the behavior of a real floppy disk. For a real 800K disk, there’s a small delay when switching between tracks, but switching between sides is instantaneous. For a normal .dsk disk image, the Emu can support this by storing track 0 side 0 and track 0 side 1 in RAM at the same time. There’s only a delay when new data is fetched from the SD card for the next track, which mimics the delay of a real floppy drive’s mechanical head stepping movement. But for 800K MOOF images, there isn’t enough RAM to store both sides. Only track 0 side 0 is stored in RAM and there’s a delay for SD card access when switching to track 0 side 1. In theory this might cause software errors or copy-protection failures, since there’s no equivalent delay with a real disk. But in practice, I don’t think it’s a problem.

This RAM-saving trick works for 400K and 800K MOOFs, but can only be extended so far. RAM limits are one of several reasons you’ll probably never see 1440K MOOF support on this hardware. But that’s no great loss since the era of media-based copy protection had mostly ended by the time 1440K disks were introduced. All of the MOOF examples in Archive.org’s Moof-A-Day collection are 400K and 800K disks.

This MOOF implementation for Floppy Emu is read-only. A few Moof-A-Day games require writing to the disk in order to play, so although they load and run, they’re not fully usable. A writable version of MOOF support is in the works. The rare MOOFs that use pure FLUX data are unsupported by the Floppy Emu, due to hardware limitations. The only example that I know is the game OIDS.

 
WOZ 3.5

The MOOF format is essentially identical to the 3.5 inch WOZ format for Apple II computers, just with different metadata. That means it’s theoretically possible to add 3.5 inch WOZ support to Floppy Emu too, and that’s my hope. But it’s unfortunately not as simple as just re-using the Macintosh MOOF code: the Apple II version of the firmware is substantially more complex than the Mac version, because it supports many more types of disk emulation and disk image formats, and it’s already pushing the limits of the microcontroller’s performance and memory, and the CPLD logic chip’s resources. It’ll be a major challenge to weave 3.5 inch WOZ support into this environment.

 
Moof-A-Day Known Issues

  • Two titles still don’t pass the copy-protection check, for unknown reasons: The Ancient Art of War and The Surgeon. The Surgeon also fails its check with archive.org’s built-in MAME environment, so it’s not just Floppy Emu that has trouble with it.
  • Mac Vegas will silently fail to write to the read-only disk, then restart or crash when you begin a mini-game.
  • Some games have other requirements like only running properly on a Mac 512K, or only when the disk is in the internal drive, or they require two disk drives.

Please give this a spin, and let me know of any problems you find with MOOF support, or with other disk emulation features that might have broken accidentally.

Download the latest Floppy Emu firmware from the project page, or buy a new Floppy Emu Model C at the BMOW Store.

Read 3 comments and join the conversation 

An Idea for Macintosh Disk Daisy-Chaining

The Apple II family of computers supports daisy chaining disk drives, but the classic Macintosh family sadly does not. This means it’s impossible to create a Mac equivalent of Floppy Emu‘s Apple II Dual 5.25 Inch Floppy emulation mode, or its four-disk Smartport hard disk mode. Apple II computers have two separate ENABLE signals on the disk I/O connector, as well as an ENABLE35 signal, which allows for directly addressing four separate drives on the same connector. This can be expanded to even larger numbers of drives through additional tricks. In contrast, the Mac only has a single ENABLE signal and no ENABLE35, so it’s physically impossible to address more than one disk drive. Unless… I recently had an exciting shower idea (my best place for inspiration) that might offer a solution.

Dual Macintosh Hard Disk

Floppy Emu can emulate an HD20-type hard disk, which is an older type of non-SCSI hard disk that connects to the computer’s floppy port. A real HD20 hard disk actually does support daisy chaining: you can plug a second one into the back of the first. The computer uses an HD20-specific mechanism for addressing the desired disk. When ENABLE is asserted, the first HD20 is selected. If PHASE3 (also called LSTROBE) is toggled while ENABLE remains asserted, logic inside the HD20 drive will deselect the first drive and select the second. Each additional PHASE3 toggle selects the next disk in the chain.

You probably didn’t know that Floppy Emu already supports this, in a limited way. At the lower-left corner of the board, there’s an unpopulated footprint labeled J7, which provides a decoded enable signal for the next HD20 hard disk in the chain. You’ll have to kluge together your own custom cable for connecting the daisy-chained HD20, but it works. I even designed a hardware adapter to make this easier, but never sold it. And now that I’ve told you about this, I’ll also tell you that I plan to break this undocumented J7 signal in a future firmware release.

You know what would be better than daisy-chaining a second physical HD20 hard disk? Making Floppy Emu emulate two separate HD20 hard disks at the same time. This is such an obvious idea that I’m unsure why I never thought of it before. Emulating two hard disks simultaneously would be fantastic for booting one and formatting the other, or copying files between the two. Both of those jobs are currently impossible with the Floppy Emu, and require using additional disks or PC-based disk image editors. It should be fairly simple to make it happen: instead of using that J7 signal to enable a second external HD20 hard disk, use the same signal to enable a second emulated disk. The necessary UI and dual-disk guts could be borrowed from the Apple II version of Floppy Emu firmware.

Dual Macintosh Floppy Drives

The PHASE3 toggling trick works for HD20 hard disks because the Macintosh ROM already contains the necessary code. But could the same trick be used to select multiple daisy-chained floppy disks? This would require a Macintosh INIT or System Extension that patches the floppy disk controller code in ROM, fools the computer into thinking there are three floppy drives (one internal and two external), and performs the PHASE3 toggling every time it accesses the floppy drive. On a real floppy drive this wouldn’t do anything, and attempting to select the second external drive would simply select the first one again. But on a Floppy Emu with appropriate firmware support, it should theoretically work as intended. This ROM patch would also need some way of detecting whether the external drive were a dual-drive capable Floppy Emu, or a single-drive Floppy Emu, or a real floppy drive.

The floppy disk controller code in ROM would also need to be reviewed to look for existing places where PHASE3 might be changed while ENABLE is asserted. These would act as false positives, triggering unwanted selection of the second drive. I’m unsure if the existing code does this, or if it does, how difficult it might be to change. Maybe a different selection mechanism than PHASE3 toggling would be required. Maybe all the disk I/O signals are already overloaded during floppy disk I/O and there’s no practical way of using them to select a second drive. More research is needed.

Whatever the final selection mechanism is, this kind of INIT-based ROM patching is far beyond my Mac programming skill level, and also beyond my interest level. But I’m hoping that somebody reading this might have interest and the necessary skills. I think there would need to be a separate patch for each unique Macintosh ROM: one for the Mac 128K and 512K, another for the Mac 512Ke and Plus, another for the Mac SE, another for each of the Macintosh II models… a lot. The necessary changes would be mostly the same in each case, but the patch location and details would differ. If this makes sense to you, and you think you have the knowledge to make an INIT patch like this, please let me know!

Assuming that ROM is patched somehow, and there now exists a way to physically select a second floppy drive, there’s still a question whether Floppy Emu could actually emulate two 3.5 inch floppy drives. There are major reasons to think it might not be possible. Although the hardware can emulate two 5.25 inch floppy drives for the Apple II, 3.5 inch floppy drives are much more complicated. 3.5 inch drives have 10 internal 1-bit state registers for tracking things like which direction to step tracks, and Floppy Emu maintains this state entirely within its CPLD logic chip. The chip doesn’t have enough logic resources to store two copies of these state registers, and there’s no mechanism for the microcontroller to directly query or set this state. Making this work for two 3.5 inch floppy drives would therefore require some creative solutions that I can’t see right now. But this is ultimately an emulator hardware limitation, and dual 3.5 is at least theoretically possible with a patched ROM.

Read 4 comments and join the conversation 

Floppy Emu Update: Odds and Ends

Here’s one more firmware update for the BMOW Floppy Emu disk emulator for classic Apple computers. This update resolves some minor problems and inconsistencies that were discovered in the previous version, but don’t get too excited because it’s all small stuff.

Macintosh/Lisa

  • Fixed a bug that broke the display type setting when selecting a Macintosh Hard Disk image

Apple II

  • Back-ported the past year’s worth of updates to the Floppy Emu Model A
  • Added a new start-up screen for the LCD display on the Model A and Model B
  • Fixed more bugs that could prevent firmware updates from completing successfully when Emu is in Smartport mode
  • Implemented a buffer overflow check for non-standard WOZ disk images (max size is 9216 bytes per track)
  • ProDOS volume names are now displayed for raw disk images whenever possible, in addition to the disk image name

Download the latest Floppy Emu firmware from the project page, or buy a new Floppy Emu Model C at the BMOW Store.

Read 2 comments and join the conversation 

Floppy Emu: New Smartport UI and Settings Menu

I’m squeezing in one more big firmware update for the BMOW Floppy Emu disk emulator before the Thanksgiving break. This update brings a major improvement for Smartport hard disk selection and management, as well as a new settings menu that combines all of the Floppy Emu’s various user preferences. Based on the suggestions and questions I’ve received in the past, I think this update is going to make a lot of people happy.

 
Disk Image Selection UI for Smartport Hard Disks

For Apple II computers, Floppy Emu offers a Smartport hard disk emulation mode, providing up to four simultaneously-available hard disks to your computer. Today’s firmware update introduces a new UI for dynamically managing and selecting the desired disk images, entirely within the Floppy Emu menus, and without needing to rename any files on the SD card. After pressing a button to pause the Smartport disk emulation, a setup screen appears. For each of the four hard disk slots, you can view or change the associated disk image, or remove the disk image and leave the slot empty. Disk images are selected through the the same file browser menus as in other emulation modes.

It sounds simple, it was a bit of a bear to implement, but it was worth it. The new interface is a much more flexible and intuitive way of configuring Smartport hard disks, and it’s no longer necessary to name or rename the disk images using a fixed naming convention like smart0-gsos-6.0.2.po.

 
System Settings Menu

This update also introduces a new system settings menu for all Macintosh, Lisa, and Apple II firmware versions. Press SELECT when prompted during Floppy Emu’s startup, and you’ll arrive at this new top-level menu. From here you can change the current emulation mode, adjust the display type and brightness, view software version information, and more. This menu replaces the scattered settings interfaces that existed before, each requiring a different hard-to-remember button combination to reach.

The Jumbo OLED option that appears in the settings menu is for a 2.4 inch display that was previously discussed in 2019. A few people have since built custom Floppy Emu enclosures using this OLED, but the standard firmware doesn’t work quite right with it: text and images appear shifted two pixels out of position. Beginning today, the jumbo OLED is graduating from a fun experiment into an officially-supported option, and changing the display type to jumbo adjusts the image position as need.

 
Update Now

Download the latest Floppy Emu firmware from the project page, or buy a new Floppy Emu Model C at the BMOW Store.

I’ve also prepared this video demo of the new one-step process for firmware updates, which was introduced last week.

Read 15 comments and join the conversation 

« Newer PostsOlder Posts »