Page 1 of 1

Decoding the startup boot process of the C4P/MF

Posted: Tue Jun 03, 2014 12:11 am
by Jeff
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

Re: Decoding the startup boot process of the C4P/MF

Posted: Tue Jun 03, 2014 2:54 am
by nama
Hi Jeff,
I just emailed you some disk images for OS65D 3.3 and 3.2 for the C2/C4.

Phil

Re: Decoding the startup boot process of the C4P/MF

Posted: Tue Jun 03, 2014 2:57 pm
by Jeff
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

Re: Decoding the startup boot process of the C4P/MF

Posted: Wed Jun 04, 2014 11:07 am
by MK14HAK
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 ?

Re: Decoding the startup boot process of the C4P/MF

Posted: Thu Jun 05, 2014 3:21 am
by Jeff
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

Re: Decoding the startup boot process of the C4P/MF

Posted: Thu Jun 05, 2014 3:28 am
by Jeff
Here is the disassembly so far...

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
 
Enjoy!

/Jeff

Re: Decoding the startup boot process of the C4P/MF

Posted: Thu Jun 05, 2014 8:09 am
by MK14HAK
; 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.