Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

ProDOS boot block?

202 views
Skip to first unread message

Steve Nickolas

unread,
Dec 20, 2021, 5:12:27 PM12/20/21
to
My head exploded when trying to parse the ProDOS boot block.

I'm trying to see whether it's possible to remove the Apple /// stuff and
add some 6502-8086 diglot stuff, given that I have an 8086 boot block that
does more or less the same thing, and that I could stuff into the second
block.

-uso.

I am Rob

unread,
Dec 24, 2021, 7:17:05 PM12/24/21
to
> My head exploded when trying to parse the ProDOS boot block.

And thus the reason no-one has replied. We are not willing to follow in your footsteps.

Steve Nickolas

unread,
Dec 24, 2021, 8:03:38 PM12/24/21
to
On Fri, 24 Dec 2021, I am Rob wrote:

>> My head exploded when trying to parse the ProDOS boot block.
>
> And thus the reason no-one has replied. We are not willing to follow in your footsteps.
>

We all know I'm a lunatic ;p

-uso.

qkumba

unread,
Dec 25, 2021, 6:04:33 PM12/25/21
to
ProBoot (part of Total Replay) parses the ProDOS file-system to find the named .SYS file to load and run.
It has no Apple III support, only Apple II and compatible. The source is in the repo on GitHub. Maybe it's useful to you somehow.

Kent Dickey

unread,
Dec 25, 2021, 6:30:42 PM12/25/21
to
In article <alpine.DEB.2.21.2...@sd-119843.dedibox.fr>,
I don't understand what you are asking. Are you trying to make a boot block
that will work on 8086 and an Apple II? If so, you'll need to work out
opcodes to start the block with that make sense for both architectures.
I don't understand why you'd want to do this and what you think this will
achieve. For the Apple II part, the first byte needs to be $01 and will
not be executed. If you want it can be any value from $01 to $0f, but
higher values will result in wasted time (it will read more sectors into
memory which will in general not be useful).

As for the ProDOS boot block, it's basic operation is to find the PRODOS
file in the volume directory, and boot from a 5.25" Disk II or a "Smartport"
device (really, the ProDOS entry point). It looks at the boot slot
$CnFF to get the ProDOS entry point (generally $07, so the entry point is
$Cn07), and then makes READBLOCK calls to find PRODOS. For Disk II, it
creates a fake driver (so the rest of the code can think in terms of blocks),
which then does the needed head moves (slower than needed, but short code)
and re-uses the $Cn5C entry point to read the sector data. It's clever,
but not too complex.

You mention Apple ///, but again I don't know what you mean. There's
special code to handle $CnFF being >= $F9, and maybe that's for Apple ///,
but I didn't trace through that code to figure out what it was doing.
My understanding is an Apple /// will boot from Block 1 (and Block 1 is
usually all 0's on volumes created on an Apple II).

Kent

Steve Nickolas

unread,
Dec 25, 2021, 7:00:21 PM12/25/21
to
On Sat, 25 Dec 2021, Kent Dickey wrote:

> In article <alpine.DEB.2.21.2...@sd-119843.dedibox.fr>,
> Steve Nickolas <usot...@buric.co> wrote:
>> My head exploded when trying to parse the ProDOS boot block.
>>
>> I'm trying to see whether it's possible to remove the Apple /// stuff and
>> add some 6502-8086 diglot stuff, given that I have an 8086 boot block that
>> does more or less the same thing, and that I could stuff into the second
>> block.
>>
>> -uso.
>
> I don't understand what you are asking. Are you trying to make a boot block
> that will work on 8086 and an Apple II? If so, you'll need to work out
> opcodes to start the block with that make sense for both architectures.
> I don't understand why you'd want to do this and what you think this will
> achieve. For the Apple II part, the first byte needs to be $01 and will
> not be executed. If you want it can be any value from $01 to $0f, but
> higher values will result in wasted time (it will read more sectors into
> memory which will in general not be useful).

That indeed was the trick.

> As for the ProDOS boot block, it's basic operation is to find the PRODOS
> file in the volume directory, and boot from a 5.25" Disk II or a "Smartport"
> device (really, the ProDOS entry point). It looks at the boot slot
> $CnFF to get the ProDOS entry point (generally $07, so the entry point is
> $Cn07), and then makes READBLOCK calls to find PRODOS. For Disk II, it
> creates a fake driver (so the rest of the code can think in terms of blocks),
> which then does the needed head moves (slower than needed, but short code)
> and re-uses the $Cn5C entry point to read the sector data. It's clever,
> but not too complex.
>
> You mention Apple ///, but again I don't know what you mean. There's
> special code to handle $CnFF being >= $F9, and maybe that's for Apple ///,
> but I didn't trace through that code to figure out what it was doing.
> My understanding is an Apple /// will boot from Block 1 (and Block 1 is
> usually all 0's on volumes created on an Apple II).
>
> Kent

I actually wrote this code:

http://6.buric.co/p86head.a86.txt

This is pretty close to what I understand the 6502 code does in principle,
but written from scratch in 8086 ASM (NASM dialect) - and I have written a
"hello world" test, though my head exploded trying to go further and
actually write a kernel.

I'm currently trying to write a small Apple ][ emulator in order to test
the code further, but I am very unfluent in 8086 being mainly a C
programmer.

-uso.

I am Rob

unread,
Dec 25, 2021, 8:14:10 PM12/25/21
to
> I'm currently trying to write a small Apple ][ emulator in order to test
> the code further, but I am very unfluent in 8086 being mainly a C
> programmer.

Someone got the most part of an 8080 simulator working on a 6502 over here:

http://forum.6502.org/viewtopic.php?f=2&t=6541

See if the code listed can give you any ideas.

qkumba

unread,
Dec 27, 2021, 1:34:11 PM12/27/21
to
> For the Apple II part, the first byte needs to be $01

It can be zero. The PROM loops while the value in $3D is < $800.
Then to make 6502/8086 compatible, the sequence can be
00 CD EB xx

which on 8086 is
00 CD ADD CH,CL
EB xx JMP SHORT [to x86-specific code]
and on 6502
00 ;1 sector read
CD EB xx CMP $xxEB
[6502 continues]

qkumba

unread,
Dec 27, 2021, 9:16:56 PM12/27/21
to
If you need to load two sectors, that's fine, too:
02 CD ADD CL,CH

qkumba

unread,
Dec 27, 2021, 9:17:11 PM12/27/21
to

Steve Nickolas

unread,
Dec 28, 2021, 12:06:57 AM12/28/21
to
Hm. So if I can plug in some x86 code that moves code out of the way to
load the second block in place of the first at 0000:7C00, i.e.,

retry: mov ax, 0x0201 ; read (AH) 1 (AL) sector
mov cx, 0x0002 ; track 0 sector 2
mov dh, 0x00 ; head 0 (DL unchanged from entry)
xor bx, bx
mov es, bx ; ES=$0000
mov bx, 0x7C00
int 0x13
jc retry
jmp 0x0000:0x7C00

(just banged out in a hurry)

it might be possible to make a diglot 6502-8086 bootloader. But I'd have
to strip out the /// stuff to have enough free space for that. And it
would probably require some better 8086 code than what I just wrote. But
it's a start.

-uso.

Steve Nickolas

unread,
Dec 28, 2021, 3:11:58 AM12/28/21
to
Currently the most efficient x86-side code I can come up with is this:

B8 01 02 B9 02 00 30 F6 31 DB 8E C3 BB 00 7C 26
C7 06 FE 7B CD 13 EA 00 7C 00 00

That's pretty much the same code I described before, except that once the
registers are set I place an "int 13h" at 0000:7BFE and jump hard to it.
(This 8086 code could probably be done even more efficiently.)

Since I haven't yet RE'd the entire ProDOS bootloader - only as far as
$096C, and that only basically - I'm not really sure what code might be
safe to maneuver around without breaking things, other than the stuff that
I was able to identify as being part of the SOS chainloader.

Still, this seems to suggest that a 6502-8086 diglot bootloader is indeed
possible. (It would only really be feasible on a 1.44 MB floppy though
which is quite rare on the Apple ][ line!)

-uso.

qkumba

unread,
Dec 28, 2021, 12:28:07 PM12/28/21
to
You'd be running already from 0000:7C00 if you're on a PC. Your read will overwrite your existing code.
Since all of the registers will have been set already for the first load, you could just
mov ax, 0x201
inc cx
pushf
push es
push bx
jmp far es:[0x004c]
and forget about retry.
Otherwise, yes it's possible to have a polyglot bootsector, even on a 5.25".
As for the ProDOS loader, block 1 is "reserved" (=unused). You could put the original sector there. Then you wouldn't need to fit the actual loader in the boot sector.

Steve Nickolas

unread,
Dec 28, 2021, 8:20:01 PM12/28/21
to
On Tue, 28 Dec 2021, qkumba wrote:

> You'd be running already from 0000:7C00 if you're on a PC. Your read
> will overwrite your existing code.

Yeah, knew that.

> Since all of the registers will have been set already for the first
> load, you could just
> mov ax, 0x201
> inc cx
> pushf
> push es
> push bx
> jmp far es:[0x004c]
> and forget about retry.

Hm. I was trying to think about how to emulate an INT by jumping (much
like the very common on the Apple ][ method of "return to subroutine",
which the ProDOS bootloader actually does use). I guess that's what I was
looking for.

0100- B8 01 02 MOV AX, 0201
0103- 41 INC CX
0104- 9C PUSHF
0105- 06 PUSH ES
0106- 53 PUSH BX
0107- EA 4C 00 00 00 JMP 0000:004C

12 bytes, eh? That's far more efficient than I'd come up with. xD

> Otherwise, yes it's possible to have a polyglot bootsector, even on a
> 5.25".

Of course most Apple ][ media wouldn't work on a PC and vice-versa - the
1.44 MB floppy being the exception.

> As for the ProDOS loader, block 1 is "reserved" (=unused). You could
> put the original sector there. Then you wouldn't need to fit the actual
> loader in the boot sector.

Yeah, that's what I was hoping to be able to do: literally the Apple ///
trick, with a PC replacing the ///.

-uso.

qkumba

unread,
Dec 29, 2021, 1:11:52 PM12/29/21
to
> 0100- B8 01 02 MOV AX, 0201
> 0103- 41 INC CX
> 0104- 9C PUSHF
> 0105- 06 PUSH ES
> 0106- 53 PUSH BX
> 0107- EA 4C 00 00 00 JMP 0000:004C
>
> 12 bytes, eh? That's far more efficient than I'd come up with. xD

The instruction at 0107 should read

0107- 26 FF 26 4C 00 JMP FAR ES:[004C]

It has to be indirect to use the vector.
If you're willing to bet that DS is also zero, then you can drop the first 26.

Steve Nickolas

unread,
Dec 29, 2021, 1:28:01 PM12/29/21
to
Didn't know you could use a segment override with JMP. o.o

The 8086 is a lot more complicated than the 6502.

(I'm also trying to write a 6502 core in 8086 asm but given that I don't
even have a fully working 6502 core in C, it's probably a fool's errand.)

-uso.
0 new messages