<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="chrome=1">

<!-- Begin Jekyll SEO tag v2.3.0 -->
<title>SJLOAD/SJLOAD.ASM | dtvwiki</title>
<meta property="og:title" content="SJLOAD/SJLOAD.ASM" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="http://pelrun.github.io/dtvwiki" />
<meta property="og:description" content="http://pelrun.github.io/dtvwiki" />
<link rel="canonical" href="https://pelrun.github.io/dtvwiki/SJLOAD/SJLOAD.ASM" />
<meta property="og:url" content="https://pelrun.github.io/dtvwiki/SJLOAD/SJLOAD.ASM" />
<meta property="og:site_name" content="dtvwiki" />
<script type="application/ld+json">
{"name":null,"description":"http://pelrun.github.io/dtvwiki","author":null,"@type":"WebPage","url":"https://pelrun.github.io/dtvwiki/SJLOAD/SJLOAD.ASM","image":null,"publisher":null,"headline":"SJLOAD/SJLOAD.ASM","dateModified":null,"datePublished":null,"sameAs":null,"mainEntityOfPage":null,"@context":"http://schema.org"}</script>
<!-- End Jekyll SEO tag -->

    <link href='https://fonts.googleapis.com/css?family=Arvo:400,700,400italic' rel='stylesheet' type='text/css'>
    <link rel="stylesheet" href="/dtvwiki/assets/css/style.css?v=adbbdc321411e7a450a3d5dffd9c6fbf1e725d98">
    <script src="/dtvwiki/assets/js/scale.fix.js"></script>
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
    <!--[if lt IE 9]>
    <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->
  </head>
  <body>
    <div class="wrapper">
      <header>
        <h1 class="header">dtvwiki</h1>
        <p class="header">http://pelrun.github.io/dtvwiki</p>

        <ul>
          
          <li><a class="buttons github" href="https://github.com/pelrun/dtvwiki">View On GitHub</a></li>
        </ul>

        
          <p class="header">This project is maintained by <a class="header name" href="https://github.com/pelrun">pelrun</a></p>
        

        
      </header>

      <section>
        <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>; SJLOAD - C64 floppy speeder and disk utility
; based on VDOS by Edward Carroll 1986
; modified for Jiffy compatibility by 1570 in 2008

; todo
;  move core routines above $e000 instead of $cb00
;  much cleanup

; xa65 assembler format

; Usage:
; LOAD"!*PROGRAM",8,1 - autostart VDOS, fastload PROGRAM
; LOAD"!",8 RUN - save autostarting VDOS to (new) disk
; VERIFY - send commands, read floppy status
; VERIFY"$" - display directory

; VDOS uses memory at CB00 and therefore limits length
; of programs loaded to basic start to about 195 blocks.

    .word $031a
    * = $031a

; BASIC header SYS 2169 ($0879)
; In case this gets loaded to BASIC start (,8)
; Will overwrite IOPEN, ICLOSE, ICHKIN, ICHKOUT,
; ICLRCH, IBASIN vectors otherwise
firstbyte:
    .byt $0b,$08,$d8
    .byt $07,$9e,$32
    .byt $31,$36,$39
    .byt $00,$00,$00

; IBASOUT/CHROUT vector ($0326)
    .word autostart
; ISTOP ($0328)
    .word $f6ed
; IGETIN ($032A)
    .word $f13e
; ICLALL ($032C)
    .word $f32f
; USRCMD ($032E)
    .word $fe66
; ILOAD ($0330)
iload:  .word $f4a5
; ISAVE ($0332)
    .word $f5ed

; $DD00 bits
; 0..1 VIC bank
; 2 RS-232 TXD Ausgang, User PA 2
; 3..5 IEC OUT. 0=High/Inactive, 1=Low/Active.
; 3 ATN OUT
; 4 CLOCK OUT
; 5 DATA OUT
; 6..7 IEC IN. 0=Low/Active, 1=High/Inactive.
; 6 CLOCK IN
; 7 DATA IN 

autostart:
    jsr $fd15   ; restore kernal vectors
    sei
    lda #$30
    sta $01
l33c    ldy #$00
l33e    lda da80code,y
l341    sta $da80,y
    iny
    bne l33e
    inc l33e+2
    inc l341+2
    lda l341+2
    cmp #$e0
    bne l33c
    lda #$00
    sta $0800   ; remove garbage in $0800 confusing RUN
l359    jsr ldace   ; install helpers, display message
    jsr $a533   ; rechain basic lines
    lda $22
    clc
    adc #$02
    sta $2d
    lda $23
    adc #$00
    sta $2e
    jsr $a660   ; clear screen
    ldy $b7 ; number of characters in filename
    dey
    bne autoload    ; b.i. more than 1 character in filename
l374    jmp ($a002) ; basic warm start

autoload:
    dey
    sty $b7 ; number of characters in filename
    lda $bb
    clc
    adc #$02
    sta $bb ; advance filename pointer by two chars ("!*")
    bcc l385
l383    inc $bc
l385    lda #$01
    sta $b9 ; current sa
    lda #$a4
    pha
    lda #$7f
    pha
    jmp $e16f   ; load (will jump through iload)

; Code called by BASIC stub.
; Just copies everything to standard location and saves.
; Located at $0879.
l392    lda #$61
    sta $b9     ; Secondary address ($61 = SAVE)
    lda #$01
    ldx #&lt;filename
    ldy #&gt;filename
    jsr $ffbd   ; Set Filename
    ldy #$00
l3a1    lda $0801,y
    sta firstbyte+$0000,y
    lda $0901,y
    sta firstbyte+$0100,y
    lda $0a01,y
    sta firstbyte+$0200,y
    lda $0b01,y
    sta firstbyte+$0300,y
    lda $0c01,y
    sta firstbyte+$0400,y
    iny
    bne l3a1
l3c2    jsr $f3d5   ; Send Secondary Address
    lda #&lt;firstbyte
    sta $c1
    lda #&gt;firstbyte
    sta $c2     ; Set start address
    lda #&lt;$07ff ; TODO use proper end address
    sta $ae
    lda #&gt;$07ff
    sta $af     ; Set end address
    jsr $f60b   ; Save (without printing "SAVING")
    lda #$01
    sta $b7     ; Number of characters in filename
    jmp autostart

filename:
da80code = * + 1
    .byt $21

    * = $da80
lda80   jsr lda89   ; swap cb00.. and db00..
    jsr ldaf2   ; move helper to 02e1
    jmp lcd6a   ; display message, install load vector, exit

; swap cb00.. and db00..
lda89   php
    pha
    stx ldafe
    sty ldaff
    lda #$db
    sta ldaa7
    sta ldaae
    lda #$cb
    sta ldaab
    sta ldab2
    ldx #$05
    ldy #$00
ldaa5   ldaa7 = * + 2
    lda $db00,y
    pha
    ldaab = * + 2
    lda $cb00,y
    ldaae = * + 2
    sta $db00,y
    pla
    ldab2 = * + 2
    sta $cb00,y
    iny
    bne ldaa5
ldab6   inc ldaa7
    inc ldaae
    inc ldaab
    inc ldab2
    dex
    bne ldaa5
ldac5   ldx ldafe
    ldy ldaff
    pla
    plp
ldace = * + 1
    rts

; this code portion is relocatable and called both at $dace and $02e1
    * = $02e1
    clc
    .byt $24    ; bit $xx
; iload vector
vload:  sec
    sei
    pha
    lda $01
    sta $92
    lda #$30
    sta $01
    bcc vlnm
    jmp ldaec   ; swap cb00/db00, load/verify
vlnm:   jmp lda80   ; install helper, display message
l2f6    jsr lda89   ; swap cb00.. and db00..
    lda $92
    sta $01
    cli
    rts

    * = $daec
ldaec   jsr lda89   ; swap cb00.. and db00..
    jmp lcc05   ; load/verify

; move helper to 02e1
ldaf2   ldy #$1e
ldaf4   lda ldace,y
    sta $02e1,y
    dey
    bpl ldaf4
ldafd   rts


ldafe   .byt $00
ldaff   .byt $00

; db00
    * = $cb00
lcb00   rts
lcb01   ora $fd,x
listDir:
    bit $c5
    bvc listDir
    lda #$60
    sta $b9 ; current sa
    jsr $f3d5   ; Send Secondary Address
lcd96   lda $ba ; device number
    jsr $ffb4   ; Command Serial Bus TALK
    lda $b9 ; current sa
    jsr $ff96   ; Send SA After Talk
;   jsr lcd96 (was doubled in VDOS?)
    jsr ldgc
    jsr ldgc
lcb13   lda #$0d
    jsr $e10c   ; Output character
    lda #$0a
    jsr $e10c   ; Output character
    lda #$20
    jsr $e10c   ; Output character
    jsr ldgc
    jsr ldgc
    jsr ldgc
    tax
    jsr ldgc
    jsr $bdcd   ; output number in FAC
    lda #$20
    jsr $e10c   ; Output character
lcb2c   jsr ldgc
    beq lcb13
lcb31   ldy $d3
    cpy #$19
    bne lcb42
lcb37   cmp #$20
    beq lcb42
lcb3b   pha
    lda #$3a    ; ":"
    jsr $ffd2   ; chrout
    pla
lcb42   jsr $ffd2   ; chrout
    jmp lcb2c

; get serial byte (with error handling)
ldgc:   jsr $ffa5
    bit $90
    bvs lcb68
lcb4f   bit $91
    bpl readError
lcb53   bit $c5
    bvs lcb63
lcb57   bit $c5
    bvc lcb57
lcb5b   bit $c5
    bvs lcb5b
lcb5f   bit $c5
    bvc lcb5f
lcb63   tay
    rts

; read error channel
readError:
    jsr $aad7   ; output cr/lf
lcb68   jsr $ffab   ; untalk
    jsr $f642   ; in save (send LISTEN?)
lcb6e   jsr $aad7   ; output cr/lf
    jsr $ab3f   ; output format character
    lda $ba ; device number
    jsr $ffb4   ; talk
    lda #$6f
    jsr $ff96   ; send sa after talk
lcb7e   jsr $ffa5   ; handhake serial byte in
    jsr $ffd2   ; chrout
    cmp #$0d
    bne lcb7e
lcb88   jsr $ffab   ; untalk
    lda #$00
    sta $c6 ; number of chars in keyboard buffer
vExit:  ldx #$fb
    txs
    lda #&gt;$a473
    ldy #&lt;$a473 ; Restart BASIC ($a474)
    jmp returnOut

; send drive command
sendCmd:
    lda #$6f
    pha
    lda $ba ; device number
    jsr $ffb1   ; Command Serial Bus LISTEN
    pla
    jsr $ff93   ; Send SA After Listen
    ldy #$00
lcd4d   lda ($bb),y
    jsr $ffa8   ; handshake serial byte out
    iny
    cpy $b7 ; number of characters in filename
    bcc lcd4d
    jsr $ffae   ; unlisten
    jmp vExit

; load/verify
lcc05   lda #$37
    sta $01
    cli
    pla
load    sta $93     ; load/verify flag
    lda #$00
    sta $90     ; iec status
    lda $ba     ; device number
    bne cdn
    jmp $f713
cdn cmp #$03
    bne lload
    bcs lload
    jmp $f4af

; actual LOAD routine
lload   ldx $ba ; device number
    cpx #$01    ; device 1 (default)? Override with 8.
    bne vnstd
    ldx #$08
    stx $ba ; device number
vnstd:  lda $93 ; load/verify
    beq lnv ; b.i. load
    lda $b7 ; number of characters in filename
    bne vsc
    jmp readError
vsc:    ldy #$00
    lda ($bb),y ; file name
    cmp #$24
    bne sendCmd
    jmp listDir
lnv:    ldx $b7     ; length of filename
    bne lfnok
    lda #&gt;$f712
    ldy #&lt;$f712
    jmp returnOut   ; illegal device number ($f713)
lfnok   ldx $b9     ; secondary address
    jsr $f5af   ; searching for filename
    sei
    lda $d011
    and #$ef
    sta $d011   ; disable screen
ld1 lda $d011   ; wait for next screen
    bpl ld1
ld2 lda $d011
    bmi ld2
    lda #$60    ; sa for load
    sta $b9     ; secondary address
    jsr $f3d5   ; open file/open secondary address
    sei     ; $f3d5 does cli
    lda $ba     ; device number
    jsr ltalk   ; talk
    lda $b9     ; secondary address
    jsr lsendsa ; send sa
    jsr lgiecin ; iecin (get load address lo)
    sta $ae     ; load address lo
    lda $90     ; iec status
    lsr
    lsr
    bcc liecok
    lda #&gt;$f703
    ldy #&lt;$f703
    jmp returnOut   ; file not found ($f704)
liecok  jsr lgiecin ; iecin (get load address hi)
    sta $af     ; load address hi
    inc $b9     ; secondary address 61 = JD load
    jsr luntalk ; untalk
    lda $ba     ; device number
    jsr ltalk   ; talk
    lda $b9     ; secondary address
    jsr lsendsa ; send sa
    dec $b9     ; secondary address
    cpx #$00    ; original secondary address
    bne lloadabs2   ; branch if load absolute
    lda $c3     ; basic start lo
    sta $ae     ; load address lo
    lda $c4     ; basic start hi
    sta $af     ; load address hi
lloadabs2   jsr $f5d2   ; loading message
    ldy #$00
    ldx #$00
ljlw:   dex
    bne ljlw
lloadinnerloop:
    lda #$03
    sta $dd00   ; IEC lines inactive/high
lwch1   bit $dd00
    bvc lwch1   ; wait until 1541 sets clock inactive/high
    bmi lprocessdrivesignal ; branch if data inactive/high (some signal to process)
ltransferblock:
    bit $dd00
    bpl ltransferblock  ; wait until 1541 sets data inactive/high
ltransferbyte:
    nop     ; timing critical section
    nop
    nop
    nop
    lda #$03
    ldx #$23
    stx $dd00   ; data=active,clock=inactive,ATN=inactive
    bit $dd00
    bvc lloadinnerloop  ; branch if 1541 sets clock active (needs to load next block)
    nop
    sta $dd00   ; set data inactive
    lda $dd00   ; read bits 1/0
    nop
    lsr
    lsr
    eor $dd00   ; read bits 3/2
    bit $00     ; burn cycles
    lsr
    lsr
    eor $dd00   ; read bits 5/4
    bit $00     ; burn cycles
    lsr
    lsr
    eor $dd00   ; read bits 7/6
    eor #$03
    sta ($ae),y ; store byte
    inc $ae     ; load address lo
    bne ltransferbyte
    inc $af     ; load address hi
    jmp ltransferbyte
lprocessdrivesignal:
    ldx #$64
lwok1   bit $dd00
    bvc lend2   ; 1541 sets clock active/low: everything ok
    dex
    bne lwok1   ; wait for ok signal or timeout
    lda #$42    ; end, error
    .byt $2c
lend2   lda #$40    ; end, okay
    jsr $fe1c   ; set iec status ($90)
    jsr luntalk ; UNTALK
    jsr $f642   ; In Save (close file)
    bcc lend3
    lda #&gt;$f703
    ldy #&lt;$f703
    jmp returnOut   ; file not found ($f704)
lend3   lda #&gt;$f5a8
    ldy #&lt;$f5a8
    jmp returnOut   ; ok ($f509)



; TALK
ltalk   ora #$40
lsendb  sta $95 ; byte to send
    jsr $ee97   ; Set Data inactive
    cmp #$3f
    bne lca1
    jsr $ee85   ; Set Clock inactive
lca1    lda $dd00
    ora #$08
    sta $dd00   ; Set ATN active
; send IEC byte
lwiecs  jsr $ee8e   ; Set Clock active
    jsr $ee97   ; Set Data inactive
    jsr $eeb3   ; Delay 1 ms
    jsr $eea9   ; Data =&gt; Carry, Clock =&gt; M
    bcc lcont1  ; branch if data active
    lda #&gt;$edac
    ldy #&lt;$edac
    jmp returnOut   ; device not found ($edad)
lcont1  jsr $ee85   ; Set Clock inactive
lcont4  jsr $eea9   ; Data =&gt; Carry, Clock =&gt; M
    bcc lcont4  ; Wait until data inactive
    jsr $ee8e   ; Set Clock active
    txa
    pha     ; save X
    ldx #$08    ; 8 bits to send
lsendbits   nop
    nop
    nop
    bit $dd00
    bmi lcont5
    pla
    tax     ; restore X
    lda #&gt;$edaf
    ldy #&lt;$edaf
    jmp returnOut   ; timeout ($edb0)
lcont5  jsr $ee97   ; Set Data inactive
    ror $95 ; byte to send
    bcs lci1
    jsr $eea0   ; Set Data active
lci1    jsr $ee85   ; Set Clock inactive
    lda $dd00
    and #$df
    ora #$10
; send two bits
    sta $dd00
    and #$08
    beq ltwobitssent
    lda $95 ; byte to send
    ror
    ror
    cpx #$02
    bne ltwobitssent
    ldx #$1e
lwack1  bit $dd00
    bpl lwack2
    dex
    bne lwack1
    beq lcont6
lwack2  bit $dd00
    bpl lwack2
    ; when we are here JD is present in floppy
lcont6  ldx #$02
ltwobitssent:
    dex     ; other dex is above
    bne lsendbits   ; branch if still bits to send
    ldx #$56
lcont7: dex
    beq ltbtimeout
    lda $dd00
    bmi lcont7  ; wait until data active
ltbok:  pla
    tax     ; restore X
    rts
ltbtimeout:
    pla
    tax     ; restore X
    lda #&gt;$edaf
    ldy #&lt;$edaf
    jmp returnOut   ; Write timeout ($edb0)

; SEND SECONDARY ADDRESS
lsendsa sta $95 ; byte to send
    jsr lwiecs  ; send IEC byte
    lda #$23    ; Data active, ATN/clock inactive
    sta $dd00
lwca1   bit $dd00
    bvs lwca1   ; Wait until clock active
    rts

; UNTALK
luntalk lda $dd00
    ora #$08
    sta $dd00   ; Set ATN active
    jsr $ee8e   ; Set Clock active
    lda #$5f    ; UNTALK command
    jsr lsendb  ; send byte
    jsr $edbe   ; Clear ATN
    txa
    ldx #$0a
ll2 dex
    bne ll2
    tax
    jsr $ee85   ; Set Clock inactive
    jmp $ee97   ; Set Data inactive


; IECIN (jumped to from EE13)
lgiecin:
ll3 lda $dd00
    cmp #$40
    bcc ll3
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    lda #$03
    nop
    nop
    sta $dd00
    nop
    nop
    nop
    nop
    nop
    nop
    ora $dd00
    lsr
    lsr
    nop
    ora $dd00
    lsr
    lsr
    eor #$03
    eor $dd00
    lsr
    lsr
    eor #$03
    nop
    eor $dd00
    pha
    lda #$23
    bit $dd00
    sta $dd00
    bvc lend1
    bpl lerr1
    pla
    lda #$42
    jmp $edb2
lerr1   lda #$40    ; Too few bytes
    jsr $fe1c   ; In Control OS Messages 
lend1   pla
    clc
    rts

; return to vector in a/y+1
returnOut:
    pha
    tya
    pha
lcd27   sei
    lda $d011
    ora #$10
    sta $d011   ; enable screen
    lda #$30
    sta $01
    jsr ldaf2   ; move helper to 02e1
    jmp l2f6    ; swap cb00/db00, cli, exit

; display message, install load vector, exit
lcd6a   pla
    lda #$37
    sta $01
    sta $92
    lda #$00
    sta $d021
    lda #$06
    sta $d020
    lda #&lt;lcdac
    ldy #&gt;lcdac
    jsr $ab1e   ; output string
    lda #&lt;vload
    ldy #&gt;vload
    sta iload
    sty iload+1
    jmp lcd27   ; install 02xx helper, swap cb00/db00, exit

; Message
lcdac   .byt $93,$11,$9e
    .asc " SJLOAD 0.96 - 2009-10-03"
    .byt $0d,$00

    .byt $08
</code></pre></div></div>

      </section>

      <footer>
        <p><small>Hosted on <a href="https://pages.github.com">GitHub Pages</a> using the Dinky theme</small></p>
      </footer>
    </div>
    <!--[if !IE]><script>fixScale(document);</script><![endif]-->
    
  </body>
</html>
