1 |
cebix |
1.1 |
/* |
2 |
|
|
* Display_Amiga.h - C64 graphics display, emulator window handling, |
3 |
|
|
* Amiga specific stuff |
4 |
|
|
* |
5 |
cebix |
1.6 |
* Frodo (C) 1994-1997,2002-2009 Christian Bauer |
6 |
cebix |
1.1 |
* |
7 |
|
|
* This program is free software; you can redistribute it and/or modify |
8 |
|
|
* it under the terms of the GNU General Public License as published by |
9 |
|
|
* the Free Software Foundation; either version 2 of the License, or |
10 |
|
|
* (at your option) any later version. |
11 |
|
|
* |
12 |
|
|
* This program is distributed in the hope that it will be useful, |
13 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 |
|
|
* GNU General Public License for more details. |
16 |
|
|
* |
17 |
|
|
* You should have received a copy of the GNU General Public License |
18 |
|
|
* along with this program; if not, write to the Free Software |
19 |
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 |
|
|
*/ |
21 |
|
|
|
22 |
|
|
#include <exec/types.h> |
23 |
|
|
#include <exec/memory.h> |
24 |
|
|
#include <intuition/intuition.h> |
25 |
|
|
#include <libraries/gadtools.h> |
26 |
|
|
#include <libraries/asl.h> |
27 |
|
|
#include <proto/exec.h> |
28 |
|
|
#include <proto/graphics.h> |
29 |
|
|
#include <proto/intuition.h> |
30 |
|
|
#include <proto/dos.h> |
31 |
|
|
#include <proto/gadtools.h> |
32 |
|
|
#include <proto/diskfont.h> |
33 |
|
|
#include <proto/asl.h> |
34 |
|
|
|
35 |
|
|
#include "C64.h" |
36 |
|
|
#include "SAM.h" |
37 |
|
|
#include "Version.h" |
38 |
|
|
|
39 |
|
|
|
40 |
|
|
/* |
41 |
|
|
C64 keyboard matrix: |
42 |
|
|
|
43 |
|
|
Bit 7 6 5 4 3 2 1 0 |
44 |
|
|
0 CUD F5 F3 F1 F7 CLR RET DEL |
45 |
|
|
1 SHL E S Z 4 A W 3 |
46 |
|
|
2 X T F C 6 D R 5 |
47 |
|
|
3 V U H B 8 G Y 7 |
48 |
|
|
4 N O K M 0 J I 9 |
49 |
|
|
5 , @ : . - L P + |
50 |
|
|
6 / ^ = SHR HOM ; * £ |
51 |
|
|
7 R/S Q C= SPC 2 CTL <- 1 |
52 |
|
|
*/ |
53 |
|
|
|
54 |
|
|
|
55 |
|
|
/* |
56 |
|
|
Tables for key translation |
57 |
|
|
Bit 0..2: row/column in C64 keyboard matrix |
58 |
|
|
Bit 3 : implicit shift |
59 |
|
|
Bit 5 : joystick emulation (bit 0..4: mask) |
60 |
|
|
*/ |
61 |
|
|
|
62 |
|
|
const int key_byte[128] = { |
63 |
|
|
7, 7, 7, 1, 1, 2, 2, 3, |
64 |
|
|
3, 4, 4, 5, 5, 6, -1,0x30, |
65 |
|
|
7, 1, 1, 2, 2, 3, 3, 4, |
66 |
|
|
4, 5, 5, 6, -1,0x26,0x22,0x2a, |
67 |
|
|
1, 1, 2, 2, 3, 3, 4, 4, |
68 |
|
|
5, 5, 6, 6, -1,0x24,0x30,0x28, |
69 |
|
|
6, 1, 2, 2, 3, 3, 4, 4, |
70 |
|
|
5, 5, 6, -1, -1,0x25,0x21,0x29, |
71 |
|
|
7, 0, -1, 0, 0, 7, 6, -1, |
72 |
|
|
-1, -1, -1, -1,8+0, 0, 0, 8+0, |
73 |
|
|
0,8+0, 0,8+0, 0, 8+0, 0, 8+0, |
74 |
|
|
-1, -1, 6, 6, -1, -1, -1, -1, |
75 |
|
|
1, 6, 1, 7, 7, 7, 7, -1, |
76 |
|
|
-1, -1, -1, -1, -1, -1, -1, -1, |
77 |
|
|
-1, -1, -1, -1, -1, -1, -1, -1, |
78 |
|
|
-1, -1, -1, -1, -1, -1, -1, -1 |
79 |
|
|
}; |
80 |
|
|
|
81 |
|
|
const int key_bit[128] = { |
82 |
|
|
1, 0, 3, 0, 3, 0, 3, 0, |
83 |
|
|
3, 0, 3, 0, 3, 0, -1, -1, |
84 |
|
|
6, 1, 6, 1, 6, 1, 6, 1, |
85 |
|
|
6, 1, 6, 1, -1, -1, -1, -1, |
86 |
|
|
2, 5, 2, 5, 2, 5, 2, 5, |
87 |
|
|
2, 5, 2, 5, -1, -1, -1, -1, |
88 |
|
|
6, 4, 7, 4, 7, 4, 7, 4, |
89 |
|
|
7, 4, 7, -1, -1, -1, -1, -1, |
90 |
|
|
4, 0, -1, 1, 1, 7, 3, -1, |
91 |
|
|
-1, -1, -1, -1, 7, 7, 2, 2, |
92 |
|
|
4, 4, 5, 5, 6, 6, 3, 3, |
93 |
|
|
-1, -1, 6, 5, -1, -1, -1, -1, |
94 |
|
|
7, 4, 7, 2, 5, 5, 5, -1, |
95 |
|
|
-1, -1, -1, -1, -1, -1, -1, -1, |
96 |
|
|
-1, -1, -1, -1, -1, -1, -1, -1, |
97 |
|
|
-1, -1, -1, -1, -1, -1, -1, -1 |
98 |
|
|
}; |
99 |
|
|
|
100 |
|
|
|
101 |
|
|
/* |
102 |
|
|
* Menu definitions |
103 |
|
|
*/ |
104 |
|
|
|
105 |
|
|
const struct NewMenu new_menus[] = { |
106 |
|
|
NM_TITLE, "Frodo", NULL, 0, 0, NULL, |
107 |
|
|
NM_ITEM, "About Frodo...", NULL, 0, 0, NULL, |
108 |
|
|
NM_ITEM, NM_BARLABEL, NULL, 0, 0, NULL, |
109 |
|
|
NM_ITEM, "Preferences...", "P", 0, 0, NULL, |
110 |
|
|
NM_ITEM, NM_BARLABEL, NULL, 0, 0, NULL, |
111 |
|
|
NM_ITEM, "Reset C64", NULL, 0, 0, NULL, |
112 |
|
|
NM_ITEM, "Insert next disk", "D", 0, 0, NULL, |
113 |
|
|
NM_ITEM, "SAM...", "M", 0, 0, NULL, |
114 |
|
|
NM_ITEM, NM_BARLABEL, NULL, 0, 0, NULL, |
115 |
|
|
NM_ITEM, "Load snapshot...", "O", 0, 0, NULL, |
116 |
|
|
NM_ITEM, "Save snapshot...", "S", 0, 0, NULL, |
117 |
|
|
NM_ITEM, NM_BARLABEL, NULL, 0, 0, NULL, |
118 |
|
|
NM_ITEM, "Quit Frodo", "Q", 0, 0, NULL, |
119 |
|
|
NM_END, NULL, NULL, 0, 0, NULL |
120 |
|
|
}; |
121 |
|
|
|
122 |
|
|
|
123 |
|
|
/* |
124 |
|
|
* Font attributes |
125 |
|
|
*/ |
126 |
|
|
|
127 |
|
|
const struct TextAttr led_font_attr = { |
128 |
|
|
"Helvetica.font", 11, FS_NORMAL, 0 |
129 |
|
|
}; |
130 |
|
|
|
131 |
|
|
const struct TextAttr speedo_font_attr = { |
132 |
|
|
"Courier.font", 11, FS_NORMAL, 0 |
133 |
|
|
}; |
134 |
|
|
|
135 |
|
|
|
136 |
|
|
/* |
137 |
|
|
* Display constructor: Create window/screen |
138 |
|
|
*/ |
139 |
|
|
|
140 |
|
|
C64Display::C64Display(C64 *the_c64) : TheC64(the_c64) |
141 |
|
|
{ |
142 |
|
|
int i; |
143 |
|
|
|
144 |
|
|
// LEDs off |
145 |
|
|
for (i=0; i<4; i++) |
146 |
|
|
led_state[i] = old_led_state[i] = LED_OFF; |
147 |
|
|
|
148 |
|
|
// Allocate chunky buffer to draw into |
149 |
|
|
chunky_buf = new UBYTE[DISPLAY_X * DISPLAY_Y]; |
150 |
|
|
|
151 |
|
|
// Open fonts |
152 |
|
|
led_font = OpenDiskFont(&led_font_attr); |
153 |
|
|
speedo_font = OpenDiskFont(&speedo_font_attr); |
154 |
|
|
|
155 |
|
|
// Open window on default pubscreen |
156 |
|
|
the_window = OpenWindowTags(NULL, |
157 |
|
|
WA_Left, 0, |
158 |
|
|
WA_Top, 0, |
159 |
|
|
WA_InnerWidth, DISPLAY_X, |
160 |
|
|
WA_InnerHeight, DISPLAY_Y + 16, |
161 |
|
|
WA_Title, (ULONG)"Frodo", |
162 |
|
|
WA_ScreenTitle, (ULONG)"Frodo C64 Emulator", |
163 |
|
|
WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_RAWKEY | IDCMP_MENUPICK | IDCMP_REFRESHWINDOW, |
164 |
|
|
WA_DragBar, TRUE, |
165 |
|
|
WA_DepthGadget, TRUE, |
166 |
|
|
WA_CloseGadget, TRUE, |
167 |
|
|
WA_SimpleRefresh, TRUE, |
168 |
|
|
WA_Activate, TRUE, |
169 |
|
|
WA_NewLookMenus, TRUE, |
170 |
|
|
TAG_DONE); |
171 |
|
|
the_screen = the_window->WScreen; |
172 |
|
|
the_rp = the_window->RPort; |
173 |
|
|
xo = the_window->BorderLeft; |
174 |
|
|
yo = the_window->BorderTop; |
175 |
|
|
|
176 |
|
|
// Create menus |
177 |
|
|
the_visual_info = GetVisualInfo(the_screen, NULL); |
178 |
|
|
the_menus = CreateMenus(new_menus, GTMN_FullMenu, TRUE, TAG_DONE); |
179 |
|
|
LayoutMenus(the_menus, the_visual_info, GTMN_NewLookMenus, TRUE, TAG_DONE); |
180 |
|
|
SetMenuStrip(the_window, the_menus); |
181 |
|
|
|
182 |
|
|
// Obtain 16 pens for the C64 colors |
183 |
|
|
for (i=0; i<16; i++) |
184 |
|
|
pens[i] = ObtainBestPen(the_screen->ViewPort.ColorMap, |
185 |
|
|
palette_red[i] * 0x01010101, palette_green[i] * 0x01010101, palette_blue[i] * 0x01010101); |
186 |
|
|
|
187 |
|
|
// Allocate temporary RastPort for WritePixelArra8() |
188 |
|
|
temp_bm = AllocBitMap(DISPLAY_X, 1, 8, 0, NULL); |
189 |
|
|
InitRastPort(&temp_rp); |
190 |
|
|
temp_rp.BitMap = temp_bm; |
191 |
|
|
|
192 |
|
|
// Draw LED bar |
193 |
|
|
draw_led_bar(); |
194 |
|
|
|
195 |
|
|
// Allocate file requesters |
196 |
|
|
open_req = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest, |
197 |
|
|
ASLFR_Window, (ULONG)the_window, |
198 |
|
|
ASLFR_SleepWindow, TRUE, |
199 |
|
|
ASLFR_TitleText, (ULONG)"Frodo: Load snapshot...", |
200 |
|
|
ASLFR_RejectIcons, TRUE, |
201 |
|
|
TAG_DONE); |
202 |
|
|
save_req = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest, |
203 |
|
|
ASLFR_Window, (ULONG)the_window, |
204 |
|
|
ASLFR_SleepWindow, TRUE, |
205 |
|
|
ASLFR_TitleText, (ULONG)"Frodo: Save snapshot...", |
206 |
|
|
ASLFR_DoSaveMode, TRUE, |
207 |
|
|
ASLFR_RejectIcons, TRUE, |
208 |
|
|
TAG_DONE); |
209 |
|
|
} |
210 |
|
|
|
211 |
|
|
|
212 |
|
|
/* |
213 |
|
|
* Display destructor |
214 |
|
|
*/ |
215 |
|
|
|
216 |
|
|
C64Display::~C64Display() |
217 |
|
|
{ |
218 |
|
|
// Free file requesters |
219 |
|
|
if (open_req != NULL) |
220 |
|
|
FreeAslRequest(open_req); |
221 |
|
|
if (save_req != NULL) |
222 |
|
|
FreeAslRequest(save_req); |
223 |
|
|
|
224 |
|
|
// Free temporary RastPort |
225 |
|
|
if (temp_bm != NULL) |
226 |
|
|
FreeBitMap(temp_bm); |
227 |
|
|
|
228 |
|
|
// Free pens |
229 |
|
|
for (int i=0; i<16; i++) |
230 |
|
|
ReleasePen(the_screen->ViewPort.ColorMap, pens[i]); |
231 |
|
|
|
232 |
|
|
// Delete menus |
233 |
|
|
if (the_menus != NULL) { |
234 |
|
|
if (the_window != NULL) |
235 |
|
|
ClearMenuStrip(the_window); |
236 |
|
|
FreeMenus(the_menus); |
237 |
|
|
} |
238 |
|
|
|
239 |
|
|
// Delete VisualInfo |
240 |
|
|
if (the_visual_info != NULL) |
241 |
|
|
FreeVisualInfo(the_visual_info); |
242 |
|
|
|
243 |
|
|
// Close window |
244 |
|
|
if (the_window != NULL) |
245 |
|
|
CloseWindow(the_window); |
246 |
|
|
|
247 |
|
|
// Close fonts |
248 |
|
|
CloseFont(speedo_font); |
249 |
|
|
CloseFont(led_font); |
250 |
|
|
|
251 |
|
|
// Free chunky buffer |
252 |
|
|
delete chunky_buf; |
253 |
|
|
} |
254 |
|
|
|
255 |
|
|
|
256 |
|
|
/* |
257 |
|
|
* Prefs may have changed |
258 |
|
|
*/ |
259 |
|
|
|
260 |
|
|
void C64Display::NewPrefs(Prefs *prefs) |
261 |
|
|
{ |
262 |
|
|
} |
263 |
|
|
|
264 |
|
|
|
265 |
|
|
/* |
266 |
|
|
* Redraw bitmap |
267 |
|
|
*/ |
268 |
|
|
|
269 |
|
|
void C64Display::Update(void) |
270 |
|
|
{ |
271 |
|
|
// Update C64 display |
272 |
|
|
WritePixelArray8(the_rp, xo, yo, DISPLAY_X + xo - 1, DISPLAY_Y + yo - 1, |
273 |
|
|
chunky_buf, &temp_rp); |
274 |
|
|
|
275 |
|
|
// Update drive LEDs |
276 |
|
|
for (int i=0; i<4; i++) |
277 |
|
|
if (led_state[i] != old_led_state[i]) { |
278 |
|
|
draw_led(i, led_state[i]); |
279 |
|
|
old_led_state[i] = led_state[i]; |
280 |
|
|
} |
281 |
|
|
} |
282 |
|
|
|
283 |
|
|
|
284 |
|
|
/* |
285 |
|
|
* Draw LED bar at the bottom of the window |
286 |
|
|
*/ |
287 |
|
|
|
288 |
|
|
void C64Display::draw_led_bar(void) |
289 |
|
|
{ |
290 |
|
|
int i; |
291 |
|
|
char str[16]; |
292 |
|
|
|
293 |
|
|
SetAPen(the_rp, pens[15]); // Light gray |
294 |
|
|
SetBPen(the_rp, pens[15]); // Light gray |
295 |
|
|
RectFill(the_rp, xo, yo+DISPLAY_Y, xo+DISPLAY_X-1, yo+DISPLAY_Y+15); |
296 |
|
|
|
297 |
|
|
SetAPen(the_rp, pens[1]); // White |
298 |
|
|
Move(the_rp, xo, yo+DISPLAY_Y); Draw(the_rp, xo+DISPLAY_X-1, yo+DISPLAY_Y); |
299 |
|
|
for (i=0; i<5; i++) { |
300 |
|
|
Move(the_rp, xo+DISPLAY_X*i/5, yo+DISPLAY_Y); Draw(the_rp, xo+DISPLAY_X*i/5, yo+DISPLAY_Y+14); |
301 |
|
|
} |
302 |
|
|
for (i=2; i<6; i++) { |
303 |
|
|
Move(the_rp, xo+DISPLAY_X*i/5-23, yo+DISPLAY_Y+11); Draw(the_rp, xo+DISPLAY_X*i/5-9, yo+DISPLAY_Y+11); |
304 |
|
|
Move(the_rp, xo+DISPLAY_X*i/5-9, yo+DISPLAY_Y+11); Draw(the_rp, xo+DISPLAY_X*i/5-9, yo+DISPLAY_Y+5); |
305 |
|
|
} |
306 |
|
|
|
307 |
|
|
SetAPen(the_rp, pens[12]); // Medium gray |
308 |
|
|
Move(the_rp, xo, yo+DISPLAY_Y+15); Draw(the_rp, xo+DISPLAY_X-1, yo+DISPLAY_Y+15); |
309 |
|
|
for (i=1; i<6; i++) { |
310 |
|
|
Move(the_rp, xo+DISPLAY_X*i/5-1, yo+DISPLAY_Y+1); Draw(the_rp, xo+DISPLAY_X*i/5-1, yo+DISPLAY_Y+15); |
311 |
|
|
} |
312 |
|
|
for (i=2; i<6; i++) { |
313 |
|
|
Move(the_rp, xo+DISPLAY_X*i/5-24, yo+DISPLAY_Y+11); Draw(the_rp, xo+DISPLAY_X*i/5-24, yo+DISPLAY_Y+4); |
314 |
|
|
Move(the_rp, xo+DISPLAY_X*i/5-24, yo+DISPLAY_Y+4); Draw(the_rp, xo+DISPLAY_X*i/5-9, yo+DISPLAY_Y+4); |
315 |
|
|
} |
316 |
|
|
|
317 |
|
|
SetFont(the_rp, led_font); |
318 |
|
|
for (i=0; i<4; i++) { |
319 |
|
|
sprintf(str, "Drive %d", i+8); |
320 |
|
|
SetAPen(the_rp, pens[0]); // Black |
321 |
|
|
Move(the_rp, xo+DISPLAY_X*(i+1)/5+8, yo+DISPLAY_Y+11); |
322 |
|
|
Text(the_rp, str, strlen(str)); |
323 |
|
|
draw_led(i, LED_OFF); |
324 |
|
|
} |
325 |
|
|
} |
326 |
|
|
|
327 |
|
|
|
328 |
|
|
/* |
329 |
|
|
* Draw one LED |
330 |
|
|
*/ |
331 |
|
|
|
332 |
|
|
void C64Display::draw_led(int num, int state) |
333 |
|
|
{ |
334 |
|
|
switch (state) { |
335 |
|
|
case LED_OFF: |
336 |
|
|
case LED_ERROR_OFF: |
337 |
|
|
SetAPen(the_rp, pens[0]); // Black; |
338 |
|
|
break; |
339 |
|
|
case LED_ON: |
340 |
|
|
SetAPen(the_rp, pens[5]); // Green |
341 |
|
|
break; |
342 |
|
|
case LED_ERROR_ON: |
343 |
|
|
SetAPen(the_rp, pens[2]); // Red |
344 |
|
|
break; |
345 |
|
|
} |
346 |
|
|
RectFill(the_rp, xo+DISPLAY_X*(num+2)/5-23, yo+DISPLAY_Y+5, xo+DISPLAY_X*(num+2)/5-10, yo+DISPLAY_Y+10); |
347 |
|
|
} |
348 |
|
|
|
349 |
|
|
|
350 |
|
|
/* |
351 |
|
|
* Update speedometer |
352 |
|
|
*/ |
353 |
|
|
|
354 |
|
|
void C64Display::Speedometer(int speed) |
355 |
|
|
{ |
356 |
|
|
static int delay = 0; |
357 |
|
|
|
358 |
|
|
if (delay >= 20) { |
359 |
|
|
char str[16]; |
360 |
|
|
sprintf(str, "%d%%", speed); |
361 |
|
|
SetAPen(the_rp, pens[15]); // Light gray |
362 |
|
|
RectFill(the_rp, xo+1, yo+DISPLAY_Y+1, xo+DISPLAY_X/5-2, yo+DISPLAY_Y+14); |
363 |
|
|
SetAPen(the_rp, pens[0]); // Black |
364 |
|
|
SetFont(the_rp, speedo_font); |
365 |
|
|
Move(the_rp, xo+24, yo+DISPLAY_Y+10); |
366 |
|
|
Text(the_rp, str, strlen(str)); |
367 |
|
|
delay = 0; |
368 |
|
|
} else |
369 |
|
|
delay++; |
370 |
|
|
} |
371 |
|
|
|
372 |
|
|
|
373 |
|
|
/* |
374 |
|
|
* Return pointer to bitmap data |
375 |
|
|
*/ |
376 |
|
|
|
377 |
|
|
UBYTE *C64Display::BitmapBase(void) |
378 |
|
|
{ |
379 |
|
|
return chunky_buf; |
380 |
|
|
} |
381 |
|
|
|
382 |
|
|
|
383 |
|
|
/* |
384 |
|
|
* Return number of bytes per row |
385 |
|
|
*/ |
386 |
|
|
|
387 |
|
|
int C64Display::BitmapXMod(void) |
388 |
|
|
{ |
389 |
|
|
return DISPLAY_X; |
390 |
|
|
} |
391 |
|
|
|
392 |
|
|
|
393 |
|
|
/* |
394 |
|
|
* Handle IDCMP messages |
395 |
|
|
*/ |
396 |
|
|
|
397 |
|
|
void C64Display::PollKeyboard(UBYTE *key_matrix, UBYTE *rev_matrix, UBYTE *joystick) |
398 |
|
|
{ |
399 |
|
|
struct IntuiMessage *msg; |
400 |
|
|
|
401 |
|
|
// Get and analyze all pending window messages |
402 |
|
|
while ((msg = (struct IntuiMessage *)GetMsg(the_window->UserPort)) != NULL) { |
403 |
|
|
|
404 |
|
|
// Extract data and reply message |
405 |
|
|
ULONG iclass = msg->Class; |
406 |
|
|
USHORT code = msg->Code; |
407 |
|
|
ReplyMsg((struct Message *)msg); |
408 |
|
|
|
409 |
|
|
// Action depends on message class |
410 |
|
|
switch (iclass) { |
411 |
|
|
|
412 |
|
|
case IDCMP_CLOSEWINDOW: // Closing the window quits Frodo |
413 |
|
|
TheC64->Quit(); |
414 |
|
|
break; |
415 |
|
|
|
416 |
|
|
case IDCMP_RAWKEY: |
417 |
|
|
switch (code) { |
418 |
|
|
|
419 |
|
|
case 0x58: // F9: NMI (Restore) |
420 |
|
|
TheC64->NMI(); |
421 |
|
|
break; |
422 |
|
|
|
423 |
|
|
case 0x59: // F10: Reset |
424 |
|
|
TheC64->Reset(); |
425 |
|
|
break; |
426 |
|
|
|
427 |
|
|
case 0x5e: // '+' on keypad: Increase SkipFrames |
428 |
|
|
ThePrefs.SkipFrames++; |
429 |
|
|
break; |
430 |
|
|
|
431 |
|
|
case 0x4a: // '-' on keypad: Decrease SkipFrames |
432 |
|
|
if (ThePrefs.SkipFrames > 1) |
433 |
|
|
ThePrefs.SkipFrames--; |
434 |
|
|
break; |
435 |
|
|
|
436 |
|
|
case 0x5d: // '*' on keypad: Toggle speed limiter |
437 |
|
|
ThePrefs.LimitSpeed = !ThePrefs.LimitSpeed; |
438 |
|
|
break; |
439 |
|
|
|
440 |
|
|
case 0x5c:{ // '/' on keypad: Toggle processor-level 1541 emulation |
441 |
|
|
Prefs *prefs = new Prefs(ThePrefs); |
442 |
|
|
prefs->Emul1541Proc = !prefs->Emul1541Proc; |
443 |
|
|
TheC64->NewPrefs(prefs); |
444 |
|
|
ThePrefs = *prefs; |
445 |
|
|
delete prefs; |
446 |
|
|
break; |
447 |
|
|
} |
448 |
|
|
|
449 |
|
|
default:{ |
450 |
|
|
// Convert Amiga keycode to C64 row/column |
451 |
|
|
int c64_byte = key_byte[code & 0x7f]; |
452 |
|
|
int c64_bit = key_bit[code & 0x7f]; |
453 |
|
|
|
454 |
|
|
if (c64_byte != -1) { |
455 |
|
|
if (!(c64_byte & 0x20)) { |
456 |
|
|
|
457 |
|
|
// Normal keys |
458 |
|
|
bool shifted = c64_byte & 8; |
459 |
|
|
c64_byte &= 7; |
460 |
|
|
if (!(code & 0x80)) { |
461 |
|
|
|
462 |
|
|
// Key pressed |
463 |
|
|
if (shifted) { |
464 |
|
|
key_matrix[6] &= 0xef; |
465 |
|
|
rev_matrix[4] &= 0xbf; |
466 |
|
|
} |
467 |
|
|
key_matrix[c64_byte] &= ~(1 << c64_bit); |
468 |
|
|
rev_matrix[c64_bit] &= ~(1 << c64_byte); |
469 |
|
|
} else { |
470 |
|
|
|
471 |
|
|
// Key released |
472 |
|
|
if (shifted) { |
473 |
|
|
key_matrix[6] |= 0x10; |
474 |
|
|
rev_matrix[4] |= 0x40; |
475 |
|
|
} |
476 |
|
|
key_matrix[c64_byte] |= (1 << c64_bit); |
477 |
|
|
rev_matrix[c64_bit] |= (1 << c64_byte); |
478 |
|
|
} |
479 |
|
|
} else { |
480 |
|
|
|
481 |
|
|
// Joystick emulation |
482 |
|
|
c64_byte &= 0x1f; |
483 |
|
|
if (code & 0x80) |
484 |
|
|
*joystick |= c64_byte; |
485 |
|
|
else |
486 |
|
|
*joystick &= ~c64_byte; |
487 |
|
|
} |
488 |
|
|
} |
489 |
|
|
} |
490 |
|
|
} |
491 |
|
|
break; |
492 |
|
|
|
493 |
|
|
case IDCMP_MENUPICK:{ |
494 |
|
|
if (code == MENUNULL) |
495 |
|
|
break; |
496 |
|
|
|
497 |
|
|
// Get item number |
498 |
|
|
int item_number = ITEMNUM(code); |
499 |
|
|
switch (item_number) { |
500 |
|
|
|
501 |
|
|
case 0: { // About Frodo |
502 |
|
|
TheC64->Pause(); |
503 |
|
|
char str[256]; |
504 |
cebix |
1.5 |
sprintf(str, "%s by Christian Bauer\n<Christian.Bauer@uni-mainz.de>\nİ Copyright 1994-1997,2002-2005", VERSION_STRING); |
505 |
cebix |
1.1 |
ShowRequester(str, "OK"); |
506 |
|
|
TheC64->Resume(); |
507 |
|
|
break; |
508 |
|
|
} |
509 |
|
|
|
510 |
|
|
case 2: // Preferences |
511 |
|
|
TheC64->Pause(); |
512 |
|
|
be_app->RunPrefsEditor(); |
513 |
|
|
TheC64->Resume(); |
514 |
|
|
break; |
515 |
|
|
|
516 |
|
|
case 4: // Reset C64 |
517 |
|
|
TheC64->Reset(); |
518 |
|
|
break; |
519 |
|
|
|
520 |
|
|
case 5: // Insert next disk |
521 |
|
|
if (strlen(ThePrefs.DrivePath[0]) > 4) { |
522 |
|
|
char str[256]; |
523 |
|
|
strcpy(str, ThePrefs.DrivePath[0]); |
524 |
|
|
char *p = str + strlen(str) - 5; |
525 |
|
|
|
526 |
|
|
// If path matches "*.?64", increment character before the '.' |
527 |
|
|
if (p[1] == '.' && p[3] == '6' && p[4] == '4') { |
528 |
|
|
p[0]++; |
529 |
|
|
|
530 |
|
|
// If no such file exists, set character before the '.' to '1', 'a' or 'A' |
531 |
|
|
FILE *file; |
532 |
|
|
if ((file = fopen(str, "rb")) == NULL) { |
533 |
|
|
if (isdigit(p[0])) |
534 |
|
|
p[0] = '1'; |
535 |
|
|
else if (isupper(p[0])) |
536 |
|
|
p[0] = 'A'; |
537 |
|
|
else |
538 |
|
|
p[0] = 'a'; |
539 |
|
|
} else |
540 |
|
|
fclose(file); |
541 |
|
|
|
542 |
|
|
// Set new prefs |
543 |
|
|
Prefs *prefs = new Prefs(ThePrefs); |
544 |
|
|
strcpy(prefs->DrivePath[0], str); |
545 |
|
|
TheC64->NewPrefs(prefs); |
546 |
|
|
ThePrefs = *prefs; |
547 |
|
|
delete prefs; |
548 |
|
|
} |
549 |
|
|
} |
550 |
|
|
break; |
551 |
|
|
|
552 |
|
|
case 6: // SAM |
553 |
|
|
TheC64->Pause(); |
554 |
|
|
SAM(TheC64); |
555 |
|
|
TheC64->Resume(); |
556 |
|
|
break; |
557 |
|
|
|
558 |
|
|
case 8: // Load snapshot |
559 |
|
|
if (open_req != NULL && AslRequest(open_req, NULL)) { |
560 |
|
|
char path[256]; |
561 |
|
|
strncpy(path, open_req->fr_Drawer, 255); |
562 |
|
|
AddPart(path, open_req->fr_File, 255); |
563 |
|
|
TheC64->Pause(); |
564 |
|
|
TheC64->LoadSnapshot(path); |
565 |
|
|
TheC64->Resume(); |
566 |
|
|
} |
567 |
|
|
break; |
568 |
|
|
|
569 |
|
|
case 9: // Save snapshot |
570 |
|
|
if (save_req != NULL && AslRequest(save_req, NULL)) { |
571 |
|
|
char path[256]; |
572 |
|
|
strncpy(path, save_req->fr_Drawer, 255); |
573 |
|
|
AddPart(path, save_req->fr_File, 255); |
574 |
|
|
TheC64->Pause(); |
575 |
|
|
TheC64->SaveSnapshot(path); |
576 |
|
|
TheC64->Resume(); |
577 |
|
|
} |
578 |
|
|
break; |
579 |
|
|
|
580 |
|
|
case 11: // Quit Frodo |
581 |
|
|
TheC64->Quit(); |
582 |
|
|
break; |
583 |
|
|
} |
584 |
|
|
break; |
585 |
|
|
} |
586 |
|
|
|
587 |
|
|
case IDCMP_REFRESHWINDOW: |
588 |
|
|
BeginRefresh(the_window); |
589 |
|
|
draw_led_bar(); |
590 |
|
|
EndRefresh(the_window, TRUE); |
591 |
|
|
break; |
592 |
|
|
} |
593 |
|
|
} |
594 |
|
|
} |
595 |
|
|
|
596 |
|
|
|
597 |
|
|
/* |
598 |
|
|
* Check if NumLock is down (for switching the joystick keyboard emulation) |
599 |
|
|
*/ |
600 |
|
|
|
601 |
|
|
bool C64Display::NumLock(void) |
602 |
|
|
{ |
603 |
|
|
return FALSE; |
604 |
|
|
} |
605 |
|
|
|
606 |
|
|
|
607 |
|
|
/* |
608 |
|
|
* Allocate C64 colors |
609 |
|
|
*/ |
610 |
|
|
|
611 |
|
|
void C64Display::InitColors(UBYTE *colors) |
612 |
|
|
{ |
613 |
|
|
// Spread pens into colors array |
614 |
|
|
for (int i=0; i<256; i++) |
615 |
|
|
colors[i] = pens[i & 0x0f]; |
616 |
|
|
} |
617 |
|
|
|
618 |
|
|
|
619 |
|
|
/* |
620 |
|
|
* Show a requester |
621 |
|
|
*/ |
622 |
|
|
|
623 |
cebix |
1.6 |
long ShowRequester(const char *str, const char *button1, const char *button2) |
624 |
cebix |
1.1 |
{ |
625 |
|
|
struct EasyStruct es; |
626 |
|
|
char gads[256]; |
627 |
|
|
|
628 |
|
|
strcpy(gads, button1); |
629 |
|
|
if (button2) { |
630 |
|
|
strcat(gads, "|"); |
631 |
|
|
strcat(gads, button2); |
632 |
|
|
} |
633 |
|
|
|
634 |
|
|
es.es_StructSize = sizeof(struct EasyStruct); |
635 |
|
|
es.es_Flags = 0; |
636 |
|
|
es.es_Title = "Frodo"; |
637 |
|
|
es.es_TextFormat = str; |
638 |
|
|
es.es_GadgetFormat = gads; |
639 |
|
|
|
640 |
|
|
return EasyRequestArgs(NULL, &es, NULL, NULL) % 1; |
641 |
|
|
} |