; ***** FUNLOCK V1.0.
; ***** Filebase unlocker/locker for MAXsBBS.
; Ram:
;     0  20200  buffer for 100 file.data records
; 20200   4400  buffer for 100 file.index records
; 20300    100  sections ram
; 20500    200  print buffer
; 20700

; get some library offsets

           include "Assempro:Includes/exec.offsets"
           include "Assempro:Includes/dos.offsets"

PR_CLI     equ     172
PR_MsgPort equ     92
mode_new   equ     1006
mode_old   equ     1005

callsys:   macro   $\1                   ;macro for exec lib calls
           jsr     _LVO\1(a6)
           endm
calldos:   macro   $\1                   ;macro for dos lib calls
           move.l  doslibbase(pc),a6
           jsr     _LVO\1(a6)
           move.l  4,a6
           endm

; Vanity embedding

           bra     startup
           dc.b    "FunLock V1.0 by Keith Bennett 10-Mar-1997",0
           align

; Start up code

startup:   move.l  sp,InitialSP          ;store stack pointer
           move.l  d0,d6                 ;remember command length
           move.l  a0,a5                 ;remember command buffer
           move.l  4,a6                  ;point a6 to execbase
           sub.l   a1,a1                 ;what task am I?
           callsys findtask
           move.l  d0,Own_Task
           move.l  d0,a4
           tst.l   PR_CLI(a4)            ;start from CLI?
           bne.s   begin                 ;yes, that's good
           lea     PR_MsgPort(a4),a0     ;wait for WB's go-ahead
           callsys waitport
           lea     PR_MsgPort(a4),a0     ;grab WB's message
           callsys getmsg
           move.l  d0,WBenchMsg
           bra     exit                  ;can't run from WB

; Start of program

begin:     lea     doslibname,a1         ;open dos lib
           sub.l   d0,d0
           callsys openlibrary
           move.l  d0,doslibbase
           beq     exit
           calldos output                ;get output channel
           move.l  d0,outbase

           subq.l  #1,d6                 ;any parameters?
           beq     error1
           move.b  #0,(a5,d6)            ;terminate parameters
           move.l  a5,path

           move.l  #20200+4400+100+200,d0;get sections & file buffer ram
           move.l  #$10000,d1            ;clear ram
           callsys allocmem
           move.l  d0,sectionram
           beq     error2
           move.l  d0,a5

           move.l  path(PC),a0           ;point to parameters
\loop1:    move.b  (a0)+,d0              ;scan for a space
           beq     error1
           cmp.b   #" ",d0
           bne     \loop1
           move.b  #0,-1(a0)             ;terminate path name

ploop:     move.b  (a0)+,d0
           and.b   #$df,d0
           move.b  #1,d7
           cmp.b   #"L",d0
           beq     ploop1
           move.b  #2,d7
           cmp.b   #"U",d0
           bne     error8

ploop1:    bsr     readnum               ;read selections
           tst.l   d0
           bmi     error8
           move.l  d0,d1
           bsr     setsect
ploop3:    move.b  (a0)+,d1
           beq     contin
           cmp.b   #" ",d1
           beq     ploop
           cmp.b   #",",d1
           beq     ploop1
           cmp.b   #"-",d1
           bne     error8
           move.l  d0,d3
           bsr     readnum
           tst.l   d0
           bmi     error8
           cmp.b   d0,d3
           blo     ploop2
           exg     d0,d3
ploop2:    cmp.b   d0,d3
           bhi     ploop3
           move.l  d3,d1
           bsr     setsect
           addq    #1,d3
           bra     ploop2
readnum:   clr.l   d0
           clr.l   d1
           move.b  1(a0),d0
           cmp.b   #"0",d0
           blo     \skip1
           cmp.b   #"9",d0
           bhi     \skip1
           move.b  (a0)+,d1
           cmp.b   #"0",d1
           blo     \skip2
           cmp.b   #"9",d1
           bhi     \skip2
           sub.b   #$30,d1
           mulu    #10,d1
\skip1:    move.b  (a0)+,d0
           cmp.b   #"0",d0
           blo     \skip2
           cmp.b   #"9",d0
           bhi     \skip2
           sub.b   #$30,d0
           add.b   d1,d0
           rts
\skip2:    moveq.l #-1,d0
           rts
setsect:   lea     20200+4400(a5),a1
           add.l   d1,a1
           move.b  d7,(a1)
           rts

contin:    lea     efdname(PC),a0        ;open file.data
           move.l  #mode_old,d2
           bsr     openfile
           move.l  d0,efdbase
           beq     error3
           move.l  d0,d1                 ;read header
           move.l  a5,d2
           move.l  #466,d3
           calldos read
           cmp.l   #466,d0
           bne     error4

           lea     txt01(PC),a0
           bsr     print
           lea     20200+4400+100(a5),a0
           bsr     print

           lea     tfdname(PC),a0        ;open file.data.temp
           move.l  #mode_new,d2
           bsr     openfile
           move.l  d0,tfdbase
           beq     error3
           move.l  d0,d1                 ;write header
           move.l  a5,d2
           move.l  #466,d3
           calldos write
           tst.l   d0
           bmi     error5

           lea     efiname(PC),a0        ;open file.index
           move.l  #mode_old,d2
           bsr     openfile
           move.l  d0,efibase
           beq     error3
           move.l  d0,d1                 ;read header
           move.l  a5,d2
           move.l  #62,d3
           calldos read
           cmp.l   #62,d0
           bne     error4

           lea     tfiname(PC),a0        ;open file.index.temp
           move.l  #mode_new,d2
           bsr     openfile
           move.l  d0,tfibase
           beq     error3
           move.l  d0,d1                 ;write header
           move.l  a5,d2
           moveq.l #62,d3
           calldos write
           tst.l   d0
           bmi     error5
           clr.l   d6                    ;record count
           clr.l   d7                    ;modified record count

bloop:     move.l  efdbase(PC),d1        ;read up to 100 file records
           move.l  a5,a3
           move.l  a3,d2
           move.l  #20200,d3
           calldos read
           move.l  d0,d5
           move.l  d0,readsize
           beq     eofiles
           bmi     error4
           move.l  efibase(PC),d1
           lea     20200(a3),a4
           move.l  a4,d2
           move.l  #4400,d3
           calldos read
           tst.l   d0
           bmi     error4

mloop:     addq.l  #1,d6                 ;increment total record count
           clr.l   d0
           move.b  17(a3),d0             ;get section number
           lea     20200+4400(a5),a1     ;read selection for section
           add.l   d0,a1
           move.b  (a1),d0
           beq     nextfile           
           move.b  16(a3),d1
           cmp.b   #1,d0                 ;lock record
           bne     \skip1
           or.b    #$02,d1
\skip1:    cmp.b   #2,d0                 ;unlock record
           bne     \skip2
           and.b   #$fd,d1           
\skip2:    move.b  d1,16(a3)             ;update file.data flags
           move.b  d1,42(a4)             ;update file.index flags
           addq.l  #1,d7

nextfile:  add.w   #202,a3
           add.w   #44,a4
           sub.l   #202,d5
           bhi     mloop

writeb:    move.l  tfdbase(PC),d1        ;write temp file.data
           move.l  a5,d2
           move.l  readsize(PC),d3
           move.l  d3,d4
           calldos write
           cmp.l   d0,d4
           bne     error5
           move.l  tfibase(PC),d1        ;write temp file.index
           lea     20200(a5),a0
           move.l  a0,d2
           move.l  readsize,d3
           divu    #202,d3
           mulu    #44,d3
           move.l  d3,d4
           calldos write
           cmp.l   d0,d4
           bne     error5
           bra     bloop

eofiles:   bsr     fclose                ;close files
           lea     rfdname(PC),a0        ;rename files
           lea     20200+4400+100(a5),a2
           bsr     getname
           move.l  d1,d2
           lea     efdname(PC),a0
           lea     20200+4400+200(a5),a2
           bsr     getname
           calldos rename
           tst.l   d0
           beq     error6
           lea     rfiname(PC),a0
           lea     20200+4400+100(a5),a2
           bsr     getname
           move.l  d1,d2
           lea     efiname(PC),a0
           lea     20200+4400+200(a5),a2
           bsr     getname
           calldos rename
           tst.l   d0
           beq     error6
           lea     efdname(PC),a0
           lea     20200+4400+100(a5),a2
           bsr     getname
           move.l  d1,d2
           lea     tfdname(PC),a0
           lea     20200+4400+200(a5),a2
           bsr     getname
           calldos rename
           tst.l   d0
           beq     error6
           lea     efiname(PC),a0
           lea     20200+4400+100(a5),a2
           bsr     getname
           move.l  d1,d2
           lea     tfiname(PC),a0
           lea     20200+4400+200(a5),a2
           bsr     getname
           calldos rename
           tst.l   d0
           beq     error6

           lea     txt02(PC),a0          ;end text
           move.l  d7,d0
           bsr     printf
           lea     txt03(PC),a0
           move.l  d6,d0
           bsr     printf
           bra     exit

; Error Handling

error1:    lea     txterr1(PC),a0
           bra     error9
error2:    lea     txterr2(PC),a0
           bra     error9
error3:    lea     txterr3(PC),a0
           bsr     print
           lea     20200+4400+100(a5),a0
           bra     error9
error4:    lea     txterr4(PC),a0
           bra     error9
error5:    lea     txterr5(PC),a0
           bra     error9
error6:    lea     txterr6(PC),a0
           bsr     print
           lea     20200+4400+200(a5),a0
           bsr     print
           lea     txterr7(PC),a0
           bsr     print
           lea     20200+4400+100(a5),a0
           bra     error9
error8:    lea     txterr8(PC),a0
           bsr     print
           lea     txterr1(PC),a0
error9:    bsr     print
           lea     txterr9(PC),a0
           bsr     print

; cleanup and exit

exit:      bsr     cleanup               ;close anything open
           tst.l   WBenchMsg             ;did we start from WB?
           beq.s   nowb                  ;nope
           callsys forbid                ;stop task switching
           move.l  WBenchMsg,a1          ;reply to WB's message
           callsys replymsg
nowb:      moveq   #0,d0                 ;clear error code
           move.l  InitialSP,sp          ;restore stack pointer
           rts                           ;and end

; close everything that's open

cleanup:   bsr     fclose                ;close files
           move.l  sectionram(PC),a1     ;free sections ram
           move.l  a1,d0
           beq     \closedos
           move.l  #20200+4400+100+200,d0
           callsys freemem
\closedos: move.l  doslibbase,a1         ;get dos lib base
           move.l  a1,d0                 ;test for zero
           beq.s   \skip                 ;is it open?   
           callsys closelibrary          ;close if open
\skip:     rts

fclose:    move.l  efdbase,d1            ;close file.data
           beq     \skip1
           calldos close
           clr.l   efdbase
\skip1:    move.l  tfdbase,d1            ;close file.data.temp
           beq     \skip2
           calldos close
           clr.l   tfdbase
\skip2:    move.l  tfibase,d1            ;close file.index.temp
           beq     \skip3
           calldos close
           clr.l   tfibase
\skip3:    move.l  efibase,d1            ;close file.index
           beq     \skip4
           calldos close
           clr.l   efibase
\skip4:    rts

;open file (a0)=file, d2=mode

openfile:  lea     20200+4400+100(a5),a2
           bsr     getname
           calldos open
           rts

getname:   move.l  a2,d1                 ;get filename - a2
           move.l  path(PC),a1
\loop1:    move.b  (a1)+,(a2)+
           bne     \loop1
           subq.l  #1,a2
\loop2:    move.b  (a0)+,(a2)+
           bne     \loop2
           rts

; printf (a0), d0=data

printf:    movem.l a2/a3,-(SP)
           lea     schar(PC),a2
           lea     20200+4400+100(a5),a3
           lea     temp(PC),a1
           move.l  d0,(a1)
           callsys rawdofmt
           lea     20200+4400+100(a5),a0
           bsr     print
           movem.l (SP)+,a2/a3
           rts
schar:     move.b  d0,(a3)+
           rts

; print (a0)

print:     movem.l a1/d2/d3,-(SP)
           move.l  outbase(PC),d1        ;get o/p channel
           beq     \skip
           move.l  a0,a1
\loop:     tst.b   (a1)+
           bne     \loop
           move.l  a0,d2
           move.l  a1,d3
           sub.l   d2,d3
           calldos write
\skip:     movem.l (SP)+,a1/d2/d3
           rts

WBenchMsg: dc.l    0                     ;pointer to WB's message
Own_Task:  dc.l    0                     ;task structure pointer
InitialSP: dc.l    0                     ;stack pointer store
sectionram:dc.l    0                     ;sections data pointer
outbase:   dc.l    0                     ;standard output channel
doslibbase:dc.l    0                     ;dos lib base
path:      dc.l    0                     ;pointer to path
efdbase:   dc.l    0                     ;file.data base
efibase:   dc.l    0                     ;file.index base
tfdbase:   dc.l    0                     ;temp file.data base
tfibase:   dc.l    0                     ;temp file.index base
readsize:  dc.l    0                     ;file read size
temp:      dc.l    0
txterr1:   dc.b    10,"Usage: funlock <path to MAXs filebase> <sections list>",10
           dc.b    "Eg:    funlock bbs:files/ l20-28 u4,32",0
txterr2:   dc.b    10,"Error allocating RAM.",0
txterr3:   dc.b    10,"Error opening ",0
txterr4:   dc.b    10,"Read error",0
txterr5:   dc.b    10,"Write error",0
txterr6:   dc.b    10,"Error renaming ",0
txterr7:   dc.b    " to ",0
txterr8:   dc.b    10,"Bad parameters",0
txterr9:   dc.b    10,10,0
txt01:     dc.b    10,"Modifying: ",0
txt02:     dc.b    10,"Complete.    Total records modified: %ld",0
txt03:     dc.b    10,"          Total records in filebase: %ld",10,10,0
doslibname:dc.b    "dos.library",0
efdname:   dc.b    "File.data",0
efiname:   dc.b    "File.index",0
tfdname:   dc.b    "File.data.temp",0
tfiname:   dc.b    "File.index.temp",0
rfdname:   dc.b    "File.data.old",0
rfiname:   dc.b    "File.index.old",0

           end
