New Project: DoubleVision SE/30 Card

(How are you so fast?)

Have you considered a passthrough PDS slot and a physical card ID selection? Stacking SE/30 cards is very handy and the more cards with passthrough, the easier it is to customize (of course, you can't really get past a few cards or power and signaling issues crop up). Along with that you can have ID conflicts with multiple boards so it's common to provide jumpers or DIP switch so you can adjust before inserting.
 
Indeed there is no support for hardware cursor in 6/7/8. I also have the hardware cursor (albeit smaller at IIRC 32x32, a clone of what available in Brooktree DACs in SPARCstations, also with a limited number of colors) but it's only useful in X11.
At that size, if the sprite is full-color (same depth and CLUT as the display), then it could replace the SW implementation.

Even if the sprite is too shallow, you could limit it to black-and-white cursors — which is most of them. A more significant limitation would be the lack of XOR mode in the blitter, used in the I-beam cursor for example.

Maybe it could be used by hijacking some of the QD functions - but it's likely going to be quite difficult to implement.

It's not out of the question. Here's a proof of concept for how it could work:


QuickDraw per se is untouched, and no traps are patched — only some jump vectors in low memory are rerouted. That is, in fact, how it works in my reimplementation of classic Mac OS — though just how closely it resembles the real thing is a topic I haven't investigated.
 
Even if the sprite is too shallow, you could limit it to black-and-white cursors — which is most of them. A more significant limitation would be the lack of XOR mode in the blitter, used in the I-beam cursor for example.
"True" hardware cursor, in the style of Brooktree, don't rely on a blitter - do you use what I would describe as an "offscreen cursor" ? (stored in additional VRAM beyond the picture, perhaps alongside a copy of the area it replaces?)

In the Brooktree style, the cursor bitmap is stored directly in the DAC, alongside its coordinate. When the HW cursor is active, inside the cursor area the DAC simply ignores the data coming from the framebuffer and use those from the cursor bitmap instead wherever the cursor bitmap is not set to "transparent". The content of the framebuffer underneath the cursor is never changed at all. It's very efficient.

It's not out of the question. Here's a proof of concept for how it could work:
QuickDraw per se is untouched, and no traps are patched — only some jump vectors in low memory are rerouted. That is, in fact, how it works in my reimplementation of classic Mac OS — though just how closely it resembles the real thing is a topic I haven't investigated.
Interesting. Does your reimplementation only cover the original QD, or the entire Color QD ? It appears to be mostly C/C++ (with a tiny bit of 68k ASM), and it makes me wonder whether some of it could be used as the basis for acceleration code. I limited myself to low-level variant(s) of BitBlit because the upper level stuff was too complex to reimplement, but if you already have done the work it might bear revisiting...
 
Indeed there is no support for hardware cursor in 6/7/8. I also have the hardware cursor (albeit smaller at IIRC 32x32, a clone of what available in Brooktree DACs in SPARCstations, also with a limited number of colors) but it's only useful in X11.
At that size, if the sprite is full-color (same depth and CLUT as the display), then it could replace the SW implementation. Maybe it could be used by hijacking some of the QD functions - but it's likely going to be quite difficult to implement.

As I said, the hardware function exists, and perhaps it will come in handy at some point. ;) Same as with the P-Vision, I will publish a complete register description of the DoubleVision. The mouse sprite is 3 colors and has its own independent palette, so it has constant appearance no matter if a CLUT or RGB color mode is displayed.

What does that mean and what is it used for on Amigas, practically?

On Amiga, any application can open its idividual screen with its own display parameters. That by itself is nothing new, but the UI concepts of Intuition (that is how the window system is called) include the concept of draggable screens.

So each application has, similar to the MAC.. err..... Macintosh(tm) ;) , a menu bar on top (even when it is invisible), and with the mouse, you can select the menu bar, click and hold the left mouse button, and then you can move the screen up- and downwards, like a curtain.

And the Amiga display hardware can do this by just updating a so-called "Display List", which is a definition of screen regions, consisting of display memory pointers, palette CLUT entries, display attributes, etc. For that, it has its own display processor called the "Copper", which is executing a program, while the display hardware draws the screen.

I'll show you a short example here.

Here, you can see a Directory / File manager application running on its own screen:

Screenshot 2026-01-22 090903.png

And by clicking and holding the menu bar, i can "pull" the application down, revealing the underlying desktop screen (Workbench):

Screenshot 2026-01-22 090930.png


AFAIK, it's a UI concept which is pretty much unique to the Amiga. Which is why my graphics core also supports this feature. ;)

You basically can handle multiple surfaces on one display by just updating a few parameters in display memory, and it is very smooth. An 68020-based Amiga has no trouble moving screens at 60fps.

You can debate whether that's a useful feature. For me personally, I cherish it, because it's easier to go "in-between" applications, than dragging windows around on a single desktop. I guess it's a matter of personal preference.

Thinking of screens, plural, on Mac, QD basically define a massive 64Ki*64Ki (16-bits signed values) area, and each display is just a small subset of that - obviously the primary screen is anchored at (0,0). They can have their own resolution and depth independently. It's very convenient for the user but as mentioned previously, makes it less than obvious what's going on if you don't go through QD.

Of course, that is supported on my graphics core. I can even define, for each display slice, a "virtual screen", and apply a per-pixel panning (scrolling) to move over this area. This is also implemented in Amiga graphics library - example:

Paint program opening a 640x480 8-bit CLUT screen:

Screenshot 2026-01-22 095510.png

Next, I "drag" the screen down, revealing the workbench at 1280x720 Hi-Color - but displayed at 640x480 display resolution.

Screenshot 2026-01-22 095610.png

To reach other regions of the desktop, I can smoothly scroll over the virtual 1280x720 surface witout changing the display for either of the 2 screens.

Screenshot 2026-01-22 095625.png


And this all being accomplished WITHOUT moving a single pixel byte in memory. ;)

I'm not suggesting that these features are applicable in MacOS, it's basically what this graphics card is going to get "for free", since the core has already been developed.
 
"True" hardware cursor, in the style of Brooktree, don't rely on a blitter - do you use what I would describe as an "offscreen cursor" ? (stored in additional VRAM beyond the picture, perhaps alongside a copy of the area it replaces?)

That's how the software cursor works. A copy of the cursor image is kept around offscreen, as is a save buffer for pixels overwritten by the onscreen cursor. (Whether either image is cached in VRAM is an implementation detail that's opaque to me as a Mac OS user and irrelevant to my emulator — since emulated memory is all the same speed.)

The benefit of the software cursor is that it does get rendered into the framebuffer, so it just works everywhere, and on any desktop-grade system it's plenty fast. It's not as good when it's a Raspberry Pi 1 running a non-JITted 68K emulation. :-) Also, if you're recording a screencast, the software cursor loses information about the cursor and generates otherwise superfluous screen updates instead of simpler cursor movements (or other changes).

In the Brooktree style, the cursor bitmap is stored directly in the DAC, alongside its coordinate. When the HW cursor is active, inside the cursor area the DAC simply ignores the data coming from the framebuffer and use those from the cursor bitmap instead wherever the cursor bitmap is not set to "transparent". The content of the framebuffer underneath the cursor is never changed at all. It's very efficient.

In stark contrast to projects that strictly emulate hardware, my goal is to make applications run. The distinction between "hardware" and "software" can get fuzzy (because in truth, it's all software). I tend to think of 68K code as "software" and anything else as "hardware".

My OpenGL-based front ends use two `glLogicOp()` calls to blit the cursor:


Neither the virtual framebuffer (in 68K address space), the transit framebuffer (in host-CPU shared memory), nor the framebuffer texture (on the GPU) are modified for "hardware" cursor changes.

Interesting. Does your reimplementation only cover the original QD, or the entire Color QD ?

Modest support for multibit displays (cursors and cursor/menu save buffering) has been publicly merged, while the vastly larger effort to implement Color QuickDraw remains a work in progress in private branches. Prince of Persia, System's Twilight, TaskMaker, and Tetris are basically playable in color, despite a few noticeable performance and palette issues.

It appears to be mostly C/C++ (with a tiny bit of 68k ASM), and it makes me wonder whether some of it could be used as the basis for acceleration code.

I would imagine so. The first step would be moving the code of interest into library projects and building them for other architectures with modern tools.

I limited myself to low-level variant(s) of BitBlit because the upper level stuff was too complex to reimplement, but if you already have done the work it might bear revisiting...

The sheer scale of the complexity difference between BitBlit and CopyBits can induce vertigo. :-)

Some of the work is done already, and I'm open to doing some more.
 
Most PCI PowerMacs have a hardware cursor, and I believe MacOS *does* use it. @joevt or @dingusdev would know more though.
There was support added, as documented in "Designing PCI Cards and Drivers for Power Macintosh Computers" (p513). However, I have never seen the relevant status/control codes called on any 68K version of the system I've tried :-(

On Amiga, any application can open its idividual screen with its own display parameters
Similar to X11; the Mac is much more simple - an application can change the screen settings if it really wants to (usually, games), but everything is displayed with whichever parameters are currently set on the display(s) they are on. So a large enough window could spread over three displays and have a part displayed in B&W, a part in 4-bits and a part in 8-bits... provided it was written entirely to Apple's specifications. Some applications (again - usually, games) would take shortcuts and don't play so nice on multi-display.

(...) you can select the menu bar, click and hold the left mouse button, and then you can move the screen up- and downwards, like a curtain.
Thanks for the explanations.

And this all being accomplished WITHOUT moving a single pixel byte in memory. ;)
Which was a distinct benefits at the time; however, it probably didn't help with multiple displays where you have no choice but to copy data from one to the other. Multi-display/multi-screen was a big selling point of NuBus Macintoshes in some markets that were critical for Apple at the time. Workstations with X11 could do multiple displays, but before Xinerama (1998) they couldn't move from one to another easily. It was new when on a '87 Mac II you could just drag a window from one display to another, and even leave it in the middle with parts on both displays.


I'm not suggesting that these features are applicable in MacOS, it's basically what this graphics card is going to get "for free", since the core has already been developed.
Yes, I think that one you can save some area in the FPGA :-) 68k Mac just need a dumb framebuffer, and maybe some acceleration if it can be done.
The only feature I added by request (liked the challenge!) in the *FPGA was the ability to change the hardware resolution; my original design only did one 'true' resolution (usually, but not necessarily, Full HD), and everything else was windowboxed - in the middle of the display, surrounded by black borders. But for some games, an user (maybe I should say the user, really, not that many *FPGA out there :-) ) asked for "real" resolutions - to get full screen 640x480 instead of a small area in the middle of a huge screen. Reconfiguring the FPGA PLL was the big challenge. To this day, there's an issue when changing resolution or depth, where the screen comes back a bit offset as for reason unknown the DMA engine and the Raster engine goes out of sync. I've never been able to fix that f*****g issue :-( (and it really annoys me, I rewrote the hardware reset code like a dozen times). Fortunately it can be "fixes" by ... changing again until it works (yuck!).
You probably want that ability to change depth and resolution ; lots of early color games only worked in 4 and/or 16 colors (later games added, then required, 256), or only worked at 512x384 (the Mac LC 12" screen resolution) or 640x480 (most early NuBus card and early onboard video, including early color Powerbooks like the 180c). Later games become more tolerant, but that was more in the PowerPC era.
 
Last edited:
Back
Top