So long story short, after changing the 3 to a 7 and cursing like a sailor....
Yeah.
You'd think that after after reading the boot sector it would be smooth sailing from there.
Yeah. No. _MountVol borked after reading part of the directory entries. This was the end of the sector so I thought there was a bug in my floppy code, but the Mac didn't ask to step to Track 1.
Hours of debugging later...
Error trying to read head 1? That should not happen, single side drive.
Wait that should be a zero.
Who sets this?
Is there a bug in my CPU?
...
:meow_angry_intensifies:
Me doing something very stupid, Exhibit A:
These are "mac-128k-encoded" floppy images... from the same source.
Well, there's your problem! :meow_googlytrash:
The real MVP here is "Apple 400k Floppy Disk Drive - 6990285A.pdf", without it I'd be there for months.
(ok Mac Almanac II.txt and apple2_IWM_Spec_Rev19_1982 helped too! And probably four other documents!)
Thank god they gave the checksum algorithm (I need it to encode the floppy image to a format digestible by the computer)
Im in ur virtual floppy, reading your boot sectorz (and calculating your checksumz)
Well my fake Mac 128k is able to read a fake sector header on my fake floppy drive spinning a fake disk at the proper (variable) fake speed. :meow_bongo_keyboard:
PROGRESS!
I mean I'm *that* close to getting it, but I don't. I'm no good at bit twiddling.
Basically the chip takes a 6 bit value (0..63) and spits out a square wave with a duty cycle 0..100%.
But the relation is not linear. The computer does a weird shifting and xoring loop thing with the value... I'm sure to make the PAL chip's job easier (apparently it's just a "counter"). But I don't get it. I see a pattern but don't get how to reverse it... (hence the lookup table) Soo frustrating!
Don't you love it when you spend all day trying to understand values and do tons of experiments and spreadsheets and tests in assembly to extract values and still can't figure out the bit twiddling at work and there is absolutely no documentation of what the PAL chip does and you finally say fuck it and build a reverse lookup table?
@grum999 I don't know if it's more complicated than an CPU...
But it's complicated because there's a lot of timing stuff that needs to happen at the right time...
Plus trying to understand old documentation.
I mean, I remember the earlier floppy controller I built for the PC/XT was hell too - for a while I thought I couldn't do it.
This one is... different. I have to take a whole other approach.
Simpler in some ways.
More complicated in others.
We'll see if I figure it out.
This means I have to emulate *everything*.
The spinny disk.
The variable motor RPM.
All the low level "move one track down" "still seeking?"
And the data.
Can't return just a neat 512 bytes sector. Noooo, you have real raw sectors, with headers and checksums and weird byte encoding.
That I have to build because (most) image files strip all of these.
I have to constantly "fly" the bytes under the (virtual) head because the disk goes spin. :meow_gummy_spincolors:
help!
I swear the Mac's floppy drive will be the death of me.
So far I've been half-faking floppies on the PC and Amstrad because when the computer uses a controller, you get a layer of abstraction.
You ask the controller "read track X, sector Y, head Z" and it does its thing and you get data.
Magic.
(ok it's still complicated. The μPD765 a weird, old and ugly state machine)
The Apple II / Mac's controller (made by the Woz) does clever things. But nothing as far as abstraction.
Hey it was only silly old me with a bug in my video class (e.g. incrementing the memory address *before* drawing the pixels :meow_googlytrash: )
Much better. Not sure how I'm going to deal with the annoying moire effects though.
So, CPU is 80%+ implemented I guess, woot!
I'm going to focus on the Mac part for a bit probably. The floppy scares me because I can do a standard floppy controller but this one is a Woz creation, so it's probably impossible to grok for a mere human.
Here are the kinds of mistakes you make when you emulate a CPU:
- Forgot to update a flag
- Wrong register used (doh!)
- Wrong width (did a byte op but it's a word - often copy paste error)
- Borked logic (oops I thought rotate did X but it does Y)
- Behaviour of the op is unclear (What is pushed on the stack on a Line1010/1111 exception? Does the program counter point to the current instruction or the next? I had to wing it looking at how the code behaves on the other side)
Getting a weird bug deep down in the Mac initialization routines makes me regret not taking the time to make unit test for every single freaking opcode.
Yeah that would have been very time consuming.
But stepping in assembly code you don't understand looking for the moment something borks is too.
And it's probably due to a missing semicolon somewhere.
Yay software!
I'm not sure why "a lot of instructions have a .byte/.word/.long versions" didn't scream "templates!!" at me sooner, but at least I caught it before I've done everything.
Welp that's almost 500 fewer lines of copy-pasted stuff (with random bonus bugs because you forgot to set a flag in one of the three versions). And more savings as I implement the rest.
Ran my first 68000 instruction*! :fast_meow_party:
Tell me if you recognize the ROM 😆
*meaning the only instruction partially implemented at the moment.
Something something we're gonna need a bigger boat.
Well that's a bit tight. I'm not sure how I'll fit a 20-byte instruction (the maximum possible) in this... 12-byte area (the section with the dots).
And that leaves 32 characters for the disassembly... which fits most instructions but some need a bit more room too.
And then you have the pathological case, the worst possible instruction on the 68000:
MOVEM.l ($12345678).l,D0-D1/D3-D4/D6-D7/A0-A1/A3-A4/A6-A7
Fun 68000 fact, the longest instructions possible (in bytes) are... (drumroll) 20 bytes long.
This happens when you do an operation on two absolute long addresses, example:
MOVE.L ($00BEEBEE).L,($12345678).L
Gives this machine code: 23F900BEEBEE12345678 (yep, Motorola CPU, so big endian. Easier to read I guess)
And with that, I can now fully disassemble every 68000 opcode.
God that was a lot of work. :meow_bongo_keyboard:
And I'm just disassembling/decoding instructions, haven't even started emulating one thing yet!
Remember when I did the MC6809 in like a week?
Yeah... this will take longer.
(oh, and no code generation... I did it... my wayyyyy)
(also, reminder that unit tests are neat. Caught so many things... should have done that for the other CPUs)