home *** CD-ROM | disk | FTP | other *** search
- ; diskreader.asm - essential functionality for game disk installers.
- ; © 1998-1999 Kyzer/CSG
-
- ; FILEMODE means that no output diskfile will be used, therefore WRITE is
- ; dropped - instead, SAVEF is used to write individual files
- IFND FILEMODE
- FILEMODE=0
- ENDC
-
- ; TRACKMODE means that all tracks are DOS tracks, so the user specifies
- ; the trackdisk-like device on the command line, and RAWREAD/RESYNC are
- ; dropped
- IFND TRACKMODE
- TRACKMODE=0
- ENDC
-
- ; MESSAGES means that each track read will print out its number for the
- ; user to see.
- IFND MESSAGES
- MESSAGES=0
- ENDC
-
- ; NO_INCLUDES means that no system includes are neccessary to use diskreader
- IFD NO_INCLUDES
- IO_COMMAND=28 ; from devices/trackdisk.i
- IO_FLAGS=30
- IO_LENGTH=36
- IO_DATA=40
- IO_OFFSET=44
- IOTD_SIZE=56
- CMD_READ=2
- TD_MOTOR=9
- TD_RAWREAD=16
- IOTDB_INDEXSYNC=4
- MODE_NEWFILE=1006 ; from dos/dos.i
- ERROR_NOT_A_DOS_DISK=225
- _LVOOpen=-30 ; from dos/dos_lib.i
- _LVOClose=-36
- _LVOWrite=-48
- _LVOIoErr=-132
- _LVOSetIoErr=-462
- _LVOPrintFault=-474
- _LVOReadArgs=-798
- _LVOFreeArgs=-858
- _LVOPutStr=-948
- _LVOVPrintf=-954
- _LVOCloseLibrary=-414 ; from exec/exec_lib.i
- _LVOOpenDevice=-444
- _LVOCloseDevice=-450
- _LVODoIO=-456
- _LVOOpenLibrary=-552
- _LVOCreateIORequest=-654
- _LVODeleteIORequest=-660
- _LVOCreateMsgPort=-666
- _LVODeleteMsgPort=-672
- ELSE
- include devices/trackdisk.i
- include dos/dos.i
- include dos/dos_lib.i
- include exec/exec_lib.i
- ENDC
-
- DOSTRACKLEN=512*11
-
- BUFFER MACRO ; buffername
- \1 equ __trk
- ENDM
-
- FAILURE MACRO ; [reason]
- IFEQ NARG
- suba.l a0,a0
- ELSE
- lea \1,a0
- ENDC
- bra __fail
- ENDM
-
- IFEQ TRACKMODE
- RAWREAD MACRO ; track
- lea __trk,a0
- move.l \1,d0
- bsr __rawrd
- ENDM
- RESYNC MACRO ; wordsync
- lea __trk,a0
- move.l \1,d0
- bsr __sync
- ENDM
- ENDC
- DOSREAD MACRO ; track
- lea __trk,a0
- move.l \1,d0
- bsr __dosrd
- ENDM
-
- IFEQ FILEMODE
- WRITE MACRO ; length, [offset]
- IFEQ NARG-2
- lea __trk,a0
- add.l \2,a0
- ELSE
- lea __trk,a0
- ENDC
- move.l \1,d0
- bsr __write
- ENDM
- WRITEDOS MACRO ; track
- DOSREAD \1
- WRITE #DOSTRACKLEN
- ENDM
-
- ELSE
- SAVEF MACRO ; filename, buffer, length
- lea \1,a0
- lea \2,a1
- move.l \3,d0
- bsr __savef
- ENDM
- ENDC
-
- ;------------------------------------
-
- call macro
- jsr _LVO\1(a6)
- endm
-
- initstk macro ; stack_symbol, stackreg
- link \2,#\1
- move.l sp,a0
- .clr\@ clr.w (a0)+
- cmp.l a0,\2
- bne.s .clr\@
- endm
-
- stackf MACRO ; stack_symbol, stackelement_symbol, [size=4]
- IFND \1
- \1 set 0
- ENDC
- IFGE NARG-3
- \1 set \1-(\3)
- ELSE
- \1 set \1-4
- ENDC
- \2 equ \1
- ENDM
-
- ; create appropriate command line arguments based on FILEMODE/TRACKMODE
- IFNE FILEMODE
- IFNE TRACKMODE
-
- ; filemode on, trackmode on
- stackf stk, __unit
- stackf stk, __device
- __args=__device
- __nargs=2
- __tmpl macro
- dc.b "DEVICE/A,UNIT/N/A",0
- endm
-
- ELSE
-
- ; filemode on, trackmode off
- stackf stk, __unit
- __args=__unit
- __nargs=1
- __tmpl macro
- dc.b "UNIT/N/A",0
- endm
-
- ENDC
- ELSE
- IFNE TRACKMODE
-
- ; filemode off, trackmode on
- stackf stk, __unit
- stackf stk, __device
- stackf stk, __output
- __args=__output
- __nargs=3
- __tmpl macro
- dc.b "DISKFILE/A,DEVICE/A,UNIT/N/A",0
- endm
-
- ELSE
-
- ; filemode off, trackmode off
- stackf stk, __unit
- stackf stk, __output
- __args=__output
- __nargs=2
- __tmpl macro
- dc.b "DISKFILE/A,UNIT/N/A",0
- endm
-
- ENDC
- ENDC
-
- ; other variables used
-
- stackf stk, __rdargs ; returned by ReadArgs()
- stackf stk, __diskport ; replyport for diskio
- stackf stk, __diskio ; IORequest to trackdisk.device
- stackf stk, __outfh ; output filehandle (NULL in filemode)
- stackf stk, __initsp ; initial (sp): move to sp then rts to quit
- stackf stk, __reason ; ptr to textual reason for failure, or NULL
- stackf stk, execbase ; exec.library
- stackf stk, dosbase ; dos.library
-
- ;------------------------------------
-
- section diskreader,code
- link a5,#stk
- move.l 4.w,a6
- move.l a6,execbase(a5)
-
- ; no printable reason for failure, but start with errorcode
- ; incase we can't open DOS
-
- clr.l __reason(a5)
- moveq #100,d7
-
- ; open dos.library
- moveq #37,d0
- lea __dosnm(pc),a1
- call OpenLibrary
- move.l d0,dosbase(a5)
- beq .nodos
- move.l d0,a6
-
- ; read arguments on command line
- lea __templ(pc),a0
- move.l a0,d1
- lea __args(a5),a0
- move.l a0,d2
- REPT __nargs
- clr.l (a0)+
- ENDR
- moveq #0,d3
- call ReadArgs
- move.l d0,__rdargs(a5)
- beq .noargs
-
- ; create the output diskfile (unless FILEMODE)
- IFEQ FILEMODE
- move.l __output(a5),d1
- move.l #MODE_NEWFILE,d2
- call Open
- move.l d0,__outfh(a5)
- beq.s .nofile
- ENDC
-
- ; open trackdisk.device (or user-specified in TRACKMODE)
- move.l execbase(a5),a6
- call CreateMsgPort
- move.l d0,__diskport(a5)
- beq.s .noport
-
- move.l d0,a0
- moveq #IOTD_SIZE,d0
- call CreateIORequest
- move.l d0,__diskio(a5)
- beq.s .noio
-
- move.l d0,a1
- move.l __unit(a5),a0
- move.l (a0),d0
- IFNE TRACKMODE
- move.l __device(a5),a0
- ELSE
- lea __tdnm(pc),a0
- ENDC
- moveq #0,d1
- call OpenDevice
- tst.l d0
- bne.s .nodev
-
-
- ;--------------------------------------
- ; call and return from the main 'slave'
- bsr __main
- ;--------------------------------------
-
-
- ; if messages mode, advance to new line for clarity
- IFNE MESSAGES
- pea 10<<24 ; "\n\0\0\0"
- move.l sp,d1
- move.l dosbase(a5),a6
- call PutStr ; print a newline
- addq.l #4,sp
- ENDC
-
- ; turn off disk motor
- move.l __diskio(a5),a1
- move.w #TD_MOTOR,IO_COMMAND(a1)
- clr.l IO_LENGTH(a1)
- move.l execbase(a5),a6
- call DoIO
-
- ; close disk device
- move.l __diskio(a5),a1
- call CloseDevice
- .nodev move.l __diskio(a5),a0
- call DeleteIORequest
- .noio move.l __diskport(a5),a0
- call DeleteMsgPort
- .noport
-
- move.l dosbase(a5),a6
-
- ; close the output diskfile (if not FILEMODE)
- IFEQ FILEMODE
- move.l __outfh(a5),d1
- call Close
- .nofile
- ENDC
-
- ; free command-line arguments
- move.l __rdargs(a5),d1
- call FreeArgs
- .noargs
-
- ; print error message if ioerror - this includes NOT_A_DOS_DISK
- ; if a printable reason exists, use that as the head of the printed
- ; error message.
-
- moveq #0,d7 ; returncode = 0
- call IoErr
- move.l d0,d1
- beq.s 1$
- moveq #20,d7 ; returncode = 20
- 1$ move.l __reason(a5),d2
- call PrintFault
-
- ; close dos.library and go home
- move.l a6,a1
- move.l execbase(a5),a6
- call CloseLibrary
- .nodos move.l d7,d0
- unlk a5
- rts
-
-
- ; internal routine to print out track number - D0 = track
- IFNE MESSAGES
- __prtrk movem.l d0-d2/a0,-(sp)
- lea __msg(pc),a0
- move.l a0,d1
- move.l sp,d2 ; points at D0 on the stack
- move.l dosbase(a5),a6
- call VPrintf
- movem.l (sp)+,d0-d2/a0
- rts
- ENDC
-
- ; if TRACKMODE, then use a complete DOSREAD routine
-
- IFNE TRACKMODE
- ;------------------------------------
- ; a0 = buffer, d0 = track
- __dosrd move.l a6,-(sp)
- IFNE MESSAGES
- bsr.s __prtrk ; print track number in messages mode
- ENDC
- move.l __diskio(a5),a1
- move.w #CMD_READ,IO_COMMAND(a1)
- move.l #DOSTRACKLEN,d1
- mulu d1,d0 ; convert D0=track to D0=offset
- move.l d1,IO_LENGTH(a1) ; D1 = length
-
- move.l a0,IO_DATA(a1)
- move.l d0,IO_OFFSET(a1)
- move.l execbase(a5),a6
- call DoIO ; read disk part
- lea __ertrk(pc),a0 ; fail with "error reading track"
- tst.l d0 ; if DoIO fails
- bne.s __fail
- move.l (sp)+,a6
- rts
- ELSE
-
- ; if not TRACKMODE, merge the common parts of RAWREAD and DOSREAD
-
- ;------------------------------------
- ; a0 = buffer, d0 = track
- __dosrd move.l a6,-(sp)
- IFNE MESSAGES
- bsr.s __prtrk
- ENDC
- move.l __diskio(a5),a1
- move.w #CMD_READ,IO_COMMAND(a1)
- move.l #DOSTRACKLEN,d1
- mulu d1,d0 ; as above, D0 = offset, D1 = length
- move.l d1,IO_LENGTH(a1)
- bra.s __rdcom
-
- ;------------------------------------
- ; a0 = buffer, d0 = track
- __rawrd move.l a6,-(sp)
- IFNE MESSAGES
- bsr.s __prtrk
- ENDC
- move.l __diskio(a5),a1
- move.w #TD_RAWREAD,IO_COMMAND(a1)
- move.b #IOTDB_INDEXSYNC,IO_FLAGS(a1) ; just for fun...
- move.l #$7ffe,IO_LENGTH(a1) ; here length always is maximum
-
- __rdcom move.l a0,IO_DATA(a1)
- move.l d0,IO_OFFSET(a1)
- move.l execbase(a5),a6
- call DoIO ; error handling as above
- lea __ertrk(pc),a0
- tst.l d0
- bne.s __fail
- move.l (sp)+,a6
- rts
- ENDC
-
- ; FAIL will always quit out of the 'slave' and return to the main
- ; routine, whatever the location on the stack
-
- ;------------------------------------
- ; a0 = failure reason
- __fail move.l a0,d0
- beq.s .noreas
- move.l d0,__reason(a5)
- move.l dosbase(a5),a6
- move.l #ERROR_NOT_A_DOS_DISK,d1
- call SetIoErr
- .noreas move.l __initsp(a5),sp
- rts
-
- ; in FILEMODE, there is a SAVEF which saves a whole file with its own name.
-
- IFNE FILEMODE
- ;------------------------------------
- ; a0 = filename, a1 = buffer, d0 = length
- __savef movem.l d2-d4/a6,-(sp)
- move.l a0,d1
- move.l a1,d3 ; d3 = buffer
- move.l d0,d4 ; d4 = length
- move.l #MODE_NEWFILE,d2
- move.l dosbase(a5),a6
- call Open
- move.l d0,d1 ; d1 = filehandle
- move.l d3,d2 ; d2 = buffer
- move.l d4,d3 ; d3 = length
- move.l d0,d4 ; d4 = filehandle
- beq.s __fail
- call Write
- move.l d0,d3
- move.l d4,d1
- call Close
- tst.l d3
- bmi.s __fail
- movem.l (sp)+,d2-d4/a6
- rts
-
- ELSE
- ; off FILEMODE, you can only write to the diskfile
-
- ;------------------------------------
- ; a0 = buffer, d0 = length
- __write movem.l d2-d3/a6,-(sp)
- move.l a0,d2
- move.l d0,d3
- move.l __outfh(a5),d1
- move.l dosbase(a5),a6
- call Write
- tst.l d0
- bmi.s __fail
- movem.l (sp)+,d2-d3/a6
- rts
- ENDC
-
- ; RAW tracks need to be WORDSYNCed to be readable - this routine does that
-
- IFEQ TRACKMODE
- ;------------------------------------
- ; a0 = buffer d0 = sync
- __sync movem.l d2-d3,-(sp)
- move.l a0,a1
- move.w #($7ffe/2)-1,d2 ; search entire trackbuffer
- .nxtwrd moveq #16-1,d3 ; find a BIT distance...
- .nxtbit move.l (a0),d1 ; and a BYTE distance..
- lsr.l d3,d1
- cmp.w d0,d1 ; ... for which we find the SYNCWORD
- beq.s .synced
- dbra d3,.nxtbit
- addq.l #2,a0
- dbra d2,.nxtwrd
- lea .err(pc),a0 ; searched through all 32k...
- bra.s __fail ; ...no sync marker found
-
- .synced move.l (a0),d1 ; match; now we shift all the remaining
- addq.l #2,a0 ; trackdata backwards by this BIT and
- lsr.l d3,d1 ; BYTE distance, so the first word in
- move.w d1,(a1)+ ; the trackbuffer is the SYNCWORD
- dbra d2,.synced
- movem.l (sp)+,d2-d3
- rts
- .err dc.b "can't find sync mark",0
- ENDC
-
- __ertrk dc.b "error reading track",0
- __dosnm dc.b "dos.library",0
- __templ __tmpl
- IFEQ TRACKMODE
- __tdnm dc.b "trackdisk.device",0
- ENDC
- IFNE MESSAGES
- __msg dc.b "reading track %ld",13,0
- ENDC
- cnop 0,4
-
- ; create 32kb CHIP BSS hunk for trackbuffer
- section trackbuf,bss,chip
- __trk ds.b $7ffe
-
- ; return to main code section
- section diskreader,code
- __main move.l sp,__initsp(a5)
-