Fixed formatting inconsistencies, plus other minor improvements.
[cake.git] / rom / bootmenu / menu.c
blob484be4539e39f6b60b2d0092627bcf6c591026eb
1 /*
2 Copyright © 1995-2009, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Main bootmenu code
6 Lang: english
7 */
9 #define DEBUG 0
10 #include <aros/debug.h>
12 #include <proto/bootloader.h>
13 #include <proto/exec.h>
14 #include <proto/graphics.h>
15 #include <proto/intuition.h>
16 #include <devices/keyboard.h>
17 #include <devices/rawkeycodes.h>
18 #include <devices/timer.h>
19 #include <exec/memory.h>
20 #include <graphics/gfxbase.h>
21 #include <libraries/bootmenu.h>
22 #include <libraries/expansionbase.h>
23 #include <aros/bootloader.h>
24 #include <aros/symbolsets.h>
25 #include <string.h>
26 #include "devs_private.h"
28 #include "bootmenu_intern.h"
30 #include LC_LIBDEFS_FILE
32 /*****************
33 ** init_gfx() **
34 *****************/
36 static BOOL init_gfx(STRPTR gfxclassname, struct BootMenuBase *BootMenuBase)
38 BOOL success = FALSE;
39 D(bug("[BootMenu] init_gfx(hiddbase='%s')\n", gfxclassname));
41 /* Call private gfx.library call to init the HIDD.
42 Gfx library is responsible for closing the HIDD
43 library (although it will probably not be neccesary).
46 D(bug("[BootMenu] init_gfx: calling private LateGfxInit() ..\n"));
47 if (LateGfxInit(gfxclassname))
49 D(bug("[BootMenu] init_gfx: calling private LateGfxInit Succeeded\n"));
50 if (LateIntuiInit(NULL))
52 D(bug("[BootMenu] init_gfx: calling private LateIntuiInit Succeeded\n"));
53 success = TRUE;
55 else
57 D(bug("[BootMenu] init_gfx: calling private LateIntuiInit Failed!\n"));
60 else
62 D(bug("[BootMenu] init_gfx: calling private LateGfxInit Failed!\n"));
64 ReturnBool ("init_gfxhidd", success);
67 static BOOL init_device( STRPTR hiddclassname, STRPTR devicename, struct BootMenuBase *BootMenuBase)
69 BOOL success = FALSE;
70 struct MsgPort *mp = NULL;
72 D(bug("[BootMenu] init_device(classname='%s', devicename='%s')\n", hiddclassname, devicename));
74 if ((mp = CreateMsgPort()) != NULL)
76 struct IORequest *io = NULL;
77 if ((io = CreateIORequest(mp, sizeof ( struct IOStdReq))) != NULL)
79 if (0 == OpenDevice(devicename, 0, io, 0))
81 #define ioStd(x) ((struct IOStdReq *)x)
82 ioStd(io)->io_Command = CMD_HIDDINIT;
83 ioStd(io)->io_Data = hiddclassname;
84 ioStd(io)->io_Length = strlen(hiddclassname);
86 /* Let the device init the HIDD */
87 DoIO(io);
88 if (0 == io->io_Error)
90 success = TRUE;
92 CloseDevice(io);
94 DeleteIORequest(io);
96 DeleteMsgPort(mp);
98 ReturnBool("init_device", success);
101 static BOOL initHidds(struct BootConfig *bootcfg, struct BootMenuBase *BootMenuBase)
103 D(bug("[BootMenu] initHidds()\n"));
105 if ((OpenLibrary(bootcfg->defaultgfx.libname, 0)) != NULL)
107 if ((init_gfx(bootcfg->defaultgfx.hiddname, BootMenuBase)) == TRUE)
110 if (!bootcfg->defaultmouse.hiddname[0])
112 return TRUE;
115 if ((OpenLibrary(bootcfg->defaultmouse.libname, 0)) != NULL)
117 if ((init_device(bootcfg->defaultmouse.hiddname, "gameport.device", BootMenuBase)) == TRUE)
120 D(bug("[BootMenu] initHidds: Hidds initialised\n"));
122 return TRUE;
127 return FALSE;
130 static struct Gadget *createGadgets(struct BootMenuBase_intern *BootMenuBase)
132 #warning "TOD: This is very unclean! free-up resources if we fail!"
134 /* Create Option Gadgets */
135 BootMenuBase->bm_MainGadgets.bootopt = createButton(
136 180, 63, 280, 14,
137 NULL, "Boot Options...",
138 BUTTON_BOOT_OPTIONS, (struct BootMenuBase *)BootMenuBase);
139 if (BootMenuBase->bm_MainGadgets.bootopt == NULL)
140 return NULL;
142 BootMenuBase->bm_MainGadgets.displayopt = createButton(
143 180, 84, 280, 14,
144 BootMenuBase->bm_MainGadgets.bootopt->gadget, "Display Options...",
145 BUTTON_DISPLAY_OPTIONS, (struct BootMenuBase *)BootMenuBase);
146 if (BootMenuBase->bm_MainGadgets.displayopt == NULL)
147 return NULL;
149 BootMenuBase->bm_MainGadgets.expboarddiag = createButton(
150 180, 105, 280, 14,
151 BootMenuBase->bm_MainGadgets.displayopt->gadget, "Expansion Board Diagnostic...",
152 BUTTON_EXPBOARDDIAG, (struct BootMenuBase *)BootMenuBase);
153 if (BootMenuBase->bm_MainGadgets.expboarddiag == NULL)
154 return NULL;
156 /* Create BOOT Gadgets */
157 BootMenuBase->bm_MainGadgets.boot = createButton(
158 16, 190, 280, 14,
159 BootMenuBase->bm_MainGadgets.expboarddiag->gadget, "Boot",
160 BUTTON_BOOT, (struct BootMenuBase *)BootMenuBase);
161 if (BootMenuBase->bm_MainGadgets.boot == NULL)
162 return NULL;
164 BootMenuBase->bm_MainGadgets.bootnss = createButton(
165 344, 190, 280, 14,
166 BootMenuBase->bm_MainGadgets.boot->gadget, "Boot With No Startup-Sequence",
167 BUTTON_BOOT_WNSS, (struct BootMenuBase *)BootMenuBase);
168 if (BootMenuBase->bm_MainGadgets.bootnss == NULL)
169 return NULL;
171 return BootMenuBase->bm_MainGadgets.bootopt->gadget;
174 static void freeGadgets(struct BootMenuBase_intern *BootMenuBase)
176 if (BootMenuBase->bm_MainGadgets.boot != NULL)
177 freeButtonGadget(BootMenuBase->bm_MainGadgets.boot, (struct BootMenuBase *)BootMenuBase);
178 if (BootMenuBase->bm_MainGadgets.bootnss != NULL);
179 freeButtonGadget(BootMenuBase->bm_MainGadgets.bootnss, (struct BootMenuBase *)BootMenuBase);
180 if (BootMenuBase->bm_MainGadgets.bootopt != NULL)
181 freeButtonGadget(BootMenuBase->bm_MainGadgets.bootopt, (struct BootMenuBase *)BootMenuBase);
182 if (BootMenuBase->bm_MainGadgets.displayopt != NULL)
183 freeButtonGadget(BootMenuBase->bm_MainGadgets.displayopt, (struct BootMenuBase *)BootMenuBase);
184 if (BootMenuBase->bm_MainGadgets.expboarddiag != NULL)
185 freeButtonGadget(BootMenuBase->bm_MainGadgets.expboarddiag, (struct BootMenuBase *)BootMenuBase);
188 static void msgLoop(struct BootMenuBase_intern *BootMenuBase, struct Window *win, struct BootConfig *bcfg)
190 BOOL exit = FALSE;
191 struct IntuiMessage *msg;
192 struct Gadget *g;
194 D(bug("[BootMenu] msgLoop(BootMenuBase @ %p, Window @ %p, Cfg @ %p)\n", BootMenuBase, win, bcfg));
198 if (win->UserPort)
200 WaitPort(win->UserPort);
201 while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
203 if (msg->Class == IDCMP_GADGETUP)
205 g = msg->IAddress;
206 switch (g->GadgetID)
208 case BUTTON_BOOT:
209 ExpansionBase->Flags &= ~EBF_DOSFLAG;
210 exit = TRUE;
211 break;
212 case BUTTON_BOOT_WNSS:
213 ExpansionBase->Flags |= EBF_DOSFLAG;
214 exit = TRUE;
215 break;
218 ReplyMsg((struct Message *)msg);
221 else
223 bug("[BootMenu] msgLoop: Window lacks a userport!\n");
224 Wait(0);
226 } while (exit == FALSE);
227 while ((msg=(struct IntuiMessage *)GetMsg(win->UserPort)))
228 ReplyMsg(&msg->ExecMessage);
231 static UWORD pens[] = {~0};
233 struct NewScreen ns =
235 0, 0, 640, 256, 4, /* left, top, width, height, depth */
236 0, 1, /* DetailPen, BlockPen */
237 HIRES, /* ViewModes */
238 CUSTOMSCREEN, /* Type */
239 NULL, /* Font */
240 NULL, /* DefaultTitle */
241 NULL, /* Gadgets */
242 NULL, /* CustomBitMap */
245 static BOOL initScreen(struct BootMenuBase_intern *BootMenuBase, struct BootConfig *bcfg)
247 struct Gadget *first = NULL;
248 BOOL res = FALSE;
250 D(bug("[BootMenu] initScreen()\n"));
252 if ((BootMenuBase->bm_Screen = OpenScreen(&ns)) != NULL)
254 D(bug("[BootMenu] initScreen: Screen opened @ %p\n", BootMenuBase->bm_Screen));
255 if ((first = createGadgets(BootMenuBase)) != NULL)
257 struct NewWindow nw =
259 0, 0, /* Left, Top */
260 BootMenuBase->bm_Screen->Width, /* Width, Height */
261 BootMenuBase->bm_Screen->Height,
262 0, 1, /* DetailPen, BlockPen */
263 IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_VANILLAKEY | IDCMP_GADGETUP | IDCMP_GADGETDOWN, /* IDCMPFlags */
264 WFLG_SMART_REFRESH | WFLG_BORDERLESS, /* Flags */
265 first, /* FirstGadget */
266 NULL, /* CheckMark */
267 NULL, /* Title */
268 BootMenuBase->bm_Screen, /* Screen */
269 NULL, /* BitMap */
270 0, 0, /* MinWidth, MinHeight */
271 0, 0, /* MaxWidth, MaxHeight */
272 CUSTOMSCREEN, /* Type */
275 D(bug("[BootMenu] initScreen: Gadgets created @ %p\n", first));
277 if ((BootMenuBase->bm_Window = OpenWindow(&nw)) != NULL)
279 D(bug("[BootMenu] initScreen: Window opened @ %p\n", BootMenuBase->bm_Window));
280 D(bug("[BootMenu] initScreen: Window RastPort @ %p\n", BootMenuBase->bm_Window->RPort));
281 D(bug("[BootMenu] initScreen: Window UserPort @ %p\n", BootMenuBase->bm_Window->UserPort));
282 SetAPen(BootMenuBase->bm_Window->RPort, 2);
283 D(bug("[BootMenu] initScreen: SetAPen 2\n"));
284 Move(BootMenuBase->bm_Window->RPort, 215, 20);
285 D(bug("[BootMenu] initScreen: Move(d) to 215, 20\n"));
286 Text(BootMenuBase->bm_Window->RPort, "AROS Early Startup Control", 26);
287 D(bug("[BootMenu] initScreen: Early Startup text displayed\n"));
288 #if defined(USE_PALNTSC)
289 #warning "TODO: Check if we are using a PAL/NTSC display mode ..."
290 SetAPen(BootMenuBase->bm_Window->RPort, 1);
291 Move(BootMenuBase->bm_Window->RPort, 225, 40);
292 Text(BootMenuBase->bm_Window->RPort, "(press a key to toggle the display between PAL and NTSC)", 23);
293 #endif
294 msgLoop(BootMenuBase, BootMenuBase->bm_Window, bcfg);
295 res = TRUE;
297 else
298 Alert(AT_DeadEnd | AN_OpenWindow);
300 CloseWindow(BootMenuBase->bm_Window);
301 freeGadgets(BootMenuBase);
303 else
304 Alert(AT_DeadEnd | AN_BadGadget);
306 CloseScreen(BootMenuBase->bm_Screen);
308 else
309 Alert(AT_DeadEnd | AN_OpenScreen);
311 return res;
314 /* From keyboard.device/keyboard_intern.h */
315 #define KB_MAXKEYS 256
316 #define KB_MATRIXSIZE (KB_MAXKEYS/(sizeof(UBYTE)*8))
317 #define ioStd(x) ((struct IOStdReq *)x)
319 static BOOL buttonsPressed(struct BootMenuBase *BootMenuBase, struct DefaultHidd *kbd)
321 BOOL success = FALSE;
322 struct MsgPort *mp = NULL;
323 UBYTE matrix[KB_MATRIXSIZE];
325 if ((mp = CreateMsgPort()) != NULL)
327 struct IORequest *io = NULL;
328 if ((io = CreateIORequest(mp, sizeof ( struct IOStdReq))) != NULL)
330 if (0 == OpenDevice("keyboard.device", 0, io, 0))
332 D(bug("[BootMenu] buttonsPressed: Checking KBD_READMATRIX\n"));
333 ioStd(io)->io_Command = KBD_READMATRIX;
334 ioStd(io)->io_Data = matrix;
335 ioStd(io)->io_Length = sizeof(matrix);
336 DoIO(io);
337 if (0 == io->io_Error)
340 int i;
341 bug("[BootMenu] buttonsPressed: Matrix : ");
342 for (i = 0; i < ioStd(io)->io_Actual; i ++)
344 bug("%02x ", matrix[i]);
346 bug("\n");
348 if (matrix[RAWKEY_SPACE/8] & (1<<(RAWKEY_SPACE%8)))
350 D(bug("[BootMenu] SPACEBAR pressed\n"));
351 success = TRUE;
354 CloseDevice(io);
356 DeleteIORequest(io);
358 DeleteMsgPort(mp);
360 return success;
363 int bootmenu_Init(LIBBASETYPEPTR LIBBASE)
365 struct BootLoaderBase *BootLoaderBase = NULL;
366 struct DefaultHidd *kbd = &LIBBASE->bm_BootConfig.defaultkbd;
367 int bmi_RetVal = (int)FALSE;
368 D(bug("[BootMenu] bootmenu_Init()\n"));
370 LIBBASE->bm_Force = FALSE; /* Set FALSE here to be sure .. */
372 if ((ExpansionBase = OpenLibrary("expansion.library", 0)) != NULL)
374 if ((GfxBase = OpenLibrary("graphics.library", 37)) != NULL)
376 if ((IntuitionBase = OpenLibrary("intuition.library", 37)) != NULL)
378 BootLoaderBase = OpenResource("bootloader.resource");
379 InitBootConfig(&LIBBASE->bm_BootConfig, BootLoaderBase);
380 if (BootLoaderBase)
382 struct List *list = NULL;
383 struct Node *node = NULL;
385 if ((list = (struct List *)GetBootInfo(BL_Args)) != NULL)
387 ForeachNode(list,node)
389 if (0 == strcmp(node->ln_Name,"bootmenu"))
391 D(bug("[BootMenu] bootmenu_Init: Forced with bootloader argument\n"));
392 LIBBASE->bm_Force = TRUE;
398 if (!kbd->hiddname[0])
400 D(bug("[BootMenu] bootmenu_Init: This system uses no keyboard HIDD\n"));
401 bmi_RetVal = (int)TRUE;
403 else if (OpenLibrary(kbd->libname, 0) != NULL)
405 if (init_device(kbd->hiddname, "keyboard.device", LIBBASE))
407 bmi_RetVal = (int)TRUE;
413 /* check keyboard */
414 if ((bmi_RetVal) && (LIBBASE->bm_Force || buttonsPressed(LIBBASE, &LIBBASE->bm_BootConfig.defaultkbd)))
416 D(kprintf("[BootMenu] bootmenu_Init: Entering Boot Menu ...\n"));
417 /* init mouse + gfx */
418 if (initHidds(&LIBBASE->bm_BootConfig, LIBBASE))
420 D(bug("[BootMenu] bootmenu_Init: Hidds Initialised\n"));
421 initScreen(LIBBASE, &LIBBASE->bm_BootConfig);
423 else
425 D(bug("[BootMenu] bootmenu_Init: Hidds Failed to initialise!\n"));
428 else
430 D(bug("[BootMenu] bootmenu_Init: Menu not requested ..\n"));
432 return bmi_RetVal;
435 ADD2INITLIB(bootmenu_Init, 0)