/* class comment */!!

inherit(MemServLib, #MemLibInst, #(workAddr1
workAddr2
memAddrSpace), 2, nil)!!

setClassVars(MemLibInst, #())!!

now(class(MemLibInst))!!

now(MemLibInst)!!

/* 11/28/1995 9:31 */
Def memCompDlg (self, hWnd | srcSpace)
{
  /* call dialog box that lives in MEM.DLL */
  srcSpace := getAddressSpace(AddressLibClass$Inst, workAddr1);
  if pcallLock(self)
    lastError :=
      pcall(procs[#MEMDLGCOMPMEMORY],  hWnd, srcSpace );
    pcallUNLock(self);
  else
    lastError := ERR_PCALL_RECURSION;
  endif;

  if (lastError <> GOOD)
    displayError(ErrorTextLibClass$Inst, lastError, CHECK_MODE);
    ^nil;  /* error */
  endif;
  ^0;
}
!!

/* 11/22/1995 17:54 */
Def memTest(self, startAddr, toAddr retAddr| struct1 index temp)
{
  temp := compareOffsets(AddressLibClass$Inst, startAddr, toAddr);
  /* ADDR_GREATER_THAN = 0, ADDR_LESS_THAN = 1, ADDR_EQUAL = 2 */
  if not((temp = ADRLIB_ADDR_GREATER_THAN) cor 
      (temp = ADRLIB_ADDR_LESS_THAN) cor 
      (temp = ADRLIB_ADDR_EQUAL))
    ^nil;  /* error */
  endif;
 
  if (temp = ADRLIB_ADDR_GREATER_THAN)
    displayFormattedError(ErrorTextLibClass$Inst, 
       ER_MEM_FROM_TO, FORCE_POPUP, nil, nil, nil);
    ^nil;
  endif;
  
  /* set offset from text */
  if not(setOffset(AddressLibClass$Inst, workAddr1, startAddr))
    ^nil;  /* error */
  endif;
  
  /* do test call */
  if pcallLock(self)
    lastError := pcall(procs[#MEMTEST], workAddr1,
         asLong((toAddr-startAddr)+1), retAddr);
    pcallUNLock(self);
  else
    lastError := ERR_PCALL_RECURSION;
  endif;

  if (lastError <> GOOD) 
    /* Report error */
/*    displayFormattedError(ErrorTextLibClass$Inst, 
       lastError, CHECK_MODE, nil, nil, nil);*/
    ^lastError; 
  endif;
  ^0; 

}
!!

/* 11/22/1995 17:46 */
/* PUBLIC -- Checksum memory. */
Def memChecksum(self, startAddr, toAddr| struct1 index temp retSumU32)
{
  retSumU32 := new(Struct,4);
  temp := compareOffsets(AddressLibClass$Inst, startAddr, toAddr);
  /* ADDR_GREATER_THAN = 0, ADDR_LESS_THAN = 1, ADDR_EQUAL = 2 */
  if not((temp = ADRLIB_ADDR_GREATER_THAN) cor 
      (temp = ADRLIB_ADDR_LESS_THAN) cor 
      (temp = ADRLIB_ADDR_EQUAL))
    ^nil;  /* error */
  endif;
 
  if (temp = ADRLIB_ADDR_GREATER_THAN)
    displayFormattedError(ErrorTextLibClass$Inst, 
       ER_MEM_FROM_TO, FORCE_POPUP, nil, nil, nil);
    ^nil;
  endif;
  
  /* set offset from text */
  if not(setOffset(AddressLibClass$Inst, workAddr1, startAddr))
    ^nil;  /* error */
  endif;
  
  /* do checksum call */
  if pcallLock(self)
    lastError := pcall(procs[#MEMCHECKSUM], workAddr1,
         asLong((toAddr-startAddr)+1), 0, retSumU32);
    pcallUNLock(self);
  else
    lastError := ERR_PCALL_RECURSION;
  endif;

  if (lastError <> GOOD) 
    /* Report error */
    displayFormattedError(ErrorTextLibClass$Inst, 
       lastError, CHECK_MODE, nil, nil, nil);
    ^nil; 
  endif;
  ^longAt(retSumU32,0); 

}
!!

/* 11/22/1995 10:40 */
/* PUBLIC -- Get address space. */
Def memGetAddrSpace(self)
{
  ^memAddrSpace;
} 
!!

/* 11/10/1995 9:23 */
/* PUBLIC -- Set address space. */
Def memSetAddrSpace(self, space)
{
  memAddrSpace := space;
  setAddrSpace(AddressLibClass$Inst, workAddr1, space);
  setAddrSpace(AddressLibClass$Inst, workAddr2, space);
} 
!!

/* PUBLIC: Set show cycles OFF. */
Def showCyclesOff(self | sim sysType proc)
{
  sysType := getCpuType(ProcLibClass$Inst);
  proc := getSpecificProcessor(ProcLibClass$Inst);
  
  if ((sysType = PROC_CPU_CPU32) cor (sysType = PROC_CPU_CPU32P)) then
    if not(sim := simRead(self))
      /* error reporting already done */
      ^nil;
    endif;
  else
    ^nil;
  endif;
  
  if ((sysType = PROC_CPU_CPU32) cor (proc = PROC_MC68349)) then
    putByte(sim,(byteAt(sim,0) bitAnd SHOW_CYCLES_OFF_MASK),0);
    ^simWrite(self, sim);
  else
    if ((sysType = PROC_CPU_CPU32P) cand (proc = PROC_MC68360)) then
      putByte(sim,(byteAt(sim,2) bitAnd SHOW_CYCLES_OFF_MASK),2);
      ^simWrite(self, sim );
    endif;
    ^nil;
  endif;
}
!!

/* PUBLIC: Set show cycles ON. */
Def showCyclesOn(self | sim sysType proc)
{
  sysType := getCpuType(ProcLibClass$Inst);
  proc := getSpecificProcessor(ProcLibClass$Inst);
  
  if ((sysType = PROC_CPU_CPU32) cor (sysType = PROC_CPU_CPU32P)) then
    if not(sim := simRead(self))
      /* error reporting already done */
      ^nil;
    endif;
  else
    ^nil;
  endif;
  
  if ((sysType = PROC_CPU_CPU32) cor (proc = PROC_MC68349)) then
    putByte(sim,(byteAt(sim,0) bitOr SHOW_CYCLES_ON_MASK),0);
    ^simWrite(self, sim);
  else
    if ((sysType = PROC_CPU_CPU32P) cand (proc = PROC_MC68360)) then
      putByte(sim,(byteAt(sim,2) bitOr SHOW_CYCLES_ON_MASK),2);
      ^simWrite(self, sim);
    endif;
    ^nil;
  endif;
}
!!

/* PUBLIC: Return 1 if show cycles on, 0 if off, nil if error. */
Def showCycles?(self | sim sysType proc)
{
  sysType := getCpuType(ProcLibClass$Inst);
  proc := getSpecificProcessor(ProcLibClass$Inst);
  if ((sysType = PROC_CPU_CPU32) cor (proc = PROC_MC68349)) then
    if not(sim := simRead(self))
      ^nil;
    endif;
  
    if ((sim[0] bitAnd SHOW_CYCLES_ON_MASK) <> 0)
      ^1;
    endif;
  
    ^0;
  endif;
  if ((sysType = PROC_CPU_CPU32P) /*cand (proc = PROC_MC68360)*/) then
    if not(sim := simRead(self))
      ^nil;
    endif;
    if ((sim[2] bitAnd SHOW_CYCLES_ON_MASK) <> 0)
      ^1;
    endif;
  
    ^0;
  endif;
  
  /* there isn't a sim */
  ^nil;
  
}
!!

/* PRIVATE: write the SIM. */
Def simWrite(self, byte | simAddress sysType proc mem)
{
  sysType := getCpuType(ProcLibClass$Inst);
  proc := getSpecificProcessor(ProcLibClass$Inst);
  
  if ((sysType = PROC_CPU_CPU32) cor (sysType = PROC_CPU_CPU32P)) then
    /* get the SIM address */
    if not(simAddress := getSimAddress(SharedDataLibClass$Inst))
      ^nil;
    endif;
  else 
    ^nil;
  endif;
  
  if ((sysType = PROC_CPU_CPU32) cor (proc = PROC_MC68349)) then
    ^writeMem(self, simAddress, 1, byte);
  else
    if ((sysType = PROC_CPU_CPU32P) cand (proc = PROC_MC68360)) then
      ^writeMem(self, simAddress, 4, byte);
    endif;
    ^nil;
  endif;
}
!!

/* PRIVATE: read the SIM. */
Def simRead(self | simAddress simByte sysType proc)
{
  sysType := getCpuType(ProcLibClass$Inst);
  proc := getProcessorFamily(ProcLibClass$Inst);

  if ((sysType = PROC_CPU_CPU32) cor (sysType = PROC_CPU_CPU32P)) then
    /* get the SIM address (error reporting already done if needed). */
    if not(simAddress := getSimAddress(SharedDataLibClass$Inst))
      ^nil;
    endif;
  else
    ^nil;
  endif;
  
  if ((sysType = PROC_CPU_CPU32) cor (proc = PROC_MC68349)) then
    /* read the contents */
    simByte := memRead(self, simAddress, 1);
  
    /* simByte will be the contents of the SIM byte, or nil for error */
    ^simByte;
  else
    if ((sysType = PROC_CPU_CPU32P) /*cand (proc = PROC_MC68360)*/) then
      simByte := memRead(self, simAddress, 4);
      ^simByte;
    endif;
    ^nil;
  endif;
}
!!

/* Read memory bytes. Don't display error. */
Def memRead(self, offset, byteCount | bufRef tempArray aStruct index)
{
  /* stuff offset into address descriptor */
  if not(setOffset(AddressLibClass$Inst, workAddr1, offset))
    ^nil
  endif;

  /* read block of bytes at address */
  bufRef := new(Struct, 4);
  
  if pcallLock(self)
    lastError := pcall(procs[#MEMREAD], workAddr1, byteCount, bufRef, 0);
    pcallUNLock(self);
  else
    lastError := ERR_PCALL_RECURSION;
  endif;

  if (lastError = GOOD)
     aStruct := copyFromLong(new(Struct, byteCount), longAt(bufRef, 0));
     /* free memory allocated by Memory server. */
     cFree(MallocLibClass$Inst, longAt(bufRef, 0));
     ^aStruct;
  endif;

  if (longAt(bufRef,0) <> 0)
     /* free memory allocated by Memory server. */
     cFree(MallocLibClass$Inst, longAt(bufRef, 0));
  endif;
  ^nil;   
}!!

/* 5/23/1993 15:28 */
Def memCopyDlg (self, hWnd)
{

  /* call dialog box that lives in MEM.DLL */
  if pcallLock(self)
    lastError :=
      pcall(procs[#MEMDLGCOPYMEMORY],  hWnd );
    pcallUNLock(self);
  else
    lastError := ERR_PCALL_RECURSION;
  endif;

  if (lastError <> GOOD)
    displayError(ErrorTextLibClass$Inst, lastError, CHECK_MODE);
    ^nil;  /* error */
  endif;
  ^0;
}
!!

/* PUBLIC -- close session
*/
Def closeSession(self)
{
  if workAddr1
    destroyAddress(AddressLibClass$Inst, workAddr1);
    workAddr1 := nil;
  endif;
  if workAddr2
    destroyAddress(AddressLibClass$Inst, workAddr2);
    workAddr2 := nil;
  endif;
  
  if (lastError <> GOOD) 
    ^nil;
  endif;
  ^0;
}!!

/* PUBLIC
   create work address. */
Def createWorkAddrs(self)
{
  /* create temporary work address if not already done */
  if not(workAddr1)
    workAddr1 := createAddress(AddressLibClass$Inst);
    if not(workAddr1)
      lastError := lastError(AddressLibClass$Inst);
      clearError(AddressLibClass$Inst);
      ^nil
    endif;
  endif;

  /* create temporary work address if not already done */
  if not(workAddr2)
    workAddr2 := createAddress(AddressLibClass$Inst);
    if not(workAddr2)
      lastError := lastError(AddressLibClass$Inst);
      clearError(AddressLibClass$Inst);
      ^nil
    endif;
  endif;

  ^0
}!!

/* PRIVATE */
Def initialize(self)
{
  /* create work address structure */
  if not(createWorkAddrs(self))
    ^nil;
  endif;
  
  ^self
}
!!

/* PUBLIC -- Compare memory. */
Def memCompare(self, firstAddr, secondAddr, length |
               resultRef result returnValue addr1 addr2)
{
  /* set offsets from text */
  lastError :=
    setOffsetText(AddressLibClass$Inst, workAddr1, firstAddr);
  if (lastError <> GOOD)
    ^#(nil, nil, nil);
  endif;
  lastError :=
    setOffsetText(AddressLibClass$Inst, workAddr2, secondAddr);
  if (lastError <> GOOD)
    ^#(nil, nil, nil);
  endif;

  /* do compare call */
  resultRef := new(Struct, 2);
  if pcallLock(self)
  then
    lastError := pcall(procs[#MEMCOMPARE], workAddr1, workAddr2,
                       asLong(length), resultRef);
    pcallUNLock(self);
  else
    lastError := ERR_PCALL_RECURSION;
  endif;

  if (lastError <> GOOD)
    displayError(ErrorTextLibClass$Inst,lastError,CHECK_MODE);
    ^#(nil, nil, nil);
  endif;

  /* result true: blocks identical; result false: get mismatch addresses */
  result := wordAt(resultRef, 0);
  /* test for C true */
  if (result <> 0)
     returnValue := #(1, 0, 0);
  else
    lastError := getAddressText(AddressLibClass$Inst, workAddr1);
    if not(lastError)
      addr1 := nil;
    else
      addr1 := lastError;
      lastError := getAddressText(AddressLibClass$Inst, workAddr2);
      if not(lastError)
        addr2 := nil;
      else
        addr2 := lastError;
      endif;
    endif;
    returnValue := #(0, addr1, addr2);  /* return beginning offsets */
  endif;
  
  ^returnValue;
}!!

/* PUBLIC -- Fill memory. */
Def memFill(self, startAddr, toAddr, pattern | struct1 index 
  temp)
{
  temp := compareOffsets(AddressLibClass$Inst, startAddr, toAddr);
  /* ADDR_GREATER_THAN = 0, ADDR_LESS_THAN = 1, ADDR_EQUAL = 2 */
  if not((temp = ADRLIB_ADDR_GREATER_THAN) cor 
      (temp = ADRLIB_ADDR_LESS_THAN) cor 
      (temp = ADRLIB_ADDR_EQUAL))
    ^nil;  /* error */
  endif;
 
  if (temp = ADRLIB_ADDR_GREATER_THAN)
    displayFormattedError(ErrorTextLibClass$Inst, 
       ER_MEM_FROM_TO, FORCE_POPUP, nil, nil, nil);
    ^nil;
  endif;
  
  /* set offset from text */
  if not(setOffset(AddressLibClass$Inst, workAddr1, startAddr))
    ^nil;  /* error */
  endif;
  
  struct1 := processPattern(self, pattern);
  if not(struct1)
    ^nil;
  endif;

  /* do fill call */
  if pcallLock(self)
    lastError := pcall(procs[#MEMFILL], workAddr1,
            asLong((toAddr-startAddr)+1), struct1, size(struct1));
    pcallUNLock(self);
  else
    lastError := ERR_PCALL_RECURSION;
  endif;

  if (lastError <> GOOD) 
    /* Report error */
    displayFormattedError(ErrorTextLibClass$Inst, 
       lastError, CHECK_MODE, nil, nil, nil);
    ^nil; 
  endif;
  ^0; 

}!!

/* PUBLIC -- Get access size. */
Def memGetAccessSize(self | wordRef)
{
  wordRef := new(Struct, 2);
  if pcallLock(self)
    lastError := pcall(procs[#MEMGETACCESSSIZE], wordRef);
    pcallUNLock(self);
  else
    lastError := ERR_PCALL_RECURSION;
  endif;

  if (lastError <> GOOD)
    ^nil;
  endif;
  ^wordAt(wordRef, 0);
}!!

/* PUBLIC -- Get access size. */
Def memGetVerifyWrites(self | byteRef)
{
  byteRef := new(Struct, 2);
  if pcallLock(self)
    lastError := pcall(procs[#MEMGETVERIFYWRITES], byteRef);
    pcallUNLock(self);
  else
    lastError := ERR_PCALL_RECURSION;
  endif;

  if (lastError <> GOOD)
    ^nil
  endif;
  ^byteAt(byteRef, 0);
}!!

/* PUBLIC -- Move memory. */
Def memMove(self, firstAddr, secondAddr, length)
{
  /* set offsets from text */
  if not(setOffset(AddressLibClass$Inst, workAddr1, firstAddr))
    ^nil;  /* error */
  endif;

  if not(setOffset(AddressLibClass$Inst, workAddr2, secondAddr))
    ^nil;  /* error */
  endif;

  /* do move call */
  if pcallLock(self)
    lastError := pcall(procs[#MEMMOVE], workAddr1, workAddr2, asLong(length));
    pcallUNLock(self);
  else
    lastError := ERR_PCALL_RECURSION;
  endif;

 
  if (lastError <> GOOD)
    /* check for failure due to not implemented yet */
    if (lastError = 0x1d0001)
      displayFormattedError(ErrorTextLibClass$Inst, 
         ER_MEM_NO_FUNC, FORCE_POPUP, nil, nil, nil);
      ^0;
    endif;      
    displayError(ErrorTextLibClass$Inst, lastError, CHECK_MODE);
    ^nil;  /* error */
  endif;
  ^0;
}!!

/* PUBLIC -- Search memory. nil= error, -1=not found, otherwise offset. */
Def memSearch(self, firstAddr, secondAddr, invert, pattern | byte
  foundRef foundFlag struct1 temp)
{
  temp := compareOffsets(AddressLibClass$Inst, firstAddr, secondAddr);
  /* NOTES:
  ** ADRLIB_ADDR_GREATER_THAN = 0, 
  ** ADRLIB_ADDR_LESS_THAN = 1, 
  ** ADRLIB_ADDR_EQUAL = 2 
  */
  if not((temp = ADRLIB_ADDR_GREATER_THAN) cor 
      (temp = ADRLIB_ADDR_LESS_THAN) cor 
      (temp = ADRLIB_ADDR_EQUAL))
    ^nil;  /* error */
  endif;
  
  if (temp = ADRLIB_ADDR_GREATER_THAN)
    displayFormattedError(ErrorTextLibClass$Inst, 
       ER_MEM_FROM_TO, FORCE_POPUP, nil, nil, nil);
    ^nil;
  endif;
    
  /* set offsets from text */
  if not(setOffset(AddressLibClass$Inst, workAddr1, firstAddr))
    ^nil;  /* error */
  endif;

  if not(setOffset(AddressLibClass$Inst, workAddr2, secondAddr))
    ^nil;  /* error */
  endif;
  
  /* stuff pattern into structure */
  if not(struct1 := processPattern(self, pattern)) 
    ^nil;
  endif;
  
  /* do search call */
  foundRef := new(Struct, 2);
  if pcallLock(self)
    lastError := pcall(procs[#MEMSEARCH], workAddr1, workAddr2, 
      asInt(invert), struct1, size(struct1), foundRef);
    pcallUNLock(self);
  else
    lastError := ERR_PCALL_RECURSION;
  endif;

  temp := nil;
  if (lastError <> GOOD)
    displayError(ErrorTextLibClass$Inst, lastError, CHECK_MODE);
  else
    /* -1 is NOT FOUND flag */
    temp := -1;
    foundFlag := wordAt(foundRef, 0);
    /* if found, return address where found */
    if (foundFlag <> 0)
      temp := getOffset(AddressLibClass$Inst, workAddr1);
    endif;
  endif;  
  ^temp;
}!!

/* PUBLIC -- Set access size. */
Def memSetAccessSize(self, size | wordRef)
{
  if pcallLock(self)
    lastError := pcall(procs[#MEMSETACCESSSIZE], size);
    pcallUNLock(self);
  else
    lastError := ERR_PCALL_RECURSION;
  endif;

  if (lastError <> GOOD)
    ^nil;
  endif;
  ^0;
}!!

/* PUBLIC -- Set access size. */
Def memSetVerifyWrites(self, flag | flagVal)
{
  if flag
    flagVal := 1
  else
    flagVal := 0;
  endif;

  if pcallLock(self)
    lastError := pcall(procs[#MEMSETVERIFYWRITES], flagVal);
    pcallUNLock(self);
  else
    lastError := ERR_PCALL_RECURSION;
  endif;

  if (lastError <> GOOD)
    ^nil
  endif;
  ^0;
}!!

/* PRIVATE
   return byte stream constructed from pattern. */
Def processPattern(self, pattern | 
   byte index struct1 byteCount byteString start col temp)
{
  /* remove leading, trailing blanks */
  col := findStrings(" "+peelBlanks(pattern), " ");
  byteString := "";
  
  index := 0;
  loop
  while index < size(col)
    temp := col[index];
    /* remove "0x" if there */
    if (size(temp) > 2) cand
       (temp[0] = '0') cand
       ((temp[1] = 'x') cor (temp[1] = 'X'))
      temp := delete(temp, 0, 2);
    endif;
    
    /* add 0 if the number of characters is odd */
    if ((size(temp) mod 2) = 1)
      temp := "0" + temp;
    endif;
    
    byteString := byteString + temp;
    index := index + 1;
  endLoop;
  
  /* create a struct to hold each of the bytes */
  byteCount := size(byteString) / 2;
  struct1 := new(Struct, byteCount);
  
  /* stuff each of the bytes into the struct */
  index := 0;
  loop
  while index < byteCount
  begin
    start := index * 2;
    byte := subString(byteString, start, start+2);
    if not(asInt(byte,16))
      displayFormattedError(ErrorTextLibClass$Inst, 
         ER_MEM_NON_NUM, FORCE_POPUP, nil, nil, nil);
      ^nil;
    endif;
    putByte(struct1, asInt(byte, 16), index);
    index := index + 1;
  endLoop;
  
  ^struct1;
}!!

/* PUBLIC -- Read a block of lines, each line consisting of 16 bytes, from
   the Memory Server.  Return an array of 16-byte arrays (workTextBytes),
   or nil if there is an error.
*/
Def readLines(self, numLines, linePosition | bufRef
    bigArray littleArray bigIndex littleIndex numBytes aStruct)
{
  /* stuff offset into address descriptor */
  if not(setOffset(AddressLibClass$Inst, workAddr1,
            (linePosition * 16)))
    ^nil
  endif;

  /* read block of bytes at address */
  bufRef := new(Struct, 4);
  numBytes := numLines * 16;
  
  if pcallLock(self)
    lastError := pcall(procs[#MEMREAD], workAddr1, numBytes, bufRef, 0);
    pcallUNLock(self);
  else
    lastError := ERR_PCALL_RECURSION;
  endif;

  if (lastError <> GOOD)
    displayError(ErrorTextLibClass$Inst,lastError,CHECK_MODE);
    ^nil;
  else
    aStruct := copyFromLong(new(Struct, numBytes), longAt(bufRef, 0));
    bigArray := new(Array, numLines);
    bigIndex := 0;
    loop
    while bigIndex < numLines
      littleArray := new(Array, 16);
      littleIndex := 0;
      loop
      while littleIndex < 16
        littleArray[littleIndex] :=
          byteAt(aStruct, (bigIndex*16) + littleIndex);
        littleIndex := littleIndex + 1;
      endLoop;
      bigArray[bigIndex] := littleArray;
      bigIndex := bigIndex + 1;
    endLoop;
  endif;
  
  /* clean up and return */
  cFree(MallocLibClass$Inst, longAt(bufRef, 0));

  ^bigArray;
}!!

/* PRIVATE */
Def setIVars(self, hL, n, o, p, gNS)
{
  hLib     := hL;
  name     := n;
  ordinals := o;
  procs    := p;
  globalNameSymbol := gNS;
}
!!

/* PUBLIC -- Write memory. */
Def writeMem(self, offset, length, bytes | mem)
{
  /* don't propogate bad data */
  if (not(offset) cor not(length) cor not(bytes))
    ^nil;
  endif;

  /* set offset */
  if not(setOffset(AddressLibClass$Inst, workAddr1, offset))
    ^nil;  /* error */
  endif;

  if ((mem := cMalloc(MallocLibClass$Inst, 4)) = 0)
    ^nil;  /* error */
  endif;

  putLong(mem, longAt(bytes, 0));
  /* do the write thing */
  if pcallLock(self)
    lastError := pcall(
      procs[#MEMWRITE],
      workAddr1,
      length,
      mem);
    pcallUNLock(self);
  else
    lastError := ERR_PCALL_RECURSION;
  endif;

  if (lastError <> GOOD)
    displayError(ErrorTextLibClass$Inst, lastError, CHECK_MODE);
    ^nil;
  endif;

  ^0;
}!!

/* MemLibInst Class Initialization Code */
