Here is my first cut for the Challenger slave portion.
Code: Select all
;
; IMG2DISK FOR OSI
; Version 0.1
; Jeff Ferguson
; June 2015
;
; Requires DOS loaded at $2200 - $3200
;
;
.setcpu "6502"
; hardware locations
ACIAControl := $FC00 ; ON A C4PMF
ACIAData := $FC01 ; ON A C4PMF
DiskPIA := $C000 ; DISK CONTROLLER
ExitVector := $FFFC ;
; locations of DOS variables and params
PagesToWrite := $265F
SectorToWrite := $265E
TrackToWrite := $2662
DriveToWrite := $265C
WriteBufferHi := $2661
WriteBufferLo := $2660
; callable DOS functions
WriteSector := $27D7
MoveToSector := $28C4
MoveToTrack := $26A6
LoadHead := $2754
LiftHead := $2761
CR := $0D
LF := $0A
IMGCMD := $49
EXITCMD := $45
ATTN := $2A
zpPages := $F0
zpBufferHi := $F2
zpBufferLo := $F1
DataBuffHi := $40
DataBuffLo := $00
; ----------------------------------------------------------------------------
.ORG $0400
; ----------------------------------------------------------------------------
Enter:
JSR SendInlineBytesToHost
.BYTE CR,LF
.BYTE "OSI CLIENT v0.1",CR,LF,CR,LF,CR,LF,CR,LF
.BYTE "READY",CR,LF,0
@ready:
JSR GetCommand
LDA CommandIn
BEQ @ready
CMP #IMGCMD ;Host is sending an Image
BEQ @handleImage
CMP #EXITCMD ;Host is done talking
BEQ @handleExit
JMP @ready
@handleImage:
JSR LoadImage
JMP @ready
@handleExit:
Quit:
JMP (ExitVector)
; ----------------------------------------------------------------------------
LoadImage:
LDA PagesIn
STA zpPages ; page count
LDA #DataBuffHi ; buffer high
STA zpBufferHi ; vector high
LDA #DataBuffLo ; buffer low
STA zpBufferLo ; vector low
LDY #$0 ; y counter
@loop:
JSR GetByteFromHost
STA (zpBufferHi),Y
INY
BNE @loop
INC zpBufferLo
DEC zpPages
BNE @loop
SaveImage:
; Place Head on Disk
JSR LoadHead
; Move to Track TRACK
LDA TrackIn
STA TrackToWrite ; Track needs to be in decimal
LDA #$0 ; Drive Number
STA DriveToWrite
JSR MoveToTrack ; Move Head To Track
; Move to Sector SECTOR
LDA SectorIn
STA SectorToWrite
JSR MoveToSector
; Write Sector (Pages count??)
LDA #DataBuffLo
STA WriteBufferLo
LDA #DataBuffHi
STA WriteBufferHi
LDA SectorIn
STA SectorToWrite
LDA PagesIn
STA PagesToWrite
JSR WriteSector
; Lift Head
JSR LiftHead
JSR SendInlineBytesToHost
.BYTE "DONE",CR,LF,0
RTS
; ----------------------------------------------------------------------------
; Looks for Byte stream '***ITSP'
; Sets CommandIn to 0 or 'I', 0 = No Cmd
; Sets TrackIn to T
; Sets SectorIn to S
; Sets PagesIn to P
;
GetCommand:
LDA #$0
STA CommandIn ; store 'not found result'
JSR GetByteFromHost
CMP #ATTN ;*
BNE @done
JSR GetByteFromHost
CMP #ATTN ;*
BNE @done
JSR GetByteFromHost
CMP #ATTN ;*
BNE @done
JSR GetByteFromHost
CMP #IMGCMD ;I
BNE @done
STA CommandIn ; store a non-zero command ('I')
JSR GetByteFromHost
STA TrackIn ; read Track
JSR GetByteFromHost
STA SectorIn ; read Sector
JSR GetByteFromHost
STA PagesIn ; read Pages
@done:
RTS
; ----------------------------------------------------------------------------
; Load a byte from the ACIA
; Result is in A
GetByteFromHost:
@loop:
LDA ACIAControl ; ACIA Status Register
LSR A ; Is there a byte ready to be read in the read register?
BCC @loop ; loop to read again
LDA ACIAData ; read a byte from ACIA Data Register
RTS ; return
; --------------------------------------------------------
; Send a null terminated bunch of bytes to the ACIA
; the bytes follow the originating JSR op-code that called us
SendInlineBytesToHost:
PLA ; get address of bytes on the stack
STA zpBufferHi ; - just happens to be our return address!
PLA ;
STA zpBufferLo
LDY #1 ; init Y
@loop:
LDA (zpBufferHi),Y
BEQ @exit ; exit if byte is 0 (string terminator)
JSR PutByteToHost
INY
BNE @loop
@exit:
TYA ; how many bytes we did
SEC ; prepare for add
ADC zpBufferHi ; add Y to our return address
STA zpBufferHi ; and store it
BCC @out ; no carry...just jmp
INC zpBufferLo ; add the carry
@out:
JMP (zpBufferHi) ; return to caller....following the inline bytes
; ----------------------------------------------------------------------------
; Save a byte to the ACIA
; byte to put is in A
PutByteToHost:
JSR SerialPortOut ; serial port output
RTS
; ----------------------------------------------------------------------------
; Save a byte to the ACIA
; byte to output is in A
SerialPortOut:
PHA ; save A
@checkStatus:
LDA ACIAControl ; load ACIA Status register to see if a byte is ready to be read
AND #$02 ; check the TDRE, bit 2... 1 indicates data register is still full
BNE @checkStatus ; not sent yet, loop until its gone
PLA ; restore A
STA ACIAData ; send it on its way
PHA ; save A
LDA #$04 ; waste 4 bunches of time
JSR Delay ; waste a bunch of time
PLA ; restore A
RTS ; return to caller
; ----------------------------------------------------------------------------
; A contains length of delay
Delay: ; start a delay loop
STA DelayCount
@loop:
DEC DelayCount
CMP DelayCount
BNE @loop
RTS
; ----------------------------------------------------------------------------
; Variable Storage
CommandIn: .byte 0
TrackIn: .byte 0
SectorIn: .byte 0
PagesIn: .byte 0
DelayCount: .byte 0
; ============================================================================
.END
If there are any 6502 assembly guru's out there with spare brain cycles and would like to improve the code, feel free, and re-post your changes. If we crowd-code, maybe it will happen sooner!
/Jeff