diff --git a/mac-cpp-source/Iomega Tester.cpp b/mac-cpp-source/Iomega Tester.cpp index 01b6799..d4f729c 100644 --- a/mac-cpp-source/Iomega Tester.cpp +++ b/mac-cpp-source/Iomega Tester.cpp @@ -10,7 +10,7 @@ #include "iomega_cmds.h" bool process_command(); -void confirm_run_tip(int id); +void confirm_run_tip(); void printn( unsigned char *c, int n ); void print_help(); void scan_bus(); @@ -60,7 +60,7 @@ bool process_command() { case 'i': dev_info(arg_val); break; case 'v': mac_list_volumes(); break; case 'u': mac_unmount(arg_val); break; - case 't': confirm_run_tip(arg_val); break; + case 't': confirm_run_tip(); break; case 'q': return false; case 'o': SetRichEditText(arg_str); break; default: printf("Unknown command, type 'h' for help\n"); @@ -68,12 +68,12 @@ bool process_command() { return true; } -void confirm_run_tip(int id) { +void confirm_run_tip() { char cmd[80]; printf("\nThis program is in BETA TESTING and may cause severe data loss!\n\nProceed [Y/N]? "); gets( cmd ); if(tolower(cmd[0]) == 'y') { - run_tip(id); + run_tip(); } printf("\n\nYou may need to REBOOT your Mac before cartridges are recognized by Mac OS."); } @@ -96,7 +96,7 @@ void print_help() { "\nIomega device operations on SCSI device:\n" " spin [n] : spin up a cartridge\n" " eject [n] : eject cartridge\n" - " tip [n] : run Steve Gibson's TIP 2.1\n" + " tip : run Steve Gibson's TIP 2.1\n" ); } diff --git a/mac-cpp-source/Iomega Tester.rsrc.bin b/mac-cpp-source/Iomega Tester.rsrc.bin index 0e1fe2f..efc02d6 100644 Binary files a/mac-cpp-source/Iomega Tester.rsrc.bin and b/mac-cpp-source/Iomega Tester.rsrc.bin differ diff --git a/mac-cpp-source/macos/text_box.cpp b/mac-cpp-source/macos/text_box.cpp index e5587eb..53686d9 100644 --- a/mac-cpp-source/macos/text_box.cpp +++ b/mac-cpp-source/macos/text_box.cpp @@ -1 +1,258 @@ -/************************************************************ text_box.cpp AUTHOR: Marcio Luis Teixeira CREATED: 3/16/95 LAST REVISION: 11/29/2021 (c) 1994-2021 by Marcio Luis Teixeira. All rights reserved. *************************************************************/ #include "text_box.h" #include #include TBHandle gCurTB; static pascal void TBScrollProc( ControlHandle cntl, short part ); static void TBGetRects(const Rect *r, Rect *viewRect, Rect *destRect, Rect *scrollRect); #define kSlowScrollSpeed 12 TBHandle TBNew( WindowPtr wind, const Rect *r ) { TBHandle tb; Rect destRect; Rect viewRect; Rect scrollRect; SetPort( wind ); TextFont( geneva ); tb = (TBHandle) NewHandle( sizeof( TBRec ) ); if( tb == NULL ) return NULL; HLock( (Handle) tb ); TBRec &my = **tb; my.frame = *r; TBGetRects(r, &viewRect, &destRect, &scrollRect); my.tbox = TEStylNew( &destRect, &viewRect ); if (my.tbox == NULL) { DisposeHandle( (Handle) tb ); return NULL; } my.scroll = NewControl( wind, &scrollRect, "\p", TRUE, 0, 0, 0, scrollBarProc, 1 ); if (my.scroll == NULL) { TEDispose( my.tbox ); DisposeHandle( (Handle) tb ); return NULL; } my.lastV = 0; my.maxV = 0; TEActivate( my.tbox ); HUnlock( (Handle) tb ); return tb; } void TBDispose( TBHandle tb ) { HLock( (Handle) tb ); TBRec &my = **tb; DisposeControl( my.scroll ); TEDispose( my.tbox ); DisposeHandle( (Handle) tb ); } void TBUpdate( TBHandle tb ) { HLock( (Handle) tb ); TBRec &my = **tb; TEUpdate( &(*my.tbox)->viewRect, my.tbox ); FrameRect( &my.frame ); HUnlock( (Handle) tb ); } void TBGetRects(const Rect *r, Rect *viewRect, Rect *destRect, Rect *scrollRect) { *viewRect = *r; viewRect->right -= 16; *destRect = *viewRect; InsetRect( viewRect, 1, 1 ); InsetRect( destRect, 4, 4 ); *scrollRect = *r; scrollRect->right--; scrollRect->left = scrollRect->right - 16; } void TBResize( TBHandle tb, const Rect *r ) { Rect destRect; Rect viewRect; Rect scrollRect; TBSetScroll( tb, 0 ); HLock( (Handle) tb ); TBRec &my = **tb; my.frame = *r; TBGetRects(r, &viewRect, &destRect, &scrollRect); (*my.tbox)->destRect = destRect; (*my.tbox)->viewRect = viewRect; TECalText( my.tbox ); MoveControl( my.scroll, scrollRect.left, scrollRect.top ); SizeControl( my.scroll, scrollRect.right - scrollRect.left, scrollRect.bottom - scrollRect.top ); my.maxV = TEGetHeight( 0, 32767, my.tbox ); my.maxV -= my.frame.bottom - my.frame.top - 30; SetCtlMax( my.scroll, my.maxV ); HUnlock( (Handle) tb ); } bool TBMouseDown( TBHandle tb, Point where, WindowPtr whichWindow ) { if (!PtInRect( where, &(*tb)->frame )) { return false; } HLock( (Handle) tb ); TBRec &my = **tb; ControlHandle whichCntl; short partCode = FindControl(where, whichWindow, &whichCntl); if (partCode) { if( partCode == inThumb ) partCode = TrackControl( whichCntl, where, (ControlActionUPP) -1L ); else { ControlActionUPP tbAction; tbAction = NewControlActionProc( TBScrollProc ); gCurTB = tb; partCode = TrackControl( whichCntl, where, tbAction ); DisposeRoutineDescriptor( tbAction ); } if (partCode == inThumb) { const short newV = GetCtlValue( my.scroll ); TBSetScroll( tb, newV ); } } HUnlock( (Handle) tb ); return true; } static pascal void TBScrollProc( ControlHandle cntl, short part ) { short newV; short max; short height; long lastTicks; TBRec &my = **gCurTB; newV = my.lastV; height = my.frame.bottom - my.frame.top; switch( part ) { case inDownButton: newV += kSlowScrollSpeed; break; case inUpButton: newV -= kSlowScrollSpeed; break; case inPageUp: newV -= height; break; case inPageDown: newV += height; break; } TBSetScroll( gCurTB, newV ); for( lastTicks = TickCount(); lastTicks == TickCount(); ); } void TBSetScroll( TBHandle tb, short scroll ) { TBRec &my = **tb; if( scroll < 0 ) scroll = 0; if( scroll > my.maxV ) scroll = my.maxV; SetCtlValue( my.scroll, scroll ); TEScroll( 0, my.lastV - scroll, my.tbox ); my.lastV = scroll; } OSErr TBReadSimpleText( TBHandle tb, const FSSpec *docSpec) { short fRefNum; TBSetScroll(tb, 0); HLock( (Handle) tb ); TBRec &my = **tb; // Load the text from the data fork OSErr err = FSpOpenDF(docSpec, fsRdPerm, &fRefNum); if(err != noErr) return err; long dataSize; GetEOF(fRefNum, &dataSize); if(dataSize > 31767) { dataSize = 31767; } Ptr data = NewPtr(dataSize); if(!data) { FSClose(fRefNum); return memFullErr; } err = FSRead(fRefNum, &dataSize, data); if(err != noErr) { FSClose(fRefNum); DisposePtr(data); return err; } // Set the text and clean up TESetText(data, dataSize, my.tbox); FSClose(fRefNum); DisposePtr(data); // Load the style information from the resource fork fRefNum = FSpOpenResFile(docSpec, fsRdPerm); if (fRefNum != -1) { short oldResFile = CurResFile(); UseResFile(fRefNum); Handle hStyle = Get1Resource('styl', 128); if (hStyle) { HNoPurge(hStyle); TEUseStyleScrap(0, dataSize, (StScrpHandle) hStyle, true, my.tbox); TECalText(my.tbox); ReleaseResource(hStyle); } UseResFile(oldResFile); CloseResFile(fRefNum); } // Adjust the scrollbar max my.lastV = 0; my.maxV = TEGetHeight( 0, 32767, my.tbox ); my.maxV -= my.frame.bottom - my.frame.top - 30; if( my.maxV < 0 ) my.maxV = 0; SetCtlMax( my.scroll, my.maxV ); HUnlock( (Handle) tb ); return noErr; } \ No newline at end of file +/************************************************************ + + text_box.cpp + + AUTHOR: Marcio Luis Teixeira + CREATED: 3/16/95 + + LAST REVISION: 11/29/2021 + + (c) 1994-2021 by Marcio Luis Teixeira. + All rights reserved. + +*************************************************************/ + +#include "text_box.h" + +#include +#include + +TBHandle gCurTB; + +static pascal void TBScrollProc( ControlHandle cntl, short part ); +static void TBGetRects(const Rect *r, Rect *viewRect, Rect *destRect, Rect *scrollRect); + +#define kSlowScrollSpeed 12 + +TBHandle TBNew( WindowPtr wind, const Rect *r ) { + TBHandle tb; + Rect destRect; + Rect viewRect; + Rect scrollRect; + + SetPort( wind ); + + TextFont( geneva ); + + tb = (TBHandle) NewHandle( sizeof( TBRec ) ); + if( tb == NULL ) + return NULL; + + HLock( (Handle) tb ); + TBRec &my = **tb; + + my.frame = *r; + TBGetRects(r, &viewRect, &destRect, &scrollRect); + my.tbox = TEStylNew( &destRect, &viewRect ); + if (my.tbox == NULL) { + DisposeHandle( (Handle) tb ); + return NULL; + } + + my.scroll = NewControl( wind, &scrollRect, "\p", TRUE, 0, 0, 0, scrollBarProc, 1 ); + if (my.scroll == NULL) { + TEDispose( my.tbox ); + DisposeHandle( (Handle) tb ); + return NULL; + } + + my.lastV = 0; + my.maxV = 0; + TEActivate( my.tbox ); + HUnlock( (Handle) tb ); + + return tb; +} + +void TBDispose( TBHandle tb ) { + HLock( (Handle) tb ); + TBRec &my = **tb; + + DisposeControl( my.scroll ); + TEDispose( my.tbox ); + DisposeHandle( (Handle) tb ); +} + +void TBUpdate( TBHandle tb ) { + HLock( (Handle) tb ); + TBRec &my = **tb; + + TEUpdate( &(*my.tbox)->viewRect, my.tbox ); + FrameRect( &my.frame ); + + HUnlock( (Handle) tb ); +} + +void TBGetRects(const Rect *r, Rect *viewRect, Rect *destRect, Rect *scrollRect) { + *viewRect = *r; + viewRect->right -= 16; + *destRect = *viewRect; + InsetRect( viewRect, 1, 1 ); + InsetRect( destRect, 4, 4 ); + *scrollRect = *r; + scrollRect->right--; + scrollRect->left = scrollRect->right - 16; +} + +void TBResize( TBHandle tb, const Rect *r ) { + Rect destRect; + Rect viewRect; + Rect scrollRect; + + TBSetScroll( tb, 0 ); + + HLock( (Handle) tb ); + TBRec &my = **tb; + + my.frame = *r; + TBGetRects(r, &viewRect, &destRect, &scrollRect); + (*my.tbox)->destRect = destRect; + (*my.tbox)->viewRect = viewRect; + TECalText( my.tbox ); + + MoveControl( my.scroll, scrollRect.left, scrollRect.top ); + SizeControl( my.scroll, scrollRect.right - scrollRect.left, + scrollRect.bottom - scrollRect.top ); + + my.maxV = TEGetHeight( 0, 32767, my.tbox ); + my.maxV -= my.frame.bottom - my.frame.top - 30; + SetCtlMax( my.scroll, my.maxV ); + + HUnlock( (Handle) tb ); +} + + +bool TBMouseDown( TBHandle tb, Point where, WindowPtr whichWindow ) { + if (!PtInRect( where, &(*tb)->frame )) { + return false; + } + + HLock( (Handle) tb ); + TBRec &my = **tb; + + ControlHandle whichCntl; + short partCode = FindControl(where, whichWindow, &whichCntl); + if (partCode) { + if( partCode == inThumb ) + partCode = TrackControl( whichCntl, where, (ControlActionUPP) -1L ); + else { + ControlActionUPP tbAction; + + tbAction = NewControlActionProc( TBScrollProc ); + gCurTB = tb; + partCode = TrackControl( whichCntl, where, tbAction ); + DisposeRoutineDescriptor( tbAction ); + } + + if (partCode == inThumb) { + const short newV = GetCtlValue( my.scroll ); + TBSetScroll( tb, newV ); + } + } + HUnlock( (Handle) tb ); + return true; +} + +static pascal void TBScrollProc( ControlHandle cntl, short part ) { + short newV; + short max; + short height; + long lastTicks; + + TBRec &my = **gCurTB; + + newV = my.lastV; + height = my.frame.bottom - my.frame.top; + + switch( part ) { + case inDownButton: newV += kSlowScrollSpeed; break; + case inUpButton: newV -= kSlowScrollSpeed; break; + case inPageUp: newV -= height; break; + case inPageDown: newV += height; break; + } + + TBSetScroll( gCurTB, newV ); + + for( lastTicks = TickCount(); lastTicks == TickCount(); ); +} + +void TBSetScroll( TBHandle tb, short scroll ) { + TBRec &my = **tb; + + if( scroll < 0 ) + scroll = 0; + if( scroll > my.maxV ) + scroll = my.maxV; + + SetCtlValue( my.scroll, scroll ); + TEScroll( 0, my.lastV - scroll, my.tbox ); + my.lastV = scroll; +} + +OSErr TBReadSimpleText( TBHandle tb, const FSSpec *docSpec) { + short fRefNum; + + TBSetScroll(tb, 0); + + HLock( (Handle) tb ); + TBRec &my = **tb; + + // Load the text from the data fork + + OSErr err = FSpOpenDF(docSpec, fsRdPerm, &fRefNum); + if(err != noErr) return err; + + long dataSize; + GetEOF(fRefNum, &dataSize); + if(dataSize > 31767) { + dataSize = 31767; + } + + Ptr data = NewPtr(dataSize); + if(!data) { + FSClose(fRefNum); + return memFullErr; + } + + err = FSRead(fRefNum, &dataSize, data); + if(err != noErr) { + FSClose(fRefNum); + DisposePtr(data); + return err; + } + + // Set the text and clean up + TESetText(data, dataSize, my.tbox); + FSClose(fRefNum); + DisposePtr(data); + + // Load the style information from the resource fork + + fRefNum = FSpOpenResFile(docSpec, fsRdPerm); + if (fRefNum != -1) { + short oldResFile = CurResFile(); + UseResFile(fRefNum); + + Handle hStyle = Get1Resource('styl', 128); + if (hStyle) { + HNoPurge(hStyle); + TEUseStyleScrap(0, dataSize, (StScrpHandle) hStyle, true, my.tbox); + TECalText(my.tbox); + ReleaseResource(hStyle); + } + UseResFile(oldResFile); + CloseResFile(fRefNum); + } + + // Adjust the scrollbar max + + my.lastV = 0; + my.maxV = TEGetHeight( 0, 32767, my.tbox ); + my.maxV -= my.frame.bottom - my.frame.top - 30; + if( my.maxV < 0 ) + my.maxV = 0; + SetCtlMax( my.scroll, my.maxV ); + + HUnlock( (Handle) tb ); + return noErr; +} \ No newline at end of file diff --git a/mac-cpp-source/macos/text_box.h b/mac-cpp-source/macos/text_box.h index 09ae904..009d6cc 100644 --- a/mac-cpp-source/macos/text_box.h +++ b/mac-cpp-source/macos/text_box.h @@ -1 +1,31 @@ -/************************************************************ Text Box.h AUTHOR: Marcio Luis Teixeira CREATED: 3/16/95 LAST REVISION: 11/29/2021 (c) 1994-2021 by Marcio Luis Teixeira. All rights reserved. *************************************************************/ #include "ctype.h" typedef struct { TEHandle tbox; Rect frame; ControlHandle scroll; short lastV; short maxV; } TBRec, *TBPtr, **TBHandle; TBHandle TBNew( WindowPtr wind, const Rect *r ); void TBDispose( TBHandle html ); void TBUpdate( TBHandle html ); void TBResize( TBHandle html, const Rect *r ); void TBSetScroll( TBHandle html, short scroll ); bool TBMouseDown( TBHandle html, Point where, WindowPtr whichWindow ); OSErr TBReadSimpleText( TBHandle tb, const FSSpec *docSpec); \ No newline at end of file +/************************************************************ + + Text Box.h + + AUTHOR: Marcio Luis Teixeira + CREATED: 3/16/95 + + LAST REVISION: 11/29/2021 + + (c) 1994-2021 by Marcio Luis Teixeira. + All rights reserved. + +*************************************************************/ + +#include "ctype.h" + +typedef struct { + TEHandle tbox; + Rect frame; + ControlHandle scroll; + short lastV; + short maxV; +} TBRec, *TBPtr, **TBHandle; + +TBHandle TBNew( WindowPtr wind, const Rect *r ); +void TBDispose( TBHandle html ); +void TBUpdate( TBHandle html ); +void TBResize( TBHandle html, const Rect *r ); +void TBSetScroll( TBHandle html, short scroll ); +bool TBMouseDown( TBHandle html, Point where, WindowPtr whichWindow ); +OSErr TBReadSimpleText( TBHandle tb, const FSSpec *docSpec); diff --git a/mac-cpp-source/tip/tip.cpp b/mac-cpp-source/tip/tip.cpp index cbf2846..f1eb586 100644 --- a/mac-cpp-source/tip/tip.cpp +++ b/mac-cpp-source/tip/tip.cpp @@ -24,12 +24,16 @@ Rect SE_Rect = SET_RECT(222, 154, 255, 221); * * Startup the Windows program. *******************************************************************************/ -void WinMain(int Device) { - CurrentDevice = Device; +void WinMain(uint8_t *DrivesSkipped) { + CurrentDevice = 0; // test for an Iomega device - EnumerateIomegaDevices(CurrentDevice); - // Disable testing button when no drives present (added by mlt) - if (!DriveCount) { + EnumerateIomegaDevices(DrivesSkipped); + if (DriveCount == 1) { + // we have only one, so select it for the user + CurrentDevice = DriveArray[0].scsi_id; + } + if (DriveCount == 0) { + // disable testing button when no drives present (added by mlt) EnableWindow(hTestButton, false); SetRichEditText(szASPITrouble); } @@ -90,7 +94,7 @@ void WndProc(long iMessage, uint16_t wParam) { case DISK_Z_TRACK_FAILURE: case DISK_TEST_FAILURE: case DISK_PROTECTED: - EjectIomegaCartridge(); + EjectIomegaCartridge(CurrentDevice); break; case DISK_LOW_SPARES: SetRichEditText(szNotRunning); diff --git a/mac-cpp-source/tip/tip.h b/mac-cpp-source/tip/tip.h index 68a57be..a6e9831 100644 --- a/mac-cpp-source/tip/tip.h +++ b/mac-cpp-source/tip/tip.h @@ -2,7 +2,7 @@ extern WindowPtr tipWindow; -void run_tip(int id); +void run_tip(); #define MINIMUM_JAZ_SPARES 500 #define MAXIMUM_JAZ_SPARES 2557 @@ -14,7 +14,7 @@ extern long DriveCount; extern long JazDrive; // true if the current drive extern long CartridgeStatus; extern long LastLBAOnCartridge; -extern unsigned long StartingInstant; +extern uint32_t StartingInstant; extern long NumberOfLBAs; extern long Side_0_SparesCount; // JAZ has only one count extern long Side_1_SparesCount; // ZIP has counts for both sides @@ -34,22 +34,38 @@ extern bool UserInterrupt; extern long LastError; extern long SingleTransferLBA; +//-------------------------- Drive Array Status Flags --------------------------- + +#define JAZ_DRIVE 0x01 +#define MEDIA_CHANGED 0x02 +#define DISK_EJECTING 0x04 // we've asked for eject and waiting ... +#define ODD_BYTE_COMPENSATION 0x08 // special handling for ODD length PSWD +#define MOUNTED_DRIVE 0x10 // drive was mounted at startup, ignore it +#define MAX_DRIVE_COUNT 8 // we can handle up to 8 Zip/Jaz drives + +struct DriveEntry { + uint8_t flags; + uint8_t scsi_id; +}; + +extern DriveEntry DriveArray[MAX_DRIVE_COUNT]; + // ----------------------- Macintosh Compatibility ----------------------- enum AlertTypes { - ERR_DLG, - YN_DLG + ERR_DLG, + YN_DLG }; enum { - BACK_COLOR = -1, - BLACK_COLOR = 0x000000, - LTGRAY_COLOR = 0xc0c0c0, - GRAY_COLOR = 0x808080, - WHITE_COLOR = 0xffffff, - BLUE_COLOR = 0x0000ff, - RED_COLOR = 0xff0000, - GREEN_COLOR = 0x00ff00, + BACK_COLOR = -1, + BLACK_COLOR = 0x000000, + LTGRAY_COLOR = 0xc0c0c0, + GRAY_COLOR = 0x808080, + WHITE_COLOR = 0xffffff, + BLUE_COLOR = 0x0000ff, + RED_COLOR = 0xff0000, + GREEN_COLOR = 0x00ff00, }; #define BDR_SUNKENOUTER 1 @@ -59,8 +75,10 @@ enum { #define SW_SHOW 1 #define SW_HIDE 2 +void SetRGBColor(long color, RGBColor *rgbColor); void SetColor(long color); void SetColor(long color, long monoColor); +void SetBackColor(long color); void DrawLed(int x, int y, long color); void StrToPascal(Str255 pStr, const char *str); int ShowAlert(AlertTypes type, const char* format, ...); @@ -71,6 +89,7 @@ void TextOut(int x, int y, const char *str); void TextOutCentered(int x, int y, int w, int h, const char *str); void SetWindowText(int id, const char *str); void EnableWindow(int id, bool enabled); +void ShowWindow(ControlHandle hCntl, int state); void ShowWindow(int id, int state); void InvalidateRect(int id); void Rectangle(int left, int top, int right, int bottom); @@ -81,42 +100,42 @@ void PostQuitMessage(); unsigned long GetSystemTime(); bool PrepareDC(int which); -#define GetDC(h) {GrafPtr oldPort; \ - GetPort(&oldPort); \ - if(PrepareDC(h)) { +#define GetDC(h) {GrafPtr oldPort; \ + GetPort(&oldPort); \ + if(PrepareDC(h)) { #define ReleaseDC(h) } SetOrigin(0,0); \ - SetPort(oldPort);} + SetPort(oldPort);} -// ------------------------------ Cartridge Status ------------------------------- +// ------------------------------ Cartridge Status ------------------------------- enum { - DISK_STATUS_UNKNOWN = 1, - DISK_AT_SPEED = 2, - DISK_SPINNING_UP = 3, - DISK_NOT_PRESENT = 4, - DISK_SPUN_DOWN = 5, - DISK_STALLED = 6, - DISK_Z_TRACK_FAILURE = 7, - DISK_PROTECTED = 8, - DISK_LOW_SPARES = 9, - DISK_TEST_UNDERWAY = 10, - DISK_TEST_FAILURE = 11, + DISK_STATUS_UNKNOWN = 1, + DISK_AT_SPEED = 2, + DISK_SPINNING_UP = 3, + DISK_NOT_PRESENT = 4, + DISK_SPUN_DOWN = 5, + DISK_STALLED = 6, + DISK_Z_TRACK_FAILURE = 7, + DISK_PROTECTED = 8, + DISK_LOW_SPARES = 9, + DISK_TEST_UNDERWAY = 10, + DISK_TEST_FAILURE = 11, - LAST_CART_STATUS = 11 + LAST_CART_STATUS = 11 }; // ---------------------------- Testing Phase Status ----------------------------- enum { - UNTESTED = 0, - READY_TO_TEST = 1, - TESTING_STARTUP = 2, - READING_DATA = 3, - WRITING_PATT = 4, - READING_PATT = 5, - WRITING_DATA = 6 + UNTESTED = 0, + READY_TO_TEST = 1, + TESTING_STARTUP = 2, + READING_DATA = 3, + WRITING_PATT = 4, + READING_PATT = 5, + WRITING_DATA = 6 }; /******************************************************************************* @@ -195,15 +214,6 @@ extern const char *szBack; extern const char *szNext; extern const char *szQuit; -enum { - hMainWnd, - hTestMonitor, - hTestButton, - hExitButton, - // Extras added by MLT - hExplainWnd -}; - #define IDB_BACK 0xFF00 #define IDB_NEXT 0xFF01 #define IDB_QUIT 0xFF02 @@ -212,14 +222,24 @@ enum { #define IDB_OKAY 0xFF05 #define IDB_READ 0xFF06 +enum { + hDefault, + hMainWnd, + hTestMonitor, + hTestButton = IDB_TEST, + hExitButton = IDB_QUIT, + // Extras added by MLT + hExplainWnd = IDB_EXPL +}; + typedef struct { - int id; - const char *name; - int x; - int y; - int w; - int h; - ControlHandle hndl; + int id; + const char *name; + int x; + int y; + int w; + int h; + ControlHandle hndl; } BtnList; extern BtnList tipBtns[]; @@ -246,15 +266,16 @@ void PreventProgramExit(); void AllowProgramExit(); void ErrorSound(); void ProcessPendingMessages(); -void WinMain(int Device); +void WinMain(uint8_t *DrivesSkipped); void WndProc(long iMessage, uint16_t wParam); void TestMonitorWndProc(); void ApplicationTimerProc(); void TestButtonClicked(); +int GetDriveEntryOffset(short Device); void GetCommandDetails(char command, char &cmd_flags, char &cmd_length); long SCSICommand(short Device, char *lpCmdBlk, void *lpIoBuf, short IoBufLen); -void EnumerateIomegaDevices(long Device); +long EnumerateIomegaDevices(uint8_t *DrivesSkipped); long GetModePage(short Device, short PageToGet, void *pBuffer, short BufLen); long SetModePage(short Device, void *pBuffer); void ModifyModePage(char *PageBuff, char eec, char retries); @@ -262,10 +283,14 @@ void SetErrorRecovery(bool Retries, bool ECC, bool Testing); long GetNonSenseData(short Device, short DataPage, void *Buffer, short BufLen); long LockCurrentDrive(); long UnlockCurrentDrive(); +void UnlockAllMedia(); long SpinUpIomegaCartridge(short Device); +void EjectAllMedia(); long GetSpareSectorCounts(char); +uint8_t GetCartridgeStatus(long Device); void HandleDriveChanging(); void SetCartridgeStatusToEAX(long eax); +void EjectIomegaCartridge(int Device); long PerformRegionTransfer(short XferCmd, void *pBuffer); void TestTheDisk(); long GetElapsedTimeInSeconds(); diff --git a/mac-cpp-source/tip/tip_aspi.cpp b/mac-cpp-source/tip/tip_aspi.cpp index 34ac595..859634e 100644 --- a/mac-cpp-source/tip/tip_aspi.cpp +++ b/mac-cpp-source/tip/tip_aspi.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "mac_scsi.h" #include "tip.h" @@ -49,14 +50,6 @@ struct DEFECT_LIST_HEADER { short DLH_DefectListLength; }; -//-------------------------- Drive Array Status Flags --------------------------- - -#define JAZ_DRIVE 0x00010000 -#define MEDIA_CHANGED 0x00020000 -#define DISK_EJECTING 0x00040000 // we've asked for eject and waiting ... -#define ODD_BYTE_COMPENSATION 0x00080000 // special handling for ODD length PSWD -#define MAX_DRIVE_COUNT 16 // we can handle up to 16 Zip/Jaz drives - #define ERROR_RECOVERY_PAGE 1 // From disassembly #define FORMAT_STATUS_PAGE 1 #define DISK_STATUS_PAGE 2 @@ -83,16 +76,20 @@ struct DEFECT_LIST_HEADER { #define BADNESS_THRESHOLD 10 -#define SS_ERR 0x00000004 // From disassembly -#define BUFFER_TOO_BIG 0x00FFFFE6 // From disassembly -#define LBA_TOO_LARGE 0x00210005 // From disassembly -#define INCOMPATIBLE_MEDIA 0x00300002 // From disassembly -#define MEDIA_NOT_PRESENT 0x003a0002 // From disassembly -#define DEFECT_LIST_READ_ERROR 0x001c0003 // From disassembly +#define SS_ERR 0x00000004 +#define DEFECT_LIST_READ_ERROR 0x001c0003 +#define LBA_TOO_LARGE 0x00210005 // accessed a non-exist LBA +#define MEDIA_CHANGE_CODE 0x00280006 // media was changed +#define INCOMPATIBLE_MEDIA 0x00300002 // 2Gb / 1Gb combo on "Read Defects" +#define MEDIA_NOT_PRESENT 0x003a0002 +#define DRIVE_COMING_READY 0x00040102 +#define SCSI_CMD_TIMED_OUT 0x00FFFF00 +#define BUFFER_TOO_BIG 0x00FFFFE6 +#define MANUAL_INTERRUPTION 0xFFFFFFFF #define CHECK_CONDITION 0x02 -long CurrentDevice = 0; +long CurrentDevice = -1; // the device that's been recognized long DriveCount = 0; long JazDrive = 0; // true if the current drive @@ -122,6 +119,20 @@ bool UserInterrupt; long LastError; long SingleTransferLBA; +DriveEntry DriveArray[MAX_DRIVE_COUNT]; + +/******************************************************************************* + * GET DRIVE ENTRY OFFSET + * + * Returns the offset of the chosen drive's status word + *******************************************************************************/ +int GetDriveEntryOffset(short Device) { + for(int i = 0; i < MAX_DRIVE_COUNT; i++) + if(DriveArray[i].scsi_id == Device) // did we find the right table slot? + return i; + return 0; +} + /******************************************************************************* * GET COMMAND DETAILS * @@ -196,9 +207,15 @@ long SCSICommand(short Device, char *lpCmdBlk, void *lpIoBuf, short IoBufLen) { printf("SCSI CHECK CONDITION (KEY %x, ASC %x, ASCQ %x)\n", sense_data.key, sense_data.asc, sense_data.ascq); // okay, we have an SS_ERR condition, let's check the SENSE DATA // assemble [00 ASC ASCQ SenseKey] - return (long(sense_data.asc) << 16) | - (long(sense_data.ascq) << 8) | - (long(sense_data.key) ); + long res = (long(sense_data.asc) << 16) | + (long(sense_data.ascq) << 8) | + (long(sense_data.key) ); + if(res == MEDIA_CHANGE_CODE) { + int index = GetDriveEntryOffset(Device); + DriveArray[index].flags |= MEDIA_CHANGED; + return 0; + } + return 0; } else { // else, if it's *NOT* a "Sense Data" error (SS_ERR) @@ -209,33 +226,72 @@ long SCSICommand(short Device, char *lpCmdBlk, void *lpIoBuf, short IoBufLen) { /******************************************************************************* * ENUMERATE IOMEGA DEVICES *******************************************************************************/ -void EnumerateIomegaDevices(long Device) { +short stricmp( const char *str1, const char *str2 ); +short stricmp( const char *str1, const char *str2 ) { + while (*str1 && *str2) { + short cmp = tolower( *str1++ ) - tolower( *str2++ ); + if(cmp != 0) return cmp; + } + return 0; +} + +long EnumerateIomegaDevices(uint8_t *DrivesSkipped) { DriveCount = 0; - JazDrive = 0; - //----------------------------------------------------------- - char InqData[96]; - char Scsi[6] = {0}; - Scsi[0] = SCSI_Cmd_Inquiry; - Scsi[4] = sizeof(InqData); - long eax = SCSICommand(Device, Scsi, InqData, sizeof(InqData)); - if(eax) goto TryNextDrive; - //----------------------------------------------------------- - InqData[14] = '\0'; - if (strcmp(szIomega, InqData + 8)) goto TryNextDrive; - //----------------------------------------------------------- - InqData[19] = '\0'; - if (!strcmp(szZip, InqData + 16)) goto FoundZipOrJaz; - //----------------------------------------------------------- - if (strcmp(szJaz, InqData + 16)) goto TryNextDrive; - JazDrive = 1; - FoundZipOrJaz: - DriveCount = 1; - if(JazDrive) - printf("Found Jaz drive\n"); - else - printf("Found Zip drive\n"); -TryNextDrive: - return; + if(DrivesSkipped) *DrivesSkipped = 0; + + printf("\nEnumerating Iomega Devices:\n"); + // now scan the devices on the SCSI host adapter + for(int Device = 0; Device < 8; Device++) { + char flags = 0; + //----------------------------------------------------------- + #ifdef NO_EXCESS_READS + scsi_inq_reply reply; + if(scsi_inquiry(Device, 0, &reply) != noErr) continue; + char *InqData = (char*) &reply; + #else + char InqData[96]; + char Scsi[6] = {0}; + Scsi[0] = SCSI_Cmd_Inquiry; + Scsi[4] = sizeof(InqData); + if(SCSICommand(Device, Scsi, InqData, sizeof(InqData))) continue; + #endif + + //----------------------------------------------------------- + InqData[14] = '\0'; + InqData[19] = '\0'; + const bool isIomega = !stricmp(szIomega, InqData + 8); + const bool isZip = !stricmp(szZip, InqData + 16); + const bool isJaz = !stricmp(szJaz, InqData + 16); + //----------------------------------------------------------- + + if (isIomega && (isZip || isJaz)) { + char flags = isJaz ? JAZ_DRIVE : 0; + // check for ANSI SCSI to see whether we need to play + // the Odd/Even password length game ... + if(InqData[2] & 0x07 == 0) { + flags |= ODD_BYTE_COMPENSATION; // turn on compensation + } + + // On the Mac, we want to ignore drives that have media in them at + // program entry, as this means the volume is mounted in Mac OS + const bool driveEmpty = GetCartridgeStatus(Device) == DISK_NOT_PRESENT; + if(driveEmpty) { + DriveArray[DriveCount].flags = flags; + DriveArray[DriveCount].scsi_id = Device; + DriveCount++; + } else { + if(DrivesSkipped) (*DrivesSkipped)++; + } + + printf(" %d: %s %s %s\n", Device, + (flags & JAZ_DRIVE) ? "JAZ" : "ZIP", + (flags & ODD_BYTE_COMPENSATION) ? "OBC" : " ", + (driveEmpty) ? "EMPTY" : "MEDIA"); + } + } + + printf("\n"); + return DriveCount; } /******************************************************************************* @@ -358,6 +414,18 @@ long UnlockCurrentDrive() { return SCSICommand(CurrentDevice, Scsi, NULL, 0); } +/******************************************************************************* + * UNLOCK ALL MEDIA + *******************************************************************************/ +void UnlockAllMedia() { + // make sure the media is not locked as we exit... + char Scsi[6] = {0}; + Scsi[0] = SCSI_Cmd_PreventAllow; + for(int i = 0; i < MAX_DRIVE_COUNT; i++) { + SCSICommand(DriveArray[i].scsi_id, Scsi, NULL, 0); + } +} + /******************************************************************************* * SPIN UP IOMEGA CARTRIDGE *******************************************************************************/ @@ -369,6 +437,16 @@ long SpinUpIomegaCartridge(short Device) { return SCSICommand(Device, Scsi, NULL, 0); } +/******************************************************************************* + * EJECT ALL MEDIA + *******************************************************************************/ +void EjectAllMedia() { + // setup the SCSI command block for the operation + for(int i = 0; i < MAX_DRIVE_COUNT; i++) { + EjectIomegaCartridge(DriveArray[i].scsi_id); + } +} + /******************************************************************************* * GET SPARE SECTOR COUNTS * @@ -475,34 +553,92 @@ long GetSpareSectorCounts(char checkPassword) { /******************************************************************************* * HANDLE DRIVE CHANGING + * + * If we're NOT in the middle of drive testing, check for any new drives + * going ready, eject all others, and Select the newer drive. + * If we *ARE* in the middle of drive testing, EJECT any new drive that's + * attempting to go ready. *******************************************************************************/ void HandleDriveChanging() { - // MLT: At the moment, we only handle one drive. + bool Selecting = false; // true while we're changing selections + uint8_t status; +Rescan: + for(int i = 0; i < DriveCount; i++) { + const int scsi_id = DriveArray[i].scsi_id; + + // query the current state of the drive + do { + // clear media changed status + DriveArray[i].flags &= ~MEDIA_CHANGED; + GetCartridgeStatus(scsi_id); + } while(DriveArray[i].flags & MEDIA_CHANGED); // do it until NO media change! + //-------------------------------------------------------------------------- + status = GetCartridgeStatus(scsi_id); + // if the device we have is NOT the currently selected one + if(scsi_id != CurrentDevice) { + // if the disk is ANYTHING other than not present ... + if(status != DISK_NOT_PRESENT) { + // we have a PRESENT DISK in a non-current drive + // if we're testing, reject it + if (Selecting || TestingPhase >= TESTING_STARTUP) { + EjectIomegaCartridge(scsi_id); + // flag that we're waiting for spindown + DriveArray[i].flags |= DISK_EJECTING; + } + // if we're not testing, and not awaiting eject + // then set the current drive ... + else if ((DriveArray[i].flags & DISK_EJECTING) == 0) { + CurrentDevice = scsi_id; + TestingPhase = 0; + Selecting = true; + //goto Rescan; + break; + // the PREVIOUS drive (if any) will be ejected on the next pass + } + } else { + // the drive HAS spun down, so clear "waiting" + DriveArray[i].flags &= ~DISK_EJECTING; + } + } else { + // we're checking the current drive ... make SURE that + // it is *NOT* empty! If it *IS* empty, kill current + if(status == DISK_NOT_PRESENT) { + CurrentDevice = -1; + SetCartridgeStatusToEAX(status); + } + // if it's not already set correctly *and* either + // the cart status is one of the pre-test ones, or + // the NEW status from the cart is NOT "at speed" ... + if((status != CartridgeStatus) && ((CartridgeStatus <= DISK_STALLED) || (status != DISK_AT_SPEED))) { + SetCartridgeStatusToEAX(status); + } + } + } + // if nothing was chosen ... set us to the "Awaiting Cartridge" status + if ((CurrentDevice == -1) && + (status == DISK_NOT_PRESENT) && + (CartridgeStatus != DISK_NOT_PRESENT)) { + SetCartridgeStatusToEAX(status); + } +} + +//----------------------------------------------------------------------------- +// GET CARTRIDGE STATUS +//----------------------------------------------------------------------------- +uint8_t GetCartridgeStatus(long Device) { long eax; char DiskStat[72]; #ifdef NO_EXCESS_READS - eax = GetNonSenseData(CurrentDevice, DISK_STATUS_PAGE, DiskStat, JazDrive ? sizeof(DiskStat) : 63); - if (eax) return; + eax = GetNonSenseData(Device, DISK_STATUS_PAGE, DiskStat, JazDrive ? sizeof(DiskStat) : 63); + if (eax) return DISK_STATUS_UNKNOWN; #else - eax = GetNonSenseData(CurrentDevice, DISK_STATUS_PAGE, DiskStat, sizeof(DiskStat)); - if (!eax) return; + eax = GetNonSenseData(Device, DISK_STATUS_PAGE, DiskStat, sizeof(DiskStat)); + if (!eax) return DISK_STATUS_UNKNOWN; #endif - char status; if (DiskStat[0] == DISK_STATUS_PAGE) { - status = DiskStat[NEW_DISK_STATUS_OFFSET]; + return DiskStat[NEW_DISK_STATUS_OFFSET]; } else { - status = DiskStat[OLD_DISK_STATUS_OFFSET]; - } - // we're checking the current drive ... make SURE that - // it is *NOT* empty! If it *IS* empty, kill current - if(status == DISK_NOT_PRESENT) { - SetCartridgeStatusToEAX(status); - } - // if it's not already set correctly *and* either - // the cart status is one of the pre-test ones, or - // the NEW status from the cart is NOT "at speed" ... - if((status != CartridgeStatus) && ((CartridgeStatus <= DISK_STALLED) || (status != DISK_AT_SPEED))) { - SetCartridgeStatusToEAX(status); + return DiskStat[OLD_DISK_STATUS_OFFSET]; } } @@ -514,17 +650,6 @@ void SetCartridgeStatusToEAX(long eax) { long PriorStatus = CartridgeStatus; CartridgeStatus = eax; - /************************************************************************** - * Added by MLT - */ - // Avoid flickering - static long LastCartridgeStatus = -1; - if (LastCartridgeStatus == CartridgeStatus) { - return; - } - LastCartridgeStatus = CartridgeStatus; - /**************************************************************************/ - // Set the text of the "action initiate button" const char *esi = 0; switch (CartridgeStatus) { @@ -666,18 +791,18 @@ void BumpErrorCounts(long ErrorCode) { /******************************************************************************* * EJECT IOMEGA CARTRIDGE *******************************************************************************/ -void EjectIomegaCartridge() { +void EjectIomegaCartridge(int Device) { // Could NOT do it through the IOCTL layer ... so eject with SCSI // make sure the media is not locked... char Scsi[6] = {0}; Scsi[0] = SCSI_Cmd_PreventAllow; - SCSICommand(CurrentDevice, Scsi, 0, 0); + SCSICommand(Device, Scsi, 0, 0); // issue an Asynchronous STOP command to induce spindown and ejection memset(Scsi, 0, sizeof(Scsi)); Scsi[0] = SCSI_Cmd_StartStopUnit; Scsi[1] = 1; // Set the IMMED bit for offline Scsi[4] = 2; // eject a Jaz disk after stopping - SCSICommand(CurrentDevice, Scsi, 0, 0); + SCSICommand(Device, Scsi, 0, 0); } /******************************************************************************* @@ -883,7 +1008,7 @@ GetOut: free(pUserDataBuffer); TestingPhase = UNTESTED; - UnlockCurrentDrive(); + UnlockAllMedia(); SetErrorRecovery(true, true, false); // reenable Retries & ECC SetWindowText(hTestButton, szPressToStart); CartridgeStatus = DISK_AT_SPEED; diff --git a/mac-cpp-source/tip/tip_main.cpp b/mac-cpp-source/tip/tip_main.cpp index 14ca0e5..355fe20 100644 --- a/mac-cpp-source/tip/tip_main.cpp +++ b/mac-cpp-source/tip/tip_main.cpp @@ -43,7 +43,7 @@ void OpenExplanationInSimpleText(); const Point mainWndOrigin = SET_POINT(0, 40); -void run_tip(int id) { +void run_tip() { RgnHandle cursorRgn = NewRgn(); NewTipWindow(); @@ -59,7 +59,19 @@ void run_tip(int id) { printf("Starting tip\n"); // Start TIP as soon as the user dismisses the intro screen inited = true; - WinMain(id); + uint8_t drivesSkipped; + WinMain(&drivesSkipped); + if(drivesSkipped) { + const char *s = drivesSkipped > 1 ? "s" : ""; + if(ShowAlert(YN_DLG, + "Found media in %d drive%s. If you wish to test that " + "media, you must quit to the Finder and eject it " + "prior to running TIP. Would you like to do so?", + drivesSkipped, s + ) == 1) { + gDone = true; + } + } } } if(timerEnabled) { @@ -93,7 +105,9 @@ void NewTipWindow() { NewCWindow(NULL,&rect, title, true, 0, (WindowPtr)-1, true, 0) : NewWindow(NULL,&rect, title, true, 0, (WindowPtr)-1, true, 0); - GetDC(hMainWnd); + SetPort(tipWindow); + SetBackColor(BACK_COLOR); + EraseRect(&tipWindow->portRect); TextSize(10); @@ -107,9 +121,8 @@ void NewTipWindow() { tipBtns[i].y + tipBtns[i].h - mainWndOrigin.v ); StrToPascal(title, tipBtns[i].name); - tipBtns[i].hndl = NewControl(tipWindow, &rect, title, true, 0, 0, 0, 0, tipBtns[i].id); + tipBtns[i].hndl = NewControl(tipWindow, &rect, title, false, 0, 0, 0, 0, tipBtns[i].id); } - ReleaseDC(hMainWnd); page = kExplainPage; GetDC(hExplainWnd); @@ -149,6 +162,9 @@ bool PrepareDC(int which) { case hMainWnd: SetOrigin(mainWndOrigin.h, mainWndOrigin.v); break; + case hDefault: + SetOrigin(0, 0); + break; } return true; } @@ -291,28 +307,28 @@ void SetPage(TipPage newPage) { page = newPage; switch(page) { case kTestingPage: - ShowWindow(IDB_TEST, SW_SHOW); + ShowWindow((*richText)->scroll, SW_HIDE); ShowWindow(IDB_BACK, SW_HIDE); ShowWindow(IDB_NEXT, SW_HIDE); - ShowWindow(IDB_EXPL, SW_SHOW); ShowWindow(IDB_OKAY, SW_HIDE); - ShowWindow(IDB_QUIT, SW_SHOW); ShowWindow(IDB_READ, SW_HIDE); - HideControl((*richText)->scroll); + ShowWindow(IDB_TEST, SW_SHOW); + ShowWindow(IDB_EXPL, SW_SHOW); + ShowWindow(IDB_QUIT, SW_SHOW); break; case kExplainPage: ShowWindow(IDB_TEST, SW_HIDE); ShowWindow(IDB_BACK, SW_HIDE); ShowWindow(IDB_NEXT, SW_HIDE); ShowWindow(IDB_EXPL, SW_HIDE); - ShowWindow(IDB_OKAY, SW_SHOW); ShowWindow(IDB_QUIT, SW_HIDE); + ShowWindow(IDB_OKAY, SW_SHOW); ShowWindow(IDB_READ, SW_SHOW); - ShowControl((*richText)->scroll); + ShowWindow((*richText)->scroll, SW_SHOW); TBSetScroll(richText, 0); break; } - InvalidateRect(hMainWnd); + InvalidateRect(hDefault); } /******************************************************************************* @@ -394,42 +410,44 @@ void OpenExplanationInSimpleText() { *******************************************************************************/ void SetRichEditText(const char *name) { - short fRefNum = 0; - // Don't reload a file that is already loaded if(textFileName == name) return; textFileName = name; - printf("Loading explanation file \"%s\"\n", name); - // Get the specification for the explanation file FSSpec docSpec; OSErr err = GetExplanationFSSpec(textFileName, &docSpec); if(err != noErr) return; - // Load the text from the data fork + // Load the text from the file + + TBReadSimpleText(richText, &docSpec); if (name != szRunning && name != szNotRunning) { SetPage(kExplainPage); + } else { + InvalidateRect(hDefault); } - - TBReadSimpleText(richText, &docSpec); } /******************************************************************************* * SET COLOR *******************************************************************************/ +void SetRGBColor(long color, RGBColor *rgbColor) { + if(color == BACK_COLOR) color = LTGRAY_COLOR; + // Use colors when available + rgbColor->red = (color & 0xFF0000) >> 8; + rgbColor->green = (color & 0x00FF00) >> 0; + rgbColor->blue = (color & 0x0000FF) << 8; +} + void SetColor(long color) { if (allowColor) { - if(color == BACK_COLOR) color = LTGRAY_COLOR; - // Use colors when available RGBColor rgbColor; - rgbColor.red = (color & 0xFF0000) >> 8; - rgbColor.green = (color & 0x00FF00) >> 0; - rgbColor.blue = (color & 0x0000FF) << 8; + SetRGBColor(color, &rgbColor); RGBForeColor(&rgbColor); } else { // Use patterns for B&W Macs @@ -464,6 +482,14 @@ void SetColor(long color, long monoColor) { } } +void SetBackColor(long color) { + if (allowColor) { + RGBColor rgbColor; + SetRGBColor(color, &rgbColor); + RGBBackColor(&rgbColor); + } +} + /******************************************************************************* * DRAW LED *******************************************************************************/ @@ -587,9 +613,9 @@ void SetWindowText(int id, const char *str) { StrToPascal(pStr, str); ControlHandle hCntl = FindControl(id); if(hCntl) { - GetDC(hMainWnd); + GetDC(hDefault); SetCTitle(hCntl, pStr); - ReleaseDC(hMainWnd); + ReleaseDC(hDefault); } } @@ -599,24 +625,27 @@ void SetWindowText(int id, const char *str) { void EnableWindow(int id, bool enabled) { ControlHandle hCntl = FindControl(id); if(hCntl) { - GetDC(hMainWnd); + GetDC(hDefault); HiliteControl(hCntl, enabled ? 0 : 255); - ReleaseDC(hMainWnd); + ReleaseDC(hDefault); } } /******************************************************************************* * SHOW WINDOW *******************************************************************************/ +void ShowWindow(ControlHandle hCntl, int state) { + // Show/hide a control by invalidating, rather than drawing it + (*hCntl)->contrlVis = (state == SW_SHOW) ? 255 : 0; + InvalRect(&(*hCntl)->contrlRect); +} + void ShowWindow(int id, int state) { ControlHandle hCntl = FindControl(id); if(hCntl) { - GetDC(hMainWnd); - if(state == SW_SHOW) - ShowControl(hCntl); - else - HideControl(hCntl); - ReleaseDC(hMainWnd); + GetDC(hDefault); + ShowWindow(hCntl, state); + ReleaseDC(hDefault); } } diff --git a/mac-cpp-source/utils/ctype.h b/mac-cpp-source/utils/ctype.h index bb1578a..ce22651 100644 --- a/mac-cpp-source/utils/ctype.h +++ b/mac-cpp-source/utils/ctype.h @@ -1 +1,4 @@ -typedef Boolean bool; typedef unsigned short uint16_t; \ No newline at end of file +typedef Boolean bool; +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned long uint32_t; \ No newline at end of file