Bootable SITU-MON cartridge image, and initial documentation on it.
Chris Pressey
6 years ago
Binary diff not shown
0 | Booting from a cartridge | |
1 | ======================== | |
2 | ||
3 | _mid-May, 2016_ | |
4 | ||
5 | Booting SITU-MON from a cartridge | |
6 | --------------------------------- | |
7 | ||
8 | This mini-project will be to get SITU-MON booting from a cartridge image. | |
9 | This is not for RetroChallenge; this is an off-season project. And while | |
10 | SITU-MON and SITU-SOL are generic 6502 machine language programs, this project | |
11 | is somewhat more C64-specific. | |
12 | ||
13 | SITU-MON starts at $8100 and SITU-SOL starts at $8200; these addresses were | |
14 | chosen so that they fall within the address space of a Commodore 64 cartridge, | |
15 | $8000-$9FFF. | |
16 | ||
17 | The Commodore 64 can boot from a cartridge, if the cartridge contains an | |
18 | autoboot signature in its first few bytes at $8000. | |
19 | ||
20 | When the KERNAL detects a cartridge and autoboots it, there are some things | |
21 | it doesn't do which it would normally do if it was booting into BASIC. So, | |
22 | along with this header, we will need some startup code in the cartridge | |
23 | which does these things, then starts SITU-MON. | |
24 | ||
25 | So the plan is: | |
26 | ||
27 | * Use SITU-MON to write the signature to $8000 and the startup code just | |
28 | after it, at $8009. | |
29 | * Save the memory range $8000-$8FFF to a binary image. | |
30 | ||
31 | What signature do we need? It's described on page 263 of the Programmer's | |
32 | Reference Guide, but basically it's | |
33 | ||
34 | * Address of the code to run for cold boot when the cartridge is | |
35 | plugged in — which will be our startup code at $8009. | |
36 | * Address of the code to run for cold boot when the cartridge is | |
37 | plugged in. I'll just use $FEBC, which I picked up somewhere along | |
38 | my travels as a "magic address" to assign to the warm-boot vector to | |
39 | disable RUN/STOP-RESTORE. In fact, if you look at the code at that | |
40 | address, it's just the tail of a KERNAL routine that just cleans up | |
41 | the stack and `RTI`'s. I'm not actually sure how well it will work here. | |
42 | * The magic characters `CBM80`, in PETSCII, and where the first 3 | |
43 | characters have their high bit set. | |
44 | ||
45 | What startup code do we need? It's described (sort of) on page 269. Reading | |
46 | it, and the description of the KERNAL routines in pages 274-306, it's apparent | |
47 | that it calls the KERNAL routines `IOINIT`, `RAMTAS`, and `CINT`. What's | |
48 | less apparent is that it also calls `RESTOR` before `CINT`. This took a | |
49 | little testing (and a peek at a disassmbly of the KERNAL's `RESET` routine) | |
50 | to figure out. It would have been nice if the Guide had just names the | |
51 | KERNAL routines involved. But oh well. Here's my chicken-scratches: | |
52 | ||
53 |  | |
54 | ||
55 | How do we save the memory range? Well, we could tell the emulator to do it, | |
56 | but in fact there is a way to get a Commodore 64 to save an arbitrary chunk | |
57 | of its memory to a disk file. (On an Apple II, the DOS command which does | |
58 | this is called `BSAVE`, but true to form, doing the equivalent thing on a | |
59 | C64 involves a series of obscure `POKE`s.) | |
60 | ||
61 | POKE 43,0:POKE 44,128:POKE 45,0:POKE 46,144 | |
62 | SAVE "SITU-MON-CART",8 | |
63 | ||
64 | Those `POKE`s change BASIC's idea of where the BASIC program begins and | |
65 | ends in memory, effectively tricking it into saving $8000-$8FFF. Yes, OK, | |
66 | this is only a 4K cartridge image, but that should be fine for now. And | |
67 | there is a small caveat: when you save a memory image like this, the first | |
68 | two bytes contain the load address. VICE seems to understand this, for | |
69 | cartridge images, but other tools, such as an EPROM burner, might not, | |
70 | because those two bytes would not be present on a real ROM itself. | |
71 | ||
72 | But first, there's a wrinkle. When SITU-MON was written it was not given | |
73 | the ability to exit, so how do we even drop to BASIC? | |
74 | ||
75 | Well, we can set the address to the BASIC warm boot routine, and then call | |
76 | it. We call it as a subroutine, because that's all SITU-MON can do, but | |
77 | BASIC will never return to SITU-MON, so in effect we lose a few bytes of | |
78 | stack space. This is fine. | |
79 | ||
80 | AA483 | |
81 | G | |
82 | ||
83 | So, putting this all together, here's a screenshot of using SITU-SOL to | |
84 | make these changes, then using BASIC to save the cartridge image to disk: | |
85 | ||
86 |  | |
87 | ||
88 | Then... in VICE, select "Attach raw 8K cartridge image..." and select the | |
89 | file we just saved and voilá! | |
90 | ||
91 |  | |
92 | ||
93 | Nothing fancy, but then I didn't expect it to be. | |
94 | ||
95 | Booting SITU-SOL from a cartridge will be the next step, but it's slightly | |
96 | harder, for two reasons: | |
97 | ||
98 | * The symbal table starts at $0900, which is not inside the address space | |
99 | of the cartridge. So a symbal table will need to be copied there, from | |
100 | the cartridge, during boot. | |
101 | * I have not actually defined an actual default symbal table with proper | |
102 | built-ins for SITU-SOL yet. So we may have to make do with the demo | |
103 | symbal table that was thrown together during RetroChallenge 2015/07. |
Binary diff not shown
Binary diff not shown
Binary diff not shown