TweetFollow Us on Twitter

HFS PathName
Volume Number:2
Issue Number:7
Column Tag:Modula-2 Mods

Make a Path Name for HFS

By Tom Taylor, Santa Clara, CA, MacTutor Contributing Editor

Extending Modula-2 for HFS Support

The Macintosh low-level File Manager is probably familiar to anyone who has programmed in another language besides Modula-2 on the Mac. Until the Heirarchical File System was released, there wasn't a tremendous amount of motivation to use the low level parameter block routines from Modula-2. The high-level File Manager routines implemented by MacModula-2 were usually enough to get the job done. With the release of the Mac Plus, however, the high level calls are not enough. Therefore, I decided to implement a library module that includes all of the low-level File Manager calls specified in the new chapter of the File Manager.

The Low-Level File Manager

Most people are already familiar with the low-level File Manager. For those who are not, a little introduction would be helpful. First of all, the low-level File Manager routines exist in ROM. The high level File Manager routines described by the File Manager Inside Macintosh chapter do not. Instead, the high level calls consist of glue code that calls the low-level routines. Each low-level procedure takes one parameter: a pointer to a parameter block. This parameter block, however, is used to hold many input and output parameters. The File Manager chapter does an excellent job of showing which fields of the parameter block are used for each call. Before using the module presented in this article, you must read the File Manager chapter of Inside Macintosh. In fact, it would be most helpful if you were to read the new chapter that explains the File Manager in terms of both MFS and HFS. There are six different types of parameter blocks. Three of the six blocks contain variant records.

A typical low-level File Manager call looks like this:

PROCEDURE PBCallName
                   (paramBlock: PtrToParamBlk;
  async: BOOLEAN) : OsErr;

The first parameter is a pointer to one of the six different parameter blocks. Generally, I find it easiest to declare the actual block as a variable and then pass ADR(block) for this parameter. The second parameter, "async", specifies whether the routine should be executed synchronously or asynchronously. It is beyond the scope of this article to explain how to use asynchronous calls in an interpreted system like MacModula-2. Therefore, my example program will always perform synchronous calls by passing FALSE for this parameter.

How it all works

The definition module, PBFileManager.DEF, is very straightforward. All of the parameter block types and procedures are defined. The implementation module is a bit trickier. Basically, every procedure makes a call to the procedure LowLevelPB passing four parameters: the parameter block address, the asynch flag, the value of the A-Trap that ends up calling the actual File Manager procedure, and a routine selector for those procedures that are implemented with the same A-Trap (which are new, HFS only calls). The LowLevelPB procedure immediately makes a call to an assembly routine that calls the toolbox. The assembly routine (source in PBFileManagerASM.ASM) must unstack the A-Trap value and the asynch flag. If the call is to be performed asynchronously, the asynch bit in the trap word is set. In either case, the A-Trap is installed and executed and the returned value is returned back to the Modula-2 calling procedure (and returned back up the many levels of procedure calls!). This has to be the simplest library module ever written, yet one of the most powerful because it gives the Modula-2 programmer almost complete control of the Mac's file system. That is why I thought it is an appropriate subject for this month's article.

Fig. 1 Standard file Dialog to select file name

An example program

Any module is incomplete without an example program. The program here, MakePath.MOD, shows how to find the complete pathname to a file. The program puts up the SFGetFile and allows the user to select any file. Then the program displays a window with the file's complete path name (up to 255 characters, anyway...). Besides showing how to use a few of the low-level File Manager routines, it also shows how to determine if the host Mac is running the HFS file system and whether a volume is an HFS or MFS volume. Because of this, the program will run on any Mac, HFS or not (fat or skinny, regular or Plus, etc.). Macintosh Technical Note #57 says that the location 03F6h contains a global flag that says whether HFS is installed or not. Therefore, the variable HFS in MakePath.MOD is declared as:

 VAR
 HFS [03f6h] : INTEGER;

If HFS = -1, the Macintosh is running MFS, else it's running HFS. When HFS is installed, it's also necessary to determine whether a volume is a MFS or HFS volume. The PBHGetVInfo call will return a field in the parameter block called IOVSigWord. This variable will be D2D7h for a MFS volume and 4244h for an HFS volume.

For HFS volumes, the PBGetCatInfo call is the basis for building path names. By passing -1 in the ioFDirIndex field, PBGetCatInfo will return information about the directory with the WDRefNum passed in the ioVRefNum field. Every directory on an HFS volume has a different directory ID. The root directory always has directory ID of 2. Not only does PBGetCatInfo return the directory ID (in ioDrDirID) and the directory's name (in ioNamePtr), it also returns the directory's parent ID. By calling PBGetCatInfo until the directory ID equals two, the path name can be built.

Fig. 2 Path Name Program constructs Path

Here are the steps for building the PBFileManager module and the example program:

--- To make the library module... ---

1-Assemble PBFileManagerASM.ASM

2-Link (using MDS or Consulair Link) the PBFileManagerASM.REL file using the file PBFileManagerASM.link

3-Run RMaker on PBFileManager.r

4-Rename PBFileManager.REL.RSRC to PBFileManager.REL

5-Using M2 Compiler, compile PBFileManager.DEF and PBFileManager.MOD

--- To make the example program... ---

1-Run RMaker on MakePath.r

2-Rename MakePath.REL.RSRC to MakePath.REL

3-Using M2 Compiler, compile and link MakePath.MOD

4-Execute MakePath.LOD and have fun!

----------- PBFileManager.DEF -----------
(* Tom Taylor
   3707 Poinciana Dr. #137
   Santa Clara, CA 95051 *)

DEFINITION MODULE PBFileManager;

(* This module defines the low level
   file system described in the latest
   File Manager documentation.  The
   types and procedures defined in
   this module support both MFS and
   HFS calls. *)
 
  FROM OSQueues IMPORT
    QElemPtr;
  FROM MacSystemTypes IMPORT
    LongCard, Ptr, OsErr,
    StringPtr;
  FROM FileManager IMPORT
    FInfo;
  FROM SYSTEM IMPORT
    ADDRESS;

  EXPORT QUALIFIED
  
  (* Types *)
    ParamBlkType, ParmBlkPtr, ParamBlockRec,
    CMovePBPtr, CMovePBRec, HParmBlkPtr,
    HParamBlockRec, WDPBPtr, WDPBRec,
    CInfoType, CInfoPBPtr, CInfoPBRec,
    FCBPBPtr, FCBPBRec,
    
  (* Procedures *)
    PBMountVol, PBGetVInfo, PBHGetVInfo,
    PBHSetVInfo, PBGetVol, PBHGetVol,
    PBSetVol, PBHSetVol, PBFlushVol,
    PBUnmountVol, PBOffLine, PBEject,
    PBOpen, PBHOpen, PBOpenRF, 
    PBHOpenRF, PBLockRange,
    PBUnlockRange, PBRead, PBWrite,
    PBGetFPos, PBSetFPos, PBGetEOF,
    PBSetEOF, PBAllocate, PBAllocContig,
    PBFlushFile, PBClose, PBCreate,
    PBHCreate, PBDirCreate, PBDelete,
    PBHDelete, PBGetFInfo, PBHGetFInfo,
    PBSetFInfo, PBHSetFInfo, PBSetFLock,
    PBHSetFLock, PBRstFLock, PBHRstFLock,
    PBSetFVers, PBRename, PBHRename,
    PBGetCatInfo, PBSetCatInfo, PBCatMove,
    PBOpenWD, PBCloseWD, PBGetWDInfo,
    PBGetFCBInfo;

  TYPE
    ParamBlkType = (ioParam, fileParam,
                    volumeParam, cntrlParam);

    ParmBlkPtr = POINTER TO ParamBlockRec;
    ParamBlockRec = RECORD
      qLink:QElemPtr;
      qType:INTEGER;
      ioTrap:    INTEGER;
      ioCmdAddr: Ptr;
      ioCompletion:ADDRESS;
      ioResult:  OsErr;
      ioNamePtr: StringPtr;
      ioVRefNum: INTEGER;
      CASE ParamBlkType OF
 ioParam:
   ioRefNum:INTEGER;
   ioVersPerm:   ARRAY [0..1] OF CHAR;
     (* ioVersPerm[0] = ioVersNum
        ioVersPerm[1] = ioPermssn *)
   ioMisc:Ptr;
   ioBuffer:Ptr;
   ioReqCount:   LongCard;
   ioActCount:   LongCard;
   ioPosMode:    INTEGER;
   ioPosOffset:  LongCard;
      | fileParam:
   ioFRefNum:    INTEGER;
   ioFVersNum:   ARRAY [0..1] OF CHAR;
     (* ioFVersNum[0] = ioFVersNum
        ioFVersNum[1] = filler1 *)
   ioFDirIndex:  INTEGER;
   ioFlAttrVers: ARRAY [0..1] OF CHAR;
     (* ioFlAttrVers[0] = ioFlAttrib
        ioFlAttrVers[1] = ioFlVersNum *)
   ioFlFndrInfo: FInfo;
   ioFlNum: LongCard;
   ioFlStBlk:    INTEGER;
   ioFlLgLen:    LongCard;
   ioFlPyLen:    LongCard;
   ioFlRStBlk:   INTEGER;
   ioFlRLgLen:   LongCard;
   ioFlRPyLen:   LongCard;
   ioFlCrDat:    LongCard;
   ioFlMdDat:    LongCard;
      | volumeParam:
   filler2: LongCard;
   ioVolIndex:   INTEGER;
   ioVCrDate:    LongCard;
   ioVLsBkUp:    LongCard;
   ioVAtrb: INTEGER;
   ioVNmFls:INTEGER;
   ioVDirSt:INTEGER;
   ioVBlLn: INTEGER;
   ioVNmAlBlks:  INTEGER;
   ioVAlBlkSiz:  LongCard;
   ioVClpSiz:    LongCard;
   ioAlBlSt:INTEGER;
   ioVNxtFNum:   LongCard;
   ioVFrBlk:INTEGER;
      | cntrlParam:
   (* used by Device Manager *)
      END;
    END;
    
    CMovePBPtr = POINTER TO CMovePBRec;
    CMovePBRec = RECORD
      qLink:QElemPtr;
      qType:INTEGER;
      ioTrap:    INTEGER;
      ioCmdAddr: Ptr;
      ioCompletion:ADDRESS;
      ioResult:  OsErr;
      ioNamePtr: StringPtr;
      ioVRefNum: INTEGER;
      filler1:   LongCard;
      ioNewName: StringPtr;
      filler2:   LongCard;
      ioNewDirID:LongCard;
      filler3:   ARRAY [1..2] OF LongCard;
      ioDirID:   LongCard;
    END;
     
    HParmBlkPtr = POINTER TO HParamBlockRec;
    HParamBlockRec = RECORD
      qLink:QElemPtr;
      qType:INTEGER;
      ioTrap:    INTEGER;
      ioCmdAddr: Ptr;
      ioCompletion:ADDRESS;
      ioResult:  OsErr;
      ioNamePtr: StringPtr;
      ioVRefNum: INTEGER;
      CASE ParamBlkType OF
 ioParam:
   ioRefNum:INTEGER;
   ioVersPerm:   ARRAY [0..1] OF CHAR;
     (* ioVersPerm[0] = ioVersNum
        ioVersPerm[1] = ioPermssn *)
   ioMisc:Ptr;
   ioBuffer:Ptr;
   ioReqCount:   LongCard;
   ioActCount:   LongCard;
   ioPosMode:    INTEGER;
   ioPosOffset:  LongCard;
      | fileParam:
   ioFRefNum:    INTEGER;
   ioFVersNum:   ARRAY [0..1] OF CHAR;
     (* ioFVersNum[0] = ioFVersNum
        ioFVersNum[1] = filler1 *)
   ioFDirIndex:  INTEGER;
   ioFlAttrVers: ARRAY [0..1] OF CHAR;
     (* ioFlAttrVers[0] = ioFlAttrib
        ioFlAttrVers[1] = ioFlVersNum *)
   ioFlFndrInfo: FInfo;
   ioDirID: LongCard;
   ioFlStBlk:    INTEGER;
   ioFlLgLen:    LongCard;
   ioFlPyLen:    LongCard;
   ioFlRStBlk:   INTEGER;
   ioFlRLgLen:   LongCard;
   ioFlRPyLen:   LongCard;
   ioFlCrDat:    LongCard;
   ioFlMdDat:    LongCard;
      | volumeParam:
   filler2: LongCard;
   ioVolIndex:   INTEGER;
   ioVCrDate:    LongCard;
   ioVLsMod:LongCard;
   ioVAtrb: INTEGER;
   ioVNmFls:INTEGER;
   ioVBitMap:    INTEGER;
   ioAllocPtr:   INTEGER;
   ioVNmAlBlks:  INTEGER;
   ioVAlBlkSiz:  LongCard;
   ioVClpSiz:    LongCard;
   ioAlBlSt:INTEGER;
   ioVNxtCNID:   LongCard;
   ioVFrBlk:INTEGER;
   ioVSigWord:   INTEGER;
   ioVDrvInfo:   INTEGER;
   ioVDRefNum:   INTEGER;
   ioVFSID: INTEGER;
   ioVBkUp: LongCard;
   ioVSeqNum:    INTEGER;
   ioVWrCnt:LongCard;
   ioVFilCnt:    LongCard;
   ioVDirCnt:    LongCard;
   ioVFndrInfo:  
 ARRAY [1..8] OF LongCard;
      END;
    END;

    WDPBPtr = POINTER 
 TO WDPBRec;
    WDPBRec = RECORD
      qLink:QElemPtr;
      qType:INTEGER;
      ioTrap:    INTEGER;
      ioCmdAddr: Ptr;
      ioCompletion:ADDRESS;
      ioResult:  OsErr;
      ioNamePtr: StringPtr;
      ioVRefNum: INTEGER;
      filler1:   INTEGER;
      ioWDIndex: INTEGER;
      ioWDProcID:LongCard;
      ioWDVRefNum: INTEGER;
      filler2:   ARRAY [1..7] OF INTEGER;
      ioWDDirID: LongCard;
    END;
     
    CInfoType = (hFileInfo, dirInfo);
    CInfoPBPtr = POINTER TO CInfoPBRec;
    CInfoPBRec = RECORD
      qLink:QElemPtr;
      qType:INTEGER;
      ioTrap:    INTEGER;
      ioCmdAddr: Ptr;
      ioCompletion:ADDRESS;
      ioResult:  OsErr;
      ioNamePtr: StringPtr;
      ioVRefNum: INTEGER;
      ioFRefNum: INTEGER;
      filler1:   INTEGER;
      ioFDirIndex: INTEGER;
      ioFlAttrib:ARRAY [0..1] OF CHAR;
 (* ioFlAttrib[0] = ioFlAttrib
    ioFlAttrib[1] = filler2 *)
      CASE CInfoType OF
 hFileInfo:
   ioFlFndrInfo: FInfo;
   ioFlNum: LongCard;
   ioFlStBlk:    INTEGER;
   ioFlLgLen:    LongCard;
   ioFlPyLen:    LongCard;
   ioFlRStBlk:   INTEGER;
   ioFlRLgLen:   LongCard;
   ioFlRPyLen:   LongCard;
   ioFlCrDat:    LongCard;
   ioFlMdDat:    LongCard;
   ioFlBkDat:    LongCard;
   ioFlXFndrInfo:FInfo;
   ioFlParID:    LongCard;
   ioFlClpSiz:   LongCard;
      | dirInfo:
   ioDrUsrWds:   ARRAY [1..8] OF INTEGER;
   ioDrDirID:    LongCard;
   ioDrNmFls:    INTEGER;
   filler3: ARRAY [1..9] OF INTEGER;
   ioDrCrDat:    LongCard;
   ioDrMdDat:    LongCard;
   ioDrBkDat:    LongCard;
   ioDrFndrInfo: ARRAY [1..8] OF INTEGER;
   ioDrParID:    LongCard;
       END;
    END;

    FCBPBPtr = POINTER TO FCBPBRec;
    FCBPBRec = RECORD
      qLink:QElemPtr;
      qType:INTEGER;
      ioTrap:    INTEGER;
      ioCmdAddr: Ptr;
      ioCompletion:ADDRESS;
      ioResult:  OsErr;
      ioNamePtr: StringPtr;
      ioVRefNum: INTEGER;
      ioRefNum:  INTEGER;
      filler1:   INTEGER;
      ioFCBIndx: LongCard;
      ioFCBFlNm: LongCard;
      ioFCBFlags:INTEGER;
      ioFCBStBlk:INTEGER;
      ioFCBEOF:  LongCard;
      ioFCBPLen: LongCard;
      ioFCBCrPs: LongCard;
      ioFCBVRefNum:INTEGER;
      ioFCBClpSiz: LongCard;
      ioFCBParID:LongCard;
    END;

    PROCEDURE PBMountVol
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBGetVInfo
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBHGetVInfo
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBHSetVInfo
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBGetVol
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBHGetVol
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBSetVol
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBHSetVol
      (pBlk: WDPBPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBFlushVol
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBUnmountVol
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBOffLine
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBEject
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBOpen
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBHOpen
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBOpenRF
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBHOpenRF
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBLockRange
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBUnlockRange
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBRead
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBWrite
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBGetFPos
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBSetFPos
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBGetEOF
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBSetEOF
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBAllocate
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBAllocContig
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBFlushFile
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBClose
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBCreate
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBHCreate
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBDirCreate
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBDelete
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBHDelete
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBGetFInfo
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBHGetFInfo
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBSetFInfo
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBHSetFInfo
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBSetFLock
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBHSetFLock
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBRstFLock
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBHRstFLock
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBSetFVers
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBRename
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBHRename
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBGetCatInfo
      (pBlk: CInfoPBPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBSetCatInfo
      (pBlk: CInfoPBPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBCatMove
      (pBlk: CInfoPBPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBOpenWD
      (pBlk: WDPBPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBCloseWD
      (pBlk: WDPBPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBGetWDInfo
      (pBlk: WDPBPtr; async: BOOLEAN) : OsErr;
    PROCEDURE PBGetFCBInfo
      (pBlk: FCBPBPtr; async: BOOLEAN) : OsErr;

END PBFileManager.

----------- PBFileManager.MOD -----------

(* Tom Taylor
   3707 Poinciana Dr. #137
   Santa Clara, CA 95051 *)

IMPLEMENTATION MODULE PBFileManager;

(* This module implements the low level
   file system described in the latest
   File Manager documentation.  The
   procedures implemented in this
   module support both MFS and HFS
   calls.  However, attempting to
   call an HFS-only routine on a
   system without HFS will bomb. *)
 
  FROM ASMInterface IMPORT
    ASM_MCode, InstallAssembly;
  FROM Terminal IMPORT
    WriteString;
  FROM MacSystemTypes IMPORT
    OsErr;
  FROM SYSTEM IMPORT
    ADDRESS;
    
  VAR
    modnum : INTEGER; (* Module number of
                         assembly routine *)

    PROCEDURE PBMountVol
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A00Fh, 0);
    END PBMountVol;
    
    PROCEDURE PBGetVInfo
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A007h, 0);
    END PBGetVInfo;
    
    PROCEDURE PBHGetVInfo
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A207h, 0);
    END PBHGetVInfo;
    
    PROCEDURE PBHSetVInfo
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A260h, 11);
    END PBHSetVInfo;
    
    PROCEDURE PBGetVol
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A014h, 0);
    END PBGetVol;
    
    PROCEDURE PBHGetVol
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A214h, 0);
    END PBHGetVol;
    
    PROCEDURE PBSetVol
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A015h, 0);
    END PBSetVol;
    
    PROCEDURE PBHSetVol
      (pBlk: WDPBPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A215h, 0);
    END PBHSetVol;
    
    PROCEDURE PBFlushVol
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A013h, 0);
    END PBFlushVol;
    
    PROCEDURE PBUnmountVol
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A00Eh, 0);
    END PBUnmountVol;
    
    PROCEDURE PBOffLine
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A035h, 0);
    END PBOffLine;
    
    PROCEDURE PBEject
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A017h, 0);
    END PBEject;
    
    PROCEDURE PBOpen
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A000h, 0);
    END PBOpen;
    
    PROCEDURE PBHOpen
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A20Fh, 0);
    END PBHOpen;
    
    PROCEDURE PBOpenRF
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A00Ah, 0);
    END PBOpenRF;
    
    PROCEDURE PBHOpenRF
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A20Ah, 0);
    END PBHOpenRF;
    
    PROCEDURE PBLockRange
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
     BEGIN
      RETURN LowLevelPB (pBlk, async, 0A260h, 16);
    END PBLockRange;
    
   PROCEDURE PBUnlockRange
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A260h, 17);
    END PBUnlockRange;
    
    PROCEDURE PBRead
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A002h, 0);
    END PBRead;
    
    PROCEDURE PBWrite
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A003h, 0);
    END PBWrite;
    
    PROCEDURE PBGetFPos
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A018h, 0);
    END PBGetFPos;
    
    PROCEDURE PBSetFPos
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A044h, 0);
    END PBSetFPos;
    
    PROCEDURE PBGetEOF
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A011h, 0);
    END PBGetEOF;
    
    PROCEDURE PBSetEOF
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A012h, 0);
    END PBSetEOF;
    
    PROCEDURE PBAllocate
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A010h, 0);
    END PBAllocate;
    
    PROCEDURE PBAllocContig
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A210h, 0);
    END PBAllocContig;
    
    PROCEDURE PBFlushFile
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A045h, 0);
    END PBFlushFile;
    
    PROCEDURE PBClose
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
     BEGIN
      RETURN LowLevelPB (pBlk, async, 0A001h, 0);
    END PBClose;
    
   PROCEDURE PBCreate
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A008h, 0);
    END PBCreate;
    
    PROCEDURE PBHCreate
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A208h, 0);
    END PBHCreate;
    
    PROCEDURE PBDirCreate
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A260h, 6);
    END PBDirCreate;
    
    PROCEDURE PBDelete
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A009h, 0);
    END PBDelete;
    
    PROCEDURE PBHDelete
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A209h, 0);
    END PBHDelete;
    
    PROCEDURE PBGetFInfo
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A00Ch, 0);
    END PBGetFInfo;
    
    PROCEDURE PBHGetFInfo
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A20Ch, 0);
    END PBHGetFInfo;
    
    PROCEDURE PBSetFInfo
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A00Dh, 0);
    END PBSetFInfo;
    
    PROCEDURE PBHSetFInfo
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A20Dh, 0);
    END PBHSetFInfo;
    
    PROCEDURE PBSetFLock
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A041h, 0);
    END PBSetFLock;
    
    PROCEDURE PBHSetFLock
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A241h, 0);
    END PBHSetFLock;
    
    PROCEDURE PBRstFLock
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A042h, 0);
    END PBRstFLock;
    
    PROCEDURE PBHRstFLock
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A242h, 0);
    END PBHRstFLock;
    
    PROCEDURE PBSetFVers
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A043h, 0);
    END PBSetFVers;
    
    PROCEDURE PBRename
      (pBlk: ParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A00Bh, 0);
    END PBRename;
    
    PROCEDURE PBHRename
      (pBlk: HParmBlkPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A20Bh, 0);
    END PBHRename;
    
    PROCEDURE PBGetCatInfo
      (pBlk: CInfoPBPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A260h, 9);
    END PBGetCatInfo;
    
    PROCEDURE PBSetCatInfo
      (pBlk: CInfoPBPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A260h, 10);
    END PBSetCatInfo;
    
    PROCEDURE PBCatMove
      (pBlk: CInfoPBPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A260h, 5);
    END PBCatMove;
    
    PROCEDURE PBOpenWD
      (pBlk: WDPBPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A260h, 1);
    END PBOpenWD;
    
    PROCEDURE PBCloseWD
      (pBlk: WDPBPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A260h, 2);
    END PBCloseWD;
    
    PROCEDURE PBGetWDInfo
      (pBlk: WDPBPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A260h, 7);
    END PBGetWDInfo;
    
    PROCEDURE PBGetFCBInfo
      (pBlk: FCBPBPtr; async: BOOLEAN) : OsErr;
    BEGIN
      RETURN LowLevelPB (pBlk, async, 0A260h, 8);
    END PBGetFCBInfo;
    

    PROCEDURE LowLevelPB (pBlk: ADDRESS;
                      async: BOOLEAN;
       trap: CARDINAL;
       selector: INTEGER) : OsErr;
    (* This procedure is responsible for calling
       the assembly language routine that actually
       calls the PB trap. *)
      PROCEDURE LowLevelPB (pBlk: ADDRESS;
 async: BOOLEAN;
         trap: CARDINAL;
 selector: INTEGER;
 modnum: INTEGER) : OsErr;
      CODE ASM_MCode; 0; END LowLevelPB;
    BEGIN
      RETURN LowLevelPB (pBlk, async, trap, selector, modnum);
    END LowLevelPB;

BEGIN
  (* Look for a MASM resource with ID
     of 1986 in current open resource
     files.  It better be in our
     .LOD file, put there by M2 Linker *)
  modnum := InstallAssembly("",1986);
  IF modnum < 1 THEN
    WriteString("Cannot load PB asm code");
    HALT
  END;
END PBFileManager.

----------- PBFileManagerASM.ASM----------

; Tom Taylor
; 3707 Poinciana Dr. #137
; Santa Clara, CA 95051
;
; The one procedure in this
; file is used to implement
; all of the PB calls.  The
; higher level Modula-2 program
; (PBFileManager.MOD)
; passes in the actual value
; of the PB trap and the
; procedure here modifies itself
; to execute that trap.

DC.W    LowLevelPB ; Offset to routine

asyncTrpBit EQU  $400

;    PROCEDURE LowLevelPB (pBlk: ParmBlkPtr;
;                          async: BOOLEAN;
;           trap: CARDINAL;
;           selector: INTEGER) : OsErr;
LowLevelPB:
 MOVE.W (A4)+,D0 ; get trap selector 
 ; (HFS only)
 MOVE.W (A4)+,D1 ; get trap value
 TST.W  (A4)+    ; check for async call
 BEQ.S  NotAsync     ; nope
 ORI.W  #asyncTrpBit,D1 ; yep, make trap async
NotAsync:
 LEA    Trapper,A0 ; get address of trap 
 ; location
 MOVE.W D1,(A0)  ; install trap
 MOVE.L (A4)+,A0 ; get param block address
Trapper:
 DC.W   0 ; PB Trap goes here
 MOVE.W D0,-(A4) ; return result
 RTS

----------- PBFileManagerASM.LINK----------

PBFileManagerASM
/Output MacModula-2:PBFileManager.made
/Type '????' '????'
$

----------- PBFileManager.r---------

* Tom Taylor
* 3707 Poinciana Dr. #137
* Santa Clara, CA 95051
* After running this file through
* RMaker, rename PBFileManager.REL.RSRC
* to PBFileManager.REL before compiling
* PBFileManager.MOD
MacModula-2:PBFileManager.REL.RSRC
LODRM2MC

Type MASM = PROC
,1986
MacModula-2:PBFileManager.made

----------- MakePath.MOD---------

(* Tom Taylor
   3707 Poinciana Dr. #137
   Santa Clara, CA  95051 *)

MODULE MakePath;

(* This program demonstrates a use of
   the PBFileManager module.
   The program puts up the SFGetFile
   dialog and allows the user to select
   a file.  The program will then print
   out the full path name to the file.
   Click the mouse to continue and 
   click the SFGetFile's cancel button
   to quit. *)

  FROM PBFileManager IMPORT
    PBGetCatInfo, CInfoPBRec,
    HParamBlockRec, PBHGetVInfo;
  FROM PackageManager IMPORT
    SFGetFile, SFReply, SFTypeList;
  FROM SYSTEM IMPORT
    ADR;
  FROM MacSystemTypes IMPORT
    Str255, LongCard;
  FROM Strings IMPORT
    StrMacCat, StrModToMac;
  FROM WindowManager IMPORT
    WindowPtr, GetNewWindow,
    DisposeWindow;
  FROM QuickDraw1 IMPORT
    MoveTo, DrawString,
    SetPort, Point, TextFont;
  FROM DialogManager IMPORT
    StopAlert;
  FROM EventManager IMPORT
    StillDown, Button;
  
  CONST
    MFSInstalled = -1;  (* Location in low
        memory tells whether
 HFS system installed *)
    HFSvolume = 04244h; (* Value specifying a
             HFS volume *)
 
  TYPE
    Str255Ptr = POINTER TO Str255;
   
  VAR
    reply       : SFReply;
    typelist    : SFTypeList;
    HFS [03f6h] : INTEGER;
    wind        : WindowPtr;
    behind      : LongCard;
    path        : Str255;
    where       : Point;
    hfsFlag     : BOOLEAN;

  PROCEDURE WriteString (s : ARRAY OF CHAR);
  (* This routine simply writes a Modula-2
     style string. *)
    VAR
      macs : Str255;
  BEGIN
    StrModToMac (macs,s);
    DrawString (macs);
  END WriteString;
    
  PROCEDURE MakePath (name : Str255Ptr;
         vRefNum : INTEGER;
       VAR path : Str255;
       VAR hfsFlag : BOOLEAN);
  (* This procedure, the focus of this
     program, takes a vRefNum (which might
     be a WDRefNum) and figures out the full
     path to the directory.  It does this
     by finding the parent each directory
     until the parent is the root.  This
     procedure works on both MFS and HFS
     Macs. *)
    VAR
      blk               : CInfoPBRec;
      volBlk           : HParamBlockRec;
      getname, volname : Str255;
      len               : CARDINAL;
      
    PROCEDURE CheckError (err : INTEGER);
    BEGIN
      IF err # 0 THEN
        err := StopAlert (1986, NIL);
 HALT
      END;
    END CheckError;
    
  BEGIN
    path    := name^; (* Start the path with
                         the destination file *)
    volname := "";    (* Clear out the volume 
                         name *)
    (* Get the volume info for the desired
       volume.  This calls works on both
       HFS and MFS systems. *)
    WITH volBlk DO
      ioCompletion := NIL;
      ioNamePtr    := ADR(volname);
      ioVRefNum    := vRefNum;
      ioVolIndex   := 0;
      ioVSigWord   := 0;
      CheckError (PBHGetVInfo (ADR(volBlk), FALSE));
    END;
    (* This next line determines whether the HFS
       system is installed and whether the current
       volume is an HFS volume. *)
    hfsFlag := (HFS # MFSInstalled) AND
               (volBlk.ioVSigWord = HFSvolume);
     
    IF hfsFlag THEN
      (* Only attempt to build a path name
         deeper than just a volume and file
  on HFS volumes *)
      WITH blk DO
 ioCompletion := NIL;
 getname      := "";
 ioNamePtr    := ADR(getname);
 ioVRefNum    := vRefNum; (* Probably a WDRefNum *)
 ioFDirIndex  := -1;  (* directory info only *)
 ioDrDirID.r  := 0.0; (* kludge for LongCard zero *)
 CheckError (PBGetCatInfo (ADR(blk), FALSE));
 WHILE (ioDrDirID.h # 0) OR
       (ioDrDirID.l # 2) DO
   (* Keep looping until the directory ID
      is the root directory (dir ID = 2) *)
      
   (* Insert a colon in the path *)
   len := CARDINAL(getname[0]);
   IF len < 255 THEN
     INC(len);
     getname[len] := ':';
     getname[0] := CHAR(len);
   END;
   (* Append the path made so
      far with the piece we
      just got. *)
   StrMacCat(getname,path);   
   (* Save the partial path
      in path. *)
   path := getname;
   getname := "";
   ioFDirIndex := -1;  (* directory info only *)
   ioDrDirID   := ioDrParID; (* Get info about
                                the parent
        directory. *)
   CheckError (PBGetCatInfo (ADR(blk), FALSE));
 END;
      END;
    END;
    (* Lastly, append the path to the volume name *)
    len := CARDINAL(volname[0]);
    INC(len);
    volname[len] := ':';
    volname[0] := CHAR(len);
    StrMacCat(volname, path);
    path := volname;
  END MakePath;
  
BEGIN
  behind.h := 65535; (* kludge for LongCard -1 *)
  behind.l := behind.h;
  where.h := 100;  (* location of SFGetFile *)
  where.v := 100;
  LOOP
    SFGetFile (where, "", NIL, -1, typelist, NIL, reply);
    WITH reply DO
      IF NOT good THEN EXIT END; (* Exit if user hit cancel *)
      
      (* Figure out path to the file *)
      MakePath (ADR(fName), vRefNum, path, hfsFlag);
      
      TextFont (0); (* so window title comes up right *)
      wind := GetNewWindow (1986, NIL, WindowPtr(behind));
      SetPort (wind);
      MoveTo (5,17);
      WriteString ("The path name on this ");
      IF hfsFlag THEN
        WriteString ("HFS");
      ELSE
        WriteString ("MFS");
      END;
      WriteString (" volume is:");
      MoveTo (5, 37);
      DrawString (path);
      WHILE StillDown () DO END;
      WHILE NOT Button () DO END;
      (* Really need to use GetNextEvent
         so this button press is eaten *)
      DisposeWindow (wind);
    END;
  END;
END MakePath.

----------- MakcPath.r----------

* Tom Taylor
* 3707 Poinciana Dr. #137
* Santa Clara, CA 95051
* After running this file through
* RMaker, rename MakePath.REL.RSRC
* to MakePath.REL before compiling
* MakePath.MOD
MacModula-2:MakePath.REL.RSRC
LODRM2MC

type ALRT
,1986
50 50 250 250
1986
7fff

type DITL
,1986
2

button
100 10 130 80
OK?

staticText
30 80 190 190
A file manager error occured!

type WIND
,1986
Path Name
50 3 100 509
Visible NoGoAway
4
0
 

Community Search:
MacTech Search:

Software Updates via MacUpdate

TunnelBear 3.5.1 - Subscription-based pr...
TunnelBear is a subscription-based virtual private network (VPN) service and companion app, enabling you to browse the internet privately and securely. Features Browse privately - Secure your data... Read more
Typinator 7.4 - Speedy and reliable text...
Typinator turbo-charges your typing productivity. Type a little. Typinator does the rest. We've all faced projects that require repetitive typing tasks. With Typinator, you can store commonly used... Read more
Fantastical 2.4.5 - Create calendar even...
Fantastical 2 is the Mac calendar you'll actually enjoy using. Creating an event with Fantastical is quick, easy, and fun: Open Fantastical with a single click or keystroke Type in your event... Read more
Monosnap 3.4.9 - Versatile screenshot ut...
Monosnap lets you capture screenshots, share files, and record video and .gifs! Features Capture Capture full screen, just part of the screen, or a selected window Make your crop area pixel... Read more
Skim 1.4.32 - PDF reader and note-taker...
Skim is a PDF reader and note-taker for OS X. It is designed to help you read and annotate scientific papers in PDF, but is also great for viewing any PDF file. Skim includes many features and has a... Read more
ForkLift 3.1.1 - Powerful file manager:...
ForkLift is a powerful file manager and ferociously fast FTP client clothed in a clean and versatile UI that offers the combination of absolute simplicity and raw power expected from a well-executed... Read more
Direct Mail 5.2.1 - Create and send grea...
Direct Mail is an easy-to-use, fully-featured email marketing app purpose-built for macOS. Create, send, and track great looking email campaigns that get results. Start your newsletter by selecting... Read more
Direct Mail 5.2.1 - Create and send grea...
Direct Mail is an easy-to-use, fully-featured email marketing app purpose-built for macOS. Create, send, and track great looking email campaigns that get results. Start your newsletter by selecting... Read more
Skim 1.4.32 - PDF reader and note-taker...
Skim is a PDF reader and note-taker for OS X. It is designed to help you read and annotate scientific papers in PDF, but is also great for viewing any PDF file. Skim includes many features and has a... Read more
ForkLift 3.1.1 - Powerful file manager:...
ForkLift is a powerful file manager and ferociously fast FTP client clothed in a clean and versatile UI that offers the combination of absolute simplicity and raw power expected from a well-executed... Read more

Latest Forum Discussions

See All

What mobile gaming can learn from the Ni...
While Nintendo might not have had things all its own way since it began developing for mobile, one thing it has got right is the release of the Switch. After the disappointment of the WiiU, which I still can't really explain, the Switch felt a... | Read more »
Programmer of Sonic The Hedgehog launche...
Japanese programmer Yuji Naka is best known for leading the team that created the original Sonic The Hedgehog. He’s moved on from the speedy blue hero since then, launching his own company based in Tokyo – Prope Games. Legend of Coin is the... | Read more »
Why doesn't mobile gaming have its...
The Overwatch League is a pretty big deal. It's an attempt to really push eSports into the mainstream, by turning them into, well, regular sports. But slightly less sweaty. It's a lavish affair with teams from all around the world, and more... | Read more »
Give Webzen’s new billiard game PoolTime...
Best known for producing hugely popular MMO titles, South Korean publisher Webzen is now taking aim at a different genre altogether. PoolTime is a realistic eight ball pool simulator, allowing you to compete in real-time matches against players... | Read more »
Let Them Come Guide - How to survive aga...
Let Them Come is all about making it as far as possible against overwhelming odds. Check out some of these tips to help you last a little longer in your unwinnable fight: [Read more] | Read more »
All the best games on sale for iPhone an...
Happy last day of the week. I hope you've been having a good one. I have. I saw ten doggos today. So because I'm in a good mood, I thought I'd round up all of the best games that are currently on sale on the App Store. [Read more] | Read more »
The very best games that came out for iP...
We're getting to the end of the first real, full, proper week of 2018. And in that time we've seen some pretty awesome games landing on the App Store. Of course, we've seen some absolute duffers as well. The sort of games that you look at and... | Read more »
Rusty Lake Paradise (Games)
Rusty Lake Paradise 1.4 Device: iOS Universal Category: Games Price: $2.99, Version: 1.4 (iTunes) Description: Jakob, the oldest son of the Eilander family, is returning to Paradise island after his mother passed away. Since her... | Read more »
Antihero Guide - Sneaky tricks to get ah...
Games of Antihero start out small and streamlined, but they quickly turn into long strategic conquests as you fight for control of the Victorian-era streets. If you find yourself struggling in the skullduggery department, here are a few things you... | Read more »
Here's why Niantic pulling Pokemon...
If there's one thing that Pokemon GO did well, it was bringing people together. I still remember seeing groups of people around the marina near where I live in the weeks after the game came out, all of them trying to grab some water Pokemon. There... | Read more »

Price Scanner via MacPrices.net

10″ iPad Pros on sale for $50-$75 off MSRP, n...
B&H Photo has 10″ and #Apple #iPad Pros on sale for up to $75 off MSRP. Shipping is free, and B&H charges sales tax in NY & NJ only. Note that some sale prices are restricted to certain... Read more
Apple refurbished Mac minis available startin...
Apple has restocked Certified Refurbished Mac minis starting at $419. Apple’s one-year warranty is included with each mini, and shipping is free: – 1.4GHz Mac mini: $419 $80 off MSRP – 2.6GHz Mac... Read more
Amazon offers Silver 13″ Apple MacBook Pros f...
Amazon has new Silver 2017 13″ #Apple #MacBook Pros on sale today for up to $150 off MSRP, each including free shipping: – 13″ 2.3GHz/128GB Silver MacBook Pro (MPXR2LL/A): $1199.99 $100 off MSRP – 13... Read more
Sale: 12″ 1.3GHz MacBooks on sale for $1499,...
B&H Photo has Space Gray and Rose Gold 12″ 1.3GHz #Apple MacBooks on sale for $100 off MSRP. Shipping is free, and B&H charges sales tax for NY & NJ residents only: – 12″ 1.3GHz Space... Read more
Apple offers Certified Refurbished 2017 iMacs...
Apple has a full line of Certified Refurbished iMacs available for up to $350 off original MSRP. Apple’s one-year warranty is standard, and shipping is free. The following models are available: – 27... Read more
13″ MacBook Airs on sale for $120-$100 off MS...
B&H Photo has 2017 13″ 128GB MacBook Airs on sale for $120 off MSRP. Shipping is free, and B&H charges sales tax for NY & NJ residents only: – 13″ 1.8GHz/128GB MacBook Air (MQD32LL/A): $... Read more
15″ Touch Bar MacBook Pros on sale for up to...
Adorama has Space Gray 15″ MacBook Pros on sale for $200 off MSRP. Shipping is free, and Adorama charges sales tax in NJ and NY only: – 15″ 2.8GHz MacBook Pro Space Gray (MPTR2LL/A): $2199, $200 off... Read more
21″ 3.4GHz 4K iMac on sale for $1399, $100 of...
Adorama has the 21″ 3.4GHz 4K #Apple #iMac on sale today for $1399. Their price is $100 off MSRP. Shipping is free, and Adorama charges sales tax in NJ and NY only: – 21″ 3.4GHz 4K iMac (MNE02LL/A... Read more
B&H offering 13″ Apple MacBook Pros for u...
B&H Photo has 13″ MacBook Pros on sale for up to $75-$120 off MSRP. Shipping is free, and B&H charges sales tax for NY & NJ residents only: – 13-inch 2.3GHz/128GB Space Gray MacBook Pro (... Read more
B&H continues to offer clearance 2016 15″...
B&H Photo has clearance 2016 15″ #MacBook Pros available for up to $800 off original MSRP. Shipping is free, and B&H charges NY & NJ sales tax only: – 15″ 2.7GHz Touch Bar MacBook Pro... Read more

Jobs Board

Commerce Engineer, *Apple* Media Products -...
# Commerce Engineer, Apple Media Products Job Number: 113161479 Santa Clara Valley, California, United States Posted: 01-Nov-2017 Weekly Hours: 40.00 **Job Summary** Read more
*Apple* Retail - Multiple Positions - Apple,...
Job Description:SalesSpecialist - Retail Customer Service and SalesTransform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
Site Reliability Engineer, *Apple* Pay - Ap...
# Site Reliability Engineer, Apple Pay Job Number: 113356036 Santa Clara Valley, California, United States Posted: 12-Jan-2018 Weekly Hours: 40.00 **Job Summary** Read more
UI Tools and Automation Engineer, *Apple* M...
# UI Tools and Automation Engineer, Apple Media Products Job Number: 86351939 Santa Clara Valley, California, United States Posted: 11-Jan-2018 Weekly Hours: 40.00 Read more
*Apple* Retail - Multiple Positions - Apple,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.