ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/Display_Amiga.h
Revision: 1.6
Committed: 2009-01-11T11:32:38Z (15 years, 2 months ago) by cebix
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.5: +2 -2 lines
Log Message:
const correctness

File Contents

# User Rev Content
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     }