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