commit 3c6cc29c52c42f20bbbe139ed1381b2f9b6285ec Author: John Bintz Date: Sun Oct 2 16:59:06 2022 -0400 hacking away at this diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5761abc --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.o diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..335111b --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +main: *.c + vamos -c ../.vamosc sc main.c LINK diff --git a/main b/main new file mode 100755 index 0000000..df9ca73 Binary files /dev/null and b/main differ diff --git a/main.c b/main.c new file mode 100644 index 0000000..042edab --- /dev/null +++ b/main.c @@ -0,0 +1,423 @@ +#include + +// this is the manual for the original intuition stuff. +// not much here is different: https://ia801905.us.archive.org/33/items/Amiga_Intuition_Reference_Manaual_1985_Adn-Wesley_Publishing_Company/Amiga_Intuition_Reference_Manaual_1985_Addison-Wesley_Publishing_Company.pdf +#include +#include +#include +#include + +#include +#include + +// gadtools gives a proper set of components for building UIs. +// http://amigadev.elowar.com/read/ADCD_2.1/Libraries_Manual_guide/node0278.html +#include +#include + +#define WINDOW_WIDTH (240) +#define WINDOW_HEIGHT (100) +#define WINDOW_TITLE "Topaz Timer" + +#define WINDOW_CHROME_WIDTH (4) + +struct NewWindow winlayout = { + 20, 20, // x, y + WINDOW_WIDTH, WINDOW_HEIGHT, // w, h + 0, 1, // detailpen, blockpen, + // you have to add the different gadget types you're looking for + // http://amigadev.elowar.com/read/ADCD_2.1/Includes_and_Autodocs_2._guide/node0106.html + IDCMP_CLOSEWINDOW | BUTTONIDCMP | SLIDERIDCMP, // IDCMP flags + WFLG_SMART_REFRESH | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | WFLG_ACTIVATE, // window flag from Window struct + NULL, // FirstGadget + NULL, // menu checkmark + WINDOW_TITLE, // title + NULL, // default screen + NULL, // bitmap + WINDOW_WIDTH, WINDOW_HEIGHT, // min size + WINDOW_WIDTH, WINDOW_HEIGHT, // max size, + WBENCHSCREEN // screen where you want the window to open +}; + +struct TextAttr Topaz80 = { "topaz.font", 8, 0, 0 }; + +// There's no native 16 pixel Topaz font so we'll use +// diskfont.library to make one. +struct TextAttr Topaz160 = { "topaz.font", 16, 0, 0 }; + +#define START_STOP_BUTTON_ID 0 +#define RESET_BUTTON_ID 1 +#define HOURS_SLIDER_ID 2 +#define MINUTES_SLIDER_ID 3 +#define SECONDS_SLIDER_ID 5 + +#define TIMER_COUNTDOWN_COUNT 3 + +struct Window *window; +struct TextFont *topaz80Font; +struct TextFont *topaz160Font; +struct Screen *screen; +void *visualInfo; + +struct Gadget *timerGadget; + +unsigned int uiHours = 0; +unsigned int uiMinutes = 12; +unsigned int uiSeconds = 0; + +unsigned int activeHours; +unsigned int activeMinutes; +unsigned int activeSeconds; + +char timerText[9]; + +BOOL timerIsRunning; + +struct Device *TimerBase; +static struct IORequest timereq; + +/** + * Initialize system stuff. + */ +int setup() { + // http://amigadev.elowar.com/read/ADCD_2.1/Includes_and_Autodocs_3._guide/node0308.html + // make sure the font exists on the computer + if (NULL == (topaz80Font = OpenFont(&Topaz80))) { + return 0; + } + + if (NULL == (topaz160Font = OpenDiskFont(&Topaz160))) { + return 0; + } + + if (NULL == (screen = LockPubScreen(NULL))) { + return 0; + } + + if (NULL == (visualInfo = GetVisualInfo(screen, TAG_END))) { + return 0; + } + + if (0 != (OpenDevice("timer.device", 0, &timereq, 0))) { + return 0; + } + + TimerBase = timereq.io_Device; + + activeHours = uiHours; + activeMinutes = uiMinutes; + activeSeconds = uiSeconds; + + return 1; +} + +/** + * Tear down system stuff. + */ +void teardown() { + if (visualInfo) FreeVisualInfo(visualInfo); + if (screen) UnlockPubScreen(NULL, screen); + if (topaz80Font) CloseFont(topaz80Font); + if (topaz160Font) CloseFont(topaz160Font); + if (timereq.io_Device) CloseDevice(&timereq); +} + +struct Gadget *buildUI() { + struct NewGadget ng; + struct Gadget *currentGadget; + struct Gadget *glist; + + currentGadget = CreateContext(&glist); + + ng.ng_LeftEdge = WINDOW_CHROME_WIDTH; + // TODO: constantize these + ng.ng_TopEdge = 11; + ng.ng_Height = 12; + + ng.ng_Width = 0; + ng.ng_GadgetText = NULL; + ng.ng_TextAttr = &Topaz80; + ng.ng_VisualInfo = visualInfo; + + // TODO: use constants to indicate which gadget is which + ng.ng_GadgetID = NULL; + ng.ng_Flags = PLACETEXT_IN; + + // Timer display + ng.ng_Width = WINDOW_WIDTH - WINDOW_CHROME_WIDTH * 2; + ng.ng_TextAttr = &Topaz160; + ng.ng_Height = 20; + + timerGadget = currentGadget = CreateGadget( + TEXT_KIND, + currentGadget, + &ng, + GTTX_Text, "", + GTTX_Justification, GTJ_CENTER, + GTTX_Border, TRUE, + TAG_END + ); + + ng.ng_TextAttr = &Topaz80; + ng.ng_Height = 12; + + ng.ng_Width = (WINDOW_WIDTH - WINDOW_CHROME_WIDTH * 2) / 2; + ng.ng_TopEdge += 18; + if (timerIsRunning) { + ng.ng_GadgetText = "_Stop"; + } else { + ng.ng_GadgetText = "_Start"; + } + + ng.ng_GadgetID = START_STOP_BUTTON_ID; + + currentGadget = CreateGadget( + BUTTON_KIND, + currentGadget, + &ng, + GT_Underscore, '_', + TAG_END + ); + + ng.ng_LeftEdge += (WINDOW_WIDTH - WINDOW_CHROME_WIDTH * 2) / 2; + ng.ng_GadgetText = "_Reset"; + ng.ng_GadgetID = RESET_BUTTON_ID; + + currentGadget = CreateGadget( + BUTTON_KIND, + currentGadget, + &ng, + GT_Underscore, '_', + GA_Disabled, timerIsRunning, + TAG_END + ); + + ng.ng_LeftEdge = 85; + ng.ng_Width = (WINDOW_WIDTH - WINDOW_CHROME_WIDTH * 2) - 85 + 4; + ng.ng_TopEdge += 12; + ng.ng_GadgetText = "Hours: "; + ng.ng_Flags = PLACETEXT_LEFT; + ng.ng_GadgetID = HOURS_SLIDER_ID; + + currentGadget = CreateGadget( + SLIDER_KIND, + currentGadget, + &ng, + GT_Underscore, '_', + GTSL_Min, 0, + GTSL_Max, 23, + GTSL_Level, uiHours, + GTSL_MaxLevelLen, 2, + GTSL_LevelFormat, "%2ld", + GA_Disabled, timerIsRunning, + TAG_END + ); + + ng.ng_TopEdge += 12; + ng.ng_GadgetText = "Mins: "; + ng.ng_GadgetID = MINUTES_SLIDER_ID; + + currentGadget = CreateGadget( + SLIDER_KIND, + currentGadget, + &ng, + GT_Underscore, '_', + GTSL_Min, 0, + GTSL_Max, 59, + GTSL_Level, uiMinutes, + GTSL_MaxLevelLen, 2, + GTSL_LevelFormat, "%2ld", + GA_Disabled, timerIsRunning, + TAG_END + ); + + ng.ng_TopEdge += 12; + ng.ng_GadgetText = "Secs: "; + ng.ng_GadgetID = SECONDS_SLIDER_ID; + + currentGadget = CreateGadget( + SLIDER_KIND, + currentGadget, + &ng, + GT_Underscore, '_', + GTSL_Min, 0, + GTSL_Max, 59, + GTSL_Level, uiSeconds, + GTSL_MaxLevelLen, 2, + GTSL_LevelFormat, "%2ld", + GA_Disabled, timerIsRunning, + TAG_END + ); + + return glist; +} + +void setTimerText() { + // TODO: don't rerender if the time hasn't changed + sprintf(timerText, "%02d:%02d:%02d", activeHours, activeMinutes, activeSeconds); + GT_SetGadgetAttrs( + timerGadget, + window, + NULL, + GTTX_Text, &timerText, + TAG_DONE + ); +} + +int main() { + struct Gadget *gad; + + BOOL terminated = FALSE; + BOOL rerenderTimer = FALSE; + + struct IntuiMessage *iMessage; + struct Gadget *targetGadget; + struct timeval currentSystemTime; + + unsigned int timerRerenderCountdown = 0; + + // timeval tv_secs is ULONG and that will let us have accurate + // time counting via timer.device. + ULONG timerStartTime, timerDistance, timerBuild; + + timerIsRunning = FALSE; + + if (0 == setup()) { + teardown(); + return 1; + } + + GetSysTime(¤tSystemTime); + timerStartTime = currentSystemTime.tv_secs; + + window = OpenWindow(&winlayout); + + gad = buildUI(); + + // use -1 for working with all gadgets + AddGList(window, gad, -1, -1, NULL); + RefreshGList(gad, window, NULL, -1); + GT_RefreshWindow(window, NULL); + + setTimerText(); + + // what the fuck, you have to set the labels afterwards? + // you know what, it's better if it's explicit rather than the + // pointer shit it was trying to do before. + //GT_SetGadgetAttrs(one, window, NULL, GTTX_Text, "wow", TAG_DONE); + + // after doing anything with gadgets, you need to refresh them + //RefreshGList(gad, window, NULL, 3); + + // you son of a bitch, this is what you need + printf("sig signal %d\n", window->UserPort->mp_SigBit); + while (!terminated) { + // what is a userport on a window + // http://amigadev.elowar.com/read/ADCD_2.1/Libraries_Manual_guide/node02EB.html + // http://www.amigadev.elowar.com/read/ADCD_2.1/Includes_and_Autodocs_2._guide/node038A.html + //WaitPort(window->UserPort); + // but we need a timer + + // this shoud be responsive enoug + Delay(4); + + if (timerIsRunning) { + timerRerenderCountdown += 1; + if (timerRerenderCountdown > TIMER_COUNTDOWN_COUNT) { + timerRerenderCountdown = 0; + + GetSysTime(¤tSystemTime); + + timerDistance = currentSystemTime.tv_secs - timerStartTime; + + timerBuild = (uiHours * 3600 + uiMinutes * 60 + uiSeconds) - timerDistance; + + activeHours = timerBuild / 3600; + activeMinutes = timerBuild / 60 % 60; + activeSeconds = timerBuild % 60; + + setTimerText(); + } + } + + while ((!terminated) && (iMessage = GT_GetIMsg(window->UserPort))) { + switch (iMessage->Class) { + case IDCMP_GADGETUP: + targetGadget = (struct Gadget *)iMessage->IAddress; + + switch (targetGadget->GadgetID) { + case START_STOP_BUTTON_ID: + timerIsRunning = !timerIsRunning; + + if (timerIsRunning) { + GetSysTime(¤tSystemTime); + + timerStartTime = currentSystemTime.tv_secs; + timerRerenderCountdown = 0; + rerenderTimer = TRUE; + } + + RemoveGList(window, gad, -1); + FreeGadgets(gad); + + gad = buildUI(); + AddGList(window, gad, -1, -1, NULL); + RefreshGList(gad, window, NULL, -1); + GT_RefreshWindow(window, NULL); + + break; + case RESET_BUTTON_ID: + rerenderTimer = TRUE; + activeHours = uiHours; + activeMinutes = uiMinutes; + activeSeconds = uiSeconds; + break; + } + + break; + case IDCMP_MOUSEMOVE: + targetGadget = (struct Gadget *)iMessage->IAddress; + + switch (targetGadget->GadgetID) { + case HOURS_SLIDER_ID: + activeHours = uiHours = iMessage->Code; + rerenderTimer = TRUE; + break; + case MINUTES_SLIDER_ID: + activeMinutes = uiMinutes = iMessage->Code; + rerenderTimer = TRUE; + break; + case SECONDS_SLIDER_ID: + activeSeconds = uiSeconds = iMessage->Code; + rerenderTimer = TRUE; + break; + } + break; + + case IDCMP_CLOSEWINDOW: + terminated = TRUE; + break; + case IDCMP_REFRESHWINDOW: + GT_BeginRefresh(window); + GT_EndRefresh(window, TRUE); + break; + } + + if (rerenderTimer) { + setTimerText(); + rerenderTimer = FALSE; + } + } + } + + RemoveGList(window, gad, -1); + FreeGadgets(gad); + + if (window) { + CloseWindow(window); + } + + teardown(); + + return 0; +} diff --git a/main.lnk b/main.lnk new file mode 100644 index 0000000..7468083 --- /dev/null +++ b/main.lnk @@ -0,0 +1,4 @@ +FROM LIB:c.o "main.o" +TO "main" +LIB LIB:sc.lib LIB:amiga.lib +