My emulator, Clock Signal, now also emulates the IIe

691 views
Skip to first unread message

Thomas Harte

unread,
Aug 5, 2018, 6:18:41 PM8/5/18
to
Just a minor announcement; it's been a long time since I was a heavy usenet user so please shout if these are an etiquette violation.

My MIT-licensed Apple II emulator for macOS and, separately, Unixes has added the IIe to its roster of supported machines. Alongside some fixes to joystick emulation and the Disk II it has now crossed the Prince of Persia threshold, according to which the time spent on it temporarily drops off as it is instead invested into playing Prince of Persia. I'm sure that's a common phenomenon.

Downloads are at https://github.com/TomHarte/CLK/releases but if you plan to build for yourself you might as well just clone the repository and track that.

All feedback always gratefully received.

Wizard1969

unread,
Aug 8, 2018, 12:15:13 AM8/8/18
to
Excellent. Thanks for the announcement!

Thomas Harte

unread,
Aug 9, 2018, 11:26:16 AM8/9/18
to
On Wednesday, 8 August 2018 00:15:13 UTC-4, Wizard1969 wrote:
> Excellent. Thanks for the announcement!

No problem; and I'm aware that most people either don't want or already have an emulator so I'm warmed by any response whatsoever.

On my immediate slate, I'm working on 65C02 support so that I can add Enhanced IIe support, and am vaguely aware that some of the vapour lock demos — such as Vince's recent waterfall — switch two columns early.

Mine is one of those emulators where the processor just produces a cycle-by-cycle accounting of memory accesses so I doubt the problem is on that side. It's not like I've pretended that all accesses occur at instruction boundaries, or any of that nonsense.

Video is cycle accurate but performed just-in-time so probably there's either an error there or else there's a delay in soft switches taking effect that I've modelled incorrectly. It could conceivably be an off-by-one error on both sides.

I also want to add proper support for 13-sector 5-and-3 disks, for completeness. Which is defined to mean recognising that a disk is 5-and-3 when opened, and substituting the proper state machine. My Disk II implementation just runs through a binary image of the original state machine so that's just a ROM substitution. Given that I support WOZ images, and do what I can with NIBs, there's no physical barrier to using such an image, and it shouldn't be a big thing to add. It's not like I've a custom implementation of the state machine, or even any sort of artificial concept of nibble access to deal with.

And Apple II resources are generally excellent, so this also probably isn't that interesting, but I've been keeping notes on some pieces of Apple architecture in the wiki at https://github.com/TomHarte/CLK/wiki — primarily the IIe memory map, documented in terms of regions and then a description of relevant soft switches rather than the conventional vice versa, and disk encoding.

So still lots to do, even without contemplating how interested I am in the IIgs.

Nick Westgate

unread,
Aug 9, 2018, 6:40:13 PM8/9/18
to
On Friday, 10 August 2018 03:26:16 UTC+12, Thomas Harte wrote:
> No problem; and I'm aware that most people either don't want or already have an emulator so I'm warmed by any response whatsoever.

There are certainly many to choose from - because it's fun programming them. ; - )

> On my immediate slate, I'm working on 65C02 support so that I can add Enhanced IIe support, and am vaguely aware that some of the vapour lock demos — such as Vince's recent waterfall — switch two columns early.

Are you aware of the undocumented 65C02 opcodes? Not all the NOPs are actually NOPs etc.

> Video is cycle accurate but performed just-in-time so probably there's either an error there or else there's a delay in soft switches taking effect that I've modelled incorrectly. It could conceivably be an off-by-one error on both sides.

When Tom was getting the French Touch demos working with the floating bus in AppleWin I think there was an off-by-2 error. Eventually he figured it out, so there will be an issue on GitHub and comments in the source.

> I also want to add proper support for 13-sector 5-and-3 disks, for completeness. Which is defined to mean recognising that a disk is 5-and-3 when opened, and substituting the proper state machine. My Disk II implementation just runs through a binary image of the original state machine so that's just a ROM substitution.

I'm sure you're aware, but the 6+2 PROM reads 5+3 bitstreams just fine. The main difference is that the boot PROM looks for the 13 sector header prologue to read sector 0.

Cheers,
Nick.

TomCh

unread,
Aug 10, 2018, 8:00:33 AM8/10/18
to
On Thursday, August 9, 2018 at 11:40:13 PM UTC+1, Nick Westgate wrote:
> > Video is cycle accurate but performed just-in-time so probably there's either an error there or else there's a delay in soft switches taking effect that I've modelled incorrectly. It could conceivably be an off-by-one error on both sides.
>
> When Tom was getting the French Touch demos working with the floating bus in AppleWin I think there was an off-by-2 error. Eventually he figured it out, so there will be an issue on GitHub and comments in the source.
>
My investigations were concluded in this comment:
https://github.com/AppleWin/AppleWin/issues/241#issuecomment-279250459

IIRC, the gist seems to be this part:

"For Ansi Story, it doesn't actually matter what cycle does the floating bus read, so it could occur on cycle 0 (instead of cycle 3). It's just important that the video mode switch occurs +2 cycles later."

btw. I just removed the fix from AppleWin and re-ran Vince's Waterfall demo, and it still works fine, so perhaps your issue is something else? The Ansi Story effect was stable mode changing mid-scanline (DGR->TEXT80->DGR).

Tom

Thomas Harte

unread,
Aug 10, 2018, 10:20:09 AM8/10/18
to
On Thursday, 9 August 2018 18:40:13 UTC-4, Nick Westgate wrote:
> Are you aware of the undocumented 65C02 opcodes? Not all the NOPs are actually NOPs etc.

Not yet I'm not. My process has been to grab Klaus Dorman's 65C02 functional tests, and start working through each failure in sequence, referencing sources such as http://wilsonminesco.com/NMOS-CMOSdif/

I've not found a source for the 65C02 that's as authoritative as 64doc.txt is for the 6502 as to instruction breakdowns so some are guesswork but mostly it's pretty confident stuff. E.g. I have BBR and BBS acting with a breakdown of:

Cycle 1: fetch instruction
2: fetch first operand
3: fetch value from zero page
4: fetch second operand
5: fetch from address implied by having added offset to the low byte of the PC but not yet having applied carry potentially to adjust the top byte

My guess being based on the observation that fetching without having yet applied carry is the usual reason when a non-read-modify-write 6502 instruction is longer than the simple count of required memory accesses implies, and the assumption that there's only the one ALU so probably nowhere to put a branch offset while loading the zero-page value. Otherwise there seems to be no reason to guess one way or the other on fetch from the zero page versus fetch of the second operand.

> I'm sure you're aware, but the 6+2 PROM reads 5+3 bitstreams just fine. The main difference is that the boot PROM looks for the 13 sector header prologue to read sector 0.

I was aware, but at some point before writing my previous post clearly stopped being aware. So it's the same amount of work — inspect the disk surface, determine that it's 5-and-3, switch a ROM — but, umm, I'll aim for switching the proper ROM.

On Friday, 10 August 2018 08:00:33 UTC-4, TomCh wrote:
> My investigations were concluded in this comment:
> https://github.com/AppleWin/AppleWin/issues/241#issuecomment-279250459
>
> IIRC, the gist seems to be this part:
>
> "For Ansi Story, it doesn't actually matter what cycle does the floating bus read, so it could occur on cycle 0 (instead of cycle 3). It's just important that the video mode switch occurs +2 cycles later."
>
> btw. I just removed the fix from AppleWin and re-ran Vince's Waterfall demo, and it still works fine, so perhaps your issue is something else? The Ansi Story effect was stable mode changing mid-scanline (DGR->TEXT80->DGR).

Video switches not taking effect for two cycles would exactly explain the problem and be a very easy fix;

As above I don't have atomic opcodes — LDA $C05n is performed by the emulator as:

Cycle 1: read instruction
Cycle 2: read first byte of address
Cycle 3: read second byte of address
Cycle 4: read from $C05n

There's no way my emulated 6502 could hit the soft switch early because it doesn't have the information to do so yet. So, I think, it can't be a cycle 0 versus cycle 3 thing.

The software I've tried has been entirely stable, but Vince's demo made me wonder whether the switch is early, and looking back at Crazy Cycles et al doesn't defeat that concern; the problem with a bouncing box mode change that isn't supposed to go right the way to the edge of the screen is that it not going quite as far right as it does left isn't especially obvious except with hindsight.

I haven't actually tested ANSI Story, because being that I can now test IIe software hasn't quite permeated my stubborn mind. I'll check it out.

Though, any idea whether the delay applies equally to all soft switches? Since, as you say, it's not a mode switch I'm looking at here.

TomCh

unread,
Aug 10, 2018, 12:39:34 PM8/10/18
to
On Friday, August 10, 2018 at 3:20:09 PM UTC+1, Thomas Harte wrote:
> Though, any idea whether the delay applies equally to all soft switches? Since, as you say, it's not a mode switch I'm looking at here.

For video soft switches, the 2 cycles is the time to load the new video data into the latch and start shifting it out.

So really the soft switch occurs immediately on the cycle of the access (eg. your cycle 4), but the video "pipeline" is 2 cycles long. Eg. if you are switching from TEXT to HGR, then after accessing $C057 (your cycle 4), HGR video data doesn't get displayed until cycle 6.

The Excel diagram attached to the above GitHub comment tries to show this for both the phase-1 and phase-0 clocks (for both address & data buses). I use half-cycle 1MHz cycles. (NB. I mistakenly use $C056 instead of $C057)

Tom

Thomas Harte

unread,
Aug 10, 2018, 1:51:43 PM8/10/18
to
On Friday, 10 August 2018 12:39:34 UTC-4, TomCh wrote:
> For video soft switches, the 2 cycles is the time to load the new video data into the latch and start shifting it out.
>
> So really the soft switch occurs immediately on the cycle of the access (eg. your cycle 4), but the video "pipeline" is 2 cycles long. Eg. if you are switching from TEXT to HGR, then after accessing $C057 (your cycle 4), HGR video data doesn't get displayed until cycle 6.
>
> The Excel diagram attached to the above GitHub comment tries to show this for both the phase-1 and phase-0 clocks (for both address & data buses). I use half-cycle 1MHz cycles. (NB. I mistakenly use $C056 instead of $C057)

Thanks for the correction and the detailed explanation! This is most certainly what I'm currently getting wrong — there's no delay for video data. If it was fetched during cycle n then it finishes its transcription onto the wire exactly before cycle n+1's fetch completes.

That will be a slightly less easy fix but I'll get it done.

Nick Westgate

unread,
Aug 12, 2018, 8:49:03 PM8/12/18
to
On Saturday, 11 August 2018 02:20:09 UTC+12, Thomas Harte wrote:
> On Thursday, 9 August 2018 18:40:13 UTC-4, Nick Westgate wrote:
> > I'm sure you're aware, but the 6+2 PROM reads 5+3 bitstreams just fine. The main difference is that the boot PROM looks for the 13 sector header prologue to read sector 0.
>
> I was aware, but at some point before writing my previous post clearly stopped being aware. So it's the same amount of work — inspect the disk surface, determine that it's 5-and-3, switch a ROM — but, umm, I'll aim for switching the proper ROM.

Well, you could still switch both PROMs if you wanted to be authentic. I suppose it might matter for 5+3 images that had some kind of timing-related protection. But for regular disks the 6+2 sequencer PROM timing is fine. Also, there are third party disk controller cards that can boot both kinds of disk - their boot ROM code looks for both types of prologue.

Thanks Tom for filling in the details about the video timing.

Also Thomas, you might be interested in something Tom just discovered, and which I gathered some data on a few years ago. The latest comments are in this issue:
https://github.com/AppleWin/AppleWin/issues/555

Basically it's this: 14M shifted pixels (HIRES80 and TEXT80) start earlier than 7M shifted ones (TEXT 40).

If you have a mixed 40 and 80 column mode then it looks like this:
https://drive.google.com/open?id=1cC9xSukp-C9Te9ektGV_lxgsSXj-RSHy

Not much practical significance, but interesting.

Cheers,
Nick.

TomCh

unread,
Aug 13, 2018, 5:53:01 AM8/13/18
to
On Monday, August 13, 2018 at 1:49:03 AM UTC+1, Nick Westgate wrote:
> Also Thomas, you might be interested in something Tom just discovered, and which I gathered some data on a few years ago. The latest comments are in this issue:
> https://github.com/AppleWin/AppleWin/issues/555
>
> Basically it's this: 14M shifted pixels (HIRES80 and TEXT80) start earlier than 7M shifted ones (TEXT 40).
>
> If you have a mixed 40 and 80 column mode then it looks like this:
> https://drive.google.com/open?id=1cC9xSukp-C9Te9ektGV_lxgsSXj-RSHy
>
> Not much practical significance, but interesting.
>
> Cheers,
> Nick.

Actually I should have paid more attention to Zellyn's a2audit, which says to look for the 1/80th shift when flicking between 40-col & 80-col inverse screens.

In terms of practical use: what happens when you switch 7M<->14M mid visible scanline? a pseudo-568 dot display? is there any potential for a creative demo based on this?

Tom

Thomas Harte

unread,
Aug 13, 2018, 12:48:58 PM8/13/18
to
On Monday, August 13, 2018 at 1:49:03 AM UTC+1, Nick Westgate wrote:
> Also Thomas, you might be interested in something Tom just discovered, and which I gathered some data on a few years ago. The latest comments are in this issue:
> https://github.com/AppleWin/AppleWin/issues/555
>
> Basically it's this: 14M shifted pixels (HIRES80 and TEXT80) start earlier than 7M shifted ones (TEXT 40).

I guess that makes a little sense; so values from main memory always start at the same position, and auxiliary values a half-clock to the left of that.

It does resolve one of my dangling issues with double high-resolution colouring though. I'd introduced a 0.25 colour clock delay in that output in order to get the right colours, reasoning that there is such a facility in hardware for the shifted single high resolution bytes so probably yet another thing that I'm too stupid to understand about the hardware is at play — the delay takes effect on double high resolution colours.

But shifting everything half a clock cycle to the left moves it 1.75 colour clock cycles. But mine were already 0.25 colour clock cycles to the right. So the net movement is exactly 2 colour clock cycles. And suddenly I've no need to figure out why the quarter-colour-clock delay is active. It isn't.

I assume the same thing was also afoot to motivate the linked "one pixel shifted to the right" AppleWin bug?

Otherwise, I had wheeled back around to this area yesterday but now I'm inclined to take a step back again. Putting together a simple 130-half-clock diagram marked with memory fetches here, colour clock there, stretched cycle here, first column from auxiliary memory (if any) here, etc, is probably the smart thing to do next.

On Monday, 13 August 2018 05:53:01 UTC-4, TomCh wrote:
> Actually I should have paid more attention to Zellyn's a2audit, which says to look for the 1/80th shift when flicking between 40-col & 80-col inverse screens.
>
> In terms of practical use: what happens when you switch 7M<->14M mid visible scanline? a pseudo-568 dot display? is there any potential for a creative demo based on this?

... and would it be pseudo-569 if you switched to regular high resolution and put a delay on the final byte?

Zellyn

unread,
Aug 13, 2018, 1:52:54 PM8/13/18
to
On Monday, August 13, 2018 at 5:53:01 AM UTC-4, TomCh wrote:
> Actually I should have paid more attention to Zellyn's a2audit, which says to look for the 1/80th shift when flicking between 40-col & 80-col inverse screens.

:-)

I actually just hacked it up in the simplest way possible for OpenEmulator, then realized that the real hardware did it the same way! :-)

Zellyn

TomCh

unread,
Aug 13, 2018, 5:28:53 PM8/13/18
to
On Monday, August 13, 2018 at 5:48:58 PM UTC+1, Thomas Harte wrote:
> On Monday, August 13, 2018 at 1:49:03 AM UTC+1, Nick Westgate wrote:
> > Also Thomas, you might be interested in something Tom just discovered, and which I gathered some data on a few years ago. The latest comments are in this issue:
> > https://github.com/AppleWin/AppleWin/issues/555
> >
> > Basically it's this: 14M shifted pixels (HIRES80 and TEXT80) start earlier than 7M shifted ones (TEXT 40).
>
> I guess that makes a little sense; so values from main memory always start at the same position, and auxiliary values a half-clock to the left of that.
>
> It does resolve one of my dangling issues with double high-resolution colouring though. I'd introduced a 0.25 colour clock delay in that output in order to get the right colours, reasoning that there is such a facility in hardware for the shifted single high resolution bytes so probably yet another thing that I'm too stupid to understand about the hardware is at play — the delay takes effect on double high resolution colours.
>
> But shifting everything half a clock cycle to the left moves it 1.75 colour clock cycles. But mine were already 0.25 colour clock cycles to the right. So the net movement is exactly 2 colour clock cycles. And suddenly I've no need to figure out why the quarter-colour-clock delay is active. It isn't.
>
> I assume the same thing was also afoot to motivate the linked "one pixel shifted to the right" AppleWin bug?
>

Yes, very similar to what you describe: a 0.25 colour clk cycle delay to get the DHGR colours right, as the assumption was that 40-col & 80-col occupied the same physical screen space... but that results in the last DHGR 14M pixel being off-screen (as AppleWin limits the Apple //e window to 560 14M dots - ie. no borders).

Tom

Wizard1969

unread,
Aug 16, 2018, 2:15:00 AM8/16/18
to
Love your emulator on MacOS X. Could not get it to run on Debian (crashes
with an OpenGL error).

Thomas Harte

unread,
Aug 17, 2018, 10:34:21 AM8/17/18
to
On Thursday, 16 August 2018 02:15:00 UTC-4, Wizard1969 wrote:
> Love your emulator on MacOS X. Could not get it to run on Debian (crashes
> with an OpenGL error).

It currently requires OpenGL 3.2 Core Profile, but crashing if it doesn't get it is definitely a bug. At one point it checks for the texture barrier extension, but doesn't actually use it.

Apple's deprecation of OpenGL means I'm going to have to revisit the whole CRT implementation anyway; the primary job is to sever the OpenGL stuff from the CPU stuff, so that I can add a Metal alternative at my leisure, but I don't think it would necessarily be a bad idea to try to add an ES 2.x back-end, for the Raspberry Pi and as a fallback for bigger machines.

Wizard1969

unread,
Aug 17, 2018, 3:15:02 PM8/17/18
to
Crash may not have been the right word. I think it just closed with the error
message. Hate to see OpenGL support leave as Metal is not even supported on
my 4 year old Mac. Deprecated , I am to understand means that new features
will not be added rather than support will be missing for OpenGL. Have you
thought about using SDL 2.0 canvas instead. I understand it gives you a metal
renderer in 2.0.8 and would allow you to support older machines with no extra
work.

Thomas Harte

unread,
Aug 18, 2018, 11:16:29 AM8/18/18
to
Oh, no, it's okay — the process on a Mac would be to try to use Metal first, and fall back on OpenGL failing that. On X11 it'd be an attempt to use regular OpenGL with an ES fallback, and I'll keep an eye on Vulkan.

At the minute all machines produce a stream of video — syncs, blanks, actual data — to the emulated CRT and the CRT produces the OpenGL calls to display them. What I need is for the emulated CRT just to decompose the input into raster scans and then pass those to a module that can display them. It's just one extra piece of abstraction.

That's also why a canvas approach wouldn't be a good fit: what's being sent out of the machines is one-dimensional, and the stuff of turning that into a two-dimensional image calls for geometry rasterisation. So I'd just end up doing a bunch of work that GPUs are built for on the CPU.

It'll probably be good for the project anyway. The original CRT code was very early stuff, and I'm sure my C++ is much better now. At the very least I hope for some threading improvements; I think I'm quite a bit more heavy on synchronisation than I need to be.

Right now though: I've just finished the 65C02, for real this time — read-modify-write indexed absolutes other than INC and DEC are quicker if no page is crossed, interrupts* aren't respected immediately after a branch that doesn't cross a page boundary, ordinary read-modify-writes perform read, read, write rather than read, write, write, etc. So I'm going to circle back around to Apple II video fetch versus output timing.

* partly because I don't want to couple my 6502 implementation to any particular machine, but also partly because adding a Mockingboard feels like a smart move shortly.

I of course looked at the 65816 while I was there, but that's not for now.

The broader stuff of underlying API can also wait; when I'm at a good stopping point, which right now feels like the Apple II being completely cycle accurate — including auxiliary output half a clock earlier than base and all output being two cycles after fetch.

Wizard1969

unread,
Aug 19, 2018, 4:15:04 PM8/19/18
to
I understand about the canvas problem. If I can throw a suggestion in the
suggestion box... a debugger for the different machines. It's what makes
Virtual ][ the killer app for me and one of the reasons I am on MacOS X.

Thomas Harte

unread,
Aug 26, 2018, 6:01:02 PM8/26/18
to
I definitely need to think of a way to do that well. The main stumbling block js somewhere between keeping it extensible and broad enough for all the modelled machines, versus C++'s lack of built-in reflection, versus what I already put in place for command-line options — which is a solution for effectively the same problem, but probably needs to be tidier for more general use. It's too much of a hassle right now. There are lots of options, I probably just need to stop dithering.

Otherwise: video alterations are done, and the 65C02-bearing Enhanced IIe is now available. https://github.com/TomHarte/CLK/releases as usual.

John Brooks

unread,
Aug 26, 2018, 8:43:08 PM8/26/18
to
Hi Thomas. Below is a grab-bag of mistakes I have seen in most //e emulators:

1) GR mode with AN3 on and 80-column off should activate 4-color 140x48 mode

2) HGR mode with AN3 on and 80-column off should activate 4-color 140x192 mode

3) 6502/65c02 P reg should have bit 5 set: PHP, PLA, AND #$20 == $20

4) 6502/65c02 should have false reads during indexed reads & writes which affects LC bank switching and DiskII writes

5) .DSK should make tracks of length 51024 bits == 1020484 cycles-per-second div 5 (300 RPM) div 4 cycles-per-disk_bit. Or if the emu supports adjustable drive RPM, the Apple drive spec is between 48473 bits (315 RPM) and 53,575.4 (285 RPM)

6) If drive RPM variation is supported, the Apple drive spec allows up to 10% variation in nibble read speed due to a disk written at 285 RPM being read on a 315 RPM drive == disk nibbles arriving as fast as every 28.8 cycles, or as slow as 35.2 cycles. 3.6us to 4.4us per bit.

7) ProDOS .DSK have VOL=$01 in sector headers, DOS 3.3 .DSK have VOL=$FE

8) Sectors on .DSK should be skewed so each track is ~4 sectors delayed from the previous track. This is due to head step time + 36ms settle time delaying writing sector 0 by ~40ms relative to the previous track during formatting.

9) The DiskII head will step to 1/4 tracks when adjacent phases are on

10) DiskII head step takes time to move (~1ms per 1/4 track for half-height drives, full-height is ~1.5ms)

11) DiskII inner head stop is at track 36.5

12) Write/erase head width is ~0.8 track, so writing a track also writes to adjacent 1/4 tracks. When writing only on full-tracks, the 1/2 tracks typically contain the previous full track data for half their length, followed by the next full track contents for the other half length due to the disk being slightly off-center and wobbling during rotation.

13) Disk II can reads & write 81 nibbles (not just the 66 used by DOS3.3 & ProDOS)

14) Disk II controller write state transition expects false-read of STA abs,X to access DiskII regs on 2 adjacent cycles: 6502 false read on 4th cycle sets controller to write mode, then 6502 write on 5th cycle writes byte to disk

-JB
@JBrooksBSI

John Brooks

unread,
Aug 26, 2018, 9:10:34 PM8/26/18
to
I tested your emu with the latest ProDOS rev and found two problems:

1) Adjacent tracks are not skewed correctly, causing a sector 0 miss and extra disk rotation on every track step (visible in stuttering boot load indicator)

2) 40-column text font is correct at power-up but gets into a bad/corrupt state in Bitsy Bye making everything unreadable. If you select the 3rd program, BASIC, the font corrects.

Here is a disk image so you can repro:

https://drive.google.com/file/d/1DNFFd2BLIXL3krPbGWvfu8E0m9fwZiRP

I tested on a rMBP w/MacOS 10.12.

-JB
@JBrooksBSI

Thomas Harte

unread,
Aug 26, 2018, 10:24:01 PM8/26/18
to
On Sunday, 26 August 2018 20:43:08 UTC-4, John Brooks wrote:
> Hi Thomas. Below is a grab-bag of mistakes I have seen in most //e emulators:

Without even checking:

> 1) GR mode with AN3 on and 80-column off should activate 4-color 140x48 mode
>
> 2) HGR mode with AN3 on and 80-column off should activate 4-color 140x192 mode

Not implemented; currently an error. The annunciators might as well be /dev/null. I guess (2) puts you back to where you were with a 1977 Apple II, ignoring the delay bit (?); I can't immediately imagine how (1) would work, presumably it's the address calculation of GR mode coupled to no-delay-bit HGR serialisation?

> 3) 6502/65c02 P reg should have bit 5 set: PHP, PLA, AND #$20 == $20

Implemented correctly.

> 4) 6502/65c02 should have false reads during indexed reads & writes which affects LC bank switching and DiskII writes

Implemented correctly. Though I took the 65C02's datasheet at its word that "Indexed addressing across page boundary" produces "Extra read of last instruction byte" rather than "Extra read of invalid address". RMWs will still perform read, read, write upon a correct address though, exactly as on a 6502.

But in general, both processors should perform all memory accesses, one per cycle, exactly as the real ones do.

> 5) .DSK should make tracks of length 51024 bits == 1020484 cycles-per-second div 5 (300 RPM) div 4 cycles-per-disk_bit. Or if the emu supports adjustable drive RPM, the Apple drive spec is between 48473 bits (315 RPM) and 53,575.4 (285 RPM)

There seems to be no canonical definition of a DSK; can you provide a reference for that?

Mine is 16 sync words, then per sector: the header, 7 sync words, the sector body, then 16 sync words. So I make that 160 + 16*(112 + 70 + 2792 + 160) = 50304 bits.

RPM is always exactly 300, so each bit on a DSK will last whatever length that makes. Obviously the bits on a WOZ will be whatever rate the disk image requires. And if you write data, that'll be written at the rate the disk controller writes at. So you might easily end up with multi-rate data across the track.

> 6) If drive RPM variation is supported, the Apple drive spec allows up to 10% variation in nibble read speed due to a disk written at 285 RPM being read on a 315 RPM drive == disk nibbles arriving as fast as every 28.8 cycles, or as slow as 35.2 cycles. 3.6us to 4.4us per bit.

No, it's fixed at 300 for now.

> 7) ProDOS .DSK have VOL=$01 in sector headers, DOS 3.3 .DSK have VOL=$FE

Implemented incorrectly. Always $FE.

> 8) Sectors on .DSK should be skewed so each track is ~4 sectors delayed from the previous track. This is due to head step time + 36ms settle time delaying writing sector 0 by ~40ms relative to the previous track during formatting.

I think this again cuts to how well defined DSK is, but this is unimplemented. It's an easy-enough fix.

WOZs, of course, have no such issue.

> 9) The DiskII head will step to 1/4 tracks when adjacent phases are on

Implemented correctly, albeit fairly uselessly for DSKs. Correct for WOZs.

> 10) DiskII head step takes time to move (~1ms per 1/4 track for half-height drives, full-height is ~1.5ms)
>
> 11) DiskII inner head stop is at track 36.5

I very much doubt that this is working.

> 12) Write/erase head width is ~0.8 track, so writing a track also writes to adjacent 1/4 tracks. When writing only on full-tracks, the 1/2 tracks typically contain the previous full track data for half their length, followed by the next full track contents for the other half length due to the disk being slightly off-center and wobbling during rotation.

Not implemented. You can create a magical 140-track disk if you want.

> 13) Disk II can reads & write 81 nibbles (not just the 66 used by DOS3.3 & ProDOS)

Implemented correctly. Write any old nibble you want. Just don't expect to be able to read it back correctly if it offends the automatic gain rule on adjoining zeroes.

> 14) Disk II controller write state transition expects false-read of STA abs,X to access DiskII regs on 2 adjacent cycles: 6502 false read on 4th cycle sets controller to write mode, then 6502 write on 5th cycle writes byte to disk

The 6502 performs every access exactly when it should. The original Disk II state machine is being used, unmodified, interpreted. No shortcuts. So whatever it normally requires should be required.

On Sunday, 26 August 2018 21:10:34 UTC-4, John Brooks wrote:
> I tested your emu with the latest ProDOS rev and found two problems:
>
> 1) Adjacent tracks are not skewed correctly, causing a sector 0 miss and extra disk rotation on every track step (visible in stuttering boot load indicator)

Indeed, with DSKs there is no attempt at skew. Easy to fix.

> 2) 40-column text font is correct at power-up but gets into a bad/corrupt state in Bitsy Bye making everything unreadable. If you select the 3rd program, BASIC, the font corrects.
>
> Here is a disk image so you can repro: ...

That's curious. I guess I'm still doing something dumb.

Anyway, I'll file all of the above that exist as issues on my GitHub project, which means they'll be fixed. None should be too troubling, and I absolutely want to get things right.

Thomas Harte

unread,
Aug 26, 2018, 10:27:20 PM8/26/18
to
On Sunday, 26 August 2018 22:24:01 UTC-4, Thomas Harte wrote:
> Implemented correctly. Though I took the 65C02's datasheet at its word that "Indexed addressing across page boundary" produces "Extra read of last instruction byte" rather than "Extra read of invalid address". RMWs will still perform read, read, write upon a correct address though, exactly as on a 6502.

Ugh. I meant RMWs will perform read, read, write on their correct address on a 65C02 very much _unlike_ the 6502, which will perform read, read, write.

The 6502 is heavily unit tested and battle tested through the various other supported machines; the 65C02 is new and less tested, but passes functional tests.

John Brooks

unread,
Aug 27, 2018, 1:15:18 AM8/27/18
to
On Sunday, August 26, 2018 at 7:24:01 PM UTC-7, Thomas Harte wrote:
> On Sunday, 26 August 2018 20:43:08 UTC-4, John Brooks wrote:
> > Hi Thomas. Below is a grab-bag of mistakes I have seen in most //e emulators:
>
> Without even checking:
>
> > 1) GR mode with AN3 on and 80-column off should activate 4-color 140x48 mode
> >
> > 2) HGR mode with AN3 on and 80-column off should activate 4-color 140x192 mode
>
> Not implemented; currently an error. The annunciators might as well be /dev/null.

How are you differentiating HGR plus 80-col text in mixed mode vs DHGR with 80-col text in mixed mode without using AN3?

> I guess (2) puts you back to where you were with a 1977 Apple II, ignoring the delay bit (?); I can't immediately imagine how (1) would work, presumably it's the address calculation of GR mode coupled to no-delay-bit HGR serialisation?

Yes, AN3 suppresses bit 7 of each HGR byte and forces HGR pixel shift even in GR mode.

>
> > 3) 6502/65c02 P reg should have bit 5 set: PHP, PLA, AND #$20 == $20
>
> Implemented correctly.
>
> > 4) 6502/65c02 should have false reads during indexed reads & writes which affects LC bank switching and DiskII writes
>
> Implemented correctly. Though I took the 65C02's datasheet at its word that "Indexed addressing across page boundary" produces "Extra read of last instruction byte" rather than "Extra read of invalid address". RMWs will still perform read, read, write upon a correct address though, exactly as on a 6502.
>
> But in general, both processors should perform all memory accesses, one per cycle, exactly as the real ones do.

Does that include the undocumented instructions which access memory and alter registers?

>
> > 5) .DSK should make tracks of length 51024 bits == 1020484 cycles-per-second div 5 (300 RPM) div 4 cycles-per-disk_bit. Or if the emu supports adjustable drive RPM, the Apple drive spec is between 48473 bits (315 RPM) and 53,575.4 (285 RPM)
>
> There seems to be no canonical definition of a DSK; can you provide a reference for that?

No, but I may be able to provide some missing details. Based on ProDOS timing and behavior, I recommend:

370 bit Gap1: 37x $FF<00> self-sync bytes. Apple spec is 128x self-sync but most of that gets overwritten.

For each of 16x sectors:
1) 112 bit Address hdr (14x disk nibbles)
2) 70 bit Gap2: 7x $FF<00> self-sync bytes
3) 2792 bit Data
4) 200 bit Gap3: 20x $FF<00> self-sync bytes
= 3166 bits per sector
* 16 sectors
= 50656 bits
+ 368 bit Gap1 ( 2 bits of Gap1 overwritten, or use an 8-bit $FF plus 36x self-sync
= 51024 bits per track @ 300 RPM

Ideally sectors are equally spaced across the disk so that each sector has max freedom to contract/expand as it gets rewritten by drives with varying RPMs.

A 160 bit gap 3 is problematic because that 2862 Gap2+data formatted at 300RPM, when rewritten on a 315 RPM drive, will stretch to cover the equivalent of 3005 bits, overwriting 143 of the 160 bit Gap3, and likely causing the head to be out of sync and unable to read the next sector's address header.

A self-sync field needs to be at least 40 bits long to guarantee sync, hence Gap3 needs to be at least 190 bits long to remain functional after a 143 bit overwrite. I recommend a Gap3 of 200, or even 220 if you want max room per sector don't mind a minimal 40-50 bit Gap1.

Since emulators can now write .woz images and be brought back to physical machines with variable RPM drives, it's important to have the emulators create tracks that will not be corrupted if sectors are rewritten at speeds other than 300RPM, even though the emulators are locked to 300RPM.

>
> Mine is 16 sync words, then per sector: the header, 7 sync words, the sector body, then 16 sync words. So I make that 160 + 16*(112 + 70 + 2792 + 160) = 50304 bits.
>
> RPM is always exactly 300, so each bit on a DSK will last whatever length that makes. Obviously the bits on a WOZ will be whatever rate the disk image requires. And if you write data, that'll be written at the rate the disk controller writes at. So you might easily end up with multi-rate data across the track.
>
> > 6) If drive RPM variation is supported, the Apple drive spec allows up to 10% variation in nibble read speed due to a disk written at 285 RPM being read on a 315 RPM drive == disk nibbles arriving as fast as every 28.8 cycles, or as slow as 35.2 cycles. 3.6us to 4.4us per bit.
>
> No, it's fixed at 300 for now.
>
> > 7) ProDOS .DSK have VOL=$01 in sector headers, DOS 3.3 .DSK have VOL=$FE
>
> Implemented incorrectly. Always $FE.
>
> > 8) Sectors on .DSK should be skewed so each track is ~4 sectors delayed from the previous track. This is due to head step time + 36ms settle time delaying writing sector 0 by ~40ms relative to the previous track during formatting.
>
> I think this again cuts to how well defined DSK is, but this is unimplemented. It's an easy-enough fix.
>
> WOZs, of course, have no such issue.
>
> > 9) The DiskII head will step to 1/4 tracks when adjacent phases are on
>
> Implemented correctly, albeit fairly uselessly for DSKs. Correct for WOZs.
>
> > 10) DiskII head step takes time to move (~1ms per 1/4 track for half-height drives, full-height is ~1.5ms)
> >
> > 11) DiskII inner head stop is at track 36.5
>
> I very much doubt that this is working.
>
> > 12) Write/erase head width is ~0.8 track, so writing a track also writes to adjacent 1/4 tracks. When writing only on full-tracks, the 1/2 tracks typically contain the previous full track data for half their length, followed by the next full track contents for the other half length due to the disk being slightly off-center and wobbling during rotation.
>
> Not implemented. You can create a magical 140-track disk if you want.

I consider this a feature. At Datasoft in the 80s, we had disk copiers with 1/4 track heads which allowed better data density and copy protection than the stock Disk II could perform.

Personally, I'd like emulators to provide the option of 1/4 track head width or 3/4 track head width.

>
> > 13) Disk II can reads & write 81 nibbles (not just the 66 used by DOS3.3 & ProDOS)
>
> Implemented correctly. Write any old nibble you want. Just don't expect to be able to read it back correctly if it offends the automatic gain rule on adjoining zeroes.

The Disk][ can read all 81 nibbles (no more than 2 zero bits between one bits) 100% of the time, but it can read three zeroes in a row too, just not at 100%. Three or more zeroes can cause extra 'ghost' 1 bits to be injected by the read head due to over-amplification, which increases the bit-rate above 4cycles-per-bit and alters byte alignment. Though a good drive can also 'go silent' on a long run of zeroes and return nothing, dropping the bit rate below 4-cycles-per bit and also breaking byte alignment.

But in either case does the drive does not return random data every 4 usecs, though that emulation technique usually suffices for passing weak-bits copy protection checks.

>
> > 14) Disk II controller write state transition expects false-read of STA abs,X to access DiskII regs on 2 adjacent cycles: 6502 false read on 4th cycle sets controller to write mode, then 6502 write on 5th cycle writes byte to disk
>
> The 6502 performs every access exactly when it should. The original Disk II state machine is being used, unmodified, interpreted. No shortcuts. So whatever it normally requires should be required.

Good!

>
> On Sunday, 26 August 2018 21:10:34 UTC-4, John Brooks wrote:
> > I tested your emu with the latest ProDOS rev and found two problems:
> >
> > 1) Adjacent tracks are not skewed correctly, causing a sector 0 miss and extra disk rotation on every track step (visible in stuttering boot load indicator)
>
> Indeed, with DSKs there is no attempt at skew. Easy to fix.
>
> > 2) 40-column text font is correct at power-up but gets into a bad/corrupt state in Bitsy Bye making everything unreadable. If you select the 3rd program, BASIC, the font corrects.
> >
> > Here is a disk image so you can repro: ...
>
> That's curious. I guess I'm still doing something dumb.
>
> Anyway, I'll file all of the above that exist as issues on my GitHub project, which means they'll be fixed. None should be too troubling, and I absolutely want to get things right.

-JB
@JBrooksBSI

John Brooks

unread,
Aug 27, 2018, 1:52:50 AM8/27/18
to
Math correction:
240 bit Gap1: 24x $FF<00> self-sync bytes. Apple spec is 128x self-sync but most of that gets overwritten.

For each of 16x sectors:
1) 112 bit Address hdr (14x disk nibbles)
2) 70 bit Gap2: 7x $FF<00> self-sync bytes
3) 2792 bit Data
4) 200 bit Gap3: 20x $FF<00> self-sync bytes
= 3174 bits per sector
* 16 sectors
= 50784 bits
+ 240 bit Gap1
= 51024 bits per track @ 300 RPM


And for safe, nearly equally spaced sectors (and a minimal Gap1):

80 bit Gap1: 8x $FF<00> self-sync bytes

For each of 16x sectors:
1) 112 bit Address hdr (14x disk nibbles)
2) 70 bit Gap2: 7x $FF<00> self-sync bytes
3) 2792 bit Data
4) 210 bit Gap3: 21x $FF<00> self-sync bytes
= 3184 bits per sector
* 16 sectors
= 50944 bits
+ 80 bit Gap1: 8x $FF<00> self-sync bytes
= 51024 bits per track @ 300 RPM

-JB
@JBrooksBSI

Thomas Harte

unread,
Aug 27, 2018, 10:10:20 AM8/27/18
to
On Monday, 27 August 2018 01:15:18 UTC-4, John Brooks wrote:
> How are you differentiating HGR plus 80-col text in mixed mode vs DHGR with 80-col text in mixed mode without using AN3?

I'm going to put the positive spin on this: as well as making many of the trite IIe emulation errors so predictable that you could reel them off without even checking, at least I also made some original ones?

https://github.com/TomHarte/CLK/blob/master/Machines/AppleII/Video.hpp#L527 is where the decision is made — **incorrectly** — and it's currently no more complicated than "if text, 80 or 40 as per the soft switch; otherwise if mixed and beyond row 160 then 80 or 40 text per (80-column) | (DHGR); otherwise single or double low or high res, as per the high resolution and double high resolution switches".

So, I guess, as well as the two missing modes described earlier, I've somehow come to believe that 40-column text cannot be matched with double-high resolution graphics.

I've updated my 'use annunciator 3' ticket; this is most definitely currently implemented in error.

> > > 4) 6502/65c02 should have false reads during indexed reads & writes which affects LC bank switching and DiskII writes
> >
> > Implemented correctly. Though I took the 65C02's datasheet at its word that "Indexed addressing across page boundary" produces "Extra read of last instruction byte" rather than "Extra read of invalid address". RMWs will still perform read, read, write upon a correct address though, exactly as on a 6502.
> >
> > But in general, both processors should perform all memory accesses, one per cycle, exactly as the real ones do.
>
> Does that include the undocumented instructions which access memory and alter registers?

Should do. Drawing from various other platforms, the 6502 passes the AllSuiteA, Klaus Dormann and Wolfgang Lorenz test suites, along with a BCD quirks test from the BBC Micro community plus a small selection of additional timing and interrupt tests — though I guess the latter aren't that helpful unless or until I implement a card that generates interrupts. But it's stuff like that CLI/SEI with an interrupt pending causes the IRQ to be taken after the SEI with the I flag set, that a suitably-placed NMI will usurp the vector used for a BRK, etc.

For the 65C02 it's really just Dormann's functional tests at the minute. I have gone through the datasheet and implemented every difference I saw beyond mere functionality — different length instructions, different memory access patterns, etc — but the testing isn't really in place yet.

> No, but I may be able to provide some missing details. Based on ProDOS timing and behavior, I recommend:
> ...

Thanks! I'll adopt that plus the ~40ms track-to-track skew.

> Since emulators can now write .woz images and be brought back to physical machines with variable RPM drives, it's important to have the emulators create tracks that will not be corrupted if sectors are rewritten at speeds other than 300RPM, even though the emulators are locked to 300RPM.

In my emulator you can't open something as a DSK but then write it as a WOZ. I mean, it'd be no problem in principle, except that the interface doesn't allow it.

That's no excuse for getting things wrong, just an observation that thankfully my emulator shouldn't be able to contribute any broken WOZs to the world.

In case it's interesting at all, on the WOZ side I run a quick PLL over each modified track in order to rationalise to a fixed clock rate, and write whatever it produces. On the DSK I run the PLL then also inspect for sectors.

> The Disk][ can read all 81 nibbles (no more than 2 zero bits between one bits) 100% of the time, but it can read three zeroes in a row too, just not at 100%. Three or more zeroes can cause extra 'ghost' 1 bits to be injected by the read head due to over-amplification, which increases the bit-rate above 4cycles-per-bit and alters byte alignment. Though a good drive can also 'go silent' on a long run of zeroes and return nothing, dropping the bit rate below 4-cycles-per bit and also breaking byte alignment.
>
> But in either case does the drive does not return random data every 4 usecs, though that emulation technique usually suffices for passing weak-bits copy protection checks.

In my case there's a 'safe gain period' of 15ms; if no actual flux transitions are detected for that long then it starts picking random intervals until the next transition. But they're not especially random, always being 2 or 3 millionths of a track length. Probably more work to do.

But the drive stuff remains completely decoupled from the controller and machine clock rates.

Also, because the emulator doesn't enforce any sort of file format limit after you've launched a machine, you can insert a whole bunch of things that aren't DSKs or WOZs and try to inspect them to the extent that the Disk II controller will allow if you really want. A useless feature, I think.

John Brooks

unread,
Aug 27, 2018, 11:04:15 AM8/27/18
to
On Monday, August 27, 2018 at 7:10:20 AM UTC-7, Thomas Harte wrote:
> On Monday, 27 August 2018 01:15:18 UTC-4, John Brooks wrote:
> > How are you differentiating HGR plus 80-col text in mixed mode vs DHGR with 80-col text in mixed mode without using AN3?
>
> I'm going to put the positive spin on this: as well as making many of the trite IIe emulation errors so predictable that you could reel them off without even checking, at least I also made some original ones?

:)

>
> https://github.com/TomHarte/CLK/blob/master/Machines/AppleII/Video.hpp#L527 is where the decision is made — **incorrectly** — and it's currently no more complicated than "if text, 80 or 40 as per the soft switch; otherwise if mixed and beyond row 160 then 80 or 40 text per (80-column) | (DHGR); otherwise single or double low or high res, as per the high resolution and double high resolution switches".
>
> So, I guess, as well as the two missing modes described earlier, I've somehow come to believe that 40-column text cannot be matched with double-high resolution graphics.

Yes, 40-col text cannot be matched with DHGR, since DHGR requires both 80-column on and AN3 on.

The question is how DHGR is being enabled without AN3 since the truth tabled for hires + mixed mode is:

80Col=0, AN3=0 HGR Text40
80Col=0, AN3=1 HGR(4-color) Text40
80Col=1, AN3=0 HGR Text80
80Col=1, AN3=1 DHGR Text80

>
> I've updated my 'use annunciator 3' ticket; this is most definitely currently implemented in error.
>
> > > > 4) 6502/65c02 should have false reads during indexed reads & writes which affects LC bank switching and DiskII writes
> > >
> > > Implemented correctly. Though I took the 65C02's datasheet at its word that "Indexed addressing across page boundary" produces "Extra read of last instruction byte" rather than "Extra read of invalid address". RMWs will still perform read, read, write upon a correct address though, exactly as on a 6502.
> > >
> > > But in general, both processors should perform all memory accesses, one per cycle, exactly as the real ones do.
> >
> > Does that include the undocumented instructions which access memory and alter registers?
>
> Should do. Drawing from various other platforms, the 6502 passes the AllSuiteA, Klaus Dormann and Wolfgang Lorenz test suites, along with a BCD quirks test from the BBC Micro community plus a small selection of additional timing and interrupt tests — though I guess the latter aren't that helpful unless or until I implement a card that generates interrupts. But it's stuff like that CLI/SEI with an interrupt pending causes the IRQ to be taken after the SEI with the I flag set, that a suitably-placed NMI will usurp the vector used for a BRK, etc.

Cool. I tested $AF LAX abs and it loaded both A & X as expected.

>
> For the 65C02 it's really just Dormann's functional tests at the minute. I have gone through the datasheet and implemented every difference I saw beyond mere functionality — different length instructions, different memory access patterns, etc — but the testing isn't really in place yet.
>
> > No, but I may be able to provide some missing details. Based on ProDOS timing and behavior, I recommend:
> > ...
>
> Thanks! I'll adopt that plus the ~40ms track-to-track skew.
>
> > Since emulators can now write .woz images and be brought back to physical machines with variable RPM drives, it's important to have the emulators create tracks that will not be corrupted if sectors are rewritten at speeds other than 300RPM, even though the emulators are locked to 300RPM.
>
> In my emulator you can't open something as a DSK but then write it as a WOZ. I mean, it'd be no problem in principle, except that the interface doesn't allow it.
>
> That's no excuse for getting things wrong, just an observation that thankfully my emulator shouldn't be able to contribute any broken WOZs to the world.
>

Okay, but can't the user mount a .dsk in drive 1, a .woz in drive 2, and copy S6D1 to S6D2 using a nibble copier like Locksmith, CopyII+, etc?

> In case it's interesting at all, on the WOZ side I run a quick PLL over each modified track in order to rationalise to a fixed clock rate, and write whatever it produces. On the DSK I run the PLL then also inspect for sectors.

Very nice. It sounds like your emu has a very solid foundation and is likely to be more accurate than what I'm seeing from other emulators.

>
> > The Disk][ can read all 81 nibbles (no more than 2 zero bits between one bits) 100% of the time, but it can read three zeroes in a row too, just not at 100%. Three or more zeroes can cause extra 'ghost' 1 bits to be injected by the read head due to over-amplification, which increases the bit-rate above 4cycles-per-bit and alters byte alignment. Though a good drive can also 'go silent' on a long run of zeroes and return nothing, dropping the bit rate below 4-cycles-per bit and also breaking byte alignment.
> >
> > But in either case does the drive does not return random data every 4 usecs, though that emulation technique usually suffices for passing weak-bits copy protection checks.
>
> In my case there's a 'safe gain period' of 15ms; if no actual flux transitions are detected for that long then it starts picking random intervals until the next transition. But they're not especially random, always being 2 or 3 millionths of a track length. Probably more work to do.
>
> But the drive stuff remains completely decoupled from the controller and machine clock rates.
>
> Also, because the emulator doesn't enforce any sort of file format limit after you've launched a machine, you can insert a whole bunch of things that aren't DSKs or WOZs and try to inspect them to the extent that the Disk II controller will allow if you really want. A useless feature, I think.

That reminds me, will inserting and removing a disk affect the write-protect sense like a real Disk][?

I'm not sure what 'typical human' disk in/out time should be, but I doubt most emulators even try to handle it.

-JB
@JBrooksBSI

fadden

unread,
Aug 27, 2018, 11:07:32 AM8/27/18
to
On Monday, August 27, 2018 at 7:10:20 AM UTC-7, Thomas Harte wrote:
> For the 65C02 it's really just Dormann's functional tests at the minute. I have gone through the datasheet and implemented every difference I saw beyond mere functionality — different length instructions, different memory access patterns, etc — but the testing isn't really in place yet.

http://laughtonelectronics.com/Arcana/KimKlone/Kimklone_opcode_mapping.html has a summary of the "LDD" no-ops.

MG

unread,
Aug 27, 2018, 5:01:38 PM8/27/18
to

I'll add some more mistakes I have seen in Apple II emulators (note that some of them will not apply to GS emulators):

* Mis-implementation of the not-defined 65C02 opcodes as 1-byte NOPs. This occurs in at least one browser-based emulator. Test (65C02 only): 300:A2 00 02 E8 8A 4C DA FD 300G, if the result is anything other than 00 the implementation is incorrect because the 02 opcode is specified as a 2 byte NOP in the data sheet, yet the INX in the second byte has executed.

* Several emulators fail to place the low 7 bits of the keyboard data latch on $C001-$C01F.

* At least one emulator fails to clear the keyboard strobe on writes to $C011-$C01F.

* At least one emulator fails to click the speaker on $C031-$C03F.

* At one point MAME had some write-only soft-switches respond to reads in the //e emulation, this was still present on the //c emulation the last time I checked.


Brian Patrie

unread,
Aug 28, 2018, 6:03:48 AM8/28/18
to
On 2018-08-26 19:43, John Brooks wrote:
> 1) GR mode with AN3 on and 80-column off should activate 4-color 140x48 mode
>
> 2) HGR mode with AN3 on and 80-column off should activate 4-color 140x192 mode

Shouldn't that be AN3 *off* ($C05E), and 40x48?
IIUC, turning AN3 on ($C05F) *disables* DGR, DHGR, and the weird modes.

Thomas Harte

unread,
Aug 28, 2018, 9:42:02 AM8/28/18
to
On Monday, 27 August 2018 17:01:38 UTC-4, MG wrote:
> I'll add some more mistakes I have seen in Apple II emulators (note that some of them will not apply to GS emulators):
>
> * Mis-implementation of the not-defined 65C02 opcodes as 1-byte NOPs. This occurs in at least one browser-based emulator. Test (65C02 only): 300:A2 00 02 E8 8A 4C DA FD 300G, if the result is anything other than 00 the implementation is incorrect because the 02 opcode is specified as a 2 byte NOP in the data sheet, yet the INX in the second byte has executed.

I didn't test this yet, but it should be implemented correctly. NOPs have various addressing modes. The 65C02 1-cycle NOP was what actually proved to be a hassle, since my 6502 core was set up ― like a real 6502 — always to fetch an operand, whether one is needed or not. So I had to make that behaviour a function of the fetched operation.

> * Several emulators fail to place the low 7 bits of the keyboard data latch on $C001-$C01F.

My emulator was at fault. Fixed; C001–C01F now give the same low 7 bits as C000 plus a vapour bit in bit 7.

(where 'fixed' means: code committed, if you're building at home therefore available now, otherwise will be in whatever is the next binary release)

> * At least one emulator fails to clear the keyboard strobe on writes to $C011-$C01F.

Implemented incorrectly, also fixed.

> * At least one emulator fails to click the speaker on $C031-$C03F.

As above; fixed.

> * At one point MAME had some write-only soft-switches respond to reads in the //e emulation, this was still present on the //c emulation the last time I checked.

That shouldn't be a problem here. I've never done more than glanced at it, and haven't even done that in at least a decade, but I think my structure is very different from MAME's indeed. The 6502 is archetypal of my structure: it's a template that shouts out its bus activity. It is instantiated with a 'bus handler', i.e. somebody who can listen to that activity and properly propagate it. Those are entirely ad hoc; they represent "the bus", which is of course entirely distinct per machine.

Conversely I think MAME is more about describing buses declaratively than programmatically? Don't quote me on that. I am not a MAME expert. All opinions are my own. Etc.

Digressing a little, thanks again (to both you and John Brooks) for the feedback! It's really helping me to get things right, I hope. Also fixed, for the same meaning of 'fixed' as above: track skew, DSK layout and Pro-DOS volume number. Graphical issues (both broken alternate text mode and the failure to factor in AN3) and a drive that is more concerned with physical reality are yet to do.

John Brooks

unread,
Aug 28, 2018, 10:37:23 AM8/28/18
to
AN3 is active low, so it is set 'on' at $C05E, and inactive at $C05F.

Which is humorously documented by Apple as:
SETAN3 EQU $C05E ;Clear annunciator 3
CLRAN3 EQU $C05F ;Set annunciator 3

-JB
@JBrooksBSI

John Brooks

unread,
Aug 28, 2018, 10:49:53 AM8/28/18
to
On Tuesday, August 28, 2018 at 3:03:48 AM UTC-7, Brian Patrie wrote:
> On 2018-08-26 19:43, John Brooks wrote:
> > 1) GR mode with AN3 on and 80-column off should activate 4-color 140x48 mode
>
> Shouldn't that be AN3 *off* ($C05E), and 40x48?

On the //e, low-res graphics with AN3 on ($C05E) activates an undocumented graphics mode of 140x48 pixels with 4-colors (7 bits per byte with high-bit ignored) located in text/GR memory (Page1: $400-$7FF or Page2:$800-$BFF).

-JB

Michael J. Mahon

unread,
Aug 28, 2018, 3:55:47 PM8/28/18
to
Thomas Harte <thomas...@gmail.com> wrote:
> On Monday, 27 August 2018 17:01:38 UTC-4, MG wrote:
>> * Several emulators fail to place the low 7 bits of the keyboard data
>> latch on $C001-$C01F.
>
> My emulator was at fault. Fixed; C001–C01F now give the same low 7 bits
> as C000 plus a vapour bit in bit 7.

I think bit 7 is always the state of the keyboard strobe, not vapor.

--
-michael - NadaNet 3.1 and AppleCrate II: http://michaeljmahon.com

qkumba

unread,
Aug 28, 2018, 10:34:55 PM8/28/18
to
On a IIe-style machine, bit 7 in $C01x is the key-down state.

Michael J. Mahon

unread,
Aug 28, 2018, 11:39:00 PM8/28/18
to
qkumba <peter....@gmail.com> wrote:
> On a IIe-style machine, bit 7 in $C01x is the key-down state.
>

...and the low seven bits are the keyboard latch, even before the keyboard
strobe is set on a key press.

Brian Patrie

unread,
Aug 29, 2018, 3:08:15 AM8/29/18
to
Weird. And i see it in the soucre listings, now.

I've been going by the description in the II,II+ Reference Manual which
describes $C05E as "off" (p24). The IIe Technical Reference Manual
agrees (p40).

Sounds like the left & right hand weren't on the same page, at Apple.
That never happens! ;)

MG

unread,
Aug 29, 2018, 4:04:03 AM8/29/18
to
On Tuesday, August 28, 2018 at 8:39:00 PM UTC-7, Michael J. Mahon wrote:
> qkumba wrote:
> > On a IIe-style machine, bit 7 in $C01x is the key-down state.
> >
>
> ...and the low seven bits are the keyboard latch, even before the keyboard
> strobe is set on a key press.
>

Bit 7 of $C010 is AKD, Bit 7 of $C011-$C01F are the soft switch status bits.

I should have been more specific in my original reply. The important thing to remember is that I/O decoding on the Apple II is very lazy, especially on the original ][ and ][ Plus. The //e and //c get more specific on the address decoding, but generally are still lazy on the data bus. The IIgs, of course, has very specific I/O decoding due to the amount of hardware built into the machine.


As a fun aside, the Apple IIe Card for Macintosh traps and emulates all of the $C0xx I/O space except for slot 6 which has a physical IWM attached. For undefined I/O locations in $C000-$C07F, the card tends to give the keyboard data in the low 7 bits, even where a standard //e would not.

MG

James Davis

unread,
Aug 29, 2018, 4:16:30 AM8/29/18
to
In the Apple IIe and later models, the KBD ($C00x) and KBDSTRB ($C01x) memory address ranges of x, from 1 to F, but not 0 (zero), are used for other purposes.

qkumba

unread,
Sep 7, 2018, 3:21:44 PM9/7/18
to
> I'll add some more mistakes I have seen in Apple II emulators (note that some of them will not apply to GS emulators):

These belong on Zellyn's a2audit disk.
I will make a PR after I fix MAME. ;-)

Zellyn

unread,
Sep 7, 2018, 3:29:25 PM9/7/18
to
On Friday, September 7, 2018 at 3:21:44 PM UTC-4, qkumba wrote:
> These belong on Zellyn's a2audit disk.
> I will make a PR after I fix MAME. ;-)

Yeah… I have this thread bookmarked, but it's fairly low down the priority list.

Eventually, I'd love to get comprehensive and incremental (fix the easy stuff first) vapor lock checks in there, and then, if those work, it might even be possible to use vapor lock checks to validate cycles-per-instruction for some of the less common instructions.

Zellyn

Thomas Harte

unread,
Sep 7, 2018, 10:14:55 PM9/7/18
to
Late response, apologies; I've not been able to find any other documentation about this. How does the addressing for 140x48 end up working from the programmer's point of view? Is it four lines of values from main RAM then four lines of values from auxiliary RAM, or vice versa, or some other arrangement I'm not imaginative enough for?

Re: the emulator, and my vanity; I was wrong to say I wasn't using annunciator 3, I'd merely read documentation that referred to it exclusively as DHIRES and failed to pay attention to the address. So I was nowhere near as far from the ball as I previously believed.

John Brooks

unread,
Sep 7, 2018, 11:34:38 PM9/7/18
to
Instead of each 4-bit nibble creating a 14MHz 16-color bit-pattern, the 4 bits are shifted out at 7MHz, generating 3.5x 4-color pixels (7 pix per byte-pair).

Like standard lo-res, the high nibble is used for 4x lines, then the low nibble is used for the next 4x lines.

BTW: There was a cool hackfest made at KFest which toggled between lores pages every 2 scan-lines to get 96 vertical rows instead of 48. If used with this mode, it seems like you could do a 2KB frame buffer that was 140x96 which could be interesting.

-JB
@JBrooksBSI

Thomas Harte

unread,
Sep 8, 2018, 8:28:56 PM9/8/18
to
On Friday, 7 September 2018 23:34:38 UTC-4, John Brooks wrote:
> On Friday, September 7, 2018 at 7:14:55 PM UTC-7, Thomas Harte wrote:
> > On Tuesday, 28 August 2018 10:49:53 UTC-4, John Brooks wrote:
> > > On Tuesday, August 28, 2018 at 3:03:48 AM UTC-7, Brian Patrie wrote:
> > > > On 2018-08-26 19:43, John Brooks wrote:
> > > > > 1) GR mode with AN3 on and 80-column off should activate 4-color 140x48 mode
> > > >
> > > > Shouldn't that be AN3 *off* ($C05E), and 40x48?
> > >
> > > On the //e, low-res graphics with AN3 on ($C05E) activates an undocumented graphics mode of 140x48 pixels with 4-colors (7 bits per byte with high-bit ignored) located in text/GR memory (Page1: $400-$7FF or Page2:$800-$BFF).
> > >
> > > -JB
> >
> > Late response, apologies; I've not been able to find any other documentation about this. How does the addressing for 140x48 end up working from the programmer's point of view? Is it four lines of values from main RAM then four lines of values from auxiliary RAM, or vice versa, or some other arrangement I'm not imaginative enough for?
> >
> > Re: the emulator, and my vanity; I was wrong to say I wasn't using annunciator 3, I'd merely read documentation that referred to it exclusively as DHIRES and failed to pay attention to the address. So I was nowhere near as far from the ball as I previously believed.
>
> Instead of each 4-bit nibble creating a 14MHz 16-color bit-pattern, the 4 bits are shifted out at 7MHz, generating 3.5x 4-color pixels (7 pix per byte-pair).

Out of interest, does that lead to discontinuities where the same byte is stored in consecutive columns? Since that would leave you 1/4 of a nibble out of sync between each column, rather than 1/2.

Otherwise: implemented, probably. With the lack of test material causing the question mark.

awanderin

unread,
Sep 9, 2018, 1:57:15 AM9/9/18
to
Is this really *140* x 48 ? Seems to my eyes that it's 40 x 48 but with
the 7 MHz pixel clock and the odd addresses don't get their pixels
auto-shifted by the hardware as with normal lo-res, so the colors
alternate when the byte-values are the same. $C05E definitely turns
this on, but I don't understand how one arrives at 140 pixels.

--
Jerry awanderin at gmail dot com

Brian Patrie

unread,
Sep 9, 2018, 2:58:41 AM9/9/18
to
It's a confusing mode. My take on it as a 40x48 mode is based upon how
it is addressed--each nibble controlling 1/40 of a line. I've only seen
it in monochrome; but, as i ponder, i suppose that, in colour, it does
render as 140 columns, but with groups of pixels being controlled by a
single nibble--i.e. they are not independent of each other. (Now i want
to set up my IIe with my 13" Trinitron, and play with it in colour.)

John Brooks

unread,
Sep 9, 2018, 3:45:08 AM9/9/18
to
The four solid colors are:
400:00 00 (black: gr color=0)
400:05 0A (lt.blue: gr color=6)
400:0A 05 (orange: gr color=9)
400:0F 0F (white: gr color=15)

But this:
400:01 08
makes black, blue, black, blue, black, blue, black
7 colored pixels in 2 low-res bytes == 140 pixel resolution

The upper nibble generates the same colors, but for the next 4 scan-lines, just like normal lo-res mode.

-JB
@JBrooksBSI

Thomas Harte

unread,
Sep 9, 2018, 7:09:17 PM9/9/18
to
It's a footnote at this point, but I've released a new version of my emulator (at https://github.com/TomHarte/CLK/releases as always), fixing all but the defects that relate to the physical realities of drive emulation — track steps remain instantaneous, there's no inner stop, and every quarter-track can hold a completely independent set of data with no cross contamination.

So it's adjusted DSK interpretation as to intra-track spacing and inter-track skew, fixed the alternate character set (including Bitsy Bye), loosened keyboard/audio decoding, and fixed graphics mode selection (including the proper 40/80-column selection in mixed modes, and implementation of the two undocumented modes).

Re: low resolution + annunciator 3 mode; the emulator works how you think it would with modern processing resources available. The machine itself just shovels out the 1-bit data stream, and that's decoded per the NTSC rules elsewhere. Various other emulators do exactly the same. But it should mean that colours work properly in the two undocumented modes as expected.
Reply all
Reply to author
Forward
0 new messages