Hi Guys,
I am going to document the startup process. Can any of you tell me which version of the Operating System that the C4P/MF uses? I have seen versions for the C1P the C4P and the OS-65D and OS-65P and versions 3.0, 3.1, 3.2, and 3.3.
Which would be the best target to investigate, and where would the best place be to download a floppy image of it?
Thanks in advance.
/Jeff
Decoding the startup boot process of the C4P/MF
-
- Posts: 370
- Joined: Fri Mar 07, 2014 4:44 am
- Location: British Columbia, Canada
-
- Posts: 375
- Joined: Wed Mar 30, 2011 9:44 am
- Location: New Zealand
- Contact:
Re: Decoding the startup boot process of the C4P/MF
Hi Jeff,
I just emailed you some disk images for OS65D 3.3 and 3.2 for the C2/C4.
Phil
I just emailed you some disk images for OS65D 3.3 and 3.2 for the C2/C4.
Phil
2P (1mhz 32k) - 502 + 8k + CEGMON + garbage collector fix BASIC, D&N MEM-CM9 + 24k, 540 (mono) [SOLD]
4PMF (2mhz 24k) - 505, 540, 527, D13 + 5.25" + Gotek
Superboard RevD - CEGMON + 610 board 24k + D13
Spares - 3 x 527, 1 x 505, Backplane
-
- Posts: 370
- Joined: Fri Mar 07, 2014 4:44 am
- Location: British Columbia, Canada
Re: Decoding the startup boot process of the C4P/MF
Thanks, Phil. I am evaluating them now.
Oh, and I just performed the 1200 to 9600 baud upgrade on my C4P/MF. It was pretty simple.
Regards
/Jeff
Oh, and I just performed the 1200 to 9600 baud upgrade on my C4P/MF. It was pretty simple.
Regards
/Jeff

-
- Posts: 356
- Joined: Wed Mar 16, 2011 1:49 am
- Location: New Zealand
Re: Decoding the startup boot process of the C4P/MF
Jeff, there is a fully commented OS65D3.2 listing on the net. Have you got that?
V3.3 is probably the best to use IMHO. The boot process for that is different of course as it loads a new keyboard and screen driver. I have details of that if you want.
Are you after 5 or 8 '' images ?
V3.3 is probably the best to use IMHO. The boot process for that is different of course as it loads a new keyboard and screen driver. I have details of that if you want.
Are you after 5 or 8 '' images ?
600RevB:16K,2MHz,64x32,470,CEGMON
SuperKit:502,540B,542B,CEGMON, 8" and 5" FDDs
Cards:PE IO,6522 D-A-D, AY3-8910,ProgramGraphics,Color,UK101
WIP:HexDOS,FDD Emulator
SuperKit:502,540B,542B,CEGMON, 8" and 5" FDDs
Cards:PE IO,6522 D-A-D, AY3-8910,ProgramGraphics,Color,UK101
WIP:HexDOS,FDD Emulator
-
- Posts: 370
- Joined: Fri Mar 07, 2014 4:44 am
- Location: British Columbia, Canada
Re: Decoding the startup boot process of the C4P/MF
Yes. I have the disassembly. I hadn't thought that the images would be different for 5 and 8, but of course they are!!! I will stick with 5 right now. I have mostly finished my disassembly of the boot rom.
The boot process starts in the rom, then to track zero and one and then onward from there. What I am hoping to do is download one big file to the C4P that would represent what the machine state would be once it has booted.
Regards
/Jeff
The boot process starts in the rom, then to track zero and one and then onward from there. What I am hoping to do is download one big file to the C4P that would represent what the machine state would be once it has booted.
Regards
/Jeff

-
- Posts: 370
- Joined: Fri Mar 07, 2014 4:44 am
- Location: British Columbia, Canada
Re: Decoding the startup boot process of the C4P/MF
Here is the disassembly so far...
Enjoy!
/Jeff
Code: Select all
; Jeff Ferguson, Chaos Designs
; Created: 2014-05-30 18:33:48
; SYN600 Notes:
; The 3 of the 8 256 byte pages in this rom are mapped into 3 areas
; of the computers, $FD00, $FE00, and $FF00. Different pages are
; used depending on the system. (Tape based, Disk based, model etc.)
; The $FD00 page is for the polled keyboard. The $FF00 page sets the
; IRQ, NMI & RST vectors and does the initial startup, the $FE00 page
; contains part of the tiny monitor & tape I/O etc.
; page 000 'H/D/M' maps to $FF00 for a C2/C4 disk system
; page 100 keypoller maps to $FD00 for a C2/C4 system
; page 200 monitor maps to $FE00 for a C2/C4 system
; page 300 'C/W/M' maps to $FF00 for a C2/C4 tape system
; page 400 ??
; page 500 keypoller maps to $FD00 (for a C1 system?)
; page 600 monitor maps to $FE00 (for a C1 system?)
; page 700 'D/C/W/M' maps to $FF00 for a C1 system
;
; On a C2/C4 system:
; ACIA is at $FC00-FCFF
; Keyboard at $DF00-DFFF
; Video $D000-D7FF, Color at $E000-E7FF
; Basic ROM $A000-BFFF
; Model 505 CPU Board (C4P/MF) Notes
; -------------------
; CPU board w/ ROM, ACIA, Floppy Disk I/O, Real Time Clock
; ROM $FDxx, $FExx, $FFxx
; Floppy disk interface: 6521 PIA at $C000, 6850 ACIA at $C010
; ACIA 6850 at $FC00 for RS-232 serial I/O. Baud jumpers for 75,150,300,600,1200,2400,4800,9600
; Disk PIA $C0xx CB1 connected to 400mSEC (2.5/sec) clock divided from system clock (RTC)
; Home security - PIA $F700-F703
;
; I/O at $C704-C70E for connection to A15 I/O board which contains connectors for keypads, joystick, buffered I/O contains A0-A3, ¯2, R/W, D0-D7 for Head End Cards.
; PIA $F7xx CA2 can be wired to WAIT input allowing control of CPU speed, 1 or 2Mhz
; PIA $F7xx CB2 output controls CTS select from Modem or Printer serial interface
; when $00FB is non-zero, only commands from cassette/serial are read. at the end of cassette/serial entry,
; need to set $00FB to zero to restore keyboard operation
; *** Program Entry Points
; VM FE00 - Restart Location
; FE0C - Bypasses UART and Stack Pointer initialization and the clearing of decimal mode
; IN FE43 - Entry into Address Mode, bypass initialization
; FE77 - Entry into Data Mode, bypass initialization
;
; *** Subroutines
; OTHER FE80 - Input an ASCII character from ACIA
; LEGAL FE93 - Returns stripped ASCII number if 0-9 or A-F, otherwise it returns a FF
; INPUT FEED - Input an ASCII character from keyboard
.setcpu "6502"
; ----------------------------------------------------------------------------
LFE0B := $FE0B
GetKeybdChar := $FEED ; Input an ASCII character from keyboard
LFEFC := $FEFC
StartOS65D := $2200
ReadFromPIA := $FF00
GetAsciiKeySub := $FD00
ResetEntry := $FFA0
MonitorWarmStart := $FE00 ; Restart Location
RestartMonWithClearScreen := $FE0C ; Bypasses UART and Stack Pointer initialization and the clearing of decimal mode.
EnterAddressMode := $FE43 ; Entry into Address Mode, bypass initialization
EnterDataMode := $FE77 ; Entry into Data Mode, bypass initialization
MonitorWarmStartVector := $FEFC
GetMSBPos := $FDC8
ConvertKeyToValue := $FE93 ; Returns stripped ASCII number if 0-9 or A-F, otherwise it returns a FF
GetACIAChar := $FE80 ; Input an ASCII character from ACIA
PollKeyboard := $FD04
Loop1000Times := $FD4A
KeyHit := $FD56
PollingKbdLoop := $FE2A
GoAtCurrentAddress := $FE4C
HandleSlash := $FE4F
ClearLow4Bits := $FEA6
EORSomeBytes := $FF85
LoadAByteFromDisk := $FF90
EmptySub := $FF99 ; really! this is the address of an rts op code. Used as an exit when called as a subroutine?
BootPrompt := $FF9A ; H/D/M?
BootHardDisk := $FFF0 ; in response to H pressed
BootMonitor := $FFF6 ; in response to M pressed
BootFloppy := $FFEA ; in response to D pressed
; Hardware locations
Keyboard := $DF00
NMIVector := $FFFA
ResetVector := $FFFC
BreakVector := $FFFE
ACIAControl := $FC00 ; referred to as "Floppy Bootstrap"
ACIAData := $FC01
DiskPIA0 := $C000 ;
DiskPIA1 := $C001 ;
DiskPIA2 := $C002 ;
DiskPIA3 := $C003 ;
ACIA10 := $C010
PIA11 := $C011
SubFEE9 := $FEE9
ShiftAndRoll := $FEDA
SubFEAC := $FEAC
Output := $FECA
; interesting addresses
KeyMap := $FDCF
ScreenOut := $D0C6 ; position on screen for monitor address
ScreenSpace1 := $D0CA ; position on screen for first space between address and data
ScreenSpace2 := $D0CB ; position on screen for second space between address and data
KbdFlag := $FB ; ROM Monitor load flag.... if set, then loading from ACIA instead of keyboard... if set keyboard input is ignored
MonitorMemLoc := $00FE ; Low Address of current memory location, also used while clearing the screen
MonitorMemLocLow := $FE ; Low Address of current memory location, also used while clearing the screen
MonitorMemLocHigh := $FF ; HighAddress of current memory location, also used while clearing the screen
MonitorMemLocLow2 := $FC ; ROM Monitor contents of currently displayed memory location
MonitorMemLocFD := $FD ; some sort of work variable
ScreenBaseLow := $FD ; used when clearing the screen
ScreenBaseHigh := $FE ; used when clearing the screen
$0213 ; Polled Keyboard temporary storage and counter
$0214 ; "
$0215 ; "
$0216 ; "
$FB06 ; vectorLow
$FB05 ; vectorHigh
; ----------------------------------------------------------------------------
GetAsciiKeySub:
txa ; FD00 8A .
pha ; FD01 48 H
tya ; FD02 98 .
pha ; FD03 48 H
PollKeyboard:
lda #$01 ; FD04 A9 01 ..
LFD06: sta Keyboard ; FD06 8D 00 DF Poke the Keyboard R0
ldx Keyboard ; FD09 AE 00 DF Keyboard Response is in X
bne LFD13 ; FD0C D0 05 ..
LFD0E: asl a ; FD0E 0A .
bne LFD06 ; FD0F D0 F5 Why 2 branches here?
beq LFD66 ; FD11 F0 53 Why 2 branches here?
LFD13: lsr a ; FD13 4A J
bcc LFD1F ; FD14 90 09 ..
rol a ; FD16 2A *
cpx #$21 ; FD17 E0 21 .!
bne LFD0E ; FD19 D0 F3 ..
lda #$1B ; FD1B A9 1B ..
bne LFD40 ; FD1D D0 21 .!
LFD1F: jsr GetMSBPos ; FD1F 20 C8 FD ..
tya ; FD22 98 .
sta $0213 ; FD23 8D 13 02 ...
asl a ; FD26 0A .
asl a ; FD27 0A .
asl a ; FD28 0A .
sec ; FD29 38 8
sbc $0213 ; FD2A ED 13 02 ...
sta $0213 ; FD2D 8D 13 02 ...
txa ; FD30 8A .
lsr a ; FD31 4A J
jsr GetMSBPos ; FD32 20 C8 FD ..
bne LFD66 ; FD35 D0 2F ./
clc ; FD37 18 .
tya ; FD38 98 .
adc $0213 ; FD39 6D 13 02 m..
tay ; FD3C A8 .
lda KeyMap,y ; FD3D B9 CF FD ...
LFD40: cmp $0215 ; FD40 CD 15 02 ...
bne LFD6B ; FD43 D0 26 .&
dec $0214 ; FD45 CE 14 02 ...
beq LFD75 ; FD48 F0 2B .+
Loop1000Times: ; start a delay loop
ldy #$05 ; FD4A A0 05 Y = 5
LoopFD4C:
ldx #$C8 ; FD4C A2 C8 X = 200
LoopFD4E:
dex ; FD4E CA X = X-1
bne LoopFD4E ; FD4F D0 FD Loop 200 times
dey ; FD51 88 Y = Y-1
bne LoopFD4C ; FD52 D0 F8 Loop 5 times
beq PollKeyboard ; FD54 F0 AE ..
KeyHit:
cmp #$01 ; FD56 C9 01 ..
beq LFD8F ; FD58 F0 35 .5
ldy #$00 ; FD5A A0 00 ..
cmp #$02 ; FD5C C9 02 ..
beq LFDA7 ; FD5E F0 47 .G
ldy #$C0 ; FD60 A0 C0 ..
cmp #$20 ; FD62 C9 20 .
beq LFDA7 ; FD64 F0 41 .A
LFD66: lda #$00 ; FD66 A9 00 ..
sta $0216 ; FD68 8D 16 02 ...
LFD6B: sta $0215 ; FD6B 8D 15 02 ...
lda #$02 ; FD6E A9 02 ..
sta $0214 ; FD70 8D 14 02 ...
bne LFD04 ; FD73 D0 8F ..
LFD75: ldx #$96 ; FD75 A2 96 ..
cmp $0216 ; FD77 CD 16 02 ...
bne LFD7E ; FD7A D0 02 ..
ldx #$14 ; FD7C A2 14 ..
LFD7E: stx $0214 ; FD7E 8E 14 02 ...
sta $0216 ; FD81 8D 16 02 ...
lda #$01 ; FD84 A9 01 ..
sta Keyboard ; FD86 8D 00 DF Poke the Keyboard R0
lda Keyboard ; FD89 AD 00 DF Key Column hit into Accum
LFD8C: lsr a ; FD8C 4A J
bcc LFDC2 ; FD8D 90 33 .3
LFD8F: tax ; FD8F AA .
and #$03 ; FD90 29 03 ).
beq LFD9F ; FD92 F0 0B ..
ldy #$10 ; FD94 A0 10 ..
lda $0215 ; FD96 AD 15 02 ...
bpl LFDA7 ; FD99 10 0C ..
ldy #$F0 ; FD9B A0 F0 ..
bne LFDA7 ; FD9D D0 08 ..
LFD9F: ldy #$00 ; FD9F A0 00 ..
cpx #$20 ; FDA1 E0 20 .
bne LFDA7 ; FDA3 D0 02 ..
ldy #$C0 ; FDA5 A0 C0 ..
LFDA7: lda $0215 ; FDA7 AD 15 02 ...
and #$7F ; FDAA 29 7F ).
cmp #$20 ; FDAC C9 20 .
beq LFDB7 ; FDAE F0 07 ..
sty $0213 ; FDB0 8C 13 02 ...
clc ; FDB3 18 .
adc $0213 ; FDB4 6D 13 02 m..
LFDB7: sta $0213 ; FDB7 8D 13 02 ...
pla ; FDBA 68 h
tay ; FDBB A8 .
pla ; FDBC 68 h
tax ; FDBD AA .
lda $0213 ; FDBE AD 13 02 ...
rts ; FDC1 60 `
LFDC2: bne KeyHit ; FDC2 D0 92
ldy #$20 ; FDC4 A0 20 .
bne LFDA7 ; FDC6 D0 DF ..
GetMSBPos: ; returns, in Y, the bit position of the MSB in Accumulator, A must not be 0
ldy #$08 ; FDC8 A0 08 maximum number of shifts, Assumes A is non-sero
LoopFDCA:
dey ; FDCA 88 affects Z and S
asl a ; FDCB 0A A = A*2, Bit 7 goes into C
bcc LoopFDCA ; FDCC 90 FC ..
rts ; FDCE 60 Return Result in Y, bit position of the MSB
; ----------------------------------------------------------------------------
KeyMap: ; Used while polling the keyboard
; ROW 1
.byte $D0 ; FDCF D0 P (High Bit Set)
.byte $BB ; FDD0 BB ; (High Bit Set)
.byte $2F ; FDD1 2F /
.byte $20 ; FDD2 20 SPACE
.byte $5A ; FDD3 5A Z
.byte $41 ; FDD4 41 A
.byte $51 ; FDD5 51 Q
; ROW 2
.byte $2C ; FDD6 2C ,
.byte $4D ; FDD7 4D M
.byte $4E ; FDD8 4E N
.byte $42 ; FDD9 42 B
.byte $56 ; FDDA 56 V
.byte $43 ; FDDB 43 C
.byte $58 ; FDDC 58 X
; ROW 3
.byte $4B ; FDDD 4B K
.byte $4A ; FDDE 4A J
.byte $48 ; FDDF 48 H
.byte $47 ; FDE0 47 G
.byte $46 ; FDE1 46 F
.byte $44 ; FDE2 44 D
.byte $53 ; FDE3 53 S
; ROW 4
.byte $49 ; FDE4 49 I
.byte $55 ; FDE5 55 U
.byte $59 ; FDE6 59 Y
.byte $54 ; FDE7 54 T
.byte $52 ; FDE8 52 R
.byte $45 ; FDE9 45 E
.byte $57 ; FDEA 57 W
; ROW 5
.byte $00 ; FDEB 00 <blank>
.byte $00 ; FDEC 00 <blank>
.byte $0D ; FDED 0D CR
.byte $0A ; FDEE 0A LF
.byte $4F ; FDEF 4F O
.byte $4C ; FDF0 4C L
.byte $2E ; FDF1 2E PERIOD
; ROW 6
.byte $00 ; FDF2 00 <blank>
.byte $FF ; FDF3 FF RUB OUT
.byte $2D ; FDF4 2D - (HYPHEN)
.byte $BA ; FDF5 BA : (High Bit Set)
.byte $30 ; FDF6 30 0
.byte $B9 ; FDF7 B9 9 (High Bit Set)
.byte $B8 ; FDF8 B8 8 (High Bit Set)
; ROW 7
.byte $B7 ; FDF9 B7 7 (High Bit Set)
.byte $B6 ; FDFA B6 6 (High Bit Set)
.byte $B5 ; FDFB B5 5 (High Bit Set)
.byte $B4 ; FDFC B4 4 (High Bit Set)
.byte $B3 ; FDFD B3 3 (High Bit Set)
.byte $B2 ; FDFE B2 2 (High Bit Set)
.byte $B1 ; FDFF B1 1 (High Bit Set)
; ----------------------------------------------------------------------------
; Start of Monitor
MonitorWarmStart:
ldx #$28 ; FE00 A2 28 X = $28
txs ; FE02 9A StackPtr = $28
cld ; FE03 D8 Clear Decimal Flag
lda $FB06 ; FE04 AD 06 FB Load Immediate A = contents of $FB06 What is at $FBxx?
lda #$FF ; FE07 A9 FF A = $FF
sta $FB05 ; FE09 8D 05 FB $FB05 = $FF What is at FB05?
RestartMonWithClearScreen:
ldx #$D8 ; FE0C A2 D8 last page to clear ($D000-D7FF)
lda #$D0 ; FE0E A9 D0 first page to clear
sta MonitorMemLocHigh ; FE10 85 FF $FF = #$D0
lda #$00 ; FE12 A9 00 A = #$0
sta ScreenBaseHigh ; FE14 85 FE $FE = 00 Zero Page
sta KbdFlag ; FE16 85 FB clear the keyboardIgnore Flag
tay ; FE18 A8 Y = 0
lda #$20 ; FE19 A9 20 blank character to store all over the screen
LoopFE1B:
sta (MonitorMemLoc),y ; FE1B 91 FE Store a blank character at $FE,FF + Y
iny ; FE1D C8 Y = Y+1
bne LoopFE1B ; FE1E D0 FB Loop until Y == 0 (256 times)
inc MonitorMemLocHigh ; FE20 E6 FF $FF = $FF + 1 Zero Page Increment Page Byte
cpx MonitorMemLocHigh ; FE22 E4 FF Done whole screen? Stop at $D800
bne LoopFE1B ; FE24 D0 F5 Loop while X != $D8
; done clearing screen
sty MonitorMemLocHigh ; FE26 84 FF $FF = Y Register (resoring contents of $FF)
beq EnterAddressMode ; FE28 F0 19 we looped on bne above, so this is a simple fast
; jmp to EnterAddressMode
PollingKbdLoop:
jsr SubFEE9 ; FE2A 20 E9 FE
cmp #$2F ; FE2D C9 2F Check for a slash (used to enter Data Mode)
beq HandleSlash ; FE2F F0 1E
cmp #$47 ; FE31 C9 47 Check for a "G" (Go Execute at current address)
beq GoAtCurrentAddress ; FE33 F0 17
cmp #$4C ; FE35 C9 4C Check for a "L" (Load mode)
beq EnterLoadMode ; FE37 F0 43
jsr ConvertKeyToValue ; FE39 20 93 FE
bmi PollingKbdLoop ; FE3C 30 EC
ldx #$02 ; FE3E A2 02
jsr ShiftAndRoll ; FE40 20 DA FE
EnterAddressMode:
lda (MonitorMemLoc),y ; FE43 B1 FE
sta MonitorMemLocLow2 ; FE45 85 FC
jsr SubFEAC ; FE47 20 AC FE
bne PollingKbdLoop ; FE4A D0 DE
GoAtCurrentAddress:
jmp (MonitorMemLoc) ; FE4C 6C FE 00 Jump to our currently displayed address (held in $00FE)
HandleSlash:
jsr SubFEE9 ; FE4F 20 E9 FE
cmp #$2E ; FE52 C9 2E Check for a "." (used to enter address mode)
beq PollingKbdLoop ; FE54 F0 D4
cmp #$0D ; FE56 C9 0D Check for a CR (used to enter data, and move to next address)
bne LFE69 ; FE58 D0 0F
inc MonitorMemLocLow ; FE5A E6 FE
bne LFE60 ; FE5C D0 02
inc MonitorMemLocHigh ; FE5E E6 FF
LFE60: ldy #$00 ; FE60 A0 00
lda (MonitorMemLoc),y ; FE62 B1 FE
sta MonitorMemLocLow2 ; FE64 85 FC
jmp EnterDataMode ; FE66 4C 77 FE
LFE69: jsr ConvertKeyToValue ; FE69 20 93 FE
bmi HandleSlash ; FE6C 30 E1
ldx #$00 ; FE6E A2 00
jsr ShiftAndRoll ; FE70 20 DA FE
lda MonitorMemLocLow2 ; FE73 A5 FC
sta (MonitorMemLoc),y ; FE75 91 FE
EnterDataMode:
LFE77: jsr SubFEAC ; FE77 20 AC FE
bne HandleSlash ; FE7A D0 D3
EnterLoadMode:
sta KbdFlag ; FE7C 85 FB Set KbdFlag to Ignore Kbd while loading
LFE7E: beq HandleSlash ; FE7E F0 CF
GetACIAChar: ; Input an ASCII character from ACIA
lda ACIAControl ; FE80 AD 00 FC ...
lsr a ; FE83 4A J
bcc GetACIAChar ; FE84 90 FA ..
lda ACIAData ; FE86 AD 01 FC ...
nop ; FE89 EA do nothing
nop ; FE8A EA do nothing
nop ; FE8B EA do nothing
and #$7F ; FE8C 29 7F ).
rts ; FE8E 60 return
; ----------------------------------------------------------------------------
; dead space
.byte $A0 ; FE8F A0
.byte $A0 ; FE90 A0
.byte $A0 ; FE91 A0
.byte $A0 ; FE92 A0
; ----------------------------------------------------------------------------
; Raw key ascii should be in A
ConvertKeyToValue:
cmp #$30 ; FE93 C9 30 Is key (in A) a "0"?
bmi Return80 ; FE95 30 12 too low, out of range, branch
cmp #$3A ; FE97 C9 3A is key (in A) < ':' (Checking for range 0-9)
bmi ClearLow4Bits ; FE99 30 0B return A & $0F if A >= '0' && < 58 ':' (Range 0-9)
cmp #$41 ; FE9B C9 41 Is A in range 'A' - 'F'
bmi Return80 ; FE9D 30 0A Return -1, key out of range
cmp #$47 ; FE9F C9 47 A < 71? "G" (Range A->F)
bpl Return80 ; FEA1 10 06 Return -1, key out of range
sec ; FEA3 38 Set Carry
sbc #$07 ; FEA4 E9 07 Subtract 7 from A, moves 'F' Ascii immediately after '9'
ClearLow4Bits:
and #$0F ; FEA6 29 0F clear 4 high bits
rts ; FEA8 60 return (result in A) (0 thru F)
Return80:
lda #$80 ; FEA9 A9 80 A = -1
rts ; FEAB 60 return error (-1)
; ----------------------------------------------------------------------------
SubFEAC:
ldx #$03 ; FEAC A2 03 ..
ldy #$00 ; FEAE A0 00 ..
LoopFEB0:
lda MonitorMemLocLow2,x ; FEB0 B5 FC Zero Page,X
lsr a ; FEB2 4A shifting...
lsr a ; FEB3 4A shifting...
lsr a ; FEB4 4A shifting...
lsr a ; FEB5 4A shifting
jsr Output ; FEB6 20 CA FE ..
lda MonitorMemLocLow2,x ; FEB9 B5 FC Zero Page,X
jsr Output ; FEBB 20 CA FE ..
dex ; FEBE CA .
bpl LoopFEB0 ; FEBF 10 EF ..
lda #$20 ; FEC1 A9 20 .
sta ScreenSpace1 ; FEC3 8D CA D0 the first space between the address and the data on the screen
sta ScreenSpace2 ; FEC6 8D CB D0 the second space between the address and the data on the screen
rts ; FEC9 60 return
; ----------------------------------------------------------------------------
Output:
and #$0F ; FECA 29 0F
ora #$30 ; FECC 09 30
cmp #$3A ; FECE C9 3A
bmi ExitFED5 ; FED0 30 03
clc ; FED2 18
adc #$07 ; FED3 69 07
ExitFED5:
sta ScreenOut,y ; FED5 99 C6 D0 Output to screen
iny ; FED8 C8
rts ; FED9 60 return
; ----------------------------------------------------------------------------
ShiftAndRoll:
ldy #$04 ; FEDA A0 04 Prep for LoopFEE0, below
asl a ; FEDC 0A Move Low Nibble into High Nibble
asl a ; FEDD 0A .
asl a ; FEDE 0A .
asl a ; FEDF 0A .
LoopFEE0: ; Loop 4 times. I think This will restore A, but its rolling the key nibbles into the target address in the monitor
rol a ; FEE0 2A Target is Accum. The Carry is shifted into bit 0 and the original bit 7 is shifted into the Carry
rol MonitorMemLocLow2,x ; FEE1 36 FC Target is Byte at Zero Page, X
rol MonitorMemLocFD,x ; FEE3 36 FD Target is Byte at Zero Page, X
dey ; FEE5 88 Y = Y-1
bne LoopFEE0 ; FEE6 D0 F8 branch 4 times
rts ; FEE8 60 return
; ----------------------------------------------------------------------------
SubFEE9:
lda KbdFlag ; FEE9 A5 FB check KbdFlag, non-zero means ignnore keyboard, continue loading from ACIA
bne LFE7E ; FEEB D0 91 not zero, so...... branch
GetKeybdChar:
jmp GetAsciiKeySub ; FEED 4C 00 FD
; ----------------------------------------------------------------------------
DeadCode: ; nothing jumps to here, this might be dead code
lda #$FF ; FEF0 A9 FF
sta Keyboard ; FEF2 8D 00 DF POKE Keyboard all rows
lda Keyboard ; FEF5 AD 00 DF read which key was pressed
rts ; FEF8 60 return
; ----------------------------------------------------------------------------
; data
.byte $EA ; FEF9 EA
.byte $30 ; FEFA 30 $0130
.byte $01 ; FEFB 01
MonitorWarmStartVector:
.byte $00 ; FEFC 00 $FE00
.byte $FE ; FEFD FE
.byte $C0 ; FEFE C0 $01C0
.byte $01 ; FEFF 01
; ================================ PAGE 1 ====================================
; this subroutine resets the disk PIA, and waits for track 0, sector 0 to be under the read head
; then reads 3 bytes from the start of the track; BufferHigh, BufferLow, NumPagesToLoad (1 page = 256 Bytes)
; when routine returns, Data is stored at address pointed to by $FD, FE and the # of pages read is in $FF
; there doesnt seem to be any error recovery code in this, so if there is a read error or a media error
; or whatever, the computer will just hang.
ReadFromPIA:
ldy #$00 ; FF00 A0 00 Y = 0
sty DiskPIA1 ; FF02 8C 01 C0 ;$C001 = #0; select DDRA.
sty DiskPIA0 ; FF05 8C 00 C0 ;$C000 = #0; 0's in DDRA indicate input.
ldx #$04 ; FF08 A2 04 X = 4
stx DiskPIA1 ; FF0A 8E 01 C0 ;$C001 = #4; select DRA. Any LDA's from $COOO will read data from DRA
sty DiskPIA3 ; FF0D 8C 03 C0 ;$C003 = #0; select DDRB
dey ; FF10 88 Y = $FF (tricky way to do LDY #$FF)
sty DiskPIA2 ; FF11 8C 02 C0 ;$C002 = #FF; 1's in DDRB indicate output.
stx DiskPIA3 ; FF14 8E 03 C0 ;$C003 = #4; select DRB, Any LDA's from $COO2 will read data from DRA
sty DiskPIA2 ; FF17 8C 02 C0 ;$C002 = #FF 1's in DDRB indicate output
lda #$FB ; FF1A A9 FB A = 251 Load Immediate Value
bne SkipToFF27 ; FF1C D0 09
LoopFF1E:
lda #$02 ; FF1E A9 02
bit DiskPIA0 ; FF20 2C 00 C0 Read Disk Status. sets the Z flag as though the value in the address tested were ANDed with the accumulator.
; The S and V flags are set to match bits 7 and 6 respectively in the value stored at the tested address.
beq SkipToFF41 ; FF23 F0 1C
lda #$FF ; FF25 A9 FF A = #$FF
SkipToFF27:
sta DiskPIA2 ; FF27 8D 02 C0 DiskPIA2 = #$FF
jsr EmptySub ; FF2A 20 99 FF returns immediately
and #$F7 ; FF2D 29 F7 Clear high bit in A
sta DiskPIA2 ; FF2F 8D 02 C0 DiskPIA2 = contents of A
jsr EmptySub ; FF32 20 99 FF returns immediately
ora #$08 ; FF35 09 08 A = A | #08
sta DiskPIA2 ; FF37 8D 02 C0 DiskPIA2 = contents of A
ldx #$18 ; FF3A A2 18 X = #$18 (#24)
jsr EORSomeBytes ; FF3C 20 85 FF EOR 24 bytes, with delay between exch byte, Address to EOR is at $FF
beq LoopFF1E ; FF3F F0 DD
SkipToFF41:
ldx #$7F ; FF41 A2 7F
stx DiskPIA2 ; FF43 8E 02 C0 DiskPIA2 = #$FF
jsr EORSomeBytes ; FF46 20 85 FF
LoopFF49:
lda DiskPIA0 ; FF49 AD 00 C0 reading status from $C000
bmi LoopFF49 ; FF4C 30 FB tight loop waiting for DiskPIA0 to go positive
LoopFF4E:
lda DiskPIA0 ; FF4E AD 00 C0 reading status from $C000
bpl LoopFF4E ; FF51 10 FB tight loop waiting for PIA0 to go negative
; setup floppy ACIA
lda #$03 ; FF53 A9 03 Master Reset the chole ACIA chip
sta ACIA10 ; FF55 8D 10 C0 ACIA10 = #3
lda #$58 ; FF58 A9 58 Selects 8 bits, even parity, 1 stop bit. Disables transmit interrupt logic. Disables receive interrupt logic.
sta ACIA10 ; FF5A 8D 10 C0 ACIA10 = #88
jsr LoadAByteFromDisk ; FF5D 20 90 FF Grab a byte from the ACIA (returned in A)
sta $FE ; FF60 85 FE Store byte at BufferHigh (Buffer pointed to at $FD,FE)
tax ; FF62 AA save the high byte of our buffer in X for a while
jsr LoadAByteFromDisk ; FF63 20 90 FF Grab a byte from the ACIA (returned in A)
sta $FD ; FF66 85 FD Store byte at BufferLow (Buffer pointed to at $FD,FE)
jsr LoadAByteFromDisk ; FF68 20 90 FF Grab a byte from the ACIA (returned in A)
sta $FF ; FF6B 85 FF Store byte at $FF (Number of 256 byte Pages to Load)
ldy #$00 ; FF6D A0 00 ..
ReadAPage:
jsr LoadAByteFromDisk ; FF6F 20 90 FF Grab a byte from the PIA (returned in A)
sta (MonitorMemLocFD),y ; FF72 91 FD Store byte Read into buffer pointed to by $FD,FE... previously set up
iny ; FF74 C8 Y counter
bne ReadAPage ; FF75 D0 F8 byte Loop..Get next byte (256 bytes)
inc $FE ; FF77 E6 FE make our buffer point to next page
dec $FF ; FF79 C6 FF decrement # of pages to load
bne ReadAPage ; FF7B D0 F2 Page Loop... get next page, stop at
; Done Loading
stx $FE ; FF7D 86 FE restore the original high byte of our buffer.
lda #$FF ; FF7F A9 FF A = -1
sta DiskPIA2 ; FF81 8D 02 C0 I think this stops the PIA from importing
rts ; FF84 60 return
; ----------------------------------------------------------------------------
; This sub eor's all the bytes from ($FF),X
EORSomeBytes: ; Contents of X Register contains number of bytes to EOR
ldy #$F8 ; FF85 A0 F8 Y = #$F8
DelayFF87:
dey ; FF87 88 Y = Y-1
bne DelayFF87 ; FF88 D0 FD Loop until zero, presumably taking time
eor MonitorMemLocHigh,x ; FF8A 55 FF EOR the byte that is at $FF-X
dex ; FF8C CA X = X-1
bne EORSomeBytes ; FF8D D0 F6 Loop back up to the start, and do it all again for X-1
rts ; FF8F 60 return
; ----------------------------------------------------------------------------
LoadAByteFromDisk: ; check $C010 register for a $80 flag, loop until flag is raised
lda ACIA10 ; FF90 AD 10 C0 A = contents of $C010
lsr a ; FF93 4A roll the high bit into the carry
bcc LoadAByteFromDisk ; FF94 90 FA still clear? load it again
lda PIA11 ; FF96 AD 11 C0 flag raised, new data, pull it out now. A = contents of $C011 register
EmptySub:
rts ; FF99 60 return
; ----------------------------------------------------------------------------
BootPrompt:
.byte $48 ; FF9A 2F H
.byte $2F ; FF9B 2F /
.byte $44 ; FF9C 44 D
.byte $2F ; FF9D 2F /
.byte $4D ; FF9E 4D M
.byte $3F ; FF9F 3F ?
; *************************************************************************************************************
ResetEntry:
;clear the screen
cld ; FFA0 D8 Clear Decimal Flag
ldx #$D8 ; FFA1 A2 D8 X = #$D8
lda #$D0 ; FFA3 A9 D0 A = #$D0
sta ScreenBaseHigh ; FFA5 85 FE $FE = #$D0
ldy #$00 ; FFA7 A0 00 Y = 0
sty ScreenBaseLow ; FFA9 84 FD ScreenBaseLow = #$00
lda #$20 ; FFAB A9 20 blank char
LoopFFAD:
sta (ScreenBaseLow),y ; FFAD 91 FD 16bit address stored at $00FD(low) and $00FE(high), then add y (Indirect Indexed)
; Stores #$20 (space) at $D000 + Y (This erases the screen)
iny ; FFAF C8 Y = Y+1
bne LoopFFAD ; FFB0 D0 FB Branch until an entire 256 bytes are stored
inc ScreenBaseHigh ; FFB2 E6 FE $00FE = $00FE+1 $D0->$D1->$D2->$D3->...$D7
cpx ScreenBaseHigh ; FFB4 E4 FE compare with #$D8
bne LoopFFAD ; FFB6 D0 F5 Loop until we reach $D800
; done clearing the screen
; Y should be zero at this point
lda #$03 ; FFB8 A9 03 both lower bits set to 1; (0000 0011)
sta ACIAControl ; FFBA 8D 00 FC $FC00 = 3
lda #$B1 ; FFBD A9 B1 A = #$B1; (1011 0001)
sta ACIAControl ; FFBF 8D 00 FC $FC00 = B1
LoopFFC2:
lda BootPrompt,y ; FFC2 B9 9A FF
bmi LFFD5 ; FFC5 30 0E
sta ScreenOut,y ; FFC7 99 C6 D0 ... H, /, D, /, M, ?
ldx $FE01 ; FFCA AE 01 FE X = contents of $FE01, holds a $28
bne LFFD2 ; FFCD D0 03
jsr LFE0B ; FFCF 20 0B FE WHAT IS HAPPENING HERE???? Jumps into Mid Instruction
LFFD2: iny ; FFD2 C8
bne LoopFFC2 ; FFD3 D0 ED
LFFD5: lda $FE01 ; FFD5 AD 01 FE Y = contents of $FE01, holds a $28
bne WaitForInput ; FFD8 D0 05
jsr MonitorWarmStart ; FFDA 20 00 FE
bcs LFFE2 ; FFDD B0 03
; Respond to H/D/M? prompt
WaitForInput:
jsr GetKeybdChar ; FFDF 20 ED FE Input an ASCII character from keyboard
LFFE2: cmp #$48 ; FFE2 C9 48 "H" Key Pressed?
beq BootHardDisk ; FFE4 F0 0A
cmp #$44 ; FFE6 C9 44 "D" Key Pressed?
bne BootMonitor ; FFE8 D0 0C Not D, it must be M, really? Any key except QUOKLN will enter the Monitor
BootFloppy:
jsr ReadFromPIA ; FFEA 20 00 FF Read Track Zero from the Floppy Drive. $FD, FE point to where data was loaded. $FF contains number of 256 byte pages that were loaded
jmp StartOS65D ; FFED 4C 00 22 Hard jump to $2200. Its a good thing that that is where track 0 was loaded to.... because, track zero *can* specify a different location!!!
BootHardDisk:
jmp GetAsciiKeySub ; FFF0 4C 00 FD
jsr ReadFromPIA ; FFF3 20 00 FF
BootMonitor:
jmp (MonitorWarmStartVector) ; FFF6 6C FC FE Jumps to $FE00
; ----------------------------------------------------------------------------
; data
.byte $EA ; FFF9 EA
NMIVector:
.byte $30 ; FFFA 30 $0130
.byte $01 ; FFFB 01
ResetVector:
.byte $A0 ; FFFC A0 $FFA0
.byte $FF ; FFFD FF
BreakVector:
.byte $C0 ; FFFE C0 $01C0
.byte $01 ; FFFF 01
/Jeff

-
- Posts: 356
- Joined: Wed Mar 16, 2011 1:49 am
- Location: New Zealand
Re: Decoding the startup boot process of the C4P/MF
; page 400 ROM BASIC Support for a C1 / Superboard $FC00 ??
; page 500 keypoller maps to $FD00 for a C1 / Superboard
; page 600 monitor maps to $FE00 for a C1 / Superboard
; page 700 'D/C/W/M' maps to $FF00 for a C1 / Superboard
LDX $FE01 ; FFCA AE 01 FE X = contents of $FE01, holds a $28 ; Serial MON has 00, ;OS65D checks this location for serial system
BNE LFFD2 ; FFCD D0 03 always ! X= $28 on C1 / Superboard
.BYTE $20,$0B,$FE ; hang over from other prom ?
(jsr LFE0B ; FFCF 20 0B FE WHAT IS HAPPENING HERE???? Jumps into Mid Instruction)
Great work Jeff.
; page 500 keypoller maps to $FD00 for a C1 / Superboard
; page 600 monitor maps to $FE00 for a C1 / Superboard
; page 700 'D/C/W/M' maps to $FF00 for a C1 / Superboard
LDX $FE01 ; FFCA AE 01 FE X = contents of $FE01, holds a $28 ; Serial MON has 00, ;OS65D checks this location for serial system
BNE LFFD2 ; FFCD D0 03 always ! X= $28 on C1 / Superboard
.BYTE $20,$0B,$FE ; hang over from other prom ?
(jsr LFE0B ; FFCF 20 0B FE WHAT IS HAPPENING HERE???? Jumps into Mid Instruction)
Great work Jeff.
600RevB:16K,2MHz,64x32,470,CEGMON
SuperKit:502,540B,542B,CEGMON, 8" and 5" FDDs
Cards:PE IO,6522 D-A-D, AY3-8910,ProgramGraphics,Color,UK101
WIP:HexDOS,FDD Emulator
SuperKit:502,540B,542B,CEGMON, 8" and 5" FDDs
Cards:PE IO,6522 D-A-D, AY3-8910,ProgramGraphics,Color,UK101
WIP:HexDOS,FDD Emulator