Line 1: |
Line 1: |
| [[File:Pippin-Atmark-Console-Set.jpg|thumb]] | | [[File:Pippin-Atmark-Console-Set.jpg|thumb]] |
| [[File:Bandia-Pippin-pcb.jpg|thumb]] | | [[File:Bandia-Pippin-pcb.jpg|thumb]] |
| + | [[File:Pippinlogo2.gif|right]] |
| | | |
| Pippin is a set of technologies designed by [[Apple Computer]] for Bandai Digital Entertainment Corporation in Japan. Pippin lets you run specially-modified Macintosh CD-ROMs on a low-cost player that plugs into a standard television set. Runs on a [[PowerPC 603]] processor. | | Pippin is a set of technologies designed by [[Apple Computer]] for Bandai Digital Entertainment Corporation in Japan. Pippin lets you run specially-modified Macintosh CD-ROMs on a low-cost player that plugs into a standard television set. Runs on a [[PowerPC 603]] processor. |
| | | |
| =Technical Specifications= | | =Technical Specifications= |
| + | [[File:Technote.gif|right]] |
| ===Hardware=== | | ===Hardware=== |
| * 66MHz [[PowerPC 603]] [[RISC]] microprocessor | | * 66MHz [[PowerPC 603]] [[RISC]] microprocessor |
Line 40: |
Line 42: |
| * Pippin System Software upgrades released through CD-ROM stamping operations | | * Pippin System Software upgrades released through CD-ROM stamping operations |
| * 68k emulator | | * 68k emulator |
− | * [[Macintosh Toolbox]] intact | + | * [[Macintosh Toolbox]] intact |
| | | |
| =Pippin Technical Notes= | | =Pippin Technical Notes= |
Line 654: |
Line 656: |
| ==Flash Access== | | ==Flash Access== |
| The Flash Access chip is a writable FlashROM chip with a 120K maximum capacity located on the Pippin main logic board. Since the Pippin does not have a hard drive to store information, and external storage devices cannot be assumed to always be present, a developer has very limited space to work with. Developers must therefore recognize the storage limitations of the Flash Access chip, and plan their titles accordingly. | | The Flash Access chip is a writable FlashROM chip with a 120K maximum capacity located on the Pippin main logic board. Since the Pippin does not have a hard drive to store information, and external storage devices cannot be assumed to always be present, a developer has very limited space to work with. Developers must therefore recognize the storage limitations of the Flash Access chip, and plan their titles accordingly. |
| + | |
| + | Flash storage will appear to a developer just like a standard Macintosh volume. To work within the limitations of this chip, title developers are encouraged to keep their "save game" options and memory storage requirements to a minimum. All design considerations and/or enhancements should be made with storage requirements clearly planned for. |
| + | |
| + | If within the design of a title, users are encouraged to keep their storage space clean, performance problems with storage will be kept to a minimum. If users are provided with these guidelines up front, many users will have little difficulty playing within this limited space. Without these guidelines clearly stated, or automatically managed within the title's design itself, memory storage dilemmas will inevitably be incurred. |
| + | |
| + | Developing efficient memory usage titles for Pippin is critical to the ultimate success of the title on the Pippin. Titles continually running into memory barriers obviously are going to take a big hit with popularity ratings as well. |
| | | |
| ==Pippin Authentication== | | ==Pippin Authentication== |
| + | ===Introduction=== |
| In order for Pippin CD-ROMs to run on a Pippin Power Player, they must first go through a Pippin authentication process. The authentication process is about applying an Apple-approved RSA signature, in the form of an electronic encrypted key, onto a Pippin CD-ROM. | | In order for Pippin CD-ROMs to run on a Pippin Power Player, they must first go through a Pippin authentication process. The authentication process is about applying an Apple-approved RSA signature, in the form of an electronic encrypted key, onto a Pippin CD-ROM. |
| + | |
| + | ===RSA's Authentication Software Library=== |
| + | Apple has licensed RSA for their public key authentication software library. The foundation of this library is non-reversible (i.e., one-way) mathematical algorithms based on using large prime numbers as keys to encrypt messages. With RSA's public key authentication system, keys are generated in pairs. One key is held privately by its owner, and the other key, the public key, is given out to be used by others to decrypt the owner's generated "keyed" messages. Public keys cannot be interchanged or swapped, and a message encrypted with a private key can only be decrypted with its corresponding matching public key. |
| + | |
| + | Encrypted messages make very good electronic signatures since they can only be decrypted by a public key which is registered to a specific person (or company). Knowing a person's public key, however, will never offer any clue as to what that person's private key might be. Since only private keys can create an encrypted message, the system is secure. |
| + | |
| + | ===Authenticating a Pippin CD=== |
| + | For Pippin, the "message" to be encrypted is the entire contents of the CD. Since this typically is a lot of data, and the algorithms are slow, the CD contents are first "digested" by a hashing algorithm which produces a small digest of the CD contents. The digest later can be used to test that the current CD content matches what it was when the digest was first created and than signed (encrypted). |
| + | |
| + | To create a Pippin-authentic CD requires two sets of key pairs. Each authorized CD stamping house has a public pair and private pair. Apple also holds both a public pair and private pair. Apple's private key is on a computer locked inside a safe which is connected to an internet mail system. Apple's public key is inside every Pippin ROM. The stamping house's private key is inside a "digesting" program at the stamping house and their public key is on file with Apple inside the safe. |
| + | |
| + | The authentication process steps are as follows: |
| + | |
| + | 1. An authorized CD stamping house digests the CD content, then signs the digest (on the CD) by encrypting it with their private key. |
| + | |
| + | 2. The stamping house then emails the signed digest encrypted with their private key to Apple's computer in the safe. |
| + | |
| + | 3. Apple's "safe" computer unsigns the digest using the stamping house's public key, and then re-signs it using Apple's private key. |
| + | |
| + | 4. The digest, which has now been effectively signed by Apple's private key, is then e-mailed back to the stamping house. |
| + | |
| + | 5. Back at the stamping house, a program is run to apply the signed authentic digest onto the CD. |
| + | |
| + | Figure 1 illustrates the flow of the Pippin authentication process. |
| + | |
| + | Figure 1 : The Pippin Authentication process |
| + | |
| + | [[File:Figure1111.gif]] |
| + | |
| + | Through this process, private keys never have to be revealed to anyone and the only data which leaves the owner's facility, via e-mail, is encrypted with a private key. |
| + | |
| + | After the stamping house applies the signed authentic digest to the CD, the CD is Pippin-authentic. During the boot process, the Pippin ROM creates a temporary digest using the same algorithm as was used to make the original, then unsigns the digest on the CD to compare the two. Only an exact match will allow the boot process to continue. |
| + | |
| + | Note: Pippin disks are not exactly encrypted since they still will mount on a Macintosh just fine. However, the still have a signature applied to them which can be read and tested. |
| | | |
| ==Applejack Input Device Driver== | | ==Applejack Input Device Driver== |
− | The Applejack input device driver combines the features of a game-player pad and a mouse or trackball in a small handheld device. Generally, Applejack input devices are attached to a Pippin Power Player (a CD-ROM multimedia player device derived from the PowerPC Macintosh). | + | ===Introduction=== |
| + | The Pippin input device, Applejack, is a custom ADB device containing trackball information and a series of 18 button states. The Applejack driver resides in the Pippin ROM and loads at system boot time. On a Macintosh, the Applejack driver resides in the system extension file. |
| + | |
| + | The Applejack driver uses a 'pipp' button mapping resource which allows any Applejack button to be mapped with either a mouse button or keyboard key function. The trackball data, however, is always treated as a "mouse" and there is no provision for remapping it. |
| + | |
| + | While provision for default button mapping is provided, applications can also include a custom 'pipp' resource for setting button functions. On Pippin ROMs, a custom 'pipp' resource would be loaded automatically when an application is launched. For applications that do not use mouse or keyboard mappings (not highly recommended), the Applejack raw data is directly readable from the driver. |
| + | |
| + | ===Setting Up=== |
| + | The Applejack Software Developer's Kit diskette contains the application for editing the 'pipp' mapping resource, and an system extension file. |
| + | |
| + | # From the SDK diskette, copy the application file to your Macintosh hard drive. |
| + | # Drag-and-drop the system extension file to the "Extensions" folder in your System Folder. |
| + | # Ensure that the Applejack input device driver(s) are plugged into the ADB jack adapter(s) on the backside of your Macintosh. |
| + | # Restart the Macintosh to initialize the system extension file. |
| + | |
| + | You are now ready to customize the Applejack input device driver. |
| + | |
| + | ===Customizing the Applejack=== |
| + | There are two ways to customize the 'pipp' mapping resource of the Applejack input device driver(s). |
| + | |
| + | The simplest way involves using the application as an interface for redefining device button mapping. This mechanism is as simple as aligning an attached Applejack device (or possibly, unattached Applejack device, as the case may be) with a visual device on the Macintosh screen. By clicking on the on-screen buttons, a developer customizes an Applejack device(s). |
| + | |
| + | The second way involves modifying the 'pipp' mapping resource code files manually, specifically defining how the button mechanisms on the device(s) should work. |
| + | |
| + | ====The Applejack Control 2.2.0 Application==== |
| + | The application is the interface used for editing the 'pipp' mapping resource. Double-click on the application icon and a window similar to Figure 1 will appear. |
| + | |
| + | Figure 1 : Applejack Control 2.2.0 Application Launch Window |
| + | |
| + | [[File:Figurea1.gif]] |
| + | |
| + | If the application does not find any Applejack device(s) physically connected to the bus, the window displays a "NO GAME PADS FOUND" message across the window instead, as follows. |
| + | |
| + | Figure 2 : NO GAME PAD FOUND Window |
| + | |
| + | [[File:Figurea2.gif]] |
| + | |
| + | Regardless of whether an Applejack device(s) is connected or not, the button settings may be edited. By clicking on desired buttons, a developer can customize the Applejack device(s). |
| + | |
| + | A dialog box similar to Figure 3 or Figure 4 appears, depending on the button clicked on. |
| + | |
| + | Figure 3 : Applejack Control 2.2.0 Dialog Box--Customizing Keyboard Key Functions |
| + | |
| + | [[File:Figurea3.gif]] |
| + | |
| + | When defining specific keyboard keys, select the "Keyboard Key" option, and press the key desired, which will appear in the character fill-in box. Also, modifiers can be designated (click on appropriate box) with a specific keyboard key, if desired. Then, click on "Ok" to proceed. |
| + | |
| + | When defining mouse button functions, click on the appropriate "mouse" functions, as desired, then click on "Ok" to proceed. |
| + | |
| + | Figure 4 : Applejack Control 2.2.0 Dialog Box--Customizing Mouse Button Functions |
| + | |
| + | [[File:Figurea4.gif]] |
| + | |
| + | By clicking "Ok" after defining each button, the Applejack driver's local data is updated. If an Applejack device is attached, the newly defined button functions can be tested immediately with the newly "customized" Applejack device(s). |
| + | |
| + | By quitting the application, the 'pipp' resource within the system extension file is updated. If you would like to write the 'pipp' resource into a separate file, use the "File:Make Resource..." menu item. |
| + | |
| + | =====Applejack Default Button Settings===== |
| + | The Driver in the Pippin ROM creates default settings for the Applejack buttons if there is no Applejack extension installed. The default Applejack button settings are as follows: |
| + | |
| + | [[File:Sect2.gif]] |
| + | |
| + | ====Modifying the 'pipp' Button Mapping Resource==== |
| + | Alternatively, 'pipp' resources can be built and keys (functions) remapped by looking at the driver's global data. Figure 5 illustrates the Applejack Input Device Driver and its corresponding button mapping. |
| + | |
| + | Figure 5 : Applejack Input Device--Button Mapping |
| + | |
| + | [[File:Figure55.gif]] |
| + | |
| + | The 'pipp' resource is identical to the driver's global data and is a structure of type AJGlobalData. This global data is pointed to by the .refCon field of the Cursor Device Manager record for each Applejack device, as defined in the following code. |
| + | <pre> |
| + | typedef struct SwitchData { |
| + | Byte function; |
| + | Byte modifiers; |
| + | Byte keyCode; |
| + | Byte charCode; |
| + | } SwitchData, *SwitchDataPtr; |
| + | |
| + | typedef struct AJGlobalData { |
| + | long signature; |
| + | Byte MyTalkR0; |
| + | Byte handlerID; |
| + | Byte ourMBState; |
| + | Byte ourLockState; |
| + | long switchStates; |
| + | SwitchData switchMappingArray[18]; |
| + | long nextjADBProc; |
| + | long cursorHandler; |
| + | } AJGlobalData, *AJGlobalDataPtr; |
| + | </pre> |
| + | Most notably in the above code is the signature. The driver installer has initialized the signature to equal 'pipp' so that applications can look through the ADB device table and find this structure. Further, the function field of the SwitchData switchMappingArray is defined as follows: |
| + | <pre> |
| + | enum { |
| + | |
| + | kNothing = 0, // maps to nothing |
| + | kMouse = 1, // maps to standard mouse button operation |
| + | kMouseDblClick = 2, // maps to mouse button double click |
| + | kMouseLock = 3, // toggles the mouse button state |
| + | kKeyboard = 4, // maps to a keyboard key |
| + | kFrontPanel = 5, // not used |
| + | kModifier = 6 // maps to a modifier key |
| + | }; |
| + | </pre> |
| + | Each element of the switchMappingArray array represents one of the switches on Applejack. The array index is equal to the bit numbers, as shown in Figure 6. |
| + | |
| + | Figure 6 : ADB Register 0 Four-Byte Packet and Bit Number to Button Mapping |
| + | |
| + | [[File:Figure66.gif]] |
| + | |
| + | If a button is mapped as kKeyboard, then the Applejack driver posts a keyDown event with the .keyCode, .keyChar and .modifiers fields in the event record. |
| + | |
| + | The following code shows an enumeration of equates for the .modifiers field. |
| + | <pre> |
| + | enum { |
| + | kCommandBit = 0, |
| + | kShiftBit = 1, |
| + | kCapsLockBit = 2, |
| + | kOptionBit = 3, |
| + | kControlBit = 4 |
| + | }; |
| + | </pre> |
| + | If a button is mapped as kModifier, then the Applejack driver sets the keyMap global for the keyCode specified in the .keyCode field. The other fields are ignored in this case. |
| + | |
| + | The following code is another enumeration of equates for the .modifiers field. |
| + | <pre> |
| + | enum { |
| + | kCommandKey = 0x37, |
| + | kShiftKey = 0x38, |
| + | kCapsLockKey = 0x39, |
| + | kOptionKey = 0x3A, |
| + | kControlKey = 0x36 |
| + | }; |
| + | </pre> |
| + | To change the mapping of a button, map a pointer to the AJGlobalData structure, then put in new values for the .switches fields for the desired switch. A good reason to do this would be if you wanted to read the Applejack raw data but did not want a button to also be generating system events. |
| + | |
| + | The following code maps a pointer to the AJGlobalData structure for each connected Applejack, and then changes the selected switch. |
| + | <pre> |
| + | void ChangeSwitchMapping (short whichSwitch, short function, short modifiers, |
| + | short keyCode, short charCode); |
| + | |
| + | void ChangeSwitchMapping (short whichSwitch, short function, short modifiers, |
| + | short keyCode, short charCode); |
| + | { |
| + | ADBAddress address; |
| + | ADBDataBlock dataBlock; |
| + | AJGlobalDataPtr myAJ; |
| + | CursorDevicePtr myCrsrDev; |
| + | short index,i; |
| + | |
| + | //We need to copy these changes into the currently installed drivers. |
| + | //Where are the Applejacks? |
| + | |
| + | //The Applejack driver uses the .refcon field of the cursor device record to |
| + | //store a pointer to its globals, a AJGlobalDataPtr. |
| + | |
| + | if(whichSwitch>=0 && whichSwitch<=17) |
| + | { // where are the AppleJacks? |
| + | index = CountADBs(); |
| + | while(index>0) |
| + | { |
| + | address=GetIndADB(&dataBlock,index); |
| + | if((dataBlock.origADBAddr)==kDevAddr) |
| + | { // make sure that this is really us |
| + | if(dataBlock.dbDataAreaAddr) |
| + | { |
| + | myCrsrDev=(CursorDevicePtr)dataBlock.dbDataAreaAddr; |
| + | if(myCrsrDev) |
| + | { |
| + | myAJ=(AJGlobalDataPtr)myCrsrDev->refCon; |
| + | if(myAJ->signature=='pipp') |
| + | { // got it. |
| + | myAJ->switchMappingArray.function[whichSwitch]=function; |
| + | myAJ->switchMappingArray.modifiers[whichSwitch]=modifiers; |
| + | myAJ->switchMappingArray.keyCode[whichSwitch]=keyCode; |
| + | myAJ->switchMappingArray.charCode[whichSwitch]=charCode; |
| + | } |
| + | } |
| + | } |
| + | } |
| + | index--; |
| + | } |
| + | </pre> |
| + | Some other ways to use this function could be as follows: |
| + | |
| + | * Map the yellow button (S10, bit 9) to do nothing: |
| + | ChangeSwitchMapping(9,kNothing,0,0,0); |
| + | * Map the red button (S8, bit 14) to be equal to command-Q (quit): |
| + | ChangeSwitchMapping(14,kKeyboard,((1<<kCommandBit)),0x0C,'Q'); |
| + | * Map the green button (S7, bit 15) to be equal to the shift key: |
| + | ChangeSwitchMapping(15,kModifier,0,kShiftKey,0); |
| + | |
| + | ===Reading Raw Applejack Data=== |
| + | To read raw Applejack data yourself, use code like the previous sample code, and ensure that you map a pointer to the AJGlobalData for each connected Applejack. You need to do this only once, but remember the pointer since it will not be moved or purged. |
| + | |
| + | Then, examine myAJ->switchStates to read the state of a button. Each button correlates with a bit in switchStates. The bit number is the same as defined in the .switchMappingArray array index. |
| + | |
| + | For example, suppose you want to know if the yellow button is pressed; the following statement might apply: |
| + | <pre> |
| + | if(!((myAJ>switchStates)&(1<<9))) // 0==DOWN |
| + | { // 1==UP |
| + | Do something useful here, yellow button is down... |
| + | } |
| + | </pre> |
| + | Be sure to keep separate pointers for each Applejack found (maximum of 4) even if you only support a single player play. If the bit number returns a value of `0', then the button is pressed. If a value of `1' is returned, the button is not pressed. No other event loop is required. |
| | | |
| ==Pippin Video== | | ==Pippin Video== |
− | This document contains PippinVideo.h and myPippinVideo.c. PippinVideo.h is a header file that contains enumerated constants and structures necessary to access functionality unique to the Pippin video architecture. myPippinVideo.c is sample code that illustrates features unique to the Pippin video architecture. | + | This document contains PippinVideo.h and myPippinVideo.c. PippinVideo.h is a header file that contains enumerated constants and structures necessary to access functionality unique to the Pippin video architecture. myPippinVideo.c is sample code that illustrates features unique to the Pippin video architecture. |
| + | |
| + | ===PippinVideo.h=== |
| + | <pre> |
| + | // ================================================================================= |
| + | // |
| + | // PippinVideo.h |
| + | // |
| + | // Copyright 1995, Apple Computer |
| + | // |
| + | |
| + | // |
| + | // (change this to a real header) |
| + | // |
| + | // This file contains enumerated constants and structures necessary |
| + | // to access functionality unique to the Pippin video architecture |
| + | // |
| + | // ================================================================================= |
| + | |
| + | enum { |
| + | kSetProgressiveScan = 0, // Progressive Scan |
| + | kSetInterlace, // Interlaced scan, no convolution |
| + | kSetInterlaceConv, // Interlaced scan, Convolution, no scaling |
| + | kSetInterlaceConvScale // Interlaced scan, convolution, and scaling |
| + | }; |
| + | |
| + | #define cscSetScanMode 128 // Used to select a scan mode for the Taos driver |
| + | #define cscGetScanMode 128 |
| + | |
| + | // structure for Requesting/Controlling Scan Mode information |
| + | |
| + | typedef struct VDControlMode VDControlMode; |
| + | |
| + | struct VDControlMode |
| + | { |
| + | UInt32 csModeSelect; |
| + | Ptr csBaseAddressA; |
| + | Ptr csBaseAddressB; |
| + | }; |
| + | </pre> |
| + | ===myPippinVideo.c=== |
| + | <pre> |
| + | //================================================================================== |
| + | // |
| + | // myPippinVideo.c |
| + | // |
| + | |
| + | // |
| + | // v1.1 March 28, 1996 |
| + | // |
| + | // (change this to a real header) |
| + | // |
| + | // Sample code illustrating features unique to the Pippin video architecture |
| + | // Shows how to use driver calls to change video scan modes |
| + | // |
| + | //================================================================================== |
| + | |
| + | |
| + | #include <stdio.h> |
| + | #include <stdlib.h> |
| + | #include <Memory.h> |
| + | #include <Displays.h> |
| + | #include <Video.h> |
| + | #include "PippinVideo.h" |
| + | |
| + | // Prototypes |
| + | unsigned long GetUserInputData (void); |
| + | void DoCurrentSettings(void); |
| + | void DoSetScanMode(void); |
| + | |
| + | // Globals |
| + | OSErr err; |
| + | short currentDepth; |
| + | GDHandle myGDHandle; |
| + | short videoDriverRefNum; |
| + | short currentScanMode; |
| + | DisplayIDType currentDisplayType; |
| + | UInt32 currentBaseAddress = 0; |
| + | short currentPage; |
| + | |
| + | //================================================================================== |
| + | // |
| + | // main() |
| + | // |
| + | // Starting point for everything |
| + | // |
| + | //================================================================================== |
| + | |
| + | |
| + | void main(void) |
| + | { |
| + | OSErr err; |
| + | VDControlMode myControlModeStruct; |
| + | VDDisplayConnectInfoRec myVDDisplayConnectInfoRec; |
| + | VDSwitchInfoRec switchInfo; |
| + | CntrlParam pBlock; |
| + | short input = 1; |
| + | MaxApplZone(); |
| + | |
| + | // ooo Need to check for Pippin Gestalt Selecter here |
| + | |
| + | printf("\nThis demo illustrates special functionality of the Pippin video |
| + | architecture\n"); |
| + | |
| + | printf("\n\tInsert explanation and other stuff here\n\n"); |
| + | |
| + | DoCurrentSettings(); |
| + | while ( input != 999 ) |
| + | { |
| + | printf("\nPlease enter a selection:\n"); |
| + | printf(" 1 = Set Scan Mode\n"); |
| + | // printf(" 2 = Swap Video Pages\n"); |
| + | printf(" 3 = Current Settings\n"); |
| + | printf("input (999 to exit)>"); |
| + | input = GetUserInputData(); |
| + | switch ( input ) |
| + | { |
| + | case 1: |
| + | DoSetScanMode(); |
| + | break; |
| + | case 2: |
| + | // DoSwapPages(); |
| + | break; |
| + | case 3: |
| + | DoCurrentSettings(); |
| + | break; |
| + | case 999: |
| + | break; |
| + | default: |
| + | printf("Invalid selection\n"); |
| + | break; |
| + | } |
| + | } |
| + | printf("\nPress Command-Q to Quit . . .\n"); |
| + | } |
| + | |
| + | //================================================================================== |
| + | // |
| + | // DoCurrentSettings() |
| + | // |
| + | // Gets Current Video Stuff by calling PBStatus repeatedly |
| + | // cscGetScanMode |
| + | // cscGetConnection |
| + | // cscGetMode <-- with different pages |
| + | // |
| + | //================================================================================== |
| + | |
| + | |
| + | void DoCurrentSettings(void) |
| + | { |
| + | OSErr err; |
| + | VDControlMode myControlModeStruct; |
| + | VDDisplayConnectInfoRec myVDDisplayConnectInfoRec; |
| + | VDPageInfo myVDPageInfoRec; |
| + | VDSwitchInfoRec switchInfo; |
| + | CntrlParam pBlock; |
| + | |
| + | printf("\n"); |
| + | printf("Scanning for driverRefNum: "); |
| + | |
| + | // We get the First video device because we know there is only one device hooked |
| + | // up to Pippin |
| + | |
| + | myGDHandle = DMGetFirstScreenDevice(dmOnlyActiveDisplays); |
| + | videoDriverRefNum = (*myGDHandle)->gdRefNum; |
| + | printf("%i\n", videoDriverRefNum); |
| + | printf("Current Scan Mode: "); |
| + | pBlock.ioCompletion = nil; |
| + | pBlock.ioCRefNum = videoDriverRefNum; |
| + | pBlock.csCode = cscGetScanMode; |
| + | |
| + | *(Ptr *)&pBlock.csParam[0] = (Ptr)&myControlModeStruct; |
| + | err = PBStatus( (ParmBlkPtr)&pBlock, true ); |
| + | if ( err ) |
| + | printf("Unsupported Functionality, err = %i\n", err); |
| + | else |
| + | { |
| + | currentScanMode = myControlModeStruct.csModeSelect; |
| + | switch (myControlModeStruct.csModeSelect) |
| + | { |
| + | case kSetProgressiveScan: |
| + | printf("kSetProgressiveScan\n"); |
| + | break; |
| + | case kSetInterlace: |
| + | printf("kSetInterlace\n"); |
| + | break; |
| + | case kSetInterlaceConv: |
| + | printf("kSetInterlaceConv\n"); |
| + | break; |
| + | case kSetInterlaceConvScale: |
| + | printf("kSetInterlaceConvScale\n"); |
| + | break; |
| + | default: |
| + | printf("Err -- unknown Scan Mode, %i\n", |
| + | myControlModeStruct.csModeSelect ); |
| + | } |
| + | } |
| + | |
| + | printf("Current Display Type: "); |
| + | pBlock.ioCRefNum = videoDriverRefNum; |
| + | pBlock.csCode = cscGetConnection; |
| + | *(Ptr *)&pBlock.csParam[0] = (Ptr)&myVDDisplayConnectInfoRec; |
| + | err = PBStatus( (ParmBlkPtr)&pBlock, true ); |
| + | currentDisplayType = myVDDisplayConnectInfoRec.csDisplayType; |
| + | |
| + | switch ( currentDisplayType ) |
| + | { |
| + | case kVGAConnect: |
| + | printf("kVGAConnect\n"); |
| + | break; |
| + | case kNTSCConnect: |
| + | printf("kNTSCConnect\n"); |
| + | break; |
| + | case kPALConnect: |
| + | printf("kPALConnect\n"); |
| + | break; |
| + | default: |
| + | printf(" -- something else (not VGA, NTSC, or PAL)\n"); |
| + | break; |
| + | } |
| + | |
| + | printf("Current Screen Depth: "); |
| + | currentDepth = (*((*myGDHandle)->gdPMap))->pixelSize; |
| + | printf("%i\n", currentDepth); |
| + | printf("Page Info:\n"); |
| + | printf(" Current Page: "); |
| + | pBlock.csCode = cscGetMode; |
| + | *(Ptr *)&pBlock.csParam[0] = (Ptr)&myVDPageInfoRec; |
| + | err = PBStatus( (ParmBlkPtr)&pBlock, true ); |
| + | currentPage = myVDPageInfoRec.csPage; |
| + | printf("%i\n", currentPage); |
| + | pBlock.csCode = cscGetBaseAddr; |
| + | myVDPageInfoRec.csPage = 0 |
| + | *(Ptr *)&pBlock.csParam[0] = (Ptr)&myVDPageInfoRec; |
| + | err = PBStatus( (ParmBlkPtr)&pBlock, true ); |
| + | printf(" Page: %i, Base Address: %X\n", myVDPageInfoRec.csPage, |
| + | myVDPageInfoRec.csBaseAddr); |
| + | |
| + | myVDPageInfoRec.csPage = 1; |
| + | err = PBStatus( (ParmBlkPtr)&pBlock, true ); |
| + | printf(" Page: %i, Base Address: %X\n", myVDPageInfoRec.csPage, |
| + | myVDPageInfoRec.csBaseAddr); |
| + | printf(" Page Count: "); |
| + | pBlock.csCode = cscGetPages; |
| + | err = PBStatus( (ParmBlkPtr)&pBlock, true ); |
| + | printf("%i\n", myVDPageInfoRec.csPage); |
| + | printf("\n"); |
| + | } |
| + | |
| + | //================================================================================== |
| + | // |
| + | // DoSetScanMode() |
| + | // |
| + | // Request and set the scan mode; |
| + | // |
| + | //================================================================================== |
| + | |
| + | |
| + | void DoSetScanMode(void) |
| + | { |
| + | short input = 1; |
| + | CntrlParam pBlock; |
| + | VDControlMode myControlModeStruct; |
| + | |
| + | pBlock.ioCompletion = nil; |
| + | pBlock.ioCRefNum = videoDriverRefNum; |
| + | pBlock.csCode = cscSetScanMode; |
| + | |
| + | *(Ptr *)&pBlock.csParam[0] = (Ptr)&myControlModeStruct; |
| + | |
| + | while ( input != 999 ) |
| + | { |
| + | printf("\nPlease enter a selection:\n"); |
| + | printf(" 1 = Progressive Scan\n"); |
| + | printf(" 2 = Interlace\n"); |
| + | printf(" 3 = Interlace, Convolution\n"); |
| + | printf(" 4 = Interlace, Convolution, Scaling\n"); |
| + | printf("input (999 to exit)>"); |
| + | input = GetUserInputData(); |
| + | |
| + | if ( input == 999 ) break; |
| + | |
| + | if ( input == 1 ) |
| + | |
| + | { |
| + | if ( currentDisplayType != kVGAConnect ) printf("err -- not in VGA |
| + | mode\n"); |
| + | else |
| + | { |
| + | myControlModeStruct.csModeSelect = kSetProgressiveScan; |
| + | err = PBControl( (ParmBlkPtr)&pBlock, true ); |
| + | } |
| + | } |
| + | else |
| + | { |
| + | if ( currentDisplayType == kVGAConnect ) printf("err -- not in NTSC/PAL |
| + | mode\n"); |
| + | else |
| + | { |
| + | if (input == 2) myControlModeStruct.csModeSelect = kSetInterlace; |
| + | else if (input == 3) myControlModeStruct.csModeSelect = |
| + | kSetInterlaceConv; |
| + | else if (input == 4) myControlModeStruct.csModeSelect = |
| + | kSetInterlaceConvScale; |
| + | err = PBControl( (ParmBlkPtr)&pBlock, true ); |
| + | } |
| + | } |
| + | if (err) printf("err in PBControl: %i", err); |
| + | } |
| + | } |
| + | |
| + | |
| + | //================================================================================== |
| + | // |
| + | // GetUserInputData() |
| + | // |
| + | // Whats until the user inputs anything other than 0 |
| + | // |
| + | //================================================================================== |
| + | |
| + | |
| + | unsigned long GetUserInputData (void) |
| + | { |
| + | long tempLong = 0; |
| + | do scanf ("%ld", &tempLong); while (tempLong == 0); |
| + | return (tempLong); |
| + | } |
| + | </pre> |
| | | |
| =External Links= | | =External Links= |