11/*
2- * main.c -- Entry point, backend selection, main loop.
2+ * main.c -- Entry point and main loop.
33 *
44 * Apollo 11 Command Module Guidance Computer
55 * Colossus 2A / Comanche 055
66 *
7- * Presents a menu to select the display backend (console, Win32
8- * GDI, or HTTP/SSE web), initializes all AGC subsystems, and runs
9- * the 100 Hz main loop: timer tick, job dispatch, display refresh,
10- * input poll.
11- *
127 * Comanche055 (Apollo 11 CM) ANSI C89 port.
138 */
149
15- #ifdef _WIN32
16- #ifndef _CRT_SECURE_NO_WARNINGS
17- #define _CRT_SECURE_NO_WARNINGS
18- #endif
19- #endif
20-
2110#include <stdio.h>
22- #include <stdlib.h>
11+ #include "menu.h"
2312#include "agc_cpu.h"
2413#include "executive.h"
25- #include "waitlist.h"
2614#include "timer.h"
27- #include "dsky.h"
28- #include "pinball.h"
2915#include "service.h"
30- #include "programs.h"
3116#include "navigation.h"
32- #include "terminal.h"
33- #ifdef _WIN32
34- #define WIN32_LEAN_AND_MEAN
35- #include <windows.h>
36- #include "dsky_gui.h"
37- #include "dsky_web.h"
38- #endif
39-
40- /* ----------------------------------------------------------------
41- * Backend selection menu
42- * ---------------------------------------------------------------- */
43-
44- typedef struct {
45- const char * label ;
46- dsky_backend_t * backend ;
47- } backend_option_t ;
48-
49- #define MENU_KEY_NONE 0
50- #define MENU_KEY_UP 1
51- #define MENU_KEY_DOWN 2
52- #define MENU_KEY_ENTER 3
53- #define MENU_KEY_SELECT 4
54-
55- static int menu_read_key (int * selected_index )
56- {
57- int ch ;
58- int next ;
59- #ifndef _WIN32
60- int third ;
61- #endif
62- * selected_index = -1 ;
63-
64- if (!hal_kbhit ())
65- return MENU_KEY_NONE ;
66-
67- ch = hal_getch ();
68- if (ch < 0 )
69- return MENU_KEY_NONE ;
70-
71- if (ch == '\r' || ch == '\n' )
72- return MENU_KEY_ENTER ;
73- if (ch >= '1' && ch <= '9' ) {
74- * selected_index = ch - '1' ;
75- return MENU_KEY_SELECT ;
76- }
77-
78- #ifdef _WIN32
79- if (ch == 0 || ch == 224 ) {
80- next = hal_getch ();
81- if (next == 72 ) return MENU_KEY_UP ;
82- if (next == 80 ) return MENU_KEY_DOWN ;
83- }
84- #else
85- if (ch == 27 ) {
86- next = hal_getch ();
87- if (next != '[' ) return MENU_KEY_NONE ;
88- third = hal_getch ();
89- if (third == 'A' ) return MENU_KEY_UP ;
90- if (third == 'B' ) return MENU_KEY_DOWN ;
91- }
92- #endif
93-
94- return MENU_KEY_NONE ;
95- }
96-
97- static void menu_render (const backend_option_t * options , int count ,
98- int selected )
99- {
100- int i ;
101- static int prev_selected = -1 ;
102- static int first_render = 1 ;
103- char line_buffer [256 ];
104-
105- if (first_render ) {
106- term_init ();
107-
108- term_set_cursor (1 , 0 );
109- printf ("===========================================" );
110- term_set_cursor (2 , 2 );
111- printf ("COMANCHE 055 -- Colossus 2A" );
112- term_set_cursor (3 , 2 );
113- printf ("Apollo 11 CM Guidance Computer" );
114- term_set_cursor (4 , 2 );
115- printf ("ANSI C89 Port" );
116- term_set_cursor (5 , 0 );
117- printf ("===========================================" );
118-
119- sprintf (line_buffer ,
120- "Select display mode (Up/Down + Enter, or 1-%d):" ,
121- count );
122- term_set_cursor (7 , 0 );
123- printf ("%s" , line_buffer );
124-
125- for (i = 0 ; i < count ; i ++ ) {
126- sprintf (line_buffer , "%s [%d] %s" ,
127- (i == selected ) ? ">" : " " , i + 1 ,
128- options [i ].label );
129- term_set_cursor (9 + i , 0 );
130- printf ("%s" , line_buffer );
131- }
132-
133- fflush (stdout );
134- first_render = 0 ;
135- prev_selected = selected ;
136- } else if (selected != prev_selected ) {
137- int menu_start_line = 9 ;
138-
139- sprintf (line_buffer , " [%d] %s" ,
140- prev_selected + 1 , options [prev_selected ].label );
141- term_set_cursor (menu_start_line + prev_selected , 0 );
142- printf ("%s" , line_buffer );
143-
144- sprintf (line_buffer , "> [%d] %s" ,
145- selected + 1 , options [selected ].label );
146- term_set_cursor (menu_start_line + selected , 0 );
147- printf ("%s" , line_buffer );
148-
149- fflush (stdout );
150- prev_selected = selected ;
151- }
152- }
153-
154- static dsky_backend_t * select_backend_interactive (void )
155- {
156- backend_option_t options [3 ];
157- int count ;
158- int selected ;
159- int key ;
160- int direct_index ;
161- int needs_render ;
162-
163- #ifdef _WIN32
164- options [0 ].label = "Console (ANSI terminal)" ;
165- options [0 ].backend = & dsky_console_backend ;
166- options [1 ].label = "Graphical (Win32 GDI)" ;
167- options [1 ].backend = & dsky_gui_backend ;
168- options [2 ].label = "Web (HTTP/SSE)" ;
169- options [2 ].backend = & dsky_web_backend ;
170- count = 3 ;
171- #else
172- options [0 ].label = "Console (ANSI terminal)" ;
173- options [0 ].backend = & dsky_console_backend ;
174- count = 1 ;
175- #endif
176-
177- selected = 0 ;
178- needs_render = 1 ;
179- hal_term_init ();
180-
181- while (1 ) {
182- if (needs_render ) {
183- menu_render (options , count , selected );
184- needs_render = 0 ;
185- }
186-
187- key = menu_read_key (& direct_index );
188- if (key == MENU_KEY_UP ) {
189- if (selected > 0 ) { selected -- ; needs_render = 1 ; }
190- } else if (key == MENU_KEY_DOWN ) {
191- if (selected < count - 1 ) { selected ++ ; needs_render = 1 ; }
192- } else if (key == MENU_KEY_ENTER ) {
193- break ;
194- } else if (key == MENU_KEY_SELECT ) {
195- if (direct_index >= 0 && direct_index < count ) {
196- selected = direct_index ;
197- break ;
198- }
199- }
200-
201- hal_sleep_ms (10 );
202- }
203-
204- hal_term_cleanup ();
205- term_cleanup ();
206- term_clear_screen ();
207- return options [selected ].backend ;
208- }
209-
210- #ifdef _WIN32
211- static void maybe_open_web_ui (dsky_backend_t * backend )
212- {
213- int rc ;
214- if (backend != & dsky_web_backend )
215- return ;
216-
217- printf ("Opening browser at http://127.0.0.1:8080/\n" );
218- rc = system ("cmd /c start \"\" \"http://127.0.0.1:8080/\"" );
219- if (rc != 0 ) {
220- printf ("Could not open browser automatically.\n" );
221- printf ("Open this URL manually: http://127.0.0.1:8080/\n" );
222- }
223- }
224- #endif
22517
22618/* ----------------------------------------------------------------
22719 * Main
@@ -231,27 +23,15 @@ int main(void)
23123{
23224 dsky_backend_t * backend ;
23325
234- backend = select_backend_interactive ();
26+ backend = menu_select_backend ();
23527
23628 printf ("Initializing AGC...\n" );
23729
23830 agc_init ();
239- exec_init ();
240- waitlist_init ();
241- timer_init ();
242- dsky_init ();
243- pinball_init ();
244- fresh_start ();
24531 nav_init ();
32+ fresh_start ();
24633
24734 backend -> init ();
248- #ifdef _WIN32
249- maybe_open_web_ui (backend );
250- #endif
251-
252- pinball_show_prog (0 );
253- pinball_show_verb (0 );
254- pinball_show_noun (0 );
25535
25636 /* Main loop: 100 Hz (10ms per tick) */
25737 while (1 ) {
0 commit comments