view CoCoOS9/level2v3/MODULES/os9p2.asm @ 31:bd2b07db8917 cocoos9lv2v3

CoCoOS9 version
author Shinji KONO <>
date Sat, 14 Jul 2018 15:16:13 +0900
line wrap: on
line source

* OS9p2 - OS-9 Level Two V3 P2 module
* $Id: os9p2.asm,v 2001/02/21 23:30:55 boisy Exp $
* Ed.    Comments                                       Who YY/MM/DD
* ------------------------------------------------------------------
* 18d    Removed bogus assumptions regarding init       BGP 98/10/05
*        module in order to shrink code size, added
*        check for CRC bit in compabibility byte of
*        init module.
* 18e    Made minor optimizations as per Curtis Boyle's BGP 98/10/10
*        optimization document

         nam   OS9p2
         ttl   OS-9 Level Two V3 P2 module

         use   defsfile

msiz     equ   256

F$IOMan  equ   $7F

rev      set   $05
edition  set   18

         mod   endmod,name,Systm,Reent+rev,entry,msiz

name     fcs   "OS9p2"
         fcb   edition

*              OS9p2 Inits Here:

entry    leay  SysCalls,pcr insert OS9p2 sys calls
         os9   F$SSvc
         ldu   <D.Init
         ldd   Maxmem,u   D=top of free mem
         lsra             D/16 (16 blocks/map)
         addd  <D.BlkMap  D+block map start
         tfr   d,x        X=D
         ldb   #NotRAM    get flag
         bra   L0036

L0030    lda   ,x+        get block marker
         bne   L0036      ..skip if used
         stb   -1,x       else set as none
L0036    cmpx  <D.BlkMap+2 end of map?
         bcs   L0030,loop

L003A    ldu   <D.Init    U=init module
         ldd   SysStr,u   point to '/D0' offset
         beq   L004F      ..none
         leax  d,u        X=name ptr
         lda   #READ.+EXEC.
         os9   I$ChgDir   'CHD /D0',CHX /D0
*         bcc   L004F      ..okay
*         os9   F$Boot     else boot
*         bcc   L003A      ..okay

L004F    ldu   <D.Init    init data
         ldd   StdStr,u   point to '/TERM'
         beq   L0077
         leax  d,u
         lda   #READ.+WRITE.
         os9   I$Open     try to open /Term
*         bcc   L0066      ..okay
*         os9   F$Boot     else boot and
*         bcc   L004F      ..try again
         bcs   Crash      crash!

L0066    ldx   <D.Proc    X=proc desc
         sta   P$Path,x   std in
         os9   I$Dup
         sta   P$Path+1,x std out
         os9   I$Dup
         sta   P$Path+2,x std err

L0077    leax  OS9p3Nam,pcr try to find OS9p3
         lbsr  SysLink
         bcs   L0083
         jsr   ,y         do it's init if it exists

L0083    ldu   <D.Init
         ldd   InitStr,u  point to 'Sysgo'
         leax  d,u
         lda   #Objct     mod type
         clrb             mem ok
         ldy   #$0000     no parms
         os9   F$Fork     start up sysgo
         os9   F$NProc    and do it.

OS9p3Nam fcs   "OS9p3"


Crash    jmp   <D.Crash   reset vector

*                  Service Calls:

SysCalls fcb   F$Unlink
         fdb   FUnlink-*-2
         fcb   F$Fork
         fdb   FFork-*-2
         fcb   F$Wait
         fdb   FWait-*-2
         fcb   F$Chain
         fdb   FChain-*-2
         fcb   F$Exit
         fdb   FExit-*-2
         fcb   F$Mem
         fdb   FMem-*-2
         fcb   F$Send
         fdb   FSend-*-2
         fcb   F$Icpt
         fdb   FIcpt-*-2
         fcb   F$Sleep
         fdb   FSleep-*-2
         fcb   F$SPrior
         fdb   FSPrior-*-2
         fcb   F$ID
         fdb   FID-*-2
         fcb   F$SSWI
         fdb   FSSWI-*-2
         fcb   F$STime
         fdb   FSTime-*-2
         fcb   F$SchBit
         fdb   FSchBit-*-2
         fcb   F$SchBit+$80 (sys)
         fdb   SSchBit-*-2
         fcb   F$AllBit
         fdb   FAllBit-*-2
         fcb   F$AllBit+$80 (sys)
         fdb   SAllBit-*-2
         fcb   F$DelBit
         fdb   FDelBit-*-2
         fcb   F$DelBit+$80
         fdb   SDelBit-*-2
         fcb   F$GPrDsc
         fdb   FGPrDsc-*-2
         fcb   F$GBlkMp
         fdb   FGBlkMp-*-2
         fcb   F$GModDr
         fdb   FGModDr-*-2
         fcb   F$CpyMem
         fdb   FCpyMem-*-2
         fcb   F$SUser
         fdb   FSUser-*-2
         fcb   F$Unload
         fdb   FUnload-*-2
         fcb   F$Find64+$80
         fdb   FFind64-*-2
         fcb   F$All64+$80
         fdb   FAll64-*-2
         fcb   F$Ret64+$80
         fdb   FRet64-*-2
         fcb   F$GProcP+$80
         fdb   FGProcP-*-2
         fcb   F$DelImg+$80
         fdb   FDelImg-*-2
         fcb   F$AllPrc+$80
         fdb   FAllPrc-*-2
         fcb   F$DelPrc+$80
         fdb   FDelPrc-*-2
         fcb   F$MapBlk
         fdb   FMapBlk-*-2
         fcb   F$ClrBlk
         fdb   FClrBlk-*-2
         fcb   F$DelRam
         fdb   FDelRam-*-2
         fcb   F$GCMDir+$80
         fdb   FGCMdir-*-2
         fcb   F$IOMan
         fdb   IOCall-*-2
         fcb   $80        End of Calls

* Link to a Systm module
SysLink  lda   #Systm
         os9   F$Link

*      The first I$Call will come here:

IOMgrNam fcs   "IOMan"

IOCall   pshs  a,b,x,y,u
         leax  IOMgrNam,pcr
         bsr   SysLink    try to find IOMan
* The following assumes os9p2 may be in the boot track and
* requires a call to F$Boot to get to IOMan.  This is
* not the case for the CoCo 3.
*         bcc   L0121      ..okay
*         os9   F$Boot     else boot
*         bcs   L012B      ..return err
*         bsr   SysLink      try again
         bcs   L012B
L0121    jsr   ,y         initialize IOMan
         puls  a,b,x,y,u
         ldx   $00FE,y    then do the call
         jmp   ,x

* Error, No IOMan:

L012B    stb   1,s        return err code
         puls  a,b,x,y,u,pc

*                     F$Unlink
FUnlink  pshs  a,b,u
         ldd   R$U,u      D=module address
         ldx   R$U,u      X=module address
         lsra             img block # = A/16
         sta   ,s         save usr map img num
         beq   L0183      ..ignore if zero

         ldu   <D.Proc    proc desc
         leay  P$DATImg,u map images
         asla             index by block#
         ldd   a,y        D= DAT image number
         ldu   <D.BlkMap  look it up
         ldb   d,u        in the block map
         bitb  #ModBlock  module in block?
         beq   L0183, okay
         leau  P$DATImg,y else see if done
         bra   L0161      with this block...

L015D    dec   ,s         at mod block?
         beq   L0183      ..yes, ignore.
L0161    ldb   ,s         usr block #
         aslb             index
         ldd   b,u        D=real number
         beq   L015D      skip if zero

         lda   ,s         else get usr blk #
         asla             *16 is module start
         clrb             B=00
         nega             A=-A
         leax  d,x        X=block begin
         ldb   ,s         usr blk #
         aslb             index
         ldd   b,y        D=img block
         ldu   <D.ModDir  U=mod dir
         bra   L0185      ..check mods in block

* Check Block for Mods:

L017C    leau  MD$ESize,u next entry
         cmpu  <D.ModEnd  end of dir?
         bcs   L0185, try more
L0183    bra   L01D0      ..yes,end.

L0185    cmpx  MD$MPtr,u  is it dir entry?
         bne   L017C, loop
         cmpd  [MD$MPDAT,u] image block same?
         bne   L017C, loop
         ldx   MD$Link,u  link count=0?
         beq   L0198      ..yes
         leax  -1,x       else link-1
         stx   MD$Link,u
         bne   L01B5      ..skip if not zero

L0198    ldx   2,s        X=reg stack
         ldx   R$U,x      X=mod ptr
         ldd   #M$Type    D=offset to type byte
         os9   F$LDDDXY   get module type/lang
         cmpa  #FlMgr     is it mgr,driver, or desc?
         bcs   L01B3
         os9   F$IODel    yes, delete it properly
         bcc   L01B3      ..ok
         ldx   MD$Link,u  else inc link count
         leax  1,x
         stx   MD$Link,u
         bra   L01D1      ..bad end.

L01B3    bsr   L01D5      delete moddir entry
L01B5    ldb   ,s         block dat
         aslb             index
         leay  b,y        Y=image ptr
         ldx   P$Links-P$DATImg,y link count
         leax  -1,x       -1
         stx   P$Links-P$DATImg,y
         bne   L01D0      ..skip if not zero

         ldd   MD$MBSiz,u block size
         bsr   L0226      change to #blocks
         ldx   #DAT.Free  free flag
L01CB    stx   ,y++       mark images free
         bne   L01CB

L01D0    clrb             okay
L01D1    leas  2,s        drop
         puls  u,pc       end unlink.

* Clear ModDir Entry:

L01D5    ldx   <D.BlkMap  X=ram map
         ldd   [MD$MPDAT,u] D=DAT img blk
         lda   d,x        A=map marker
         bmi   L0225      ..bra if not ram
         ldx   <D.ModDir  point to module dir

L01DF    ldd   [MD$MPDAT,x] get block #
         cmpd  [MD$MPDAT,u] same as this?
         bne   L01EA

         ldd   MD$Link,x  link cnt zero?
         bne   L0225
L01EA    leax  MD$ESize,x skip to next entry
         cmpx  <D.ModEnd  last?
         bcs   L01DF, keep looking

         ldx   <D.BlkMap  block map ptr
         ldd   MD$MBSiz,u module block size
         bsr   L0226      convert to #blocks
         pshs  y          save y
         ldy   MD$MPDAT,u module image ptr
L01FB    pshs  a,x        save #blocks, ptr
         ldd   ,y         get block number
         clr   ,y+        clear the image
         clr   ,y+
         leax  d,x        point to blkmap entry
         ldb   ,x
         andb  #^(RAMinUse+ModBlock) free block
         stb   ,x
         puls  a,x
         deca             last block done?
         bne   L01FB, loop

         puls  y
         ldx   <D.ModDir  module dir ptr
         ldd   MD$MPDAT,u image ptr

L0216    cmpd  ,x         was module here?
         bne   L021F
         clr   MD$MPDAT,x clear entry
         clr   MD$MPDAT+1,x
L021F    leax  MD$ESize,x next dir entry
         cmpx  <D.ModEnd  last?
         bcs   L0216, keep looking

L0225    rts              end clear moddir entry.

* Convert BlockSize to #Blocks:

L0226    addd  #$1FFF     round up

*                     F$Fork
FFork    pshs  u
         lbsr  L02EA      get proc desc
         bcc   L0238      ..ok, fork
         puls  u,pc       else err.

L0238    pshs  u          save child proc desc ptr
         ldx   <D.Proc    get parent's
         ldd   P$User,x   copy user index
         std   P$User,u
         lda   P$Prior,x  priority & age
         sta   P$Prior,u

         pshs  x,u        save proc. desc. addresses

         leax  P$NIO,x    copy Net IO ptrs <NEW>
         leau  P$NIO,u    <NEW>
         ldb   #NefIOSiz  Net table size <NEW>

L0250    lda   ,x+
         sta   ,u+
         bne   L0250

         puls  x,u        recover proc. desc. addresses
         leax  P$DIO,x    copy default data/exec dirs:
         leau  P$DIO,u
         ldb   #DefIOSiz
L0261    lda   ,x+
         sta   ,u+
         bne   L0261

         ldy   #3

* dup 1st 3 paths:

L026C    lda   ,x+
         beq   L0276      skip if not open
         os9   I$Dup
         bcc   L0276

* as std in/out/err:

L0276    sta   ,u+
         leay  -1,y       count-1
         bne   L026C

         ldx   ,s         X=child proc desc
         ldu   2,s        U=caller regs
         lbsr  L04B1      link/load mod, set proc desc
         bcs   L02CF      ..err
         pshs  a,b        save size
         os9   F$AllTsk   get task# for child
         bcs   L02CF

L028C    lda   P$PagCnt,x D=mem amt
         subd  ,s         D-mod size
         tfr   d,u        U=dest
         ldb   P$Task,x   B=child task# for parm copy
         ldx   <D.Proc    parent's proc desc
         lda   P$Task,x   and task
         leax  ,y         X=parameter ptr
         puls  y          Y=count
         os9   F$Move     X(A)-->U(B) *Y copy over data

         ldx   ,s         copy over child's stack
         lda   <D.SysTsk
         ldu   P$SP,x
         leax  P$Stack-R$Size,x
         ldy   #R$Size
         os9   F$Move     X(A)-->U(B) *Y

         puls  x,u
         os9   F$DelTsk   release child task#
         ldy   <D.Proc    Y=parents proc desc
         lda   P$ID,x     X=childs proc desc
         sta   R$A,u      return it
         ldb   P$CID,y    B=sibling
         sta   P$CID,y    let parent have child
         lda   P$ID,y     parents ID
         std   P$PID,x    set child's parent/sibling
         lda   P$State,x
         anda  #^SysState take child out of sys
         sta   P$State,x  state and
         os9   F$AProc    activate it
         rts              end.

* Error - couldn't link/load pgm:

L02CF    puls  x          bad proc desc
         pshs  b          save error
         lbsr  L05A5      close paths & unlink mem
         lda   P$ID,x     get bad id
         lbsr  L0386      delete proc desc & task#
         comb             set err
         puls  b,u,pc     bad end.

*                     F$AllPrc
FAllPrc  pshs  u          save reg ptr
         bsr   L02EA      allocate process desc
         bcs   L02E8      ..err
         ldx   ,s         get reg ptr
         stu   R$U,x      return proc desc ptr
L02E8    puls  u,pc       end.

* Allocate a Proc Desc:

L02EA    ldx   <D.PrcDBT  X=proc table
L02EC    lda   ,x+        search 'til empty
         bne   L02EC      is found

         leax  -1,x       back up to it
         tfr   x,d        D=addrss
         subd  <D.PrcDBT  D=index
         tsta             >256?
         beq   L02FE, ok
         comb             else
         ldb   #E$PrcFul  'Process Table Full'
         bra   L032F

L02FE    pshs  b          save index
         ldd   #P$Size    get 512 bytes
         os9   F$SRqMem   for proc desc
         puls  a          A=index
         bcs   L032F      ..err
         sta   P$ID,u     set proc ID
         tfr   u,d        D=proc desc addrss
         sta   ,x         set proc desc msb in table

         clra             D=0000
         leax  P$PID,u    start after ID
         ldy   #$80       256 byte count
L0317    std   ,x++       clear proc desc
         leay  -1,y
         bne   L0317

         ldy   <D.Proc    get current proc desc address
         ldx   <D.SysPrc  get system proc desc address
         stx   <D.Proc    make system current proc
         leax  P$DatBeg,u new proc desc creation date/time tag
         os9   F$Time     ignore any error...
         sty   <D.Proc    restore current proc desc address

         lda   #SysState  set system state
         sta   P$State,u
         ldb   #DAT.BlCt  mark all blocks as unused
         ldx   #DAT.Free
         leay  P$DATImg,u in the proc images
L0329    stx   ,y++
         bne   L0329
         clrb             okay
L032F    rts   

*                     F$DelPrc
FDelPrc  lda   R$A,u      get proc id
         bra   L0386      delete it

*                     F$Wait
FWait    ldx   <D.Proc    proc desc
         lda   P$CID,x    any children?
         beq   L0368, quick return

L033A    lbsr  L0B2E      find child proc desc
         lda   P$State,y
         bita  #Dead      has it died?
         bne   L036C      ..yes
         lda   P$SID,y    else does it have sibling?
         bne   L033A      ..yes, check it

         sta   R$A,u      return child's id

         sta   R$B,U

         pshs  cc         save CC
         orcc  #IntMasks  stop interrupts

         lda   P$SIGNAL,X
         beq   N035D
         bne   N035A
         sta   P$SIGNAL,X
N035A    lbra  L071B

N035D    ldd   <D.WProcQ  insert caller
         std   P$Queue,x  into waiting proc
         stx   <D.WProcQ  queue
         puls  cc         restore CC
         lbra  L0780      and go wait.

L0368    comb  
         ldb   #E$NoChld  'No Child Error'

L036C    lda   P$ID,y     get child id
         ldb   P$Signal,y and its death signal
         std   R$A,u      return to caller
         leau  ,y         child proc desc
         leay  P$CID-P$SID,x
         bra   L037C      go bury child

L0379    lbsr  L0B2E      find proc desc
L037C    lda   P$SID,y    is sibling the link?
         cmpa  P$ID,u
         bne   L0379, try next
         ldb   P$SID,u    link in other
         stb   P$SID,y    siblings

* Delete Proc Desc & Task#:

L0386    pshs  a,b,x,u

         cmpa  WGlobal+G.AlPID is alarm call for this task?
         bne   NEWLABEL   no ....
         clr   WGlobal+G.AlPID clear task #
         clr   WGlobal+G.AlSig clear signal

NEWLABEL ldb   ,s         <NEW LABEL>
         ldx   <D.PrcDBT  X=proc desc table
         abx              index task
         lda   ,x         get pointer
         beq   L03AC      ..quick ok if none
         clrb             else clear ptr
         stb   ,x
         tfr   d,x        X=proc desc
         os9   F$DelTsk   release task flag
         leau  ,x         U=proc desc
         ldd   #P$Size    return 512 byte
         os9   F$SRtMem   proc desc mem
L03AC    puls  a,b,x,u,pc end.

*                     F$Chain
FChain   pshs  u          save U
         lbsr  L02EA      allocate proc desc
         bcc   L03B7      ..go chain
         puls  u,pc

* Copy Proc Desc Data:

L03B7    ldx   <D.Proc    save proc
         pshs  x,u
         leax  P$SP,x     copy from P$SP-->
         leau  P$SP,u
         ldy   #$007E     252 byte count

L03C3    ldd   ,x++       copy bytes
         std   ,u++
         leay  -1,y
         bne   L03C3

         ldu   2,S        get new proc desc address
         leau  P$DATImg,u point to DAT image
         ldx   ,S         get old proc desc
         lda   P$Task,x   get old task #
         asla             task # x2 is index
         ldx   <D.TskIPt  point to DAT image table
         stu   A,X        put image address into table

         ldx   <D.Proc    proc desc
         clra             D=0000
         stb   P$Task,x   set no task#
         std   P$SWI,x    sys swi's
         std   P$SWI2,x
         std   P$SWI3,x
         sta   P$Signal,x no signal/vecs
         std   P$SigVec,x
         ldu   P$PModul,x unlink primary module
         os9   F$Unlink
         ldb   P$PagCnt,x mem page count
         addb  #$1F       round up
         lsrb             B/16 (pages-->blocks)
         lda   #DAT.BlCt  max count=16
         pshs  b          -num used
         suba  ,s+        =number to release:
         leay  P$DATImg,x Y=images
         aslb             index
         leay  b,y        first block
         ldu   #DAT.Free  not used flag
L040C    stu   ,y++       clear proc images
         bne   L040C

         ldu   2,s        set new proc desc
         stu   <D.Proc
         ldu   P$SP,s
         lbsr  L04B1      link/load module

         bcs   L04A1      ..err

         pshs  a,b        save size
         os9   F$AllTsk   get task# for new proc (if possible)
         bcc   L0425

* Chain Error:

         leas  2,s        dump parm size

         puls  x,u
         stx   <D.Proc    reset proc
         pshs  cc,b       save error status/info
         lda   P$ID,u     get temp proc id
         lbsr  L0386      and delete proc desc
         puls  cc,b       recover error status/info
         os9   F$Exit     and exit gracefully

L0425    ldu   <D.Proc    U=new proc
         lda   P$Task,u   A=source tsk#
         ldb   P$Task,x   B=dest tsk#
         leau  P$Stack-R$Size,x ($01F4)
         leax  ,y         source ptr
         ldu   R$X,u      dest ptr
         pshs  u          source ptr >
         cmpx  ,s++       dest ptr?
         puls  y          size
         bhi   L0471      ..yes
         beq   L0474      same place
         leay  ,y         size=zero?
         beq   L0474      ..yes

         pshs  a,b,x
         tfr   y,d        size
         leax  d,x        source end ptr
         pshs  u          save dest
         cmpx  ,s++       source within dest?
         puls  a,b,x
         bls   L0471

         pshs  a,b,x,y,u
         tfr   y,d        size
         leax  d,x        source end ptr
         leau  d,u        dest end ptr

* Copy Parms:

L0457    ldb   ,s         source task#
         leax  -1,x       back up fm end
         os9   F$LDABX    get byte
         exg   x,u        src <--> dest
         ldb   1,s        task#
         leax  -1,x       back up dest ptr
         os9   F$STABX    store byte
         exg   x,u
         leay  -1,y       cnt-1
         bne   L0457

         puls  a,b,x,y,u
         bra   L0474

L0471    os9   F$Move     X(A)-->U(B) *Y
L0474    lda   <D.SysTsk  from sys map
         ldx   ,s         get proc desc
         ldu   P$SP,x     and stack pointer
         leax  P$Stack-R$Size,x point to proc stack
         ldy   #R$Size    stack count
         os9   F$Move     X(A)-->U(B) *Y copy from proc desc
         puls  x,u        stack to user reg stack
         lda   P$ID,u     get id
         lbsr  L0386      delete temp proc desc & free task#
         os9   F$DelTsk   delete task#
         orcc  #IntMasks  halt interrupts
         ldd   <D.SysPrc  set system as proc
         std   <D.Proc
         lda   P$State,x  drop system state
         anda  #^SysState
         sta   P$State,x
         os9   F$AProc    insert in active queue
         os9   F$NProc    and start next process.
* NOTE:  F$NProc will NOT return control to caller.
*        This routine ends here, no error possible.

* Init New Proc Desc:
* Link or Load Primary Module:

L04B1    pshs  a,b,x,y,u
         ldd   <D.Proc    proc desc
         pshs  a,b        save it
         stx   <D.Proc    temp proc
         lda   R$A,u      type
         ldx   R$X,u      name
         ldy   ,s         new proc desc
         leay  P$DATImg,y Y=new images
         os9   F$SLink    link in primary mod
         bcc   L04D7      ..ok

         ldd   ,s         else restore old proc
         std   <D.Proc
         ldu   4,s        get new proc desc
         os9   F$Load     use sys f$load
         bcc   L04D7      ..ok
         leas  4,s        else drop junk
         puls  x,y,u,pc   return err.

L04D7    stu   2,s        save mod address
         pshs  a,y        save mod type,entry
         ldu   $0B,s      U=usr regs (old P$SP)
         stx   R$X,u      update name ptr
         ldx   7,s        set new process desc
         stx   <D.Proc
         ldd   5,s        set primary module addrss
         std   P$PModul,x
         puls  a          module type
         cmpa  #Prgrm+Objct is it program module?
         beq   L04FB      ..yes
         cmpa  #Systm+Objct is it system module?
         beq   L04FB      ..yes

         ldb   #E$NEMod   'Non-Executable Module'
L04F4    leas  2,s        drop return
         stb   3,s        return err code
         comb             set err
         bra   L053E      restore proc desc & rts.

* Allocate data memory and set child regs:

L04FB    ldd   #M$Mem     offset to mem size
         leay  P$DATImg,x image
         ldx   P$PModul,x mod address
         os9   F$LDDDXY   get mem size
         cmpa  R$B,u      greater than user request?
         bcc   L050E      ..yes
         lda   R$B,u      no, use request
         clrb             to page boundary
L050E    os9   F$Mem      get U=data memory
         bcs   L04F4      ..err

         ldx   6,s        parent proc desc
         leay  P$Stack-R$Size,x
         pshs  a,b        save mem size
         subd  R$Y,u      -parm size
         std   R$X,y      is new parm pointer
         subd  #R$Size    memsize-reg stack
         std   P$SP,x     is new stack pointer

         ldd   R$Y,u      get parm size
         std   R$D,y      D is parm size
         std   6,s        return to caller
         puls  a,b,x      mem and entry
         std   R$Y,y      Y is end of data mem
         ldd   R$U,u      parm ptr
         std   6,s        return
         lda   #Entire    CC register is full rti
         sta   R$CC,y     set cc reg
         sta   R$DP,y     DP is 00
         std   R$U,y      U is data address
         stx   R$PC,y     PC is module exec address

L053E    puls  a,b        restore proc desc
         std   <D.Proc
         puls  a,b,x,y,u,pc return.

*                     F$Exit
FExit    ldx   <D.Proc    proc desc
         bsr   L05A5      close paths & return memory
         ldb   R$B,u      get exit signal
         stb   P$Signal,x and save in proc desc
         leay  P$CID-P$SID,x parent id
         bra   L0563      go find kids...

L0551    clr   P$SID,y    clear sibling pointer
         lbsr  L0B2E      find its proc desc
         clr   P$PID,y    clear its parent ptr (us)
         lda   P$State,y  get child's state
         bita  #Dead      is it dead?
         beq   L0563
         lda   P$ID,y     else get its id
         lbsr  L0386      and destroy its proc desc
L0563    lda   P$SID,y    did it have a sibling?
         bne   L0551      ..yes,loop

         leay  ,x         kid's proc desc
         ldx   #D.WProcQ-P$Queue
         lds   <D.SysStk  use system stack
         pshs  cc         save CC
         orcc  #IntMasks  halt interrupts while queuing
         lda   P$PID,y    get our parent id
         bne   L0584      ..and wake him up

         puls  cc         restore CC
         lda   P$ID,y     our id
         lbsr  L0386      give up our proc desc
         bra   L05A2      and start next active process.

* Search For Waiting Parent:

L0580    cmpa  P$ID,x     is proc desc our parent's?
         beq   L0592      ..yes!

L0584    leau  ,x         U is base desc
         ldx   P$Queue,x  X is next waiter
         bne   L0580      see if parent
         puls  cc         restore CC
         lda   #SysState+Dead set us to system state
         sta   P$State,y  and mark us as dead
         bra   L05A2      so F$Wait will find us; next proc.

* Found Parent (X):

L0592    ldd   P$Queue,x  take parent out of  wait queue
         std   P$Queue,u
         puls  cc         restore CC
         ldu   P$SP,x     get parents reg stack
         ldu   R$U,u
         lbsr  L036C      get child's death signal to parent
         os9   F$AProc    move parent to active queue
L05A2    os9   F$NProc    start next proc in active queue.

* Close Proc I/O Paths & Unlink Mem:

L05A5    pshs  u          save
         ldb   #NumPaths  B=up to 16 paths
         leay  P$Path,x   point to proc desc paths
L05AC    lda   ,y+        get path desc#
         beq   L05B9      ..skip if not used
         clr   -1,y       else clr it
         pshs  b          save cnt
         os9   I$Close    close path
         puls  b
L05B9    decb             count-1
         bne   L05AC      ..loop

         clra             begin block=00
         ldb   P$PagCnt,x any memory used?
         beq   L05CB
         addb  #$1F       round up mem
         lsrb             mem/16 = blocks used
         os9   F$DelImg   return mem
L05CB    ldd   <D.Proc    save current proc
         pshs  a,b
         stx   <D.Proc    set bad proc
         ldu   P$PModul,x pgrm ptr
         os9   F$Unlink   unlink aborted pgrm
         puls  a,b,u
         std   <D.Proc    reset parent proc
         os9   F$DelTsk   release X's task#
         rts              .

*                     F$Mem
FMem     ldx   <D.Proc    proc
         ldd   R$D,u      get mem request
         beq   L0638      ..return current size request
         addd  #$00FF     else round up size
         bcc   L05EE      ..okay if <64K
         ldb   #E$MemFul  'Memory Full'
         bra   L0629      ..err end

L05EE    cmpa  P$PagCnt,x same as current?
         beq   L0638      ..yes
         pshs  a          save amt
         bcc   L0602      ..go for more mem

         deca             go for less mem
         ldb   #$F4       enuf room for SP?
         cmpd  P$SP,x
         bcc   L0602      ..yes
         ldb   #E$DelSP   'Suicide Attempt'
         bra   L0627

L0602    lda   P$PagCnt,x get current size
         adda  #$1F       round up
         lsra             A/16 = block cnt
         ldb   ,s         B=pages wanted
         addb  #$1F       round up
         bcc   L0615      ..ok
         ldb   #E$MemFul  'Memory Full'
         bra   L0627

L0615    lsrb             B/16 = blocks wanted
         pshs  a          save #blocks now
         subb  ,s+        B=# difference
         beq   L0634      ..same
         bcs   L062C      ..less
         os9   F$AllImg   else get mem
         bcc   L0634      ..err

* Error ends:

L0627    leas  1,s
L0629    orcc  #Carry

* Need Less Mem:

L062C    pshs  b          save amt less
         adda  ,s+        + amt now
         os9   F$DelImg   return mem blocks
L0634    puls  a          get new amt
         sta   P$PagCnt,x set in proc desc

* Return Mem Size to user:

L0638    lda   P$PagCnt,x D=byte count
         std   R$D,u      return size
         std   R$Y,u      and upper bound

*                     F$Send
FSend    ldx   <D.Proc    proc desc
         lda   R$A,u      A=dest proc
         bne   L0652      ..send if <> 00
         inca             else send to all ('cept zero)
L0647    cmpa  ,x         our proc?
         beq   L064D      ..skip if is
         bsr   L0652      else send signal
L064D    inca             ID+1
         bne   L0647      done 255?
         clrb             yep
         rts              end.

* Send signal to Proc A:

L0652    lbsr  L0B2E      find proc desc
         pshs  cc,a,y,u
         bcs   L066A      ..not found
         tst   R$B,u      is signal = zero? (Kill)
         bne   L066D
         ldd   P$User,x   are we superuser?
         beq   L066D      ..yes
         cmpd  P$User,y   else same user?
         beq   L066D      ..yes
         ldb   #E$IPrcID  'Illegal Proc ID'
         inc   ,s         set carry bit
L066A    lbra  L06F4

L066D    orcc  #IntMasks  stop interrupts
         ldb   R$B,u      B=signal
         bne   L067B      skip if not Kill

         ldb   #E$PrcAbt  'Keyboard Abort' (#2)
         lda   P$State,y
         ora   #Condem    condemn process
         sta   P$State,y

* Wake Up Dest Process:

L067B    lda   P$State,y
         anda  #^Suspend  (F7) drop suspend
         sta   P$State,y  state
         lda   P$Signal,y have signal now?
         beq   L068F
         deca             else was it wake?
         beq   L068F      ..yes
         inc   ,s         set carry
         ldb   #E$USigP   'Signal Error'
         bra   L06F4

L068F    stb   P$Signal,y save signal
         ldx   #D.SProcQ-P$Queue search sleep queue
         clra             ticks left=0000

L0697    leay  ,x         Y is base desc
         ldx   P$Queue,x  X is next qproc
         beq   L06D3      ..last
         ldu   P$SP,x     else get process
         addd  R$X,u      add ticks
         cmpx  2,s        same as dest proc desc?
         bne   L0697, loop

         pshs  a,b        save tick count
         lda   P$State,x  is process time sleeping?
         bita  #TimSleep
         beq   L06CF it's not

         ldd   ,s         get tick count
         beq   L06CF      ..bra if none
         ldd   R$X,u      get time left
         pshs  a,b        save it
         ldd   2,s        get ticks left
         std   R$X,u      make it new time left
         puls  a,b        tick count
         ldu   P$Queue,x  qproc after this one?
         beq   L06CF
         std   ,s
         lda   P$State,u  time sleeping?
         bita  #TimSleep
         beq   L06CF its not

         ldu   P$SP,u     next proc SP
         ldd   ,s         update tick count
         addd  R$X,u
         std   R$X,u

L06CF    leas  2,s        drop
         bra   L06E0      give signal...

L06D3    ldx   #D.WProcQ-P$Queue search wait queue
L06D6    leay  ,x         base proc desc
         ldx   P$Queue,x  get next in queue
         beq   L06F4      ..end if none
         cmpx  2,s        signal dest proc?
         bne   L06D6

L06E0    ldd   P$Queue,x  take proc out of queue
         std   P$Queue,y
         lda   P$Signal,x has signal
         deca             other than S$Wake?
         bne   L06F1      ..yes
         sta   P$Signal,x no, clear for wakeup
         lda   ,s         restore CC
         tfr   a,cc
L06F1    os9   F$AProc    insert proc in active queue
L06F4    puls  cc,a,y,u,pc return.

*                     F$Icpt
FIcpt    ldx   <D.Proc    proc desc
         ldd   R$X,u      set signal vector
         std   P$SigVec,x
         ldd   R$U,u      and data area
         std   P$SigDat,x
         clrb             ok
         rts              end.

*                     F$Sleep
FSleep   pshs  cc         save int masks
         ldx   <D.Proc    proc desc
         orcc  #IntMasks  stop interrupts here
         lda   P$Signal,x have unprocessed signal?
         beq   L0722
         deca             yes, was it Wake?
         bne   L0715
         sta   P$Signal,x yes, ignore it

L0715    lda   P$STATE,X
         anda  #^SUSPEND  DROP SUSPEND
         sta   P$STATE,X

L071B    puls  cc         restore CC
         os9   F$AProc    activate immediately
         bra   L0780

* Do the Sleep:

L0722    ldd   R$X,u      sleep forever?
         beq   L076D      ..yes
         subd  #$0001     else -1 already
         std   R$X,u      save tick cnt

         beq   L071B      ..awake if was just 1
         pshs  x,y        save
         ldx   #D.SProcQ-P$Queue

L0732    std   R$X,u      return tick count
         stx   2,s        temp var
         ldx   P$Queue,x  X=next queue proc
         beq   L074F      ..end of line
         lda   P$State,x  is it still
         bita  #TimSleep  asleep?
         beq   L074F
         ldy   P$SP,x     yes, get its
         ldd   R$X,u      X register and
         subd  R$X,y      compare to ours
         bcc   L0732      ..try next if we're more

         nega             else negate count
         sbca  #$00
         std   R$X,y      and update proc sleep ticks
L074F    puls  x,y        queue proc ptrs
         lda   P$State,x  set proc as
         ora   #TimSleep  tick sleeping
         sta   P$State,x
         ldd   P$Queue,y  insert us in queue
         stx   P$Queue,y
         std   P$Queue,x
         ldx   R$X,u      get ticks requested
         bsr   L0780      go wait for wakeup

         stx   R$X,u      return ticks left
         ldx   <D.Proc
         lda   P$State,x  drop sleep flag
         anda  #^TimSleep
         sta   P$State,x
         puls  cc,pc      return to caller.

L076D    ldx   #D.SProcQ-P$Queue start at first asleep

L0770    leay  ,x         Y is base proc
         ldx   P$Queue,x  X is next qproc
         bne   L0770      ..not last yet
         ldx   <D.Proc    else get our proc
         clra             D=0000
         stx   P$Queue,y  put us at end of queue
         std   P$Queue,x  and mark none after us now
         puls  cc         restore CC

* Wait for Signal/Wakeup:

L0780    pshs  x,y,u,pc   make vars
         leax  <L079C,pcr point to wakeup code
         stx   6,s        put as rts pcr
         ldx   <D.Proc
         ldb   P$Task,x   are we sys proc?
         cmpb  <D.SysTsk
         beq   L0792      ..yes
         os9   F$DelTsk   else release task#
L0792    ldd   P$SP,x     save stack pointer
         pshs  cc,a,b,dp
         sts   P$SP,x     and temp SP
         os9   F$NProc    go do next proc.

* Proc Wakes up here:

L079C    pshs  x          save tick count
         ldx   <D.Proc
         std   P$SP,x     restore real SP
         clrb             ok
         puls  x,pc       return from sleep.

*                     F$SPrior
FSprior  lda   R$A,u      get id
         lbsr  L0B2E      find proc desc
         bcs   L07C0      ..err
         ldx   <D.Proc    get our user index
         ldd   P$User,x
         beq   L07B7 is ok
         cmpd  P$User,y   same as id?
         bne   L07BD, err
L07B7    lda   R$B,u      get desired priority
         sta   P$Prior,y  set it in id
         clrb             ok
         rts              end.

L07BD    comb  
         ldb   #E$IPrcID  'Illegal Process ID'
L07C0    rts   

*                     F$ID
FID      ldx   <D.Proc    proc desc
         lda   P$ID,x     get id
         sta   R$A,u      return it
         ldd   P$User,x   and user
         std   R$Y,u      index to caller
         clrb             ok
         rts              end.

*                     F$SSWI
FSSWI    ldx   <D.Proc    proc desc
         leay  P$SWI,x    point to SWI vectors
         ldb   R$A,u      B=swi to set
         decb             B-1
         cmpb  #$03       0-2?
         bcc   L07DF, err
         aslb             else index
         ldx   R$X,u      get new vector
         stx   b,y        and set it
         rts              end.

L07DF    comb  
         ldb   #E$ISWI    'Illegal SWI code'

*                     F$STime
ClockNam fcs   "Clock"

FSTime   ldx   R$X,u      X=time packet
         tfr   dp,a       A=DP
         ldb   #D.Time    B=sys time addrss
         tfr   d,u        U=sys time location
         ldy   <D.Proc
         lda   P$Task,y   A=from tsk#
         ldb   <D.SysTsk  B=to (sys) tsk#
         ldy   #$0006     copy over time data
         os9   F$Move     X(A)-->U(B) *Y
         ldx   <D.Proc    save user proc
         pshs  x
         ldx   <D.SysPrc  make sys for link
         stx   <D.Proc
         leax  ClockNam,pcr link to Clock
         lbsr  SysLink
         puls  x
         stx   <D.Proc    restore user proc
         bcs   L0816      ..err end
         jmp   ,y         else go do Clock init.

L0816    rts   

*                     F$AllBit
FAllBit  ldd   R$D,u      number of first bit
         ldx   R$X,u      map address
         bsr   L086E      get X=addrss, A=mask
         ldy   <D.Proc    proc desc
         ldb   P$Task,y   use usr map
         bra   L082C

SAllBit  ldd   R$D,u      number of first bit
         ldx   R$X,u      map address
         bsr   L086E      get X=addrss, A=mask
         ldb   <D.SysTsk  use sys map

L082C    ldy   R$Y,u      Y=number of bits
         beq   L086C      ..none
         sta   ,-s        save mask
         bmi   L0847      skip if no bit0
         os9   F$LDABX    get map byte
L0838    ora   ,s         set bit
         leay  -1,y       count-1
         beq   L0867      ..quik end if last
         lsr   ,s         next bit
         bcc   L0838      ..loop if not bit7

         os9   F$STABX    else store map byte
         leax  1,x        map addrss+1

L0847    lda   #$FF       now quik set byte at a time
         bra   L0852

* Byte at a Time:

L084B    os9   F$STABX    store map byte
         leax  1,x        map addrss+1
         leay  -8,y       bit count-8/byte

L0852    cmpy  #$0008     under 8 bits to go?
         bhi   L084B, continue byte at a time
         beq   L0867      ..exactly one byte left

* Last byte:

L085A    lsra             move mask into pos
         leay  -1,y       for last byte
         bne   L085A      ..

         coma             fix mask
         sta   ,s         save it
         os9   F$LDABX    get last map byte
         ora   ,s         set last bits
L0867    os9   F$STABX    update last map byte
         leas  1,s        drop mask
L086C    clrb             okay
         rts              return.

L086E    pshs  b,y        save regs & low order 0-7
         rorb             D/8
         leax  d,x        X=byte address
         puls  b          B=low order
         leay  <L0883,pcr table of A shifted
         andb  #$07       B=bit count
         lda   b,y        get mask for A
         puls  y,pc       return.

* Mask Table:

L0883    fcb   $80
         fcb   $40
         fcb   $20
         fcb   $10
         fcb   $08
         fcb   $04
         fcb   $02
         fcb   $01

*                     F$DelBit
FDelBit  ldd   R$A,u
         ldx   R$X,u
         bsr   L086E
         ldy   <D.Proc
         ldb   P$Task,y
         bra   L08A0

SDelBit  ldd   R$A,u
         ldx   R$X,u
         bsr   L086E
         ldb   <D.SysTsk

L08A0    ldy   R$Y,u
         beq   L08E0
         sta   ,-s
         bpl   L08BC
         os9   F$LDABX
L08AD    anda  ,s
         leay  -1,y
         beq   L08DB
         asr   ,s
         bcs   L08AD
         os9   F$STABX
         leax  1,x
L08BC    clra  
         bra   L08C6

L08BF    os9   F$STABX
         leax  1,x
         leay  -8,y
L08C6    cmpy  #8
         bhi   L08BF
         beq   L08DB
L08CF    lsra  
         leay  -1,y
         bne   L08CF
         sta   ,s
         os9   F$LDABX
         anda  ,s
L08DB    os9   F$STABX
         leas  1,s
L08E0    clrb  

*                     F$SchBit
FSchBit  ldd   R$D,u      search start bit #
         ldx   R$X,u      map address
         bsr   L086E      set byte mask
         ldy   <D.Proc    use user map
         ldb   P$Task,y
         bra   L08F8      do it

SSchBit  ldd   R$D,u      search start bit #
         ldx   R$X,u      map address
         lbsr  L086E      set byte mask
         ldb   <D.SysTsk  use sys map

L08F8    pshs  cc,a,b,x,y,u
         clra             D=0000
         std   3,s
         ldy   R$D,u
         sty   7,s
         bra   L0911

L0906    sty   7,s
L0909    lsr   1,s
         bcc   L091C
         ror   1,s
         leax  1,x
L0911    cmpx  R$U,u      end of map?
         bcc   L093A      ..yes
         ldb   2,s
         os9   F$LDABX
         sta   ,s
L091C    leay  1,y
         lda   ,s
         anda  1,s
         bne   L0906

         tfr   y,d
         subd  7,s
         cmpd  R$Y,u
         bcc   L0943
         cmpd  3,s
         bls   L0909
         std   3,s
         ldd   7,s
         std   5,s
         bra   L0909

L093A    ldd   3,s
         std   R$Y,u
         ldd   5,s
         bra   L0945

L0943    ldd   7,s
L0945    std   R$D,u
         leas  9,s

*                     F$GPrDsc
FGprDsc  ldx   <D.Proc    proc desc
         ldb   P$Task,x   B=dest task#
         lda   R$A,u      A=desired ID
         os9   F$GProcP   get B=ptr to proc desc
         bcs   L0962
         lda   <D.SysTsk  A=from tsk#
         leax  ,y         X=proc desc
         ldy   #P$Size    512 bytes
         ldu   R$X,u      U=dest buffer
         os9   F$Move     X(A)-->U(B) *Y
L0962    rts              end.

*                     F$GBlkMp
FGblkMp  ldd   #$2000     RETURN 8K BLOCK SIZE
         std   R$D,u
         ldd   <D.BlkMap+2 return blk map size
         subd  <D.BlkMap
         std   R$Y,u
         tfr   d,y        Y=count
         lda   <D.SysTsk  A=from sys
         ldx   <D.Proc
         ldb   P$Task,x   B=to user
         ldx   <D.BlkMap  X=block map
         ldu   R$X,u      U=dest buffer
         os9   F$Move     X(A)-->U(B) *Y

*                     F$GModDr
FGModDr  ldd   <D.ModDir+2 D=end of moddir
         subd  <D.ModDir  -begin
         tfr   d,y        Y=size
         ldd   <D.ModEnd  D=top of dir stack
         subd  <D.ModDir  D=size
         ldx   R$X,u      X=dest buffer
         leax  d,x        plus size
         stx   R$Y,u      return size to user
         ldx   <D.ModDir  and moddir
         stx   R$U,u      address

         lda   <D.SysTsk  A=sys task
         ldx   <D.Proc    B=usr task
         ldb   P$Task,x
         ldx   <D.ModDir  X=moddir
         ldu   R$X,u      U=dest buffer
         os9   F$Move     X(A)-->U(B) *Y
         rts              end.

*                     F$SUser
FSUser   ldx   <D.Proc    proc desc
         ldd   R$Y,u      D=user num
         std   P$User,x   set it
         clrb             ok
         rts              end.

*                     F$CpyMem
FCpyMem  ldd   R$Y,u      byte count
         beq   L0A01      ..skip if none
         addd  R$U,u      plus dest buff
         bcs   L0A01
         leas  -$10,s
         leay  ,s
         pshs  a,b,y      save buff end,img ptr
         ldx   <D.Proc
         ldb   P$Task,X
         pshs  b          save caller task#
         leay  P$DATImg,x
         ldx   R$D,u      X=caller DAT img ptr
         ldb   #8
         pshs  b,u
         ldu   P$Task,s   U=tempdat ptr

L09C7    clra             D=0000
         os9   F$LDDDXY   move user DAT image
         std   ,u++       to sys tempDAT img
         leax  2,x
         dec   ,s
         bne   L09C7      ..loop

         puls  b,u
         ldx   R$X,u      X=offset
         ldu   R$U,u      U=dest buffer
         ldy   3,s        Y=tmpDAT

         puls  b
         bra   L09E7

N09D6    leax  $E000,x
         leay  2,y

* Copy Loop:

L09E7    cmpx  #$2000
         bcc   N09D6

L09EC    os9   F$LDAXY    get byte
         leax  1,x
         exg   x,u

         os9   F$STABX    store byte
         leax  1,x        plus one
         cmpx  ,s
         exg   x,u
         bcs   L09E7
         leas  $14,s

L0A01    clrb             ok
         rts              end.

*                     F$UnLoad
FUnload  pshs  u
         lda   R$A,u      A=type
         ldx   <D.Proc    proc desc
         leay  P$DATImg,x images ptr
         ldx   R$X,u      X=name
         os9   F$FModul   find the module
         puls  y          reg stack
         bcs   L0A4F      ..err

         stx   R$X,y      update name ptr
         ldx   MD$Link,u  get module link cnt
         beq   L0A21
         leax  -1,x       else decrement it
         stx   MD$Link,u
         bne   L0A4E      ..skip if still in use

L0A21    cmpa  #FlMgr     system module?
         bcs   L0A4B

         ldx   [MD$MPDAT,u] get module block
         ldy   <D.SysDAT  check against sys map
L0A2B    adda  #$02       next offset
         cmpa  #DAT.ImSz  last?
         bcc   L0A4B      ..yes
         cmpx  a,y        else found right img?
         bne   L0A2B, loop

         asla             A/8 block# -->address
         addd  MD$MPtr,u  point to module
         tfr   d,x
         os9   F$IODel    delete I/O module
         bcc   L0A4B      ..ok

         ldx   MD$Link,u  else if error,
         leax  1,x
         stx   MD$Link,u  increment link cnt
         bra   L0A4F

L0A4B    lbsr  L01D5      clear moddir entry
L0A4E    clrb             ok
L0A4F    rts              end.

*                     F$Find64
FFind64  lda   R$A,u      get pd block number
         ldx   R$X,u      get block address
         bsr   L0A5C      find it
         bcs   L0A5B      ..err
         sty   R$Y,u      return address
L0A5B    rts              end.

* Find Path/Process Descriptor:

L0A5C    pshs  a,b        save number, make space
         tsta             number=zero?
         beq   L0A70      ..yes,bad
         clrb             else...
         lsra             number/4
         rorb             (point to block ptr)
         lda   a,x        use index to get
         tfr   d,y        block address
         beq   L0A70      ..none
         tst   ,y         is block in use?
         bne   L0A71      ..yes, okay!
L0A70    coma             set error
L0A71    puls  a,b,pc     return.

*                     F$All64
FAll64   ldx   R$X,u      get base page
         bne   L0A7F      ..okay if have one
         bsr   L0A89      else allocate page
         bcs   L0A88      ..err
         stx   ,x         insert first page flag
         stx   R$X,u      return base page
L0A7F    bsr   L0A9F      get one 64-byte block
         bcs   L0A88      ..err
         sta   R$A,u      return block number
         sty   R$Y,u      return block address
L0A88    rts              end.

* Allocate Base Block:

L0A89    pshs  u          save U
         ldd   #$0100     get 256-byte page
         os9   F$SRqMem
         leax  ,u         X=page address
         puls  u
         bcs   L0A9E      ..err
         clra             A=00
         clrb             256 byte count
L0A99    sta   d,x        clear block
         bne   L0A99
L0A9E    rts   

* Find & Set Block In Use:

L0A9F    pshs  x,u
L0AA2    pshs  a
         lda   a,x
         beq   L0AB4
         tfr   d,y
L0AAC    tst   d,y
         beq   L0AB6
         addb  #64
         bcc   L0AAC
L0AB4    orcc  #Carry
L0AB6    leay  d,y
         puls  a
         bcc   L0AE1
         inca             try all pages
         cmpa  #64        until 64th page
         bcs   L0AA2

L0AC2    tst   a,x
         beq   L0AD0
         cmpa  #64
         bcs   L0AC2

         ldb   #E$PthFul  'Path Table Full'
         bra   L0AEE

L0AD0    pshs  a,x
         bsr   L0A89
         bcs   L0AF0
         leay  ,x
         tfr   x,d
         tfr   a,b
         puls  a,x
         stb   a,x

* D=Block Address:

L0AE1    aslb  

         ldb   #$3F

* Clear Block:

L0AE7    clr   b,y
         bne   L0AE7
         sta   ,y
L0AEE    puls  x,u,pc     okay rts.

L0AF0    leas  3,s        drop vars
         puls  x,u,pc     return.

*                     F$Ret64
FRet64   lda   R$A,u
         ldx   R$X,u
         pshs  a,b,x,y,u
         beq   L0B22
         pshs  a
         lda   a,x
         beq   L0B20
         tfr   d,y
         clr   ,y
         tfr   d,u
L0B10    tst   d,u
         bne   L0B20
         addb  #64
         bne   L0B10
         os9   F$SRtMem
         lda   ,s
         clr   a,x
L0B20    clr   ,s+
L0B22    puls  a,b,x,y,u,pc

*                     F$GProcP
FGProcP  lda   R$A,u      get id
         bsr   L0B2E      find proc esc
         bcs   L0B2D      ..err
         sty   R$Y,u      return pointer
L0B2D    rts              end.

*   Find Process Descriptor A, address --> Y:

L0B2E    pshs  a,b,x      save id, etc
         ldb   ,s         B=id
         beq   L0B40      ..can't be zero
         ldx   <D.PrcDBT  proc desc table
         abx              index
         lda   ,x         get pointer
         beq   L0B40      ..err if none by that id
         clrb             else make address
         tfr   d,y        return in Y
         puls  a,b,x,pc   end.

L0B40    puls  a,b,x
         ldb   #E$IPrcId

*                     F$DelImg
FDelImg  ldx   R$X,u      X=proc desc
         ldd   R$D,u      A=start, B=count
         leau  P$DATImg,x U=image table
         asla             index first
         leau  a,u        point to it
         tfr   d,y        Y=count
         pshs  x          save desc

L0B55    ldd   0,u        D=block number
         addd  <D.BlkMap  plus map begin
         tfr   d,x        X=map address
         lda   ,x         get marker
         anda  #^RAMinUse release mem
         sta   ,x
         ldd   #DAT.Free  flag image
         std   ,u++       as free
         leay  -1,y       count-1
         bne   L0B55      ..loop

         puls  x          proc desc
         lda   P$State,x
         ora   #ImgChg    flag image change
         sta   P$State,x
         clrb             okay
         rts              end.

*                     F$MapBlk
FMapBlk  lda   R$B,u      get number of blocks

         beq   L0BAA      <NEW>

         cmpa  #DAT.BlCt  over 16? (8 ON COCO)
         bhi   L0BAA      ..err WAS BCC

         leas  -$10,s
         ldx   R$X,u      beginning block# desired
         leay  ,s         point to local vars
         ldb   #1         ++BGP
L0B82    stx   ,y++       put images
*         leax  1,x        desired on
         abx              ++BGP
         deca             the local stack
         bne   L0B82

         ldb   R$B,u      number of blocks
         ldx   <D.Proc    point to process's
         leay  P$DATImg,x image map
         os9   F$FreeHB   find contiguous blocks free
         bcs   L0BA6      ..err
         pshs  a,b        save begin free#,amt
         asla             first free*16 = mem address
         std   R$U,u      return addrss of first block
         puls  a,b        drop
         leau  ,s         point to images wanted
         os9   F$SetImg   map them into callers space
L0BA6    leas  $10,S
         rts              return.

L0BAA    comb             set err
         ldb   #E$IBA     'Illegal Block Address'
         rts              return.

*                     F$ClrBlk
FClrBlk  ldb   R$B,u      B=block count
         beq   L0BE9
         ldd   R$U,u      D=first block addrss
         bne   L0BAA      ..must be even page
         bita  #$1F
         bne   L0BAA      ..and on 4k boundary
         ldx   <D.Proc    get proc desc
         lda   P$SP,x     and it's SP
         anda  #$E0
         suba  R$U,u      -mem
         bcs   L0BCE      ..err if sp mem
         lsra             address -> block#
         cmpa  R$B,u      end of mem?
         bcs   L0BAA      ..error
L0BCE    lda   P$State,x  mark image change
         ora   #ImgChg
         sta   P$State,x
         lda   R$U,u      get mem ptr
         lsra             index as image ptr
         leay  P$DATImg,x proc images
         leay  a,y        point to block image
         ldb   R$B,u      get block count
         ldx   #DAT.Free  free flag
L0BE4    stx   ,y++       clear image(s)
         bne   L0BE4
L0BE9    clrb             okay
         rts              end.

*                     F$DelRam
FDelRam  ldb   R$B,u      get block count
         beq   L0C11
         ldd   <D.BlkMap+2 end of block map
         subd  <D.BlkMap  D=max block#
         subd  R$X,u      cmp to desired block#
         bls   L0C11      ..bad number

         tsta             close to end of map?
         bne   L0C00
         cmpb  R$B,u      block cnt easy?
         bcc   L0C00
         stb   R$B,u      save block cnt lsb
L0C00    ldx   <D.BlkMap  point to block map
         ldd   R$X,u      get start block#
         leax  d,x        index into map
         ldb   R$B,u      get count
L0C08    lda   ,x         get block flag
         anda  #^RAMinUse release for use
         sta   ,x+
         decb             count-1
         bne   L0C08      ..'til done.

L0C11    clrb             okay
         rts              end.

*                     F$GCMDir
FGCMDir  ldx   <D.ModDir  module dir ptr
         bra   L0C1D garbage collect

L0C17    ldu   ,x         get DAT entry
         beq   L0C23      ..empty
         leax  MD$ESize,x else point to next

L0C1D    cmpx  <D.ModEnd  end of dir?
         bne   L0C17, loop
         bra   L0C4B      yes, do it

L0C23    tfr   x,y        Y=entry
         bra   L0C2B it

L0C27    ldu   ,y         get DAT entry
         bne   L0C34 use
L0C2B    leay  MD$ESize,y point to next entry
         cmpy  <D.ModEnd  last?
         bne   L0C27
         bra   L0C49      do it.

* Move Entries Up:

L0C34    ldu   ,y++       2
         stu   ,x++
         ldu   ,y++       4
         stu   ,x++
         ldu   ,y++       6
         stu   ,x++
         ldu   ,y++       8 bytes
         stu   ,x++
         cmpy  <D.ModEnd  end of dir?
         bne   L0C27

L0C49    stx   <D.ModEnd  set new dir end
L0C4B    ldx   <D.ModDir+2 end of dir
         bra   L0C53

L0C4F    ldu   ,x         get entry
         beq   L0C5B      ..not used
L0C53    leax  -2,x       back up in entry
         cmpx  <D.ModDAT  end?
         bne   L0C4F
         bra   L0C93      else end if all done.

L0C5B    ldu   -2,x
         bne   L0C53
         tfr   x,y
         bra   L0C67

L0C63    ldu   ,y         get entry
         bne   L0C70
L0C67    leay  -2,y
L0C69    cmpy  <D.ModDAT
         bcc   L0C63
         bra   L0C81

L0C70    leay  2,y        go back
         ldu   ,y         do last entry
         stu   ,x
L0C76    ldu   ,--y
         stu   ,--x
         beq   L0C87
         cmpy  <D.ModDAT  end?
         bne   L0C76
         stx   <D.ModDAT  set new end
         bsr   L0C95      change images
         bra   L0C93      end.

L0C87    leay  2,y
         leax  2,x
         bsr   L0C95
         leay  -4,y
         leax  -2,x
         bra   L0C69
L0C93    clrb             okay
         rts              end.

* Update Module Dir Image Ptrs:

L0C95    pshs  u
         ldu   <D.ModDir  module dir start
         bra   L0CA4

L0C9B    cmpy  MD$MPDAT,u same DAT ptrs?
         bne   L0CA2, skip
         stx   MD$MPDAT,u else update ptr
L0CA2    leau  MD$ESize,u next entry
L0CA4    cmpu  <D.ModEnd  last entry?
         bne   L0C9B
         puls  u,pc       yes, return.

endmod   equ   *