;
; Disassembly listing of eternal ramdisk program
; adapted for DRI assembler by Alain Birtz
; further mods for MegaST2 and MegaST4 by Richard Morris 11-25-87
; (also converted to AssemPro and MADMAC)
;
def_device      = 3                     ; Default device number( 2=C:,3=D:, 4=E:, 5=F:, 6=G:, 7=H:, 8=I: ...)
def_size        = 1500                  ; (1.5 meg is default) Default ramdisk size (in units of 1K)
magic           = $200                  ; Used to detect restart
megast2         = $200000               ; phystop in megast2
megast4         = $400000               ; phystop in megast4

; Absolute memory locations

reset_v         = $004
membot          = $432
memtop          = $436
phystop         = $42E
hdv_bpb         = $472
hdv_rw          = $476
hdv_mediach     = $47E
drivebits       = $4C4

; DOS operation codes

Mshrink = $4A
Super   = $20
Fopen   = $3D
Fclose  = $3E
Fread   = $3F

        text

        movea.l a7,a5           ; save old stack ptr
        movea.l #stack,a7       ; new stack
        movea.l 4(a5),a5        ; get address of base page
        move.l  12(a5),d0       ; compute length of program
        add.l   20(a5),d0
        add.l   28(a5),d0
        add.l   #$100,d0
        move.l  d0,-(a7)        ; size
        move.l  a5,-(a7)        ; mem
        move.w  d0,-(a7)        ; zero
        move.w  #Mshrink,-(a7)  ; return unused memory
        trap    #1              ; DOS
        adda.l  #12,a7          ; pop stack
        clr.l   -(a7)           ; 0
        move.w  #Super,-(a7)    ; Super
        trap    #1              ; DOS
        addq.l  #6,a7           ; pop stack
        move.l  d0,old_ssp      ; save old SSP
        movea.l #memtop,a4
        movea.l #phystop,a5

        move.l  (a5),d0         ; find out if you have a megast2 or megast4
        cmp.l   #megast2,d0     ; if megast2 then you will have 200000 in d0
        beq     initialize      ; jump over the megast crash site
        cmp.l   #megast4,d0     ; if megast4 then you will have 400000 in d0
        beq     initialize      ; jump over the megast crash site

        move.l  (a5), a1        ; now we will check to see if you ran this before (or initialze on a smaller machine)
        cmpi.w  #magic, (a1)    ; this is the statement that crashes the megas the first time the program is run
        beq     restart         ; second or more time through, skip initialization

; read filename (modified from original...)
; the filename MUST be of type DnnnnRAM.xxx, where nnnn is the 4 digits
; ramdisk size in K, D the drive letter id. and xxx the normal extention
; (PRG or TOS). by example E0425RAM.PRG given a ramdisk of id. E and size 425
; WARNING: don't forget the 0 between E and 425.
initialize:
        move.w  #$2f,-(sp)      ; Fgetdta function
        trap    #1              ; GEMDOS
        addq.l  #2,sp
        movea.l d0,a3           ; save it

        move.w  #%11,-(sp)      ; attribute
        pea     filename
        move.w  #$4e,-(sp)      ; Fsfirst function
        trap    #1              ; GEMDOS
        addq.l  #8,sp
        tst.l   d0
        bne.s   L3

        lea     30(a3),a3       ; address of filename
        moveq   #0,d0           ; clear register
        move.b  (a3)+,d0        ; drive letter id
        sub.w   #'A',d0
        bmi.s   L3
        cmpi.w  #16,d0          ; id between 0 and 15 only
        bcc.s   L3

        move.w  d0,device_no    ; save for future use
        move.w  d0,rd_mediach+2 ; put device number in cmpi instr.
        move.w  d0,rd_bpb+2
        move.w  d0,rd_rw+2

        moveq   #3,d1           ; extract 4 digits
        moveq   #0,d0           ; hold ramdisk size
        moveq   #0,d2           ; clear d2

digit:  mulu    #10,d0          ; 10 ; old value
        move.b  (a3)+,d2
        sub.b   #'0',d2
        add.w   d2,d0           ; plus current digit
        dbra    d1,digit

        bra.s   L5
        
L3:     move.l  #def_size,d0    ; file not found -- use default size

L5:     move.w  d0,numcl        ; put number of clusters in bpb
        moveq.l #10,d2
        lsl.l   d2,d0           ; d0 = ramdisk size in bytes
        add.l   #9216+512,d0    ; leave space for boot sector
                                ;  + FAT + root dir + BPB + driver

        move.l  d0,d1           ; make sure to leave at least 128K to user
        add.l   membot,d1
        add.l   #$20000,d1
        cmp.l   (a4),d1
        bge.s   exit

        sub.l   d0,(a4)         ; okay, so reserve memory
        sub.l   d0,(a5)
        move.l  hdv_bpb,old_bpb+2               ; save hdv_bpb vector
        move.l  hdv_rw,old_rw+2                 ; save hdv_rw vector
        move.l  hdv_mediach,old_mediach+2       ; save hdv_mediach vector

        movea.l #driver,a0      ; copy drivers to reserved memory
        movea.l (a5),a1 
        moveq.l #127,d7         ; move 512 bytes
L4:     move.l  (a0)+,(a1)+
        dbf     d7,L4

        movea.l reset_v,a0      ; force a reset
        jmp     (a0)

restart:
        move.l  (a5),d1
        add.l   #rd_bpb-driver,d1
        move.l  d1,hdv_bpb      ; set hdv_bpb vector

        move.l  (a5),d1
        add.l   #rd_rw-driver,d1
        move.l  d1,hdv_rw       ; set hdv_rw vector

        move.l  (a5),d1
        add.l   #rd_mediach-driver,d1
        move.l  d1,hdv_mediach  ; set hdv_mediach vector

        movea.l (a5),a0         ; mark ramdisk as present
        adda.l  #device_no-driver,a0
        move.w  (a0),d1      
        move.w  drivebits,d0
        bset    d1,d0
        move.w  d0,drivebits

exit:   move.l  old_ssp,-(a7)   ; leave supervisor mode
        move.w  #Super,-(a7)
        trap    #1
        addq.l  #6,a7
        clr.w   -(a7)           ; exit using Pterm0
        trap    #1

;-----------------------------------------------

; Following bytes moved into high memory

driver:

; ramdisk bios parameter block

recsiz: dc.w    512     ; bytes per sector   (512 std)
clsiz:  dc.w    2       ; sectors per clustor(2 std)
clsizb: dc.w    1024    ; cluster size in bytes (1024 std)
rdlen:  dc.w    7       ; root dir length in sectors
fsiz:   dc.w    5       ; FAT size in sectors
fatrec: dc.w    6       ; sector # 2nd FAT start
datrec: dc.w    18      ; sector # data start
numcl:  dc.w    $1EC    ; number of clusters (filled in above)
bflags: dc.w    0

rd_mediach:
        cmpi    #def_device,4(a7)       ; mediach handler
        bne     old_mediach
        moveq.l #0,d0
        rts

rd_bpb:
        cmpi    #def_device,4(a7)       ; bpb handler
        bne     old_bpb
        move.l  phystop,d0
        rts

rd_rw:
        cmpi    #def_device,14(a7)      ; rw handler
        bne     old_rw
        movea.l phystop,a0
        adda.l  #magic,a0               ; set flag for ramdisk being present
        movea.l 6(a7),a1                ; buffer address
        moveq.l #0,d1
        move.w  12(a7),d1               ; logical record number
        moveq.l #9,d0                   ; 2^9
        asl.l   d0,d1
        adda.l  d1,a0                   ; + ramdisk base = sector address
        move.w  10(a7),d0               ; sector count
        move.l  a1,d2                   ; is buffer address odd?
        btst    #0,d2
        bne.s   L8                      ; --yes, then branch
        btst    #0,5(a7)                ; check mode
        bne.s   L6                      ; branch if write
        exg     a1,a0                   ; read, so copy other way round
L6:     move.w  #15,d1                  ; loop 16 times
L7:     move.l  (a1)+,(a0)+             ; move 32 bytes quickly
        move.l  (a1)+,(a0)+
        move.l  (a1)+,(a0)+
        move.l  (a1)+,(a0)+
        move.l  (a1)+,(a0)+
        move.l  (a1)+,(a0)+
        move.l  (a1)+,(a0)+
        move.l  (a1)+,(a0)+
        dbf     d1,L7
        subq.l  #1,d0                   ; decrement count
        bne.s   L6                      ; loop if more sectors to move
        rts

L8:     btst    #0,5(a7)                ; odd address buffer, so use slow move
        bne.s   L9                      ; branch if write
        exg     a1,a0                   ; read, so copy other way round
L9:     move.w  #63,d1                  ; loop 64 times
L10:    move.b  (a1)+,(a0)+             ; move 8 bytes
        move.b  (a1)+,(a0)+
        move.b  (a1)+,(a0)+
        move.b  (a1)+,(a0)+
        move.b  (a1)+,(a0)+
        move.b  (a1)+,(a0)+
        move.b  (a1)+,(a0)+
        move.b  (a1)+,(a0)+
        dbf     d1,L10
        subq.l  #1,d0                   ; decrement count
        bne.s   L9                      ; loop if more sectors to move
        rts

old_bpb:
        jmp     $10000                  ; vector to old bpb handler
old_mediach:
        jmp     $10000                  ; vector to old mediach handler
old_rw:
        jmp     $10000                  ; vector to old rw handler

; N.B. originaly 0, with $10000 force to be absolute long, needed in 'restart:'

device_no:      dc.w    def_device

;----------------------- end of driver code -------------------------

        data

filename:       dc.b    "\auto\?????RAM.*",0  ; you will have to escape the \ in mad mac (see next line)
;           ------------- note: MADMAC users ------------
;filename:       dc.b    "\\auto\\????RAM.*",0 ; uncomment this for madmac
        bss

        align                           ; change to even for madmac

old_ssp:        ds.b    $4              ; saved system stack pointer
                ds.b    $200            ; stack
stack:


        end

 