So anyway, I've made some updates to asm89. Now it does forward location references at least as well as ASM89 (Intel's version) did, which is that it assumes an 8-bit displacement and will require you to use the L version if it's wrong. And the int literal parsing is improved so you can't do bogus things like [PP].38271. And I also half-way implemented LPDI. The segment is 0 and it produces no relocation information, but it's there. https://bytex64.net/apricot/asm89/

#Aprilcot

asm89 8089 assembler

Alright, that was a lot of work, but I got it working. And the answer isโ€ฆ 12. Itโ€™s slower. ๐Ÿ˜

#Aprilcot

Well #Aprilcot is over, but we've still got some loose ends to tie up. I've got to actually use the 8089 for sprite blits now that I fixed the MAME bug, and I've got to build one of these MFM emulators and see if it even works.

But all that might have to wait. I had wanted to participate again in the Tiny Tapeout demoscene competition, but I realized too late the deadline is very soon. I'd still like to try, though. I'm not gonna make a winner in 10 days, but I could probably still make something cool?

Guess who found a bug in MAME? Getting my ducks in a row here, this is just doing a pointer load so I can get the address of the pixels I want to copy, then copying something from that memory to the X and Y parameters.

lpd ga, [pp].8
mov gb, [ga].4
mov [pp].4, gb
mov [pp].6, [ga].6
hlt

The first one is done by MOVing into the GB register first, then from GB to memory. The second one uses the 8089's memory-to-memory MOV. And it turns out MAME's 8089 core doesn't implement mem-mem MOV correctly, leaving zero in the Y parameter instead of 7. I thought I was going mad!

#Aprilcot

So it's a little convoluted, but it does make it simple to interleave lots of 8089 programs running under the supervision of different parts of the system. You just wait for a channel to not be busy, load the CCB with the address of your own CPB, and let 'er rip. If a higher priority task needs a channel but one is not available, it can pause a running task, save the CCB info, swap in its own task, run that, swap the old one back in, and continue it. AFAIK nothing in the Apricot system does this, and it's probably moot anyway since the way the 8089 is implemented shares the bus with the CPU, so the 8086 can't make much progress while the 8089 is running, anyway.

Apricot typically uses channel 1 for the floppy drive controller. I've read somewhere that channel 2 is used by the Winchester controller, but as far as I've seen in the emulated system, that's not the case. I've also read that the system will run without an 8089, so probably there are some Apricots out there without them.

#Aprilcot

I should probably explain a little bit about the interface to the 8089. Early in the system initialization, the CPU tells the IOP to read the address of a System Configuration Block from the top of ROM. That address is right next to the 8086 reset location at FFFF8h, so if you've ever wondered what those unused bytes were, that's what they're for! This sets up the Channel Control Block, which defines the locations and parameters for executing Channel Parameter Blocks, which define a pointer to the 8089 machine code and parameters to the task. When the 8089 gets a "channel attention" (on the Apricot connected to I/O ports 70h and 72h), it re-reads the CCB for the signaled channel and starts/stops any tasks defined there.

#Aprilcot

But anyway, with that worked around, invoking the 8089 from Pascal seems to work. The code here is very simple:

MOVI GA, 1
ADD [PP].4, GA
HLT

It just adds 1 to the word at offset 4 in the parameter block. The first two words point to the code itself, so the third one is where parameters live. The Pascal code that invokes it just sets that to 0, and the output below shows that it has been changed, and then dumps the state of the 8089 Channel Control Block.

#Aprilcot

We've maxed out the CPU, but the Apricot has another trick - the 8089. It's a dedicated I/O coprocessor, and theoretically it can push bytes even faster than the CPU. If... I can get it working.

I've discovered the hard way that Turbo Pascal is really picky about what it can link with. It _only_ wants to link with external functions. If the OBJ file you're linking with has _any_ data segment symbols, it flat out refuses to deal with it. At first I thought this was a subtle bug in how asm89 generates OMF files, but it does the same with a C file compiled with Turbo C. And since asm89 defines the 8089 machine code symbols as data (which I think is correct from the POV of the CPU), it just doesn't work. :/

So I guess I'll just have to copy the machine code into the Pascal source as raw data. That sucks.

#Aprilcot

I'm reading about what GRAPHICS.EXE is, and it's an implementation of Digital Research's GSX (https://en.wikipedia.org/wiki/Digital_Research_GEM#GSX). GSX is a cross-platform (CP/M86, Concurrent CP/M, and PC/MS-DOS) graphics library. Well, more of a resident graphics platform, since it's all accessed through interrupt handlers (they call the drawing routines GDOS and the drivers GIOS). It evolved into the graphics system for GEM. It seems ACT used it for their stuff too, and in ports like GW-BASIC.

GSX is mentioned in the technical manual briefly, but I didn't really understand it because it's just talking about the platform specific differences. If you want to understand what it is, there's a whole other manual for that: https://archive.org/details/gsx-handbook-digital-researchacme

The manual states that the command for DOS is `GSX`, but here it's `GRAPHICS`. So maybe the version ACT was using was a fairly early release.

#Aprilcot

GEM (desktop environment) - Wikipedia

Oh, so the other part of this adventure was figuring out how to get my greaseweazle to write single-sided 70 track disks. There wasn't a definition for it, so I looked at the diskdefs and made my own. Or at least... there wasn't a definition in the stable release. Turns out @crashtestdev beat me to it last month. Thanks! :D https://github.com/keirf/greaseweazle/blob/master/src/greaseweazle/data/diskdefs_apricot.cfg

#Aprilcot

greaseweazle/src/greaseweazle/data/diskdefs_apricot.cfg at master ยท keirf/greaseweazle

Tools for accessing a floppy drive at the raw flux level - keirf/greaseweazle

GitHub