From acb@yoyo.cc.monash.edu.au Tue Dec  7 21:20:22 1993
Path: klaava!news.funet.fi!sunic!EU.net!howland.reston.ans.net!math.ohio-state.edu!uwm.edu!msuinfo!harbinger.cc.monash.edu.au!yoyo.cc.monash.edu.au!acb
From: acb@yoyo.cc.monash.edu.au (Andrew Bulhak)
Newsgroups: comp.sys.cbm
Subject: Source code: copying tape fastloaders to disk
Date: 7 Dec 1993 15:49:29 GMT
Organization: People in a Position to Know, Inc.
Lines: 283
Distribution: world
Message-ID: <2e28m9$gc4@harbinger.cc.monash.edu.au>
NNTP-Posting-Host: yoyo.cc.monash.edu.au
X-Newsreader: TIN [version 1.2 PL1]

	OK, here's something I hacked up recently. There is no nice
interface, but it works (and what's more, the business end has to fit
into the tape buffer).

	This program will read any tape written in the turbo-loader
format named ".DSL1.A" (which may or may not be named "DTAPE" as well; I
think it's some freezer-cartridge format) and write the contents to a
disk file (on device 8, drive 0, named "DCOPY.OUT"); then the program
will reset the C64 (the program being copied overwrites part of the
copying program).

	Since the UUEncoded binary is only a few lines, I have included
it here as well.


--
  Andrew Bulhak             |
  acb@yoyo.cc.monash.edu.au | "Parboiled are the lambs, that they may 
  Monash Uni, Clayton,      |  not be so crunchy and hard to eat."
  Victoria, Australia       |

----- SOURCE CODE FOLLOWS -----
	processor 6502
; 	dcopy.asm	Program for reading/copying
;			some fast-saved tape files
;	Author:		acb
;	Commenced:	20-11-1993
;	Platform:	Commodore 64
;	Tools used:	dasm 2.12, running on Linux
;
; dcopy is a short program for copying tape files in the
; ".DSL1.A" (or "DTAPE"?) fast-loader format to disk.
; This program loads the turbo loader, positioning the tape,
; reads the bulk of the file (using direct tape I/O) and
; writes it to disk, in nice bite-sized chunks.

	include	"kernel.inc"

; global defines

lfs_in	equ	32
lfs_out	equ	33

dev_tape equ	1
dev_disk equ	8

chksum	equ	$90	; address of XOR checksum work area

	org $0801	; room for a BASIC stub

; BASIC stub goes here

	dc $0b, $08, $66, $19, $9E, $32, $30, $36, $31, 0, 0, 0
	;jmp start	; jump to the start

start:

; set up what is necessary

; load the fastloader code, positioning tape as needed
; and allowing interesting stuff to be extracted

	lda	#lfs_in
	ldx	#dev_tape
	ldy	#$00	; relocate
	jsr	setlfs
	lda	#0
	jsr	setnam	; no name requested

	lda	#$00	; load, not verify
	ldx	#$00
	ldy	#$80	; load at $8000 (why not?)
	jsr	load

	lda	#$00	; make screen black, for debugging purposes
	sta	$d020
	sta	$d021

; now copy all the code to where it shall be safe
; assume that it is less than one page in size

	ldx	#<relocatable
	stx	$ac	; temporary
	ldy	#>relocatable
	sty	$ad
	ldx	#$34
	stx	$ae
	ldx	#$03
	stx	$af
	ldy	#$00

copy_loop1:
	lda	($ac),y
	sta	($ae),y
	ldx	$ac
	iny
	cpy	#<[reloc_end-reloc_start]
	bne	copy_loop1

copy_done:
	jmp	resume


relocatable:
	rorg	$0334

reloc_start:

; global variables go here

outname:
	dc	"@0:DCOPY.OUT"
outname_end:
	dc	0

; subroutines go here

; Subroutine getbyte, getbits
; 
; Reads a byte/several bits from the tape in the fast-loader format
;
; Input:
;	X:	#$19 (to be put into a register)
;	Y:	# of bits (getbits only)
;
; Output:
;	A:	byte/bits retrieved

getbyte:
	ldy	#$08	; byte = 8 bits, dig?
getbits:
getbit:	lda	#$10
inloop:	bit	$dc0d	; tape read IRQ triggered?
	beq	inloop	; no, wait until it is so.

	lda	$dd0d	; this stuff is copied verbatim
	stx	$dd0f	; from ".DSL1.A"; at time of writing
	lsr		; I do not claim to fully understand it.
	lsr		; but I think $bd accumulates bits
	ror	$bd
	inc	$d020	; do cheesy border flashing effect

	dey		; any more bits left to read
	bne	getbit	; if so, read them

	lda	$bd	; pick up our result ...
	rts		; ...and leave

resume:
; load the fast-saved file and write it to disk

; initialise the hardware; heavy wizardry begins here

	sei
	ldx	#$df	; cassette motor on
	stx	$01

	lda	#$80
	sta	$dd06	; timer B value = $0180
	ldy	#$01
	sty	$dd07
	ldx	#$00	; the meaning of these three lines is unknown.
	ldy	#$00	; It probably has something to do with timing,
	nop		; though.....
	ldx	#$19
	stx	$dd0f 

; handle the magic values
	
magic1:	ldy	#$09	; read 9 bits
	jsr	getbits
	cmp	#$02	; some magic code, I think.....
	bne	magic1

magic2:	jsr	getbyte
	cmp	#$02	; this magic works differently (?)
	beq	magic2	; (or maybe its some kind of sync code?)

	cmp	#$52
	bne	magic1

	jsr	getbyte
	cmp	#$42
	bne	magic1

; get file load address, size, etc.

; first, load address is acquired

	jsr	getbyte
	sta	$ac
	sta	$c1
	jsr	getbyte
	sta	$ad
	sta	$c2

	jsr	getbyte
	sta	$ae
	jsr	getbyte
	sta	$af
	ldy	#$00
	sta	$90		; clear checksum

; read the stuff into memory

readloop:
	jsr	getbyte

	sta	($ac),y		; write byte to memory
	eor	$90		; update checksum
	sta	$90

	ldy	$ac
	iny
	sty	$ac
	bne	foo
	ldy	$ad
	iny
	sty	$ad
foo:
	ldy	$ad
	cpy	$af
	bne	readloop
	ldy	$ac
	cpy	$ae
	bne	readloop

; read complete

; now check the checksum
	jsr	getbyte
	eor	$90
;	beq	check_ok
;	jmp	$fce2		; error!
check_ok:
	sta	$90

; now write the disk file

	lda 	#$fe		; stop motor, switch BASIC ROM out
	sta	$01		; (Ghod help us if the program extends
				; under the kernel ROM...)
	cli	
	lda	#lfs_out
	ldx	#8
	ldy	#255
	jsr	setlfs

	lda	#[outname_end-outname]
	ldx	#<outname
	ldy	#>outname
	jsr	setnam

	lda	#$c1		; offset of start location
	ldx	$ae
	;inx
	ldy	$af
	;iny
	jsr	save

; since vectors are munged and we have a fastloader routine
; sitting in memory, we might as well reset

	jmp	$fce2

reloc_end:
----- END OF SOURCE CODE -----

begin 644 dcopy.prg
M 0@+"&89GC(P-C$   "I(*(!H  @NO^I ""]_ZD H@"@@"#5_ZD C2#0C2'0
MHDR&K* (A*VB-(:NH@.&KZ  L:R1KJ:LR,#$T/5,70- ,#I$0T]062Y/550 
MH BI$"P-W/#[K0W=C@_=2DIFO>X@T(C0Z:6]8'BBWX8!J8"-!MV@ 8P'W:( 
MH #JHAF.#]V@"2!# \D"T/<@00/) O#YR5+0["!! \E"T.4@00.%K(7!($$#
MA:V%PB!! X6N($$#A:^@ (60($$#D:Q%D(60I*S(A*S0!:2MR(2MI*W$K]#E
MI*S$KM#?($$#19"%D*G^A0%8J2&B"*#_(+K_J0RB-* #(+W_J<&FKJ2O(-C_
#3.+\
 
end






