Anyone help with DevPac?

ptp170

R Tape loading error, 0:1
AmiBayer
Blogger
Joined
Aug 20, 2010
Posts
715
Country
UK
Region
Devon
After a long journey and painful journey with a Chinon HD floppy (https://www.amibay.com/showthread.php?73920-Chinon-HD-drive-won-t-read-HD-floppies) I came across a thread here from Joe Fenton (http://www.amiga.org/forums/showthread.php?t=19858)

I am trying to assemble the source code in Joe's thread in DevPac. I've included 'system.gs' but the assembly fails on the CALLSYS lines returning 'Error instruction not recognised at line ### etc'.

Can anyone tell me what I'm doing wrong??
hammer.gif


Chris
 
CALLSYS is not a standard instruction - maybe it's a custom written macro to make calling system functions easier. Since the function names are more or less self-explanatory, you could replace each CALLSYS instance with the equivalent

jsr _LVO{equivalent library function name here}(a6)

instruction.

All belong to exec.library except GetSysTime which belongs to timer.device, see RKM - Libraries & Devices.

Peeking into the relevant .i include files in Devpac may get you the associated EQU negative offsets, so you'd then just

jsr -$xyz(a6) or
jsr -XYZ(a6)

without needing _LVO translation, where -$xyz / -XYZ the relevant offset, depending if it's given in hex or dec format.
 
CALLSYS is not a standard instruction - maybe it's a custom written macro to make calling system functions easier. Since the function names are more or less self-explanatory, you could replace each CALLSYS instance with the equivalent

jsr _LVO{equivalent library function name here}(a6)

instruction.

All belong to exec.library except GetSysTime which belongs to timer.device, see RKM - Libraries & Devices.

Peeking into the relevant .i include files in Devpac may get you the associated EQU negative offsets, so you'd then just

jsr -$xyz(a6) or
jsr -XYZ(a6)

without needing _LVO translation, where -$xyz / -XYZ the relevant offset, depending if it's given in hex or dec format.

So I'll need to dig out more include files if I use the jsr _LVO method? I've got a disk full of includes etc that I can use.

Sorry for the simplistic reply but this really is VERY alien to me.


Chris
 
Last edited:
So I'll need to dig out more include files if I use the jsr _LVO method? I've got a disk full of includes etc that I can use.

Sorry for the simplistic reply but this really is VERY alien to me.


Chris

It's alien to me too, my experience with Devpac was ages ago as a teen, and only coded hardware-hitting simple demos anyway. Not much interest in the OS. But in general _LVOxyz names are resolved at link time by amiga.lib, you should look into DevPac's documentation for more details (in fact I never used Devpac to produce linkable code, only directly executables).
Another approach is getting the offsets directly, they're in the offset reference table of RKM - Includes & Autodocs, although I'm not sure you'll find the DeviceList structure offset there.
 
So I'll need to dig out more include files if I use the jsr _LVO method? I've got a disk full of includes etc that I can use.

Sorry for the simplistic reply but this really is VERY alien to me.


Chris

It's alien to me too, my experience with Devpac was ages ago as a teen, and only coded hardware-hitting simple demos anyway. Not much interest in the OS. But in general _LVOxyz names are resolved at link time by amiga.lib, you should look into DevPac's documentation for more details (in fact I never used Devpac to produce linkable code, only directly executables).
Another approach is getting the offsets directly, they're in the offset reference table of RKM - Includes & Autodocs, although I'm not sure you'll find the DeviceList structure offset there.

Don't know if this will help, but I came across a macro definition for CALLSYS that looks reasonable. I've done very little Amiga development to date so I'm not sure if this is exactly what you need or not.

macro CALLSYS
xref _LVO\1
jsr _LVO\1(a6)
endm
 
Weleace Wodderwick.

what your name wapscallian

my name is brian

Bwian eh!!

no BRIAN ........ SLAP!!!! AHH!

:D


sorry i couldn't resist one of my favorite films :)
 
Last edited:
So I'll need to dig out more include files if I use the jsr _LVO method? I've got a disk full of includes etc that I can use.

Sorry for the simplistic reply but this really is VERY alien to me.


Chris

It's alien to me too, my experience with Devpac was ages ago as a teen, and only coded hardware-hitting simple demos anyway. Not much interest in the OS. But in general _LVOxyz names are resolved at link time by amiga.lib, you should look into DevPac's documentation for more details (in fact I never used Devpac to produce linkable code, only directly executables).
Another approach is getting the offsets directly, they're in the offset reference table of RKM - Includes & Autodocs, although I'm not sure you'll find the DeviceList structure offset there.

Don't know if this will help, but I came across a macro definition for CALLSYS that looks reasonable. I've done very little Amiga development to date so I'm not sure if this is exactly what you need or not.

macro CALLSYS
xref _LVO\1
jsr _LVO\1(a6)
endm

Have now got the following. Not sure if the Macro is inserted in the correct place? All 18 of the CALLSYS errors have disappeared but now I get:

Code:
source expired prematurely

Which according to the DevPac manual means: within an IF, MACRO or REPT and the source ran out.


:unsure:

Code:
; Universal Drive Patch

; Copyright (C) 1997 Joseph Fenton. All rights reserved.



        include /DriveIDCK/system.gs
        include dh0:devpac/include2.0/include/resources/disk.i
        include dh0:devpac/include2.0/include/exec/exec.i
        include dh0:devpac/include2.0/include/devices/timer.i
        output  c:udp



;--------------------------------------------------------------------

; note: this program cannot be run from WB



entry       bra.b   start



; Standard 2.x/3.x version string



        dc.b    0,'$VER: Universal Drive Patch 2.0 (3.6.97)',0



        CNOP    0,4



; The main program code.



start       movea.l 4.w,a6

CALLSYS MACRO
JSR _LVO\1(A6)
ENDM


        CALLSYS Forbid



; get memory for AE drive command function



        moveq   #4,d0

        move.l  #MEMF_CLEAR+MEMF_CHIP+MEMF_PUBLIC,d1

        cmpi.w  #39,LIB_VERSION(a6)

        blo.b   .ac         ; pre-39 was buggy in reverse

        ori.l   #MEMF_REVERSE,d1

.ac     CALLSYS AllocMem

        move.l  d0,ChipPtr

        bne.b   .ok0



        CALLSYS Permit

        move.l  #ERROR_NO_FREE_STORE,d0

        rts



; get memory for ReadUnitID patch code



.ok0        move.l  #CODE_LENGTH,d0

        move.l  #MEMF_CLEAR+MEMF_PUBLIC,d1

        cmpi.w  #39,LIB_VERSION(a6)

        blo.b   .af         ; pre-39 was buggy in reverse

        ori.l   #MEMF_REVERSE,d1

.af     CALLSYS AllocMem

        move.l  d0,MemPtr

        bne.b   .ok1



        moveq   #4,d0

        movea.l ChipPtr,a1

        CALLSYS FreeMem



        CALLSYS Permit

        move.l  #ERROR_NO_FREE_STORE,d0

        rts



; get timer.device base



.ok1        lea DeviceList(a6),a0

        lea timerName,a1

        CALLSYS FindName

        move.l  d0,TimerBase

        bne.b   .ok2



        move.l  #CODE_LENGTH,d0

        movea.l MemPtr,a1

        CALLSYS FreeMem



        moveq   #4,d0

        movea.l ChipPtr,a1

        CALLSYS FreeMem



        CALLSYS Permit

        move.l  #RETURN_WARN,d0

        rts



; copy patch code into the allocated memory



.ok2        lea ReadUnitID,a0

        move.l  MemPtr,a1

        move.l  #CODE_LENGTH,d0

        CALLSYS CopyMem



; get disk.resource base



        lea DskRsrcName,a1

        CALLSYS OpenResource

        tst.l   d0

        bne.b   .ok3



        move.l  #CODE_LENGTH,d0

        movea.l MemPtr,a1

        CALLSYS FreeMem



        moveq   #4,d0

        movea.l ChipPtr,a1

        CALLSYS FreeMem



        CALLSYS Permit

        move.l  #RETURN_WARN,d0

        rts



; Patch disk.resource ReadUnitID() function.

; This is the system-friendly method!



.ok3        lea _LVOReadUnitID,a0   ; function offset

        movea.l d0,a1           ; library base

        move.l  MemPtr,d0       ; new function pointer

        CALLSYS SetFunction



; Exit leaving patch in memory. You don't have to 'run' this program.



        CALLSYS Permit

        moveq   #RETURN_OK,d0

        rts



;--------------------------------------



        CNOP    0,4



MemPtr      dc.l    0



DskRsrcName dc.b    'disk.resource',0

        even



timerName   dc.b    'timer.device',0





;--------------------------------------------------------------------



        CNOP    0,4



; This is the new ReadUnitID() function.  It handles the disk identification

; and AEHD drive controlling.



ReadUnitID  movem.l d2-d3/a3,-(a7)

        move.l  d0,d2           ; unit number

        move.b  #8,d3

        lsl.b   d0,d3           ; drive select bit

        lea $30(a6),a0      ; unit id table

        lsl.l   #2,d0           ; offset for unit

        lea (a0,d0.w),a3        ; ptr to this unit id

        bsr.w   GetDriveID      ; get 32bit ID

        cmpi.l  #DRT_EMPTY,d0       ; drive present?

        bne.b   .1          ; yes, check for HD

        tst.l   d2          ; check unit number

        bne.b   .2          ; external, no drive

        moveq   #DRT_AMIGA,d0       ; assume internal present

.1      bsr.w   CheckDrive      ; check disk type

.2      move.l  d0,(a3)         ; set disk type



; Check for whether ReadUnitIDwas called from trackdisk.device. If not,

; simply exit back to the calling code.  If called from trackdisk, cleanup

; the stack, determine which setup vector to return in a1, and return to

; trackdisk at appropriate offset.



        movea.l 12(a7),a3       ; return address

        cmpi.l  #$2C5F4E75,(a3)     ; movea.l (a7)+,a6  rts

        bne.b   .4          ; not trackdisk

        movea.l 20(a7),a3       ; next return addr

        cmpi.w  #$B0AB,(a3)     ; cmp.l d16(a3),d0

        bne.b   .4          ; not trackdisk



; trackdisk is trying to determine the disk type



        movem.l (a7)+,d2-d3/a3

        addq.l  #4,a7           ; pop 1st return address

        movea.l (a7)+,a6

        movea.l (a7)+,a1        ; trackdisk return addr



; Determine structure offset for different versions of trackdisk. This

; allows the code to be mostly independent of the version of trackdisk.

; This works for versions 37 through 40.



        move.w  2(a1),d2        ; prev ID offset

        subi.w  #$54,d2         ; offset for this version

        cmp.l   $54(a3,d2.w),d0     ; same type as previously?

        bne.b   .3          ; no

        jmp (a1)            ; yes, return to trackdisk



; determine which setup routine is needed for this disk type



.3      pea $22(a1)         ; new return address

        lea SetupDD(pc),a1

        cmpi.l  #DRT_AMIGA,d0

        beq.b   .5          ; 3.5" DD

        lea SetupAE(pc),a1

        cmpi.l  #$0F03FFFF,d0

        beq.b   .5          ; AEHD drive in HD mode

        lea SetupHD(pc),a1

        cmpi.l  #DRT_150RPM,d0

        beq.b   .5          ; 3.5" HD



; not recognized, return and use previous disk type settings



        movea.l (a7)+,a1        ; return address

        lea 4-$22(a1),a1        ; branch if same address

        cmp.l   d0,d0           ; same as previous

        jmp (a1)



.4      movem.l (a7)+,d2-d3/a3

.5      rts



;--------------------------------------



        CNOP    0,4



; Read the drive ID bits and set the AEHD speed select if needed.



GetDriveID  not.b   d3          ; drive select low

        lea $BFD100,a0



; turn motor on, then off to reset drive ID circuit



        move.b  #$7F,d0

        move.b  d0,(a0)         ; assert motor

        and.b   d3,d0

        move.b  d0,(a0)         ; select drive, motor on

        move.b  #$FF,(a0)       ; deassert motor

        move.b  d3,(a0)         ; select drive, motor off

        move.b  #$FF,(a0)       ; deselect drive



; read drive ID bits



        moveq   #31,d1          ; 32 bits

        moveq   #0,d0

.1      lsl.l   #1,d0

        move.b  d3,(a0)         ; select drive

        btst    #5,$BFE001      ; get ID bit

        beq.b   .2

        bset    #0,d0

.2      move.b  #$FF,(a0)       ; deselect drive

        dbra    d1,.1           ; next bit



        not.b   d3          ; drive select high



        move.l  d0,d1

        andi.l  #$FF1FFFFF,d1       ; AEHD drive ID mask

        cmpi.l  #$0F03FFFF,d1       ; AEHD drive?

        beq.b   .3          ; yes

        rts



; AEHD drive - determine the disk type and set the drive speed.



.3      btst    #21,d0          ; disk type bit

        bne.w   AEHD            ; HD disk

        bra.w   AEDD            ; DD disk



;--------------------------------------



        CNOP    0,4



; Determine if disk reported as DD is really HD by timing the track

; using the index pulse.



CheckDrive  cmpi.l  #DRT_AMIGA,d0       ; 3.5" DD?

        bne.w   .exit           ; no, exit

        cmpi.l  #$0F03FFFF,d1       ; AEHD drive?

        beq.w   .exit           ; yes, exit



        not.b   d3          ; drive select low

        lea $BFD000,a0

        move.b  #$7F,d2

        move.b  d2,$100(a0)     ; assert motor

        and.b   d3,d2

        move.b  d2,$100(a0)     ; select drive, motor on



        bsr.w   GetSystemTime

        move.l  d0,d2

        addi.l  #800,d2         ; .8 sec

.loop0      btst    #5,$1001(a0)        ; /RDY

        beq.b   .1          ; motor up to speed

        bsr.b   GetSystemTime

        cmp.l   d2,d0

        blt.b   .loop0          ; wait for motor to spin up



.1      tst.b   $D00(a0)        ; clear icr

        bsr.b   GetSystemTime

        move.l  d0,d2

        addi.l  #500,d2         ; .5 sec

.loop1      btst    #4,$D00(a0)     ; /INDEX = FLG bit in icr

        bne.b   .2          ; found index

        bsr.b   GetSystemTime

        cmp.l   d2,d0

        blt.b   .loop1          ; wait for index pulse

        bra.b   .dd         ; timeout



.2      move.l  d0,d2

        addi.l  #500,d2         ; .5 sec

.loop2      btst    #4,$D00(a0)     ; /INDEX = FLG bit in icr

        bne.b   .3          ; found index

        bsr.b   GetSystemTime

        cmp.l   d2,d0

        blt.b   .loop2          ; wait for index pulse

        bra.b   .dd         ; timeout



.3      sub.l   d0,d2           ; time left in .5 sec

        cmpi.l  #250,d2

        blt.b   .hd         ; took more than .25 sec



.dd     moveq   #DRT_AMIGA,d0       ; 3.5" DD

        bra.b   .4



.hd     move.l  #DRT_150RPM,d0

.4      not.b   d3          ; drive select high

        move.b  #$FF,$100(a0)       ; deselect drive

.exit       rts



;------------------



        CNOP    0,4



GetSystemTime   movem.l d1/a0-a1/a6,-(a7)

        lea SysTime(pc),a0

        movea.l TimerBase(pc),a6

        CALLSYS GetSysTime

        lea SysTime(pc),a0

        move.l  #$FFFFF,d0

        and.l   (a0)+,d0        ; tv_secs & 000FFFFF

        mulu.w  #1000,d0        ; ms

        move.l  (a0),d1         ; tv_micro

        divu.w  #1000,d1        ; ms

        andi.l  #$FFFF,d1

        add.l   d1,d0           ; total ms

        movem.l (a7)+,d1/a0-a1/a6

        rts



;--------------------------------------



        CNOP    0,4



; Set the AEHD drive to the proper speed for the disk type.



AEDD        moveq   #DRT_AMIGA,d0       ; 3.5" DD

        move.b  #$F9,d2         ; set DD speed opcode

        bra.b   SetAE



AEHD        move.l  d1,d0           ; AEHD drive in HD mode

        move.b  #$FB,d2         ; set HD speed opcode



SetAE       movem.l d0/a1,-(a7)

        lea $BFD000,a0

        lea $DFF000,a1

        not.b   d3          ; drive select low

        move.b  d2,$100(a0)     ; speed

        and.b   d3,d2

        move.b  d2,$100(a0)     ; select drive, set speed



; write a longword of 0 to activate the AEHD setting



        move.w  #$4000,dsklen(a1)

        move.w  #$1002,intreq(a1)   ; clear disk ints

        move.l  ChipPtr(pc),dskpt(a1)

        move.w  #$C002,dsklen(a1)

        move.w  #$C002,dsklen(a1)   ; start write to set speed



; wait for DSKBLK



        move.l  #$20000,d2

.loop       move.w  intreqr(a1),d0      ; ints

        btst    #1,d0           ; DSKBLK

        bne.b   .1          ; done

        subq.l  #1,d2

        bne.b   .loop



; timeout, stop the DMA



        move.w  #$4000,dsklen(a1)

.1      move.w  #$4000,dsklen(a1)   ; stop any disk DMA

        move.w  #2,intreq(a1)       ; clear DSKBLK



        move.b  #$FF,$100(a0)       ; deselect drive

        not.b   d3          ; drive select high

        movem.l (a7)+,d0/a1

        rts



;--------------------------------------



        CNOP    0,4



; These routines setup the trackdisk variables needed to distinguish

; one format from another. They call a common track buffer setup.



SetupDD     move.l  #880*1024,$44(a3,d2.w)  ; total storage

        move.l  #300000,$50(a3,d2.w)    ; timeout

        move.w  #11,$4E(a3,d2.w)    ; # sec/trk

        move.w  #15296,$48(a3,d2.w) ; track length + overlap

        move.w  #13628,$4A(a3,d2.w) ; track length

        move.w  #1660,$4C(a3,d2.w)  ; gap length

        move.l  #DRT_AMIGA,$54(a3,d2.w) ; disk type

        move.b  #DRIVE3_5,$40(a3,d2.w)  ; drive type

        bra.b   SetupTrkBuffer



        CNOP    0,4



SetupAE     move.l  #1520*1024,$44(a3,d2.w) ; total storage

        move.l  #500000,$50(a3,d2.w)    ; timeout

        move.w  #19,$4E(a3,d2.w)    ; # sec/trk

        move.w  #24004,$48(a3,d2.w) ; track length + overlap

        move.w  #22334,$4A(a3,d2.w) ; track length

        move.w  #1662,$4C(a3,d2.w)  ; gap length

        move.l  #$0F03FFFF,$54(a3,d2.w) ; disk type

        move.b  #4,$40(a3,d2.w)     ; drive type

        bra.b   SetupTrkBuffer



        CNOP    0,4



SetupHD     move.l  #1760*1024,$44(a3,d2.w) ; total storage

        move.l  #600000,$50(a3,d2.w)    ; timeout

        move.w  #22,$4E(a3,d2.w)    ; # sec/trk

        move.w  #30584,$48(a3,d2.w) ; track length + overlap

        move.w  #27256,$4A(a3,d2.w) ; track length

        move.w  #3320,$4C(a3,d2.w)  ; gap length

        move.l  #DRT_150RPM,$54(a3,d2.w) ; disk type

        move.b  #DRIVE3_5_150RPM,$40(a3,d2.w) ; drive type



SetupTrkBuffer  movea.l $68(a3,d2.w),a1     ; track buffer ptr

        move.w  #-1,(a1)        ; track invalid

        clr.b   2(a1)           ; clear track flags

        move.w  $4C(a3,d2.w),d0     ; gap length

        lea $68(a1,d0.w),a0

        adda.w  d2,a0

        adda.w  d2,a0           ; start of data area

        move.l  a0,4(a1)        ; track data ptr

        suba.w  d0,a0           ; start of gap area

        lsr.w   #2,d0           ; # longs in track gap

        subq.w  #1,d0           ; for dbra

        move.l  #$AAAAAAAA,d1       ; MFM zero value

.1      move.l  d1,(a0)+        ; clear track gap

        dbra    d0,.1

        rts



;--------------------------------------



        CNOP    0,4



ChipPtr     dc.l    0



TimerBase   dc.l    0



SysTime     dc.l    0,0





;--------------------------------------------------------------------



CODE_END:



CODE_LENGTH equ CODE_END-ReadUnitID



end
 
Put the macro definition before the code, i.e. before the

entry bra.b start

line

That did make a difference but now DevPac gives an slightly different error of: Error source expired prematurely in assembly options
 
Weleace Wodderwick.

what your name wapscallian

my name is brian

Bwian eh!!

no BRIAN ........ SLAP!!!! AHH!

:D


sorry i couldn't resist one of my favorite films :)

Just don't throw me to the floor...
 
Back
Top Bottom