TweetFollow Us on Twitter

Macsbug Template
Volume Number:8
Issue Number:7
Column Tag:Debugging

Related Info: Time Manager Vert. Retrace Mgr

Macsbug Template Use

Accessing your globals in MacsBug

By David T. Roach, Austin, Texas

Note: Source code files accompanying article are located on MacTech CD-ROM or source code disks.

Introduction

When writing an application in C, high-level debuggers such as Think C’s Debugger and SADE eliminate quite a bit of pain from the development process since they are able to display references to variables by name.

Developers of lower-level code, such as INITs, drivers, control panel devices, code resources, plug-ins, XCMDs, etc., must use either MacsBug or TMON, neither of which accesses variables directly by name. This is because the global variables are referenced from the A5 register, or in some cases the A4 register, and the temporary variables are accessed via the A6 register.

On the other hand, MacsBug and TMON have no problem finding your routines by name, because each has a method for searching the current (target) heap zone for the presence of the function name immediately following the associated function. This facility has recently been updated to include function names longer than 8 characters, with support for this from the most popular compilers.

It is possible to trick MacsBug 6.2 (or higher) into believing that what it perceives as the first instruction in a named function is really a pointer or handle to a place in memory that contains your globals, which you can access by name. In order to do so, you must do several things you might not do otherwise:

Instead of using A5 or A4 to point to your globals under compiler control, you must allocate a Pointer or Handle and fill it in using a data structure which defines your globals explicitly.

You must store this pointer or handle in your main code segment. Technically this is self-modifying code. However you only modify the code once during initialization, and it remains unmodified after that. This is essentially the same method that a VBL or Time Manager (version 1) task uses to store a pointer to it’s globals, so this method should remain valid as long as Apple maintains support for programs written under the past and current versions of the Vertical Retrace Manager. This method has not varied since the introduction of the 128K Mac, which is a fairly good reason to believe that it will remain the same in the future (although not infallible).

Create a separate ‘.r’ text file which contains ‘mxbm’ (macro) and ‘mxwt’ (template) resource types which define your very own globals structure.

Use the MPW Rez tool or SARez (a precompiled version of the Rez tool included with Think C 5.0) to compile and merge these resources into your Debugger Prefs file in the system folder. MPW includes the Rez resource compiler tool, which is activated from command line input in MPW. Also included is a Commando interface for Rez, which is a dialog used to build a command line specific to Rez. SARez is a utility included with Think C 5 which is a double-clickable version of MPW’s commando interface to Rez. It also creates a command line, then parses it and executes it immediately. Unless stated otherwise, all further references to Rez in this article also refer to SARez.

While it’s possible to use ResEdit to perform this and the previous step, it’s slow and painful. Additionally, ResEdit cannot deal with really large templates.

In order for MacsBug to find it at startup time, the Debugger Prefs file must exist at the main level of your system folder, and not in any other folders such as Control Panels or Extensions. It would make sense for future versions of MacsBug to look in the Prefs Folder as well.

Reboot and enjoy debugging your variables by name. Each time you add a data element to your structure(s), you must also update the corresponding ‘.r’ file and recompile it using Rez. While this sounds like a pain (it is the first few times), the payback on the stability and integrity of your project is tremendous.

What It Takes

MacsBug 6.2 and Think C 5 or MPW C package v3.2, are required for implementing the symbolic display of variables under MacsBug, using the techniques described in this article. Other development environments and debuggers will have slightly different requirements, but shouldn’t present any serious obstacles to implementation. The techniques for dealing with this feature under MPW are somewhat different than those required by Think C 5, but the differences have been isolated into separate source files so that the remaining files can be run under either compiler.

Why It Works

MacsBug has been able to reference functions by name almost since the release of the first Macintoshes. More recently the ability to include user templates and macros, as well as logging to an output file, have been included. MacsBug names (officially known as Procedure Definitions) are documented on page 408 of the "MacsBug Reference and Debugging Guide for MacsBug version 6.2", which you’ll find on bookstore shelves next to the Inside Macintosh volumes if you don’t already have it. It’s the official documentation for MacsBug. MacsBug names can have a fixed size of 8 or 16 characters, or they can be of a variable length. MPW C or Think C 5 will generate these names optionally. In the case of the MPW Assembler, you are required to build the names into your code (which isn’t really so bad once you figure out how to do it).

What we want to do is to use a MacsBug name to represent a pointer to all of our data rather than the entry point of a routine. To do this, we have to structure the program under development to always reference this pointer, rather than A5 or A4. In some cases it’s also useful to include values that would normally be stack-based and temporary in the globals allocation, so we can observe their value the last time that they were used. In doing so, we gain the advantage of being able to access more than 32k worth of global data. All the globals are all defined in a single ‘.h’ or ‘.a’ file, with a corresponding ‘.r’ containing exactly the same data structure(s) in MacsBug/Rez format.

The pointer to our data is embedded into one of our code segments as a fake function, with routines in the same segment which set or get the current value. It should only be necessary to initialize this pointer once. Calling StripAddress on the pointer before we set it and FlushInstructionCache after we set it will assure 32-bit addressing and 040 caching compatibility. The fake function (our pointer) and the routines which manipulate it are handled in an object-oriented style. The fake function is the object’s data field, and the routines are methods to manipulate or access the single data field. If Apple ever changes the way VBL tasks access their globals (thereby rendering this scheme useless), then these routines most probably can be modified to use the new method.

The fake function simply consists of a 4-byte pointer, an assembly language ‘RTS’ instruction, and the MacsBug name. Think C 5 requires some additional gymnastics to build this apparently simple piece of code. This is because Think C insists on mapping all function entry points via the main jump table, which is in turn referenced from A5 or A4. When referencing our pointer from the two routines which access it, we need PC-relative addressing. We get around this by declaring three different entry points into a single C function in Think C. Each of these individual functions can then reference each of the other two with PC-relative addressing. Of course, one of these three functions is the fake function. Any external references to this function will still be referenced via the jump table, so when using Think C you must use the two routines to manipulate the globals pointer. You will not be able to access it directly by name from anywhere else in the program, even though it may look like it’s compiling OK.

Under MPW, we create a ‘.a’ file in assembly language, which contains the pointer and the two routines. It’s simply linked into the project. Since MPW doesn’t insist on referencing each and every function through the jump table, the code will appear to be much more straightforward, although it is functionally identical. In other words, don’t look at the Think C code first if you want to understand how this works.

Once we’ve defined the data structure in C or MPW Assembler, then it’s time to define an identical structure in Rez format. MPW 3.1 shipped with some MacsBug-specific ‘.r’ files on the MacsBug distribution disk. For some mysterious reason, these files are not part of MPW 3.2. These ‘.r’ files defined the ‘mxwt’ and ‘mxbm’ templates in both MacsBug and ResEdit formats. The ‘TMPL’ resources are the ResEdit templates used in defining the ‘mxbm’ and ‘mxwt’ resources. The ‘mxwt’ resources are MacsBug data templates which are used by MacsBug to display various data types.

Built-in templates already included in Debugger Prefs include classics such as WindowPtr, GrafPtr, pstring, cstring, etc. An ‘mxwt’ template can reference a data type defined in another ‘mxwt’ template, since MacsBug is essentially interpretive in this regard. Templates can also be singly or doubly dereferenced, so if you have a handle or a pointer to a data structure, you can display the entire structure. If it contains a handle or a pointer to a structure, you can display that structure too, ad infinitum. The ability to deal with linked lists of structures is also included.

Macros created by the ‘mxbm’ resources or created directly by the MacsBug user can also reference any of these templates. So, if we define a template which corresponds directly to our program’s data structures and we are able to access the pointer to our data structures via name in MacsBug, then we have a mechanism to display all the data by name and value. Furthermore, if MacsBug’s logging option is enabled, everything gets stored to a disk file for later examination.

For instance, if we name our fake function ‘theGlobals’ and we have a template named ‘theTemplate’, then anytime we’re in MacsBug and the target heap contains our code we can type

dm theGlobals theTemplate

to view all of our data’s current values. We can even create a macro which types out this line for us, maybe with a name like ‘globs’. Then if we’d like, in the middle of any routine we can place a debugger call such as

/* 1 */

 DebugStr("\pglobs;g"); 

which will disable all the interrupts, display all the globals, re-enable the interrupts, and then go on running. Or we can break at a specific function and do the same thing in MacsBug by typing

 BR funcname ‘;globs;g’

Once over the learning hump, life becomes much easier. Various versions of the main data template can be created which only display a subset of data. It’s also possible to develop function-specific templates which display values on the stack when MacsBug breaks at a function entry point. This is useful in object-oriented programming where the pointer to the object is always at a certain position on the stack, and you can then break on any method and display the object’s variables.

Sanity checking

It always helps to be sure that what you’re looking at really is your data, and that your ‘mxwt’ template does in fact match your data structure. You can make life easier on yourself by storing your application’s OSType signature at both the beginning and end of your data structure. Fill in these fields immediately after initializing the pointer in the fake function. If you don’t have a signature, you can use something like ‘dBug’. By having the same 4 bytes at both the start and end of your data structure, you can easily see whether you’re looking at the right address (is the first OSType filled in correctly?), and if you are, whether the template matches the structure (is the last OSType filled in correctly?). Without these sanity checks in place, you can easily fall back into a questioning mindset (Grumble, grumble, is this really my data, or does it just look like it might be my data??).

Updating Debugger Prefs using SARez or the Rez Commando dialog

If you’re not familiar with Rez, then the prospect of compiling resources and merging them into your Debugger Prefs file can be a bit daunting. Until you’re confident of the methodology, it may be a good idea to drag a fresh copy of the Debugger Prefs file into your System Folder each time you plan to add new template and macro resources. Never work on your original of Debugger Prefs, only on a copy!

We need to specifically tell Rez where our source ‘.r’ file is, where Debugger Prefs is, and that we want to merge our resources into Debugger Prefs rather than blow the existing file away. Since all the templates and definitions we need to compile our file are actually in the file already, there is no need for search paths or any additional description files. If we ask for progress information, then we get a listing which includes any errors made during compilation. This is one of the few places in this cycle that you’ll get any kind of specific error messages, so make sure that you don’t have any.

If you’re an MPW script monger, then you can probably sit down and type out the command line. Otherwise, it’s probably easier to use the Commando interface the first time and copy the command line into MPW for future use. SARez users will need to remember to do the same things in the commando dialog each time you compile the file.

Referring to the dialog, note that ‘Progress Information’ is checked, and that the ‘Merge resources into resource file’ radio button is selected. Click on the ‘Description Files ’ push button to determine which file to compile, and click on the ‘Resource Output File’ popup menu to select the destination file. Since we want to modify Debugger Prefs, we ‘Select an existing output file ’. Everything else in this dialog is unused.

If you’re using MPW, now’s the time to select the Command Line and copy it, then Cancel Rez and paste the line into the MPW worksheet, select it, hit enter, and off you go. You can now use this over and over again without calling up the Commando interface. Of course, if you rename your hard disk or any of the folders, then it stops working.

It’s a good idea to make an alias of Debugger Prefs and put it in your project’s folder. If you’re using SARez you won’t regret moving the working copy of SARez into your project folder. An alias won’t do the trick here, regretfully. Also, don’t try dragging your ‘.r’ file onto SARez in the Finder and hope that it will launch, it just bombs instead.

Resource Management in Debugger Prefs

Make sure that you always operate on a copy of Debugger Prefs. Rez and SARez will wreak havoc on this file if the settings are wrong. It’s best to think through the resource numbering scheme used in Debugger Prefs before compiling your ‘.r’ file. ‘mxwt’ resources have both a name and a number. Each ‘mxwt’ resource can contain up to 32768 templates. Debugger Prefs can contain up to 32768 ‘mxwt’ resources, although the lowest numbers are reserved by Apple and are used to define quite a few OS templates.

The template name is how MacsBug references the template. If you have two differently numbered resources which each contain a template of the same name, only one template will win out in the end. Which one to use is determined by the resource’s position in the Debugger Prefs resource map, which is determined by the order in which the resources were compiled. This is obviously something you can’t rely on, so make sure that you have only one occurrence of each template name.

The ‘mxbm’ macro definition resource works the same way. Up to 32K macros can be in one resource, and up to 32K resources can exist in Debugger Prefs, with the lower numbers reserved by Apple. The same holds true here, try to avoid any duplication of names. Be especially careful of resources that were merged into Debugger Prefs during a previous project which used this debugging technique.

Caveats

You must verify each and every macro that you write. The only way to do this is to compile it into Debugger Prefs and then restart. What you’re looking for is whether the macro can expand fully. Apparently if the macro length is greater than the length of the command line at the bottom of the MacsBug screen, then it can’t expand. This seems like a pretty stupid limitation to me, and has caused me more grief than any other shortcoming, since the debug/test cycle involves a reboot. Right now, a tester has to type 6 to 10 different commands to execute all the macros which I, the programmer, would like to see in case of a crash. If the macro expansion was longer in length, this could be accomplished by a single command which would open the log file, log all the macros, and then close the log file. Hopefully future versions of MacsBug will address this.

You must maintain the ‘.r’ file’s one to one correspondence with the data structure in the ‘.h’ file religiously. It’s easy to find out if you’re out of sync by looking at the id’s that you placed at the beginning and end of your data structure. A good technique for maintaining the ‘.r’ and ‘.h’ files together is to place them on the screen side by side. Make sure there are just as many blank lines in each file, so that the names of the variables line up next to each other. Then when you page down in one, you can page down exactly the same amount in the other and they’ll still line up. This technique forces any data elements that are out of sync to show up immediately.

If you use SetUpA4() or SetUpA5(), consider switching to this method so that you’re not storing two different variables into your code segment. Changing one 32-bit long in one place in one code segment only one time during initialization should be the maximum extent of self-modification, and will correspondingly affect the operating system minimally.

If you’re on a LocalTalk network, don’t stay in MacsBug for a long period of time. After a while, the network will time out and your machine will appear to be frozen. If you wait long enough (5 to 10 minutes), it will time out again and come back to life. If you can’t afford to wait that long, then it’s time to reach for the programmer’s switch (or the OFF/ON switch on LC class machines, ow!). Maybe MacsBug 6.3 will fix this.

Special Requests

For the MPW team or some well-meaning hacker to create a Rez-like tool which compiles ‘mxwt’ resources directly from C structures defined in a ‘.h’ file and inserts them directly into Debugger Prefs, as well as managing name and numbering conflicts.

Credits

Thanks to Tim Morgan and Daniel Schwarz of Articulate Systems for refinements and feature requests, and to David Zicarelli for arcane Mac OS and Think C knowledge.

Listing:  globals.h
// globals.h -- prototypes for low level functions to
// manipulate globals pointer
// Copyright ©1992, David T. Roach, All Rights Reserved

#ifndef __globals__
#define __globals__

#ifndef __TYPES__
#include<Types.h>
#endif  __TYPES__

#ifndef __TRAPS__
#include<Traps.h>
#endif  __TRAPS__

// unused C function which has three more entry points
void dummy(void);
// where we store the pointer
void GlobPtr(void);
// how we set the pointer
OSErr SetGlobPtr(Ptr globalsPtr);
// how we access the pointer
OSErr GetGlobPtr(Ptr * globalsPtr);

// application defined OSErrs

// returned if globalsPtr is odd or NIL
#define BadPointer 10000

// defined in MPW’s traps.a, but not traps.h
#ifndef _FlushInstructionCache 
#define _FlushInstructionCacheMOVEQ#1,D0   \
 DC.W   _HWPriv
#endif

#endif  __globals__

Listing:  project.h
// project.h -- C-language structure definitions
// for test project
// Copyright ©1992, David T. Roach, All Rights Reserved

#ifndef __project__
#define __project__

#ifndef __globals__
#include"globals.h"
#endif  __globals__
#define AppSignature ’main’

// PROJECT SPECIFIC DEFINES

#define ArraySize1 3
#define ArraySize2 2

// PROJECT SPECIFIC STRUCTURES

typedef struct
{
 short  m[ArraySize2];
}
AnotherStruct,*AnotherStructPtr;

typedef struct
{
 Booleana;
 Byte   b;
 short  c;
 long   d;
 Str255 e;
 AnotherStruct f;
}
OtherStruct,*OtherStructPtr;

typedef struct
{
 OSType id1;
 long   long_hex;
 long   long_unsigned;
 long   long_signed;
 short  short_hex;
 short  short_unsigned;
 short  short_signed;
 Byte   byte_hex;
 Booleanbool;
 OtherStructPtr  other[ArraySize1];
 OSType id2;
}
GlobStruct,*GlobStructPtr;

#endif  __project__

Listing: main.c
// main.c -- project to test symbolic variable listing in 
// Macsbug
// Copyright ©1992, David T. Roach, All Rights Reserved

#include  <stdio.h>

#ifndef __MEMORY__
#include  <memory.h>
#endif  __MEMORY__

#ifndef __project__
#include"project.h"
#endif  __project__

// prototypes
void main(void);
OSErr SetupGlobals(void);
GlobStructPtr FetchGlobals(void);

void main(void)
{
 register OSErr err;
 register short i;
 register short j;
 register GlobStructPtr g;
 register unsigned char * s;
 
 if (err = SetupGlobals()) {
 printf("error in setting up globals");
 }
 else { 
 // put some values in the globals
 g = FetchGlobals();
 
 g->long_hex = 0x12345678;
 g->long_unsigned = 0x90000000;
 g->long_signed = -1L;
 g->short_hex = 0x1234;
 g->short_unsigned = 0x9000;
 g->short_signed = -1;
 g->byte_hex = 0xFF;
 g->bool = true;
 
 for (i=0;i<ArraySize1;i++) {
 g->other[i] = (OtherStructPtr)
 NewPtrClear(sizeof(OtherStruct));
 if (g->other[i]) {
 g->other[i]->a = false;  // Boolean
 g->other[i]->b = 0x80;   // Byte
 g->other[i]->c = 0x8000; // short
 g->other[i]->d = 0x80000000; // long
 s = &g->other[i]->e[0];
 *s++  =  3;// pstring length
 *s++  = ‘x’;    // char in pstring
 *s++  = ‘y’;    // char in pstring
 *s++  = ‘z’;    // char in pstring
 for (j=0;j<ArraySize2;j++) {
 g->other[i]->f.m[j] = j+i; // array of short
 }
 }
 }
 DebugStr("\p;dump");
 }
}

// intermediate layer of calls to set or get globals
// handles and checks application specific info

OSErr SetupGlobals(void)
{
 OSErr err;
 register GlobStructPtr x;

 x = (GlobStructPtr)NewPtrClear((long)sizeof(GlobStruct));
 
 if (err = SetGlobPtr((Ptr)x)) {
 return(err);
 }
 else {
 x->id1 = AppSignature;
 x->id2 = AppSignature;
 }
 return(noErr);
}

GlobStructPtr FetchGlobals(void)
{
 GlobStructPtr x;
 OSErr err;
 
 // returns NIL if error encountered during GetGlobPtr
 
 if(err = GetGlobPtr((Ptr *)&x)) {
 return(0L);
 }
 
 // test that our signature is at the beginning and end of
 // our structure
 
 if ((AppSignature != x->id1) || (AppSignature != x->id2)) {
 return(0L);
 }
 
 // our structure checks out OK
 return(x);
}

Listing:  globals.a
*-----------------------------------------------------------
* NAME
*globals.a -- routines to store and access a pointer to *      
 our private globals
*
* DESCRIPTION
*port of Dragon Systems TMS32010 code to 680x0 
*environment
*
* COPYRIGHT
*©1992, David T. Roach
*All rights reserved.
*-----------------------------------------------------------

CASE    ON
INCLUDE ‘SysEqu.a’
INCLUDE ‘Traps.a’

ENTRY GetGlobPtr : CODE
ENTRY SetGlobPtr : CODE

* heh-heh, this really isn’t code, but where we
* store our ptr to globals
ENTRY GlobPtr    : CODE 

EXPORT  GetGlobPtr
EXPORT  SetGlobPtr

STRING  PASCAL

* returned if globalsPtr is odd or NIL
BadPointerEQU  10000
************************************************************
* OSErr SetGlobPtr(Ptr globalsPtr)
*
* see prototype for arguments & return type
* routine to setup the global pointer
* called only once at init time
* modifies A0 and returns w/ OSErr in D0
*  
* unlike using SetUpA5, it shouldn’t make any 
* difference if you’re at interrupt level
* or application level when you call this 
* function to set up your global pointer
* as long as you’re sure the handle or pointer 
* you’re passing in is valid 

SetGlobPtrPROC   ; pass in A3 set to GlobPtr
* get globals ptr off stack

MOVE.L  4(A7),D0 

* branch if not NIL, error if NIL

BNE.S   @TestForOdd


MOVE.L  #BadPointer,D0    
RTS

@TestForOdd

BTST    #1,D0

* branch if even address, error if odd

BEQ.S   @DoStripAddress

MOVE.L  #BadPointer,D0    
RTS

@DoStripAddress
* we should perform a strip address to zero out 
* the most significant byte of our globalsPtr
* in a 24-bit addressing world, so that 
* we are not caught with our pants down 
* if we’re called during an interrupt when
* a Nubus card’s DRVR has switched the call 
* SwapMMUMode in order to 
* address more than 1 meg of Nubus space, .
* 
* IM Vols V & IV both document StripAddress 
* incorrectly. See TechNote #213 for correct 
* documentation.
* 
* _StripAddress was first implemented on MacII
* System 4.x. You can probably count on the 
* fact that it always exists, but those of us
* that are really safety conscious should 
* check it w/ TrapAvailable()

_StripAddress

* save A0 on the stack so we don’t trash it

MOVEM.L A0,-(A7)

* now get the address of our globals ptr storage
* (which is the address of the fake function)
* this forces ThinkC to use PC relative addressing 
* because GlobPtr is within the same C routine

LEAGlobPtr,A0    
MOVE.L  D0,(A0)

* now restore A0

MOVEM.L (A7)+,A0

* we only set ‘GlobPtr’ once during initialization,
* but Tech Note #261 (updated April 1992) 
* is very clear that you should flush the cache 
* anytime you change a value that’s stored in 
* a code segment
* 
* safety note from TN261: Before you call any of 
* these [cache] routines, make sure that the
* _HWPriv ($A198) trap is implemented, or 
* your program will crash. _HWPriv
* is implemented in the Macintosh IIx ROMs 
* and later, as well as System 6.0.3 
* and later. The correct way to check for the 
* trap is using the TrapAvailable 
* function documented in Inside Macintosh 
* Volume VI (pages 3-7 to 3-9)

_FlushInstructionCache

* return noErr
MOVEQ   #0,D0    
RTS

* macsbug symbol

DC.B  $80
DC.B  ’SetGlobPtr’

* constants used in this routine

DC.W  0

ENDPROC ; SetGlobPtr

************************************************************
* OSErr GetGlobPtr(Ptr * globalsPtr);
* routine to access the global pointer
* may be called at any time
* 
GetGlobPtr PROC

* get the address in which we want to
* return the globals pointer

MOVE.L  4(A7),D0

* save A0 on the stack so we don’t trash it

MOVEM.L A0,-(A7)
MOVEM.L D1,-(A7)

* now get the address of our globals ptr storage
* (which is the address of the fake function)
* this forces ThinkC to use PC relative addressing 
* because GlobPtr is within the same C routine

LEAGlobPtr,A0
MOVE.L  (A0),D1
BNE.S   @TestEven

* restore all registers and return
* with BadPointer error in D0

MOVEM.L (A7)+,D1 
MOVEM.L (A7)+,A0 
MOVE.L  #BadPointer,D0    
RTS

@TestEven

BTST    #0,D1
BEQ.S   @DoGlobals

* restore all registers and return
* with BadPointer error in D0

MOVEM.L (A7)+,D1
MOVEM.L (A7)+,A0
MOVE.L  #BadPointer,D0
RTS

@DoGlobals

MOVEA.L D0,A0
MOVE.L  D1,(A0)

* restore registers

MOVEM.L (A7)+,D1 
MOVEM.L (A7)+,A0

* return noErr

MOVEQ   #0,D0
RTS

* macsbug symbol

DC.B  $80
DC.B  ’GetGlobPtr’

* constants used in this routine

DC.W  0

ENDPROC ; GetGlobPtr

************************************************************
* turn off optimization so our DC.L 0 doesn’t disappear
OPTNONE

* this isn’t really a proc, but we need to link
* to this address
GlobPtr PROC
* to put our globals here during the init call
* we always get our globals back from here, no matter
* where we came in
DC.L  $00000000
RTS

* variable-length macsbug symbol

DC.B  $80
DC.B  ’GlobPtr’

* constants used in this routine

DC.W  0

ENDPROC ; GlobPtr

OPTALL
************************************************************

END
 
AAPL
$99.76
Apple Inc.
+2.09
MSFT
$44.08
Microsoft Corpora
+0.45
GOOG
$520.84
Google Inc.
+9.67

MacTech Search:
Community Search:

Software Updates via MacUpdate

Macgo Blu-ray Player 2.10.9.1750 - Blu-r...
Macgo Mac Blu-ray Player can bring you the most unforgettable Blu-ray experience on your Mac. Overview Macgo Mac Blu-ray Player can satisfy just about every need you could possibly have in a Blu-ray... Read more
Apple iOS 8.1 - The latest version of Ap...
The latest version of iOS can be downloaded through iTunes. Apple iOS 8 comes with big updates to apps you use every day, like Messages and Photos. A whole new way to share content with your family.... Read more
TechTool Pro 7.0.5 - Hard drive and syst...
TechTool Pro is now 7, and this is the most advanced version of the acclaimed Macintosh troubleshooting utility created in its 20-year history. Micromat has redeveloped TechTool Pro 7 to be fully 64... Read more
PDFKey Pro 4.0.2 - Edit and print passwo...
PDFKey Pro can unlock PDF documents protected for printing and copying when you've forgotten your password. It can now also protect your PDF files with a password to prevent unauthorized access and/... Read more
Yasu 2.9.1 - System maintenance app; per...
Yasu was originally created with System Administrators who service large groups of workstations in mind, Yasu (Yet Another System Utility) was made to do a specific group of maintenance tasks... Read more
Hazel 3.3 - Create rules for organizing...
Hazel is your personal housekeeper, organizing and cleaning folders based on rules you define. Hazel can also manage your trash and uninstall your applications. Organize your files using a... Read more
Autopano Giga 3.7 - Stitch multiple imag...
Autopano Giga allows you to stitch 2, 20, or 2,000 images. Version 3.0 integrates impressive new features that will definitely make you adopt Autopano Pro or Autopano Giga: Choose between 9... Read more
MenuMeters 1.8 - CPU, memory, disk, and...
MenuMeters is a set of CPU, memory, disk, and network monitoring tools for Mac OS X. Although there are numerous other programs which do the same thing, none had quite the feature set I was looking... Read more
Coda 2.5 - One-window Web development su...
Coda is a powerful Web editor that puts everything in one place. An editor. Terminal. CSS. Files. With Coda 2, we went beyond expectations. With loads of new, much-requested features, a few... Read more
Arq 4.6.1 - Online backup to Google Driv...
Arq is super-easy online backup for the Mac. Back up to your own Google Drive storage (15GB free storage), your own Amazon Glacier ($.01/GB per month storage) or S3, or any SFTP server. Arq backs up... Read more

Latest Forum Discussions

See All

This Week at 148Apps: October 13-17, 201...
Expert App Reviewers   So little time and so very many apps. What’s a poor iPhone/iPad lover to do? Fortunately, 148Apps is here to give you the rundown on the latest and greatest releases. And we even have a tremendous back catalog of reviews; just... | Read more »
Angry Birds Transformers Review
Angry Birds Transformers Review By Jennifer Allen on October 20th, 2014 Our Rating: :: TRANSFORMED BIRDSUniversal App - Designed for iPhone and iPad Transformed in a way you wouldn’t expect, Angry Birds Transformers is a quite... | Read more »
GAMEVIL Announces the Upcoming Launch of...
GAMEVIL Announces the Upcoming Launch of Mark of the Dragon Posted by Jessica Fisher on October 20th, 2014 [ permalink ] Mark of the Dragon, by GAMEVIL, put | Read more »
Interview With the Angry Birds Transform...
Angry Birds Transformers recently transformed and rolled out worldwide. This run-and-gun title is a hit with young Transformers fans, but the ample references to classic Transformers fandom has also earned it a place in the hearts of long-time... | Read more »
Find Free Food on Campus with Ypay
Find Free Food on Campus with Ypay Posted by Jessica Fisher on October 20th, 2014 [ permalink ] iPhone App - Designed for the iPhone, compatible with the iPad | Read more »
Strung Along Review
Strung Along Review By Jordan Minor on October 20th, 2014 Our Rating: :: GOT NO STRINGSUniversal App - Designed for iPhone and iPad A cool gimmick and a great art style keep Strung Along from completely falling apart.   | Read more »
P2P file transferring app Send Anywhere...
File sharing services like Dropbox have security issues. Email attachments can be problematic when it comes to sharing large files. USB dongles don’t fit into your phone. Send Anywhere, a peer-to-peer file transferring application, solves all of... | Read more »
Zero Age Review
Zero Age Review By Jordan Minor on October 20th, 2014 Our Rating: :: MORE THAN ZEROiPad Only App - Designed for the iPad With its mind-bending puzzles and spellbinding visuals, Zero Age has it all.   | Read more »
Hay Ewe Review
Hay Ewe Review By Campbell Bird on October 20th, 2014 Our Rating: :: SAVE YOUR SHEEPLEUniversal App - Designed for iPhone and iPad Pave the way for your flock in this line drawing puzzle game from the creators of Worms.   | Read more »
My Very Hungry Caterpillar (Education)
My Very Hungry Caterpillar 1.0.0 Device: iOS Universal Category: Education Price: $3.99, Version: 1.0.0 (iTunes) Description: Care for your very own Very Hungry Caterpillar! My Very Hungry Caterpillar will captivate you as he crawls... | Read more »

Price Scanner via MacPrices.net

2013 15-inch 2.0GHz Retina MacBook Pro availa...
B&H Photo has leftover previous-generation 15″ 2.0GHz Retina MacBook Pros now available for $1599 including free shipping plus NY sales tax only. Their price is $400 off original MSRP. B&H... Read more
Updated iPad Prices
We’ve updated our iPad Air Price Tracker and our iPad mini Price Tracker with the latest information on prices and availability from Apple and other resellers, including the new iPad Air 2 and the... Read more
Apple Pay Available to Millions of Visa Cardh...
Visa Inc. brings secure, convenient payments to iPad Air 2 and iPad mini 3as well as iPhone 6 and 6 Plus. Starting October 20th, eligible Visa cardholders in the U.S. will be able to use Apple Pay,... Read more
Textkraft Pocket – the missing TextEdit for i...
infovole GmbH has announced the release and immediate availability of Textkraft Pocket 1.0, a professional text editor and note taking app for Apple’s iPhone. In March 2014 rumors were all about... Read more
C Spire to offer iPad Air 2 and iPad mini 3,...
C Spire on Friday announced that it will offer iPad Air 2 and iPad mini 3, both with Wi-Fi + Cellular, on its 4G+ LTE network in the coming weeks. C Spire will offer the new iPads with a range of... Read more
Belkin Announces Full Line of Keyboards and C...
Belkin International has unveiled a new lineup of keyboard cases and accessories for Apple’s newest iPads, featuring three QODE keyboards and a collection of thin, lightweight folios for both the... Read more
Verizon offers new iPad Air 2 preorders for $...
Verizon Wireless is accepting preorders for the new iPad Air 2, cellular models, for $100 off MSRP with a 2-year service agreement: - 16GB iPad Air 2 WiFi + Cellular: $529.99 - 64GB iPad Air 2 WiFi... Read more
Price drops on refurbished Mac minis, now ava...
The Apple Store has dropped prices on Apple Certified Refurbished previous-generation Mac minis, with models now available starting at $419. Apple’s one-year warranty is included with each mini, and... Read more
Apple refurbished 2014 MacBook Airs available...
The Apple Store has Apple Certified Refurbished 2014 MacBook Airs available for up to $180 off the cost of new models. An Apple one-year warranty is included with each MacBook, and shipping is free.... Read more
Refurbished 2013 MacBook Pros available for u...
The Apple Store has Apple Certified Refurbished 13″ and 15″ MacBook Pros available starting at $929. Apple’s one-year warranty is standard, and shipping is free: - 13″ 2.5GHz MacBook Pros (4GB RAM/... Read more

Jobs Board

Project Manager / Business Analyst, WW *Appl...
…a senior project manager / business analyst to work within our Worldwide Apple Fulfillment Operations and the Business Process Re-engineering team. This role will work Read more
*Apple* Retail - Multiple Positions (US) - A...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
Position Opening at *Apple* - Apple (United...
…customers purchase our products, you're the one who helps them get more out of their new Apple technology. Your day in the Apple Store is filled with a range of Read more
Position Opening at *Apple* - Apple (United...
**Job Summary** At the Apple Store, you connect business professionals and entrepreneurs with the tools they need in order to put Apple solutions to work in their Read more
Position Opening at *Apple* - Apple (United...
**Job Summary** The Apple Store is a retail environment like no other - uniquely focused on delivering amazing customer experiences. As an Expert, you introduce people Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.