TweetFollow Us on Twitter

System CDEV
Volume Number:5
Issue Number:5
Column Tag:Forth Forum

Related Info: Control Panel

System CDEV

By Jörg Langowski, MacTutor Editorial Staff

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

“System configuration cdev”

There is a nice public domain CDEV utility, called Systat, that shows the system configuration you’re running on: machine type, CPU, floating point hardware, etc. Ever since my last system update, this CDEV doesn’t run anymore on my Mac II. Don’t know what I did wrong or what INIT I installed that conflicts with it. So to have that utility back, I decided to write my own - in Mach2 - to give you an example how to write CDEVs and how to use the SysEnvirons trap [which is unfortunately left unimplemented in Mach 2.14].

SysEnvirons

The Macintosh world has evolved a long way from the one-configuration era of the 128K Mac. There are now - at least - 8 different types of machines on which an application could run, the 512K old ROM Mac (yes, some still have one), the Lisa, the 512KE, Mac Plus, Mac SE, SE/030, Mac II and Mac IIx. I’m not counting the ‘small’ MacII with fewer slots since I haven’t seen that machine as of this writing.

Add to this variety of machines all the different accessories that could be present, such as large screens or accelerator cards, and you end up with an impressing array of different configurations. The confusion is far from being as bad as in the MS-DOS world, but it’s there; no wonder that some applications start having problems running on all possible configurations.

It is for this reason that the SysEnvirons trap - described in IM V-6 - has been added to the system. This routine returns information about the system configuration the program is running on, so that you can exit gracefully from your application if - for instance - color Quickdraw is needed but not available.

SysEnvirons accepts two arguments: a pointer to a data structure called a sysEnvRec in A0 and a version number in D0. The version number is used to maintain upward compatibility. Right now, two versions of the trap call exist, version 1 and 2, which both return the same information. If, at a later time, new versions are defined that return more or other information, the old calls can still be used, returning the data in the same old format. SysEnvirons returns the sysEnvRec pointer in A0 and a result code in D0.

The sysEnvRec, at the moment, has the following fields (in Forth notation):

0 CONSTANT environsVersion

2 CONSTANT machineType

4 CONSTANT systemVersion

6 CONSTANT processor

8 CONSTANT hasFPU

9 CONSTANT hasColorQD

10 CONSTANT keyBoardType

12 CONSTANT atDrvrVersNum

14 CONSTANT sysVRefNum

The fields are described in IM V, but some newer configurations are not mentioned in the book. As pointed out earlier, environsVersion can be 1 or 2 (according to my experimentation), but the information returned is the same in both cases. machineType can be 0 to 7, because in addition to the MacII, we have the Mac IIx, the MacII ‘small version’, and the SE/030 now. processor can be 0 to 4, the last value corresponding to the 68030.

[Incidentally, I know about two otherwise very good programs which check the processor type, but don’t think about Motorola’s upward compatibility. TMON at first wouldn’t run on my IIx, because it doesn’t know the processor type returned by SysEnvirons. There are processor-specific resources MonC and MonI in TMON, and the 68030 requires MonC ID=3 and MonI ID=3 to be present. If one simply duplicates the MonC ID=2 and MonI ID=2 resources and changes their IDs to 3, TMON runs. Languages Systems Fortran, too, has its problems. If you compile a program with the 68020 code option on, it won’t run on a IIx, because that machine has no 68020! Obviously, LS Fortran should check for 68020 or greater, and not for 68030 only. They know about that bug and will revise it.]

The SysEnvirons trap glue code, and some words returning individual values from the sysEnv record, are printed in the example. The last part contains some code that you may execute from the Mach2 environment and which will print the system configuration information directly to the console window. So now you know what machine you’re using (isn’t that great).

The CDEV

To put the SysEnvirons information to some practical use, we’ll write a control panel utility (CDEV) that displays this information in the control panel window. CDEVs are described in IM V-323, and Steven Sheets has also written an article about them (MT V3#10, p.59). I’ll briefly summarize the relevant points.

A control panel utility is a file of type ‘cdev’ and arbitrary creator (we use JLMT, for obvious reasons. Not even registered with Apple yet!). The file contains BNDL, ICN# and FREF ID=-4064 resources, and a JLMT ID=0 resource, to make its icon correctly appear on the desktop. The resources actually relevant to the control panel are:

mach ID=-4064, nrct ID=-4064, DITL ID=-4064, and cdev ID=-4064. ‘mach’ determines which machine the CDEV can run on; the control panel will display the CDEVs icon on the left side of the panel only on machines corresponding to the number contained in ‘mach’ (see IM for details). The ‘nrct’ resource contains a number of rectangles that are drawn in the right part of the control panel when the CDEV is opened. These rectangles are filled with white and framed with a 2-pixel thick black border. The rest of the control panel is filled with light gray. After the rectangles, the dialog items in the DITL resource are drawn. The contents of the DITL are appended to the control panel’s own DITL. Later when a dialog item on the left hand side of the panel is referenced, its item number will have to be incremented by the number of items in the control panel’s own DITL.

‘cdev’ contains the actual code for the control panel handler. It is a code resource with its entry point at the very beginning (like XCMDs, MDEFs, etc.), and it is called like a Pascal function with the following parameters:

{1}

FUNCTION cdev( message,item,numItems,CPanelID: INTEGER; 
 VAR theEvent:EventRecord; cDevValue: LONGINT;
 CPDialog: DialogPtr):LONGINT;

Our Forth code has to go through the usual gymnastics to be called correctly. We jump from the start of the resource to a piece of glue code which saves the old registers, sets up local Forth and loop return stacks, and moves the parameters from the A7 stack to the Forth stack. The main cdev routine is then called with the parameters on the Forth stack (see the listing). message will tell the routine what to do on this call. item is the item number of the dialog item that was hit; this parameter is only relevant for the hitDev message. numItems is the number of items that precede the CDEVs DITL in the item list. To address a dialog item from its own DITL, the CDEV has to add this number to the item number. CPanelID is the resource ID of the control panel DA. theEvent is a pointer to en event record, valid for hitDev, nulDev, activDev, deActivDev and keyEvtDev messages. cdevValue contains the return value of the last call of the cdev routine. A CDEV might, for instance, allocate its private storage and pass a handle to it as a function result; the next time it is called, it will find this handle back in the cdevValue parameter. CPDialog is the dialog pointer to the control panel dialog.

CDEV messages

A CDEV can receive several different messages in the message parameter. For our purpose, the initDev message is the only relevant one. This message is sent once when the CDEV is opened. All we need to do is to find the system information at this time and fill in the dialog items so they can be displayed. Once this is done, updating of the dialog will be handled by the control panel. Other CDEVs might need to handle more messages. The allowed values are:

initDev=0, hitDev=1, closeDev=2, nulDev=3, updateDev=4, activDev=5, deActivDev=6, keyEvtDev=7, macDev=8, undoDev=9, cutDev=10, copyDev=11, pasteDev=12, clearDev=13.

hitDev corresponds to a mouse down event in control panel dialog item. closeDev is sent when the control panel is closed, updateDev to keyEvtDev are sent to handle events, and undoDev to clearDev are sent when the corresponding Edit menu item is selected.

nulDev works like the accRun message in a desk accessory; it is sent periodically and allows the CDEV to perform actions like cursor blinking, time updating, etc.

macDev is sent optionally on initialization, depending on the value of the ‘mach’ resource; when this message is sent, the control panel should check whether it can really run on this particular machine configuration.

Our CDEV routine only handles the initDev message. It will beep once, and then put string constants corresponding to machine type, system version etc. in the various dialog items. It has been checked on a Mac 512KE, Mac Plus, Mac SE, SE/030, Mac II and IIx. It’s up to you to add the checking code for the 64K ROM Mac and Lisa.

Language Systems Fortran and Prototyper

Even though this is ‘officially’ a Forth column, I’d like to tell you some more of my experiences with Language Systems Fortran. That system, together with Prototyper, gives you an amazingly powerful environment to outfit Fortran programs with a nice Mac-ish interface. And you can even have lengthy calculations run in the background, if you modify your Fortran code slightly.

I won’t describe the program that I’ve been working on in detail. Suffice it to say that it’s quite long, used for some kind of curve fitting, and uses some 2-5 seconds per iteration on a Microvax II. It compiles nicely under MPW/LS Fortran, and the resulting application runs from a dumb terminal window and even gives the same results as the Vax. However. Once started, Fortran takes control and releases it only at the very end of the program. 50 iterations, 2 seconds per iteration = 100 seconds of twiddling thumbs.

There is an easy way to give some Multifinder compatibility to LS Fortran applications. Listing 2 shows a small routine that calls WaitNextEvent with an event mask corresponding to update events and app4 events (context switching). Putting calls to this routine in strategic places of your Fortran program, so that it is called several times per second, will make the program ‘background-able’. A mouse click on another application’s window will switch the Fortran program to the background, where it will continue to execute. However, your word processing, or spreadsheet activity, is slowed down only slightly. My pause routine will also set the cursor to a watch when the button is pressed inside the Fortran window. That way, the program can indicate that it is still calculating, and reset the cursor to an arrow when one iteration is done; other routines could at that point grab the mouse down event and handle it, to change parameters of the calculation etc.

The second step of making a Fortran program ‘Mac-ish’ is to add a real menu/dialog interface for entering and changing the parameters to the program. Typically, one would enter file names, initial values, matrix sizes, etc. In my particular case, I used Prototyper to generate the interface, which gave me Pascal code. The Fortran program was split up in convenient subroutines, which were called as Externals from the Pascal main program.

The strategy was the following: Input parameters, file names, etc. were set via menus and dialogs. When all parameters had been set, a menu item could be selected to start the calculation. This menu selection would simply set a flag in the Pascal program, doCalc. The main event loop’s null event handler would check this flag and if it was set, run one iteration of the Fortran code per event loop. Of course, since each iteration took several seconds, this would slow down the user interaction way too much.

Therefore, whenever a non-null event was detected in the main event loop, another flag was set which disabled null event background processing. This flag was kept on for 5 seconds after each non-null event.

In summary, this strategy will transform your Fortran program into an application that can be juggled into the background at any time with 0.1 sec delay and calculate in the background. When you click on the application in the foreground, the cursor will change to a watch, the current iteration will finish, and then you can change parameters, stop the calculation, print intermediate results, etc. through the interface provided by Prototyper. When no user action is detected for 5 seconds, the program will start calculating again.

French Hacker Story - the End (???)

You might have followed the story of Faraglace: The French hacker who was supposed to pay very heavily for the mistake of having removed the copy protection from some programs - notably 4th Dimension. He did this out of his own private curiosity, the products of this activity got into the hands of some pirates, and the whole issue was taken to court. It seems, after the result of a recent lawsuit last month, that the story is finally coming to a more reasonable conclusion: The total amount of fines and damages has gone down from a sum of the order of $100,000 to an amount of more like $2,000 (!). This does not settle the issue for the pirates who sold the de-protected stuff; that’s separate. But the fact that a court has recognized that cracking and stealing software are not quite the same thing relieves me. ACI is still going to appeal this verdict. More to come, hopefully good news.

Till next month, happy threading

Listing 1: SysConfig cdev

\ System configuration cdev 
\ Example for MacTutor written in Mach2 Forth
\ J.Langowski March 1989

only forth also mac also assembler

\ Define SysEnvirons trap; not present in Mach2.14 
\ alternatively, use the trap compiler accessible on the
\ GEnie Mach2 libraries and on the V5#1 source code disk

.TRAP _SysEnvirons $A090

0CONSTANT environsVersion
2CONSTANT machineType
4CONSTANT systemVersion
6CONSTANT processor
8CONSTANT hasFPU
9CONSTANT hasColorQD
10 CONSTANT keyBoardType
12 CONSTANT atDrvrVersNum
14 CONSTANT sysVRefNum

\ compiler support words for kernel-independent
\ definitions, defproc resources, etc.
\ :xdef compiles a JMP at the beginning of the
\ block, which is resolved at the end of the definition
\ by ;xdef.

: :xdef ( -- branch marker )
 create -4 allot
 $4EFA w, ( JMP )
 0 w,  ( entry point to be filled later )
 0 ,   ( length of routine to be filled later )
 here 6 - 76543 ( marker for stack checking )
;

: ;xdef { branch marker entry | -- }
 marker 76543 <> abort” xdef mismatch”
 entry branch - branch w!
 here branch - 2+ branch 2+ !
; 
 
: xlen 4 + @ ; ( get length word of external definition )

\ **** cdev proc glue macros for kernel-independent code

CODE cdev.prelude
 LINK A6,#-512   ( 512 bytes of local Forth stack )
 MOVEM.LA0-A5/D0-D7,-(A7) ( save registers )
 MOVE.L A6,A3    ( setup local loop return stack )
 SUBA.L #256,A3  ( in the low 256 local stack bytes )
 MOVE.L 8(A6),D0 ( CPDialog )
 MOVE.L 12(A6),D1  ( cdevValue )
 MOVE.L 16(A6),D2  ( theEvent )
 CLR.L  D3
 MOVE.W 20(A6),D3  ( CPanelID )
 EXT.L  D3( in case this is negative )
 CLR.L  D4
 MOVE.W 22(A6),D4  ( numItems )
 CLR.L  D5
 MOVE.W 24(A6),D5  ( Item )
 CLR.L  D6
 MOVE.W 26(A6),D6  ( message )
 MOVE.L D6,-(A6)
 MOVE.L D5,-(A6)
 MOVE.L D4,-(A6)
 MOVE.L D3,-(A6)
 MOVE.L D2,-(A6)
 MOVE.L D1,-(A6)
 MOVE.L D0,-(A6)
 RTS    \ just to indicate the MACHro stops here 
END-CODE MACH

CODE cdev.epilogue ( resCode -- )
 MOVE.L (A6)+,D0
 MOVE.L D0,28(A6)( store function result )
 MOVEM.L (A7)+,A0-A5/D0-D7( restore registers )
 UNLK A6
 MOVE.L (A7)+,A0 ( return address )
 ADD.W  #20,A7 ( pop off 20 bytes of parameters )
 JMP  (A0)
 RTS
END-CODE MACH

\ the actual cdev code starts here.
\ REMEMBER: don’t use CALL for the toolbox routines;
\ use (CALL) instead, which is not dependent on D4 
\ pointing to a correct stack.

:xdef myCdev

\ just to put some text into the resource
\ for easier identification

: start “ Mach2 Forth cdev example, JL/MacTutor 1989” ;

CODE SysEnvirons 
 ( theWorld versrequested -- theWorld resCode )
 MOVEA.L4(A6),A0
 MOVE.L (A6)+,D0
 ADDQ.L #4,A6
 _SysEnvirons
 MOVE.L A0,-(A6)
 EXT.L  D0
 MOVE.L D0,-(A6)
 RTS
END-CODE

\ words which extract single items from the SysEnvRec

: ?mach { | [ 12 lallot ] sysEnvRec -- machine# }
 ^ sysEnvRec 1 SysEnvirons drop 2+ w@ ;

: ?sys { | [ 12 lallot ] sysEnvRec -- system# revision# }
 ^ sysEnvRec 1 SysEnvirons drop 
 dup 5 + c@  swap 4+ c@ ;

: ?proc { | [ 12 lallot ] sysEnvRec -- machine# }
 ^ sysEnvRec 1 SysEnvirons drop 6 + w@ ;

: ?fpu { | [ 12 lallot ] sysEnvRec -- machine# }
 ^ sysEnvRec 1 SysEnvirons drop 8 + c@ ;

: ?colorQD { | [ 12 lallot ] sysEnvRec -- machine# }
 ^ sysEnvRec 1 SysEnvirons drop 9 + c@ ;

: ?keyType { | [ 12 lallot ] sysEnvRec -- machine# }
 ^ sysEnvRec 1 SysEnvirons drop 10 + w@ ;

: ?atkVers { | [ 12 lallot ] sysEnvRec -- machine# }
 ^ sysEnvRec 1 SysEnvirons drop 12 + w@ ;

: ?sysVRef { | [ 12 lallot ] sysEnvRec -- machine# }
 ^ sysEnvRec 1 SysEnvirons drop 14 + w@ l_ext ;

\ factored out the GetDItem/SetIText stuff

: set.item ( string dlgPtr #item ) { | type hItem box -- }
 ^ type ^ hItem ^ box (call) GetDItem
 hItem swap (call) SetIText ;

\ display system characteristics 
\ in the cdev dialog box (DITL -4064 resource dependent)
\ the strings are hard-coded, but could as well be contained 
\ in a STR# resource
 
: display.it {  numItems dlgPtr | [ 16 lallot ] str1 -- }
 ?mach CASE 
 0 OF “ unknown” ENDOF
 1 OF “ Mac 512KE” ENDOF
 2 OF “ Mac Plus” ENDOF
 3 OF “ Mac SE” ENDOF
 4 OF “ Mac II” ENDOF
 5 OF “ Mac IIx” ENDOF
 \ wasn’t sure whether machine=6 is the new baby MacII,
 \ so left out that case
 7 OF “ Mac SE/030” ENDOF
 “ NEW MACHINE”
 ENDCASE dlgPtr 3 numItems + set.item

 \ get system version # 
 \ and convert to string, format X.XX 
 \ if you don’t know Forth, this might be hard to read :-)
 ?sys 
 ^ str1 swap (call) numtostring 
 dup c@ 1+ + swap (call) numtostring 
 dup c@ 1 = IF dup 1+ c@ over 2+ c! 
 dup 1+ ascii 0 swap c! THEN
 ascii . swap c!  
 ^ str1 dup c@ 3 + swap c!
 ^ str1 dlgPtr 5 numItems + set.item 

 ?proc CASE
 0 OF “ unknown” ENDOF
 1 OF “ 68000” ENDOF
 2 OF “ 68010” ENDOF
 3 OF “ 68020” ENDOF
 4 OF “ 68030” ENDOF
 “ NEW”
 ENDCASE dlgPtr 7 numItems + set.item

 ?fpu IF “ yes” ELSE “ none” THEN
 dlgPtr 9 numItems + set.item 

 ?colorQD IF “ yes” ELSE “ no” THEN
 dlgPtr 11 numItems + set.item 

 ?keyType CASE 
 0 OF “ unknown type” ENDOF
 1 OF “ ‘old’ Macintosh keyboard” ENDOF
 2 OF “ ‘old’ Macintosh keyboard with keypad” 
 ENDOF
 3 OF “ Macintosh Plus keyboard” ENDOF
 4 OF “ Apple Desktop Bus extended keyboard” 
 ENDOF
 5 OF “ Apple Desktop Bus standard keyboard” 
 ENDOF
 “ something NEW” 
 ENDCASE dlgPtr 13 numItems + set.item 

 ^ str1 ?atkVers (call) numtostring
 dlgPtr 15 numItems + set.item 
;
 
: testCdev { message item numItems CPanelID
  theEvent cdevValue CPDialog -- result }
 \ we only need to respond to the initDev message
 \ by putting the system configuration info
 \ into the cdev’s dialog items
 message CASE
 0 OF ( initDev ) 1 (call) sysbeep 
 numItems CPDialog display.it ENDOF
 ( insert handlers for other messages here)
 ENDCASE
 cdevValue \ everything OK: return old cdevValue
;

: cdev.glue 
 cdev.prelude
 testCdev
 cdev.epilogue
;

‘ cdev.glue ;xdef

\ end of cdev code


\ making the cdev resource, the usual way

: $create-res call CreateResFile call ResError L_ext ;

: $open-res { addr | refNum -- result }
 addr call openresfile -> refNum
 call ResError L_ext
 dup not IF drop refNum THEN 
;

: $close-res call CloseResFile call ResError L_ext ;

: make-cdev { | refNum -- }
 “ cdev.res” dup $create-res
 abort” You have to delete the old ‘cdev.res’ file first.”
 $open-res dup -> refNum call UseResFile 
 [‘] myCdev dup xlen
 call PtrToHand drop ( result code )
 ASCII cdev -4064 “ cdev JL” call AddResource
 refNum $close-res drop ( result code )
;

\ End of cdev creation code.
\ Following are some words that can be executed 
\ from within the Mach2 system, and output 
\ system configuration information directly to the console.
  
: myMachine cr .” This is a”
 ?mach CASE
 0 OF .” n unknown machine,” ENDOF
 1 OF .”  Mac 512KE,” ENDOF
 2 OF .”  Mac Plus,” ENDOF
 3 OF .”  Mac SE,” ENDOF
 4 OF .”  Mac II,” ENDOF
 5 OF .”  Mac IIx,” ENDOF
 7 OF .”  Mac SE/030,” ENDOF
 .”  NEW MACHINE,”
 ENDCASE
;

: mySystem ?sys
 .”  running system v. “ 
 <# # #> type ascii . emit 
 <# # # #> type ascii . emit
;

: myProcessor cr .” It uses a”
 ?proc CASE
 0 OF .” n unknown” ENDOF
 1 OF .”  68000" ENDOF
 2 OF .”  68010" ENDOF
 3 OF .”  68020" ENDOF
 4 OF .”  68030" ENDOF
 .”  NEW”
 ENDCASE
 .”  processor”
;

: myFPU ?fpu IF
   ascii , emit cr 
   .” and has an arithmetic coprocessor installed.” 
 ELSE
   ascii . emit
 THEN
;

: myCQD cr .” Color QuickDraw is “
 ?colorQD 0= IF .” not “ THEN
 .” available.”
;

: myKeyBoard cr .” The Keyboard is “
 ?keyType CASE 
 0 OF .” of an unknown type.” ENDOF
 1 OF .” the ‘old’ Macintosh type.” ENDOF
 2 OF .” the ‘old’ Macintosh type with keypad.” ENDOF
 3 OF .” the Mac Plus type.” ENDOF
 4 OF .” the ADB extended type.” ENDOF
 5 OF .” the standard ADB type.” ENDOF
 .” a NEW type.” 
 ENDCASE
;

: myAtkDrvr cr .” Appletalk v. “ ?atkVers . 
 .” is installed.”
;

: machTest 
 myMachine mySystem 
 myProcessor myFPU
 myCQD
 myKeyBoard
 myAtkDrvr
 cr
;
Listing 2: Language Systems Fortran background enabler

 subroutine pause(sleep)
!!m Inlines.f
 integer*4 sleep
c
ccall Waitnextevent to generate a pause.
csleep parameter in ticks.
c
cwill discard all Multifinder events (update, Suspend/Resume)
cand set cursor to watch if button is pressed 
c
 include ‘::fincludes:Memtypes.f’
 include ‘::fincludes:Quickdraw.f’
 include ‘::fincludes:OSIntf.f’
 include ‘::fincludes:Toolintf.f’
 record /eventrecord/ myEvtRec
 record /CursHandle/ myCurs
 logical*1 p
 
 p = waitnextevent (%val(updateEvt+app4Evt),
  %ref(myEvtRec), %val(sleep), %val(0))

 if (button) then 
 myCurs.CrsrH = getCursor(%val(watchcursor))
 call setCursor(%val(myCurs.CrsrH^.CrsrP))
 end if
 
 return
 end

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

TunnelBear 3.0.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
ExpanDrive 5.4.0 - Access cloud storage...
ExpanDrive builds cloud storage in every application, acts just like a USB drive plugged into your Mac. With ExpanDrive, you can securely access any remote file server directly from the Finder or... Read more
Opera 40.0.2308.62 - High-performance We...
Opera is a fast and secure browser trusted by millions of users. With the intuitive interface, Speed Dial and visual bookmarks for organizing favorite sites, news feature with fresh, relevant content... Read more
Apple iOS 10.0.2 - The latest version of...
iOS 10 is the biggest release of iOS ever. A massive update to Messages brings the power of the App Store to your conversations and makes messaging more personal than ever. Find your route with... Read more
Herald 7.0 - Notification plugin for Mai...
Note: Versions 2.1.3 (for OS X 10.7), 3.0.6 (for OS X 10.8), 4.0.8 (for OS X 10.9), 5.0.2 (for OS X 10.10), and 6.0.3 (for OS X 10.11) are no longer supported by the developer. Herald is a... Read more
Postbox 5.0.2 - Powerful and flexible em...
Postbox is a new email application that helps you organize your work life and get stuff done. It has all the elegance and simplicity of Apple Mail, but with more power and flexibility to manage even... Read more
Yummy FTP Pro 1.11.10 - $29.99
Yummy FTP Pro is an advanced Mac file transfer app which provides a full-featured professional toolkit combined with blazing speeds and impeccable reliability, so whether you want to transfer a few... Read more
Tidy Up 4.1.17 - $29.99
Tidy Up is a full-featured duplicate finder and disk-tidiness utility. Features With Tidy Up you can search for duplicate files and packages by the owner application, content, type, creator,... Read more
Logitech Control Center 3.9.5 - Keyboard...
Logitech Control Center (LCC) is designed to support OS X and allows you to take full advantage of your Logitech keyboard, mouse, or trackball. With the LCC you can: Browse the Internet using... Read more
Macgo Blu-ray Player 2.16.17 - Blu-ray p...
Macgo 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

How to build and care for your team in D...
Before you hit the trail and become a dog sledding legend, there’s actually a fair bit of prep work to be done. In Dog Sled Saga, you’re not only racing, you’re also building and caring for a team of furry friends. There’s a lot to consider—... | Read more »
How to win every race in Dog Sled Saga
If I had to guess, I’d say Dog Sled Saga is the most adorable racing game on the App Store right now. It’s a dog sled racing sim full of adorable, loyal puppies. Just look at those fluffy little tails wagging. Behind that cute, pixelated facade is... | Read more »
Let the war games commence in Gunship Ba...
Buzz Lightyear famously said, “This isn’t flying, this is falling – with style!” In the case of Gunship Battle: Second War, though, this really is flying - with style! The flight simulator app from Joycity puts you in control of 20 faithfully... | Read more »
How to get a high score in Fired Up
Fired Up is Noodlecake Games’ high score chasing, firefighting adventure. You take control of a wayward firefighter who propels himself up the side of a highrise with blasts of water. Sound silly? It is. It’s also pretty difficult. You can’t... | Read more »
NBA 2K17 (Games)
NBA 2K17 1.0 Device: iOS iPhone Category: Games Price: $7.99, Version: 1.0 (iTunes) Description: Following the record-breaking launch of NBA 2K16, the NBA 2K franchise continues to stake its claim as the most authentic sports video... | Read more »
Dog Sled Saga (Games)
Dog Sled Saga 1.0.1 Device: iOS Universal Category: Games Price: $3.99, Version: 1.0.1 (iTunes) Description: A game by Dan + Lisa As a rookie musher, foster a dogsledding team whose skills will grow if they're treated right. Week by... | Read more »
60 Seconds! Atomic Adventure (Games)
60 Seconds! Atomic Adventure 1.2 Device: iOS Universal Category: Games Price: $2.99, Version: 1.2 (iTunes) Description: 60 Seconds! is a dark comedy atomic adventure of scavenge and survival. Collect supplies and rescue your family... | Read more »
Tons of Bullets! (Games)
Tons of Bullets! 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: Tons of BulletsA retro 2D pixel platformer infused with tons of bullets and tons of features!Fight as Kenji the Ninja and... | Read more »
Sorcery! 4 (Games)
Sorcery! 4 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: *** PLEASE NOTE: Sorcery! 4 requires a minimum of iPad 3 or iPhone 4 *** An epic adventure through a cursed citadel of monsters,... | Read more »
Building the perfect Animation Throwdown...
Animation Throwdown is a casual card game full of plenty of inside jokes from some of your favorite cartoons. It’s accessible as far as card games go, but that’s not to say that it hands your victories to you easily. There’s quite a bit that goes... | Read more »

Price Scanner via MacPrices.net

Duplicate Sweeper Free On Mac App Store For O...
To celebrate the launch of Apple’s latest macOS Sierra, Stafford, United Kingdom based Wide Angle Software has announced that its duplicate file finder software, Duplicate Sweeper, is now available... Read more
13-inch Retina MacBook Pros on sale for up to...
B&H Photo has 13″ Retina Apple MacBook Pros on sale for up to $150 off MSRP. Shipping is free, and B&H charges NY tax only: - 13″ 2.7GHz/128GB Retina MacBook Pro: $1174.99 $125 off MSRP - 13... Read more
Evidence Surfaces Pointing To New A10X Chip F...
Citing a job description for a Project Lead position at Apple’s Austin, Texas engineering labs, Motley Fool’s Ashraf Eassa deduces that development is progressing well on Apple’s next-generation in-... Read more
Check Print’R for macOS Allows Anyone to Easi...
Delaware-based Match Software has announced the release and immediate availability of Check Print’R 3.21, an important update to their easy-to-use check printing application for macOS. Check Print’R... Read more
Apple refurbished 11-inch MacBook Airs availa...
Apple has Certified Refurbished 11″ MacBook Airs (the latest models), available for up to $170 off the cost of new models. An Apple one-year warranty is included with each MacBook, and shipping is... Read more
Apple refurbished 15-inch Retina MacBook Pros...
Apple has Certified Refurbished 2015 15″ Retina MacBook Pros available for up to $380 off the cost of new models. An Apple one-year warranty is included with each model, and shipping is free: - 15″ 2... Read more
Major Version 5 Release Of Free myTuner Radio...
AppGeneration Software has announced the release of myTuner Radio 5.0.1, an important update to their live radio app for iOS and Android platforms. With myTuner Radio, you can listen to more than 30,... Read more
TheAppStore Searches And Filters iOS And macO...
Boston based InchWest has announced the official launch of TheAppStore, a free web based service that lets users search iOS and Mac apps on the web without iTunes or the App store. TheAppStore... Read more
2TB Time Capsule on sale for $199, save $100
Amazon has 2TB Apple Time Capsules on sale for $199 including free shipping. Their price is $100 off MSRP. Choose Amazon as the seller when making your purchase, rather than a third party seller. Read more
12-inch 1.2GHz Rose Gold Retina MacBook on sa...
Amazon.com has the 2016 12″ 1.2GHz Rose Gold Retina MacBook on sale for $1254.02 including free shipping. Their price is $345 off MSRP, and it’s the lowest price available for this model from any... Read more

Jobs Board

Senior *Apple* Administrator - Pratt Instit...
POSITION SUMMARY: Directs the coordination and standardization of campus-wide Apple systems, including planning, analysis and implementation of Apple -related Read more
Restaurant Manager (Neighborhood Captain) - A...
…in every aspect of daily operation. WHY YOU'LL LIKE IT: You'll be the Big Apple . You'll solve problems. You'll get to show your ability to handle the stress and Read more
*Apple* Retail - Multiple Positions- Napervi...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
US- *Apple* Store Leader Program - Apple (Un...
…Summary Learn and grow as you explore the art of leadership at the Apple Store. You'll master our retail business inside and out through training, hands-on Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.