
; Burst load in an entire FD 2000 disk image.
; 1998 by Todd S. Elliott
; Feel free to use, but please attribute it in some fashion.
; Optimized for the SCPU's SuperRAM and is only for version 2 boards
; should be simple to convert these routines for 1750XL REU's capable of
; snarfing in an entire FD 2000 disk image at once.
; Can read in an entire FD 2000 disk image in 3 minutes, 45 seconds.
; With some work, it can read in a FD 4000 disk image, but I have not
tried
; this yet, even though I do have a FD 4000 disk drive and some ED
floppies.
; I'm lazy. :)
; Possible uses for these routines include archival backup, compression,
; transfers between computers, defragmenters, etc.

; Equates
sb     = $11f0; start bank of exp. RAM
              ; The user must set this to a value that will not interfere
              ; with the system.
tr       = $fb; current track
se       = $fc; current sector
filename = $0400; buffer of 20 chars for the filename
grabpx = $0b00; temp buffer for the SuperRAM+Disk routines
errbuffer = filename+20; buffer of 30 characters for the command channel
ciasdr = $dc0c; burst serial data register
ciaicr = $dc0d; burst serial data byte register
ci2pra = $dd00; CIA #2 data ports A - Controls the 16k addressing range
of VIC
setbnk = $ff68; sets the source bank
setlfs = $ffba; set logical file channel
setnam = $ffbd; set filename
open   = $ffc0; opens a file
close  = $ffc3; closes a file
load   = 65493; loads a file
chkin  = $ffc6; defines an input channel
chkout = $ffc9; defines an output channel
clrchn = $ffcc; clears all channels and restores devices
chrin  = $ffcf; inputs a character
chrout = $ffd2; outputs a character

; for the CMDFD drive
burst'FD'image =*; gets a disk image and store it into SuperRAM
; When done, side 0 of the FD disk will be first in SuperRAM, and side 1
of
; the FD disk will follow, aligned on a bank boundary in SuperRAM.
; prep up the routine with prelim stuff.
  lda #$01
  sta se+2; get two sides of a FD disk
  lda #$00
  sta cmd'read+5; read side 0 of a FD disk
  lda #$00
  sta d2+2; set up high byte of destination page in destination bank
  lda sb; get start bank for destination transfers
  sta d1+1; SB must be set earlier to point to a valid start bank in
SuperRAM.
  jsr set'FD'params; sets up prelim variables
  jsr inquire'disk; issues the inquire disk function
 
new'cmd'track =*; issues a track command to read in an entire track
  jsr send'u0'cmd; issues BCIS command
  jsr burst'read'physical'sectors; reads in 1024 byte sectors

  cli
  lda #$0a; $14 if you want to read in a FD 4000 image - never tried
this.
  sta se; reset the sector count
  inc cmd'read+4; point it to the current track for the current burst
reading
  inc cmd'read+1; point it to the very next track for the burst read
routines
  dec tr; are we done with tracks 1-80 of a FD disk?
  bne new'cmd'track

  ldx se+2; get side counter
  dex
  bmi +
  jsr get'FD'syspart; get the FD system partition located at track 81

+ lda #16; read side 1 of the FD disk
  sta cmd'read+5
  lda #$00
  sta d2+2; set up high byte of destination page in destination bank
  inc d1+1; set up bank byte so that each disk side falls on a bank
boundary
  jsr set'FD'params; set up the variables for the other side of the FD
disk
  dec se+2; are we done with two sides?
  bpl new'cmd'track
  jsr close'command'channel
  jmp disk'error'check; and RTS

set'FD'params =*; sets up the parameters for the FD whole disk read
routine
  ldx #$00
  stx cmd'read+4; initial track
  inx
  stx cmd'read+3; set up the initial sector
  stx cmd'read+1; keep on reading in the next track
  lda #10; set up end of sector for the first half of disk image
  ; but change this to 20 for a FD 4000 disk - Never tried this before.
  sta cmd'read+2
  sta se; set up the initial sector read
  lda #80
  sta tr; set up the initial track read
  rts

get'FD'syspart =*; gets the FD system partition
; prep up the routine with prelim stuff.
  lda #$03; read only three sectors
  sta cmd'read+2; may be different if a FD 4000 disk is used.
  sta se

; issues a track command to read the system partition
  jsr send'u0'cmd
  jsr burst'read'physical'sectors
  cli
  rts

; saves the SuperRAM image into a .f20 file
save'f20 =*; for the FD 2000
; Since side 0 and side 1 are stored in SuperRAM in their respective
regions,
; this routine splices them together, storing side 0, track 1, side 1,
track
; 1, side 0, track 2, side 1, track 2, and so on into a sequential and
; understandable disk image file. Due to its size, the file is split in
half.
  jsr set'imagename; give it a default filename

; these values are optimized for FD 2000 disks. Some changes are
necessary
; if one wanted to save FD 4000 disk images.
  lda #$01
  sta se; get two disk sides
  lda #$07
  sta se+1; move 2Kb of system partition info
  lda sb; get start bank in SuperRAM
  clc
  adc #12; save partition information first which is at sb+12+$8400
  sta d6+2
  lda #$84
  sta d5+2; set high byte of SuperRAM
- jsr getblox; fetches system partition info and saves it
  bpl -

  lda #$00
  sta d5+2; set the high byte of SuperRAM
  sta z2+2; set the high byte of SuperRAM
  lda sb
  sta d6+2; set start bank in SuperRAM
  clc
  adc #13; get offset for side 1 of the FD disk
  sta z3+2; and make it also a start bank in SuperRAM
lp1 =*
  lda #$80
  sta se+1
  lda #12
  sta se+2; move 12*65536+128*256 bytes

lp0 =*
  lda #39
  sta tr; move 40 sectors at a time
- jsr getblox; fetches the disk image data and saves it
  bne +
  dec se+2; get high byte as well
+ dec tr
  bpl -

  lda #39
  sta tr; reset the sector count
- jsr fetch'diskblock'too; get side 1
  ldy #$00
- lda grabpx,y; get the disk block data
  jsr chrout; and save it to disk
  iny
  bne -
  inc z2+2; get next page in SuperRAM
  bne +
  inc z3+2; get next bank in SuperRAM
+ dec se+1; decrement the disk block count
  bne +
  dec se+2; get high byte as well
  bmi ++
+ dec tr
  bpl --
  bne lp0; go back again

+ lda #$02
  jsr close
  jsr disk'error'check; check for an error, etc.
  beq +; check for an error
  rts; otherwise, abort.
+ dec se
  bmi +
  inc fd'image'name+5; put the next number in the image.fhd file
  jsr set'imagename
  jmp lp1
+ rts

send'u0'cmd =*; issues the u0 command
  ldx #$0f
  jsr chkout
  ldy #$07
- lda cmd'read,y
  jsr chrout; issues the U0 BCIS burst read command that the FD
understands
  dey
  bpl -
  jmp clrchn; and RTS

burst'read'physical'sectors =*; uses burst method to load in physical
sectors
                              ; in 1Kb chunks
; use burst serial routines
  sei; disable interrupts for maximum xfer rate
  bit ciaicr; clears the register by merely reading it
  jsr afrd; ack for req signal
read'physical'sector =*; for reading the next batch of bytes in a burst
sequence
  jsr get'burst'byte; gets the first byte to look for an error
  and #%00001111; get only the last four bits
  cmp #$02; check for error
  bcc +
  cli
  pla
  pla; clean up stack
  jmp burst'error; handle it
+ ldx #$03; 1024 byte sectors
  stx se+1
- ldy #$00
- jsr get'burst'byte
  sta grabpx,y; stores it for the SuperRAM routines
  iny
  bne -
  jsr stash'disk'block; stash the disk block into superRAM
  inc d2+2; increment the SuperRAM addy by a page
  bne +
  inc d1+1; increment high byte if necessary
+ dec se+1
  bpl --
  dec se
  bne read'physical'sector
  rts

set'imagename =*; sets the filename sequence for the save disk image
routine.
  lda #$02; LFN
  ldx dv
  tay; SA
  jsr setlfs
  lda #14; length
  ldx #<fd'image'name
  ldy #>fd'image'name
  jsr setnam
  ldx #$0f
  jsr setbnk
  jsr open
  ldx #$02
  jmp chkout

getblox =*; fetches a disk block of 256 bytes
  jsr fetch'disk'block
  ldy #$00
- lda grabpx,y;
  jsr chrout
  iny
  bne -
  inc d5+2; get next page in SuperRAM
  bne +
  inc d6+2; get next bank in SuperRAM
+ dec se+1; decrement the disk block count
  rts

inquire'disk =*; issues the inquire disk function command
; this routine is needed so a FD 2000 disk can be logged into for further
; BCIS activities.
  jsr open'command'channel
  jsr chkout
  ldy #$03
- lda burst'cmd,y; issues the inquire disk function
  jsr chrout
  dey
  bpl -
  jsr clrchn
  sei
  bit ciaicr
  jsr afrd; burst handshake
  jsr get'burst'byte
  cli
  and #%00001111; get rid of upper nybble
  cmp #$02; check for error
  bcc +
  pla
  pla; clean up stack
  jmp burst'error; and handle the error
+ rts

; Error checking routines
disk'error'check =*
  jsr open'command'channel
  jsr chkin; redirect input to device
  ldy #$00
- jsr chrin; gets a single byte, etc.
  sta errbuffer,y; stores it in error buffer
  iny
  cmp #13; <CR> detected?
  bne -
  dey
  lda #$00
  sta errbuffer,y; delimit it.
  jsr close'command'channel
; add code here to print out the error
; ---
; add code here to print out the error
  lda errbuffer; get the first digit
  asl:asl:asl:asl; get the digit
  sta errbuffer
  lda errbuffer+1; get the second digit
  and #%00001111; get rid of upper nybble
  ora errbuffer; combine the upper/lower nybbles
; .A will contain the error code.
  sec; indicate error
  rts

burst'error =*; checks for burst serial errors
; simplistic error checking.
  jsr close'command'channel
  lda #$ff
  sta errbuffer; indicate an error
  rts

;Opens the Command channel
open'command'channel =*
  lda #$0f; logical file number
  tay     ; secondary address
  ldx dv  ; current device number
  jsr setlfs
  lda #$00
  jsr setnam
  jsr open
  ldx #$0f; select the command channel for the following CHKIN or CHKOUT
  rts

close'command'channel =*
  jsr clrchn; restores default i/o
  lda #$0f; select the logical file number
  jmp close

get'burst'byte =*; taken from the Compute!'s 128 Programmer's Guide
  lda #$08
- bit ciaicr; wait for 8 bits to arrive over the burst serial bus
  beq -
afrd =*; ack for req protocol
  lda ci2pra
  eor #$10
  sta ci2pra; toggles theCLK line
  lda ciasdr; now, get the byte that was bursted earlier
  rts

stash'disk'block =*; stashes a disk block to SuperRAM
; Should be simple to convert these routines for the 1750XL REU's.
; now the block is at the grabpx area - move it to SuperRAM
  clc
.byte $fb; XCE command
.byte $c2,$30; REP #%00110000- turn on 16 bit regs and acc
.byte $8b; PHB instruction
.byte $a2
.word grabpx; LDX #grabpx- source addy for memory move
d2 .byte $a0,$00,$00; ldy #$0000- dest addy for memory move
.byte $a9,$ff,$00; lda #$00ff- move only 256 bytes
d1 .byte $54,$00,$00; MVN $00,$02- move from bank 0 to bank 2, etc.
.byte $ab; PLB instruction
.byte $e2,$30; SEP #%00110000- turn on 8 bit regs and acc
  sec
.byte $fb; XCE command- go back into emulation mode
  rts

fetch'disk'block =*; fetches a disk block from SuperRAM
  clc
.byte $fb; XCE command
.byte $c2,$30; REP #%00110000- turn on 16 bit regs and acc
d5 .byte $a2,$00,$00; LDX #$0000- source addy for memory move
.byte $a0
.word grabpx; ldy #grabpx- dest addy for memory move
.byte $a9,$ff,$00; lda #$00ff- move only 256 bytes
d6 .byte $54,$00,$00; MVN $00,$02- move from bank 0 to bank 2, etc.
.byte $e2,$30; SEP #%00110000- turn on 8 bit regs and acc
  sec
.byte $fb; XCE command- go back into emulation mode
  rts; and exits the routine

fetch'diskblock'too =*; fetches a disk block from SuperRAM
  clc
.byte $fb; XCE command
.byte $c2,$30; REP #%00110000- turn on 16 bit regs and acc
z2 .byte $a2,$00,$00; LDX #$0000- source addy for memory move
.byte $a0
.word grabpx; ldy #grabpx- dest addy for memory move
.byte $a9,$ff,$00; lda #$00ff- move only 256 bytes
z3 .byte $54,$00,$00; MVN $00,$02- move from bank 0 to bank 2, etc.
.byte $e2,$30; SEP #%00110000- turn on 8 bit regs and acc
  sec
.byte $fb; XCE command- go back into emulation mode
  rts; and exits the routine

;Data for the routines
cmd'read =*; the actual FD burst read command
.byte 13,1,10,1,0,64
.asc "0u"

burst'cmd =*; initializes the burst channel
.byte 13,4
.asc "0u"

fd'image'name =*; default FD disk image name
.asc "image0.fhd,p,w"

; end file fd2k loader

___________________________________________________________________
You don't need to buy Internet access to use free Internet e-mail.
Get completely free e-mail from Juno at http://www.juno.com/getjuno.html
or call Juno at (800) 654-JUNO [654-5866]

