AmendHub

Download:

vkoskiv

/

MacNTP

/

amendments

/

14

Show icon on startup and remove InitGraf trap

Earlier, I thought that I had to run the NTP querying code in a trap
instead of the main INIT invocation, but I now found that not to be
true. This simplifies main.c quite a bit.
I also fetched a copy of ShowInitIcon, fixed it up a bit, and now we
show the MacNTP icon on startup.
The icon has 3 variants: Pending, Success and Failure.
We initially show the pending variant, and then swap to one of the
other two depending on the result of the NTP query.

vkoskiv made amendment 14 7 months ago
--- MacNTP.π.r Thu Sep 7 20:07:34 2023 +++ MacNTP.π.r Fri Sep 8 20:41:01 2023 @@ -1,16 +1,35 @@ +data 'STR ' (128, "NTPSERVER", sysheap) { + $"0F74 696D 652E 676F 6F67 6C65 2E63 6F6D" /* .time.google.com */ +}; + data 'STR ' (129, "UTCOFFSETMINUTES", sysheap) { - $"0130" /* .0 */ + $"0331 3830" /* .180 */ }; -data 'STR ' (128, "NTPSERVER", sysheap) { - $"0F74 696D 652E 676F 6F67 6C65 2E63 6F6D" /* .time.google.com */ +data 'ICN#' (128, "NTPPENDING", sysheap) { + $"FFFF FFFF 8080 0001 8080 7C01 8881 8301" /* ....ÄÄ..ÄÄ|.àÅÉ. */ + $"9482 0081 9484 0041 9484 8041 9488 4421" /* îÇ.ÅîÑ.AîÑÄAîàD! */ + $"9488 2821 9488 1021 9488 0021 9488 0021" /* îà(!îà.!îà.!îà.! */ + $"9484 0041 BE84 0041 A282 0081 A281 8301" /* îÑ.AæÑ.A¢Ç.Å¢ÅÉ. */ + $"BE80 7C01 9480 2801 9480 0001 9480 0001" /* æÄ|.îÄ(.îÄ..îÄ.. */ + $"9480 0001 9480 2801 9480 7C01 9480 4401" /* îÄ..îÄ(.îÄ|.îÄD. */ + $"9480 4401 9480 7C01 9480 5401 94AF 93F5" /* îÄD.îÄ|.îÄT.îØì. */ + $"8880 2801 80AF C7F5 8080 0001 FFFF FFFF" /* àÄ(.ÄØ«.ÄÄ...... */ + $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ................ */ + $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ................ */ + $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ................ */ + $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ................ */ + $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ................ */ + $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ................ */ + $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ................ */ + $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ................ */ }; -data 'ICN#' (-4064) { +data 'ICN#' (-4064, preload) { $"FFFF FFFF 8080 0001 8080 7C01 8881 8301" /* ....ÄÄ..ÄÄ|.àÅÉ. */ - $"9482 1081 9484 1041 9484 1041 9488 1021" /* îÇ.ÅîÑ.AîÑ.Aîà.! */ - $"9488 1021 9488 1021 9488 0821 9489 C421" /* îà.!îà.!îà.!îâƒ! */ - $"9485 8241 BE85 4441 A282 3881 A281 8301" /* îÖÇAæÖDA¢Ç8Å¢ÅÉ. */ + $"9482 0081 9484 0041 9484 8041 9488 4421" /* îÇ.ÅîÑ.AîÑÄAîàD! */ + $"9488 2821 9488 1021 9489 C021 9489 8221" /* îà(!îà.!îâ¿!îâÇ! */ + $"9485 4441 BE84 3841 A282 0081 A281 8301" /* îÖDAæÑ8A¢Ç.Å¢ÅÉ. */ $"BE80 7C01 9480 2801 9480 2801 9480 2801" /* æÄ|.îÄ(.îÄ(.îÄ(. */ $"9480 2801 9480 2801 9480 7C01 9480 4401" /* îÄ(.îÄ(.îÄ|.îÄD. */ $"9480 4401 9480 7C01 9480 5401 94AF 93F5" /* îÄD.îÄ|.îÄT.îØì. */ @@ -25,16 +44,23 @@ data 'ICN#' (-4064) { $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ................ */ }; -data 'PICT' (-4041, purgeable) { - $"0085 00B7 00DF 00C9 00F0 1101 A030 3901" /* .Ö.∑...…....†09. */ - $"000A 00B7 00DF 00C9 00F0 3200 C800 DF00" /* ...∑...…..2.»... */ - $"C900 F090 0004 00B7 00D8 00C8 00F0 00B7" /* …..ê...∑.ÿ.»...∑ */ - $"00DF 00C8 00F0 00B7 00DF 00C8 00F0 0000" /* ...»...∑...».... */ - $"0007 C000 0018 3000 0021 0800 0041 0400" /* ..¿...0..!...A.. */ - $"0081 0200 0081 0200 0101 0100 0101 0100" /* .Å...Å.......... */ - $"0101 0100 0100 8140 0100 4100 3880 22DC" /* ......Å@..A.8Ä". */ - $"A480 1252 A440 0452 2420 0852 2418 3052" /* §Ä.R§@.R$ .R$.0R */ - $"0007 C000 FF" /* ..¿.. */ +data 'ICN#' (130, "NTPFAILED", sysheap) { + $"FFFF FFFF 8080 0001 8080 7C01 8881 8301" /* ....ÄÄ..ÄÄ|.àÅÉ. */ + $"9482 0081 9484 0041 9484 8241 9488 4421" /* îÇ.ÅîÑ.AîÑÇAîàD! */ + $"9488 2821 9488 1021 9488 2821 9488 4421" /* îà(!îà.!îà(!îàD! */ + $"9484 8241 BE84 0041 A282 0081 A281 8301" /* îÑÇAæÑ.A¢Ç.Å¢ÅÉ. */ + $"BE80 7C01 9480 2801 9480 2801 9480 2801" /* æÄ|.îÄ(.îÄ(.îÄ(. */ + $"9480 2801 9480 2801 9480 7C01 9480 4401" /* îÄ(.îÄ(.îÄ|.îÄD. */ + $"9480 4401 9480 7C01 9480 5401 94AF 93F5" /* îÄD.îÄ|.îÄT.îØì. */ + $"8880 2801 80AF C7F5 8080 0001 FFFF FFFF" /* àÄ(.ÄØ«.ÄÄ...... */ + $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ................ */ + $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ................ */ + $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ................ */ + $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ................ */ + $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ................ */ + $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ................ */ + $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ................ */ + $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ................ */ }; data 'mach' (-4064, "init", purgeable) { @@ -43,5 +69,28 @@ data 'mach' (-4064, "init", purgeable) { data 'sysz' (0) { $"0002 7100" /* ..q. */ +}; + +data 'BNDL' (-4064, "init", purgeable) { + $"564B 4F53 0000 0001 4652 4546 0001 0000" /* VKOS....FREF.... */ + $"0080 0001 0081 4943 4E23 0001 0000 F020" /* .Ä...ÅICN#..... */ + $"0001 F020" /* ... */ +}; + +data 'VKOS' (0, "Owner resource") { + $"1956 616C 7474 6572 6920 4B6F 736B 6976" /* .Valtteri Koskiv */ + $"756F 7269 2C20 3230 3233" /* uori, 2023 */ +}; + +data 'FREF' (-4064, purgeable) { + $"6364 6576 0000 00" /* cdev... */ +}; + +data 'FREF' (128) { + $"6364 6576 0000 00" /* cdev... */ +}; + +data 'FREF' (129) { + $"494E 4954 0001 00" /* INIT... */ }; --- main.c Fri Sep 8 00:03:01 2023 +++ main.c Fri Sep 8 20:35:25 2023 @@ -14,36 +14,38 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +/* +TODO: +- Remove dump_error and save an error to rsrc STR instead +- Implement cdev +- Display possible errors in cdev +*/ + #include <SetUpA4.h> -#include <OSUtils.h> #include "MacNTP.h" -#include "tcp.h" -#include "prefs.h" +#include "ShowInitIcon.h" // This enables DebugStr() printouts to aid development. // This also disables the system time check, so it tries NTP // on every boot. //#define DEBUGGING -pascal void NewInitGraf(Ptr globalPtr); void dump_error(enum MacNTPError error, OSErr oserror); int TryMacNTP(void); -void GetOurFilename(Str255 name); -#define InitGrafTrapnum 0xA86E -#define NTP_URL_STR_ID 128 -#define UTC_OFFSET_STR_ID 129 +#define SECONDS_TO_02_09_1996 2924510400ul +#define MACNTP_ICN_ID_PENDING 128 +#define MACNTP_ICN_ID_SUCCESS -4064 // Also used for cdev +#define MACNTP_ICN_ID_FAILURE 130 -long g_old_initgraf_address; -int g_ntp_success; -int g_ntp_error; Handle g_mtcp_init_handle; -// NTP URL and UTC offset strings -// These are loaded into sys heap on boot +#define NTP_URL_STR_ID 128 StringHandle g_url; -StringHandle g_utc; +#define UTC_OFFSET_STR_ID 129 +StringHandle g_utc; // Offset in minutes, + #ifdef DEBUGGING void dump_error(enum MacNTPError error, OSErr oserror) { Str255 numstr; @@ -132,44 +134,17 @@ int TryMacNTP(void) { return 0; } -#define SECONDS_TO_02_09_1996 2924510400ul - -pascal void NewInitGraf(Ptr globalPtr) { - unsigned long systime; - SetUpA4(); - if (g_ntp_success || g_ntp_error) goto skip; // Pretend we weren't here! -#ifndef DEBUGGING - // We only try to update the clock if we're well into the 20th century - ReadDateTime((unsigned long *)&systime); - if (systime > SECONDS_TO_02_09_1996) { - g_ntp_success = 1; - goto skip; - } -#endif - - if (!TryMacNTP()) { - g_ntp_success = 1; - } else { - g_ntp_error = 1; - } - -skip: - CallPascal(globalPtr, g_old_initgraf_address); - RestoreA4(); -} - void main() { - Ptr mtcp_init_ptr; + Ptr our_init_ptr; + unsigned long systime; asm { - move.L A0, mtcp_init_ptr; + move.L A0, our_init_ptr; } RememberA0(); SetUpA4(); - g_mtcp_init_handle = RecoverHandle(mtcp_init_ptr); + g_mtcp_init_handle = RecoverHandle(our_init_ptr); DetachResource(g_mtcp_init_handle); - //TODO: Load STR resources, movhhi and lock. Maybe Unlock+dispos in - // trap ? g_url = GetString(NTP_URL_STR_ID); g_utc = GetString(UTC_OFFSET_STR_ID); if (!g_url || !g_utc) { @@ -184,12 +159,28 @@ void main() { MoveHHi(g_utc); HLock(g_utc); - g_old_initgraf_address = NGetTrapAddress(InitGrafTrapnum, ToolTrap); - NSetTrapAddress((long)&NewInitGraf, InitGrafTrapnum, ToolTrap); + ShowInitIcon(MACNTP_ICN_ID_PENDING, false); - g_ntp_success = 0; - g_ntp_error = 0; +#ifndef DEBUGGING + // We only try to update the clock if we're well into the 20th century + ReadDateTime((unsigned long *)&systime); + if (systime > SECONDS_TO_02_09_1996) { + ShowInitIcon(MACNTP_ICN_ID_SUCCESS, true); + goto skip; + } else { + ShowInitIcon(MACNTP_ICN_ID_PENDING, false); + } +#else + ShowInitIcon(MACNTP_ICN_ID_PENDING, false); +#endif + if (!TryMacNTP()) { + ShowInitIcon(MACNTP_ICN_ID_SUCCESS, true); + } else { + ShowInitIcon(MACNTP_ICN_ID_FAILURE, true); + } + +skip: error: RestoreA4(); } --- ShowInitIcon.c Fri Sep 8 20:25:45 2023 +++ ShowInitIcon.c Fri Sep 8 20:25:45 2023 @@ -0,0 +1,168 @@ +// ShowInitIcon - version 1.0.1, May 30th, 1995 +// This code is intended to let INIT writers easily display an icon at startup time. +// View in Geneva 9pt, 4-space tabs + +// Written by: Peter N Lewis <peter@mail.peter.com.au>, Jim Walker <JWWalker@aol.com> +// and François Pottier <pottier@dmi.ens.fr>, with thanks to previous ShowINIT authors. +// Send comments and bug reports to François Pottier. + +// Hacked a bit by Valtteri Koskivuori on 08.09.2023: +// * Removed Sys7/Color QD code +// * Added missing QDGlobals struct +// * Now compiles in Think C 5.0.1 under System 6 + + +// This version features: +// - Short and readable code. +// - Correctly wraps around when more than one row of icons has been displayed. +// - works with System 6 +// - Built with Universal Headers & CodeWarrior. Should work with other headers/compilers. + +#include <Memory.h> +#include <Resources.h> +#include <Icons.h> +#include <OSUtils.h> +#include <Quickdraw.h> +#include "ShowInitIcon.h" + +// You should set SystemSixOrLater in your headers to avoid including glue for SysEnvirons. + +// --------------------------------------------------------------------------------------------------------------------- +// Set this flag to 1 if you want to compile this file into a stand-alone resource (see note below). +// Set it to 0 if you want to include this source file into your INIT project. + +#if 0 +#define ShowInitIcon main +#endif + +// --------------------------------------------------------------------------------------------------------------------- +// The ShowINIT mechanism works by having each INIT read/write data from these globals. +// The MPW C compiler doesn't accept variables declared at an absolute address, so I use these macros instead. +// Only one macro is defined per variable; there is no need to define a Set and a Get accessor like in <LowMem.h>. + +#define LMVCoord (* (short*) 0x92A) +#define LMVCheckSum (* (short*) 0x928) +#define LMHCoord (* (short*) 0x92C) +#define LMHCheckSum (* (short*) 0x92E) + +// --------------------------------------------------------------------------------------------------------------------- +// Prototypes for the subroutines. The main routine comes first; this is necessary to make THINK C's "Custom Header" option work. + +static unsigned short CheckSum (unsigned short x); +static void ComputeIconRect (Rect* iconRect, Rect* screenBounds); +static void AdvanceIconPosition (Rect* iconRect); +static void DrawBWIcon (short iconID, Rect *iconRect); + +// --------------------------------------------------------------------------------------------------------------------- +// Main routine. + +// vkoskiv 08.09.2023: +// This file is probably too new for our Sys6 environment, since Think C 5 +// doesn't know about QDGlobals. Luckily they document it, so I'll just patch +// in a suitable struct. + +// The offsets from A5 are negative, so we flip the order they appear in the doc +typedef struct { + char privates[76]; // No idea what this is, spotted it elsewhere + long randSeed; + BitMap screenBits; + Cursor arrow; + Pattern dkGray; + Pattern ltGray; + Pattern gray; + Pattern black; + Pattern white; + GrafPtr thePort; +} QDGlobals; + +typedef struct { + QDGlobals qd; // Storage for the QuickDraw globals + long qdGlobalsPtr; // A5 points to this place; it will contain a pointer to qd +} QDStorage; + +pascal void ShowInitIcon (short iconFamilyID, Boolean advance) +{ + long oldA5; // Original value of register A5 + QDStorage qds; // Fake QD globals + CGrafPort colorPort; + GrafPort bwPort; + Rect destRect; + + oldA5 = SetA5((long) &qds.qdGlobalsPtr); // Tell A5 to point to the end of the fake QD Globals + InitGraf(&qds.qd.thePort); // Initialize the fake QD Globals + + ComputeIconRect(&destRect, &qds.qd.screenBits.bounds); // Compute where the icon should be drawn + + OpenPort(&bwPort); + DrawBWIcon(iconFamilyID, &destRect); + ClosePort(&bwPort); + + if (advance) AdvanceIconPosition (&destRect); + + SetA5(oldA5); // Restore A5 to its previous value +} + +// --------------------------------------------------------------------------------------------------------------------- +// A checksum is used to make sure that the data in there was left by another ShowINIT-aware INIT. + +static unsigned short CheckSum (unsigned short x) +{ + return ((x << 1) | (x >> 15)) ^ 0x1021; +} + +// --------------------------------------------------------------------------------------------------------------------- +// ComputeIconRect computes where the icon should be displayed. + +static void ComputeIconRect (Rect* iconRect, Rect* screenBounds) +{ + if (CheckSum(LMHCoord) != LMHCheckSum) // If we are first, we need to initialize the shared data. + LMHCoord = 8; + if (CheckSum(LMVCoord) != LMVCheckSum) + LMVCoord = screenBounds->bottom - 40; + + if (LMHCoord + 34 > screenBounds->right) { // Check whether we must wrap + iconRect->left = 8; + iconRect->top = LMVCoord - 40; + } + else { + iconRect->left = LMHCoord; + iconRect->top = LMVCoord; + } + iconRect->right = iconRect->left + 32; + iconRect->bottom = iconRect->top + 32; +} + +// AdvanceIconPosition updates the shared global variables so that the next extension will draw its icon beside ours. + +static void AdvanceIconPosition (Rect* iconRect) +{ + LMHCoord = iconRect->left + 40; // Update the shared data + LMVCoord = iconRect->top; + LMHCheckSum = CheckSum(LMHCoord); + LMVCheckSum = CheckSum(LMVCoord); +} + +// DrawBWIcon draws the 'ICN#' member of the icon family. It works under System 6. + +static void DrawBWIcon (short iconID, Rect *iconRect) +{ + Handle icon; + BitMap source, destination; + GrafPtr port; + + icon = Get1Resource('ICN#', iconID); + if (icon != NULL) { + HLock(icon); + // Prepare the source and destination bitmaps. + source.baseAddr = *icon + 128; // Mask address. + source.rowBytes = 4; + SetRect(&source.bounds, 0, 0, 32, 32); + GetPort(&port); + destination = port->portBits; + // Transfer the mask. + CopyBits(&source, &destination, &source.bounds, iconRect, srcBic, nil); + // Then the icon. + source.baseAddr = *icon; + CopyBits(&source, &destination, &source.bounds, iconRect, srcOr, nil); + } +} --- ShowInitIcon.h Fri Sep 8 17:34:53 2023 +++ ShowInitIcon.h Fri Sep 8 17:34:53 2023 @@ -0,0 +1,13 @@ +#ifndef __ShowInitIcon__ +#define __ShowInitIcon__ + +#include <Types.h> + +// Usage: pass the ID of your icon family (ICN#/icl4/icl8) to have it drawn in the right spot. +// If 'advance' is true, the next INIT icon will be drawn to the right of your icon. If it is false, the next INIT icon will overwrite +// yours. You can use it to create animation effects by calling ShowInitIcon several times with 'advance' set to false. + +pascal void ShowInitIcon (short iconFamilyID, Boolean advance); + +#endif /* __ShowInitIcon__ */ +