10 REM > BLib.GoMMC 1.01 15-Feb-2005
   20 REM =============================
   30 REM GoMMC access routines
   40 REM ---------------------
   50 REM Depends: String: FNuc(), FNstr0()
   60 :
   70 REM PROCmmc - Issue GoMMC command
   80 REM -----------------------------
   90 REM action% - GoMMC action
  100 REM addr%   - BBC memory address
  110 REM mmc%    - GoMMC address
  120 REM -----------------------------
  130 DEFPROCmmc_(action%,addr%,mmc%,num%)
  140 !X%=&1212:X%!2=action%:X%?4=&01:X%!6=addr%:X%!10=mmc%:X%!14=num%:A%=&B0:CALL&FFF1:ENDPROC
  150 :
  160 REM FNmmc_Type - Return GoMMC object type
  170 REM -------------------------------------
  180 DEFFNmmc_Type(A%):IFA%<4:=MID$("NONEFSIMTOOLDISK",A%*4+1,4) ELSE =" "+FNh0(A%,2)+" "
  190 :
  200 REM FNmmc_Find - Find an entry in GoMMC catalog
  210 REM -------------------------------------------
  220 REM name$ - onject name to add, can be terminated with '*'
  230 REM mem%  - 64 bytes of memory for object entry
  240 REM
  250 REM Returns: 0   - Object not found
  260 REM          <>0 - Object found, mem% contains info
  270 REM -------------------------------------------
  280 DEFFNmmc_Find(A$,mem%)
  290 LOCAL csz%,n%,l%,match%
  300 mem%!0=0:PROCmmc_(&4003,mem%,0,64)           :REM Read global catalog
  310 mem%?8=13:IF$mem%<>"GoMMCCat":=0             :REM No global catalog
  320 csz%=mem%!16:IFcsz%=0:=0                     :REM Catalog empty
  330 A$=FNuc(A$):IFRIGHT$(A$,1)="*":l%=LENA$-1 ELSE l%=255
  340 n%=0:REPEAT:PROCmmc_(&4003,mem%,512+64*n%,64)
  350   match%=LEFT$(FNuc(FNstr0(mem%+16)),l%)=LEFT$(A$,l%)
  360 n%=n%+1:UNTILn%=csz% OR match%:IFmatch%:=n% ELSE =0
  370 :
  380 REM FNmmc_Add - Add an entry to GoMMC catalog
  390 REM -----------------------------------------
  400 REM name$ - object name to add
  410 REM size% - size of object to add
  420 REM type% - object type
  430 REM subt% - object subtype
  440 REM mem%  - 64 bytes of memory for object entry
  450 REM
  460 REM Returns: 0    - No GoMMC catalog or catalog full
  470 REM          <>0  - GoMMC data address of new object
  480 REM          mem% - contains object catalog info
  490 REM -----------------------------------------
  500 DEFFNmmc_Add(name$,size%,type%,subt%,mem%)
  510 LOCAL csz%,free%,add%
  520 size%=(size%+511)AND-512
  530 mem%!0=0:PROCmmc_(&4003,mem%,0,32)           :REM Read global catalog
  540 mem%?8=13:IF$mem%<>"GoMMCCat":=0             :REM No global catalog
  550 mem%?8=0:csz%=mem%!16:free%=mem%!20
  560 add%=free%-size%:IFadd%-512<&240+csz%*64:=0 :REM GoMMC full
  570 !mem%=type%:mem%?1=subt%:mem%!4=add%:mem%!8=size%:mem%!12=0
  580 $(mem%+16)=name$:mem%?(16+LENname$)=0
  590 PROCmmc_(&4103,mem%,512+64*csz%,64)          :REM Add catalog entry
  600 PROCmmc_(&4103,mem%,add%-512+16,64)          :REM Add object entry copy
  610 $mem%="GoMMCEnt":mem%!8=0:mem%!12=0
  620 PROCmmc_(&4103,mem%,add%-512,16)             :REM Add object header
  630 PROCmmc_(&4003,mem%,16,8)
  640 mem%!0=csz%+1:mem%!4=add%-512                :REM Update catsize, free
  650 PROCmmc_(&4103,mem%,16,8)                    :REM Update global header
  660 !mem%=type%:mem%?1=subt%:mem%!4=add%:mem%!8=size%:mem%!12=0
  670 $(mem%+16)=name$:mem%?(16+LENname$)=0:=add%
  680 :
  690 REM List the GoMMC catalogue
  700 REM ------------------------
  710 REM mem%  - 64 bytes of memory for reading object entry
  720 REM Returns: free space pointer
  730 REM -----------------------------------------
  740 DEFFNmmc_Cat(mem%)
  750 LOCAL free%,csz%,n%
  760 PRINT" No Type    Start  Length Name"
  770 mem%!0=0:PROCmmc_(&4003,mem%,0,32)
  780 mem%?8=13:IF$mem%<>"GoMMCCat":PRINT" **No global catalog**":=0
  790 csz%=mem%!16:free%=mem%!20
  800 IF csz%:FOR n%=0 TO csz%-1:PROCmmc_(&4003,mem%,512+64*n%,64):PRINT" "FNd(n%+1,2)" "FNmmc_Type(mem%?0)" "FNh0(mem%?1,2)" "FNh0(mem%!5,6)" "FNh0(mem%!9,6)" "LEFT$(FNstr0(mem%+16),14)CHR$8:NEXT
  810 !mem%=free%:mem%!4=(512+csz%*64+511)AND-512:!mem%=!mem%-mem%!4
  820 PROCmmc_(&0201,0,0,0)
  830 PRINTSPC4FNh0(X%!7-32,6)SPC2FNh0(mem%!5+2,6)SPC1FNh0(mem%!1,6)" Free space"
  840 =free%
  850 :
  860 REM Sort the GoMMC catalogue
  870 REM ------------------------
  880 REM sort% - object word to sort by, or 0 to sort by type+name
  890 REM mem%  - 64 bytes of memory for object entry
  900 REM
  910 REM Returns: 0    - No GoMMC catalog
  920 REM          <>0  - Number of catalog entries
  930 REM -----------------------------------------
  940 DEFFNmmc_Sort(sort%,mem%)
  950 LOCAL swap%,diff%,csz%,n%
  960 mem%!0=0:PROCmmc_(&4003,mem%,0,32)
  970 mem%?8=13:IF$mem%<>"GoMMCCat":=0
  980 csz%=mem%!16:IF csz%<2:=1
  990 REPEAT:swap%=0:FOR n%=0 TO csz%-2
 1000     PROCmmc_(&4003,mem%+00,512+64*n%,64):PROCmmc_(&4003,mem%+64,&240+64*n%,64)
 1010     diff%=0:IF sort%:diff%=mem%!(sort%+64)-mem%!sort% ELSE A%=0:REPEAT:diff%=mem%?A%-mem%?(A%+64):A%=A%+1:A%=A%-12*(A%=4):UNTIL diff% OR A%=64
 1020     IF diff%>0:PROCmmc_(&4103,mem%+00,&240+64*n%,64):PROCmmc_(&4103,mem%+64,512+64*n%,64):swap%=1
 1030 NEXT n%:UNTIL swap%=0:=csz%
 1040 :