MS-DOS Simulator on the C64 and other OS and web browser

I’m still wondering why the C64 Kernal (and other computers) not starting at 0 /A000 after a cold start, but there are hardware reset vectors in all Commodore home computers starting in FFFA /FFFC (=FC E2) and then continue there (if there isn’t a module present).
The BASIC has another vector at A000 jumping to E394 (for cold start).

By coincidence I found on the German C64-wiki, an MS-DOS Simulator for the C64. First released in Italy, then Germany.
One problem is, that due to the different hardware disk coding (MFM/GCR) someone can’t read/write DOS disks.
So I wonder if this is useful. Maybe for learning before buying a PC?
There are also some other OS for the C64 including linux, CP/M, GEOS and Contiki including a Web browser (surfing the web by a C64, OMG that is limited)

I’m not sure I understand the question, but the MOS 6502 loads the PC with FFFCh/FFFDh at boot time, and that’s not something that the C64 Kernal gets to choose. The 6502 architecture strongly requires RAM (not ROM) in the first 512 bytes of RAM, as the first 256 bytes are the “zero page” (which is effectively an extended register file) and the second 256 bytes are the stack, and this is not negotiable – it is hard-wired in the CPU. This means that resetting to location 0 would require temporarily mapping FFFCh/FFFDh to location 0 only until the first two fetches are complete (or shortly thereafter), versus simply mapping ROM to the top of memory.

In practice, malleable interrupt vectors are valuable, so often the top of memory can be remapped to RAM anyway, so the “benefit” of this simplification may be less than otherwise on systems that are large enough to have memory management anyway.

The 8080/Z80, on the other hand, have no reset “vector”, and simply begin execution at address 0.

Strictly speaking, addresses $0000 – $01FF must be mapped in some way (compare the Atari VCS, where this mapped to auxialliary processors and 128 bytes of RAM in one of them, mapped both to $0000 and $0100). :slight_smile:

Other required addresses are:

$FFFA/$FFFB ... NMI (Non-Maskable Interrupt) vector
$FFFC/$FFFD ... RES (Reset) vector
$FFFE/$FFFF ... IRQ (Interrupt Request) vector

This really somewhat pre-determines the principal architecture to a certain extent, as this requires RAM at the low end of the address space (for the zeropage and stack) and ROM at the high end (for the jump vectors). You certainly need some zero page RAM, as the built-in registers (accumulator and the X and Y registers) are not enough to accomplish anything complex (so we may think of the zeropage as an extended set of registers), and the stack is required for any subroutines and interrupts.

Notably, the 6510 found in the C64 differs a bit from this, as addresses 0000 and 0001 are used for port configuration (which facilitates the bank switching scheme of the C64). Meaning, there must be something at these addresses, as well, either RAM or even hard wired, and these addresses cannot be used for normal zero page operations.

As for C64 startup operations: The CPU looks up the contents of the vector (for cold start/reset $FFFC/$FFFD) und uses contents for PC. In the case of the C64, this points to the start routine at $FCE2. This sets the interrupt disable flag, initializes the the stack pointer and clears the decimal flag. Then a subroutine at $FD02–$FD0F is called. This checks for the presence of the byte sequence $C3 $C2 $CD $38 $30 (“CBM80” in PETSCII) at addresses $8004–$8008. If so, it’s assumed that a cartridge is mapped at $8000 and an indirect jump using the pointer at $8000–$8001 (as another vector) is performed. Otherwise, normal setup procedures are followed.

The same mechanism is used for non-maskable interrupts (NMI), where the code in ROM also checks for the presence of a cartridge. If the magic code is found, the pointer at $8002–$8003 is used. (So cartridges have their own NMI routines. If you use this for your own startup/reset mechanism by setting “CBM80” at $8004, be sure to implement the NMI vector as well.)

So a C64 cartridge starts with the following values:

$8000/$8001 ... start/reset vector
$8002/$8003 ... NMI vector
$8004-$8008 ... $C3 $C2 $CD $38 $30 ("CBM80")

Edit: As a side effect, this makes it really easy to implement something, which is loaded from disk, but should handle some I/O like keyboard shortcuts/commands, even before the operating system scans for any input:

$8000 .WORD $FCEC ;continues as normally, as if no cartridge is found
$8002 .WORD $8009 ;own NMI routine
$8004 .PETSCII "CBM80"
$8009 ;start of own NMI routine, scan keyboard, etc
      JMP $FE5E ;exit to where the NMI routine continues normally

E.g., we could check for F1 pressed to start our own monitor or port listening program.

Regarding the usefulness of the DOS emulator: If this really runs GWBASIC natively, I can see some use for this. Mind that the original IBM 5150 PC wasn’t much faster than the C64 anyway. (The effective processor speed is about the same and 16-bit operations are not always faster, since the 8088 has 8-bit ports, which means additional wait states. So a C64 may be even faster on operations that require 8-bit values only.) Moreover, you get the familiar disk commands.

1 Like

I wonder how many bought the magazine for running GWBASIC on a C64.
The main question rather was if someone had a PC then, not the speed.
And as you can’t use DOS disks, you have to write your own GWBASIC software.
But probably most would rather play games anyway.

Concerning the hardware vectors, thanks for the details. You can say for short: so is the chip design.
It’s still strange, jumping even twice. Yes, it needs to be checked if there’s a cartridge, and checking/initialize other stuff like delete the SID volume register and turn off the datasette motor.