|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * BeBox port specific stuff
5: *
6: * (c) 1996 Christian Bauer
7: */
8:
9: #include <AppKit.h>
10: #include <InterfaceKit.h>
11: #include <KernelKit.h>
12:
13: #include <stdio.h>
14: #include <stdlib.h>
15: #include <string.h>
16: #define __STDC__ 1
17: #define __GNU_LIBRARY__
18: #include <getopt.h>
19: #undef __GNU_LIBRARY__
20: #undef __STDC__
21:
22: #ifndef __bebox__
23: #error Compiling bebox.cpp, but __bebox__ unset.
24: #endif
25:
26: extern "C" {
27: #include "sysconfig.h"
28: #include "sysdeps.h"
29: #include "config.h"
30: #include "options.h"
31: #include "memory.h"
32: #include "custom.h"
33: #include "newcpu.h"
34: #include "disk.h"
35: #include "debug.h"
36: #include "xwin.h"
37: #include "os.h"
38: #include "filesys.h"
39: #include "keybuf.h"
40: #include "keyboard.h"
41: }
42:
43:
44: class UAEWindow;
45: class BitmapView;
46: class Emulator;
47:
48:
49: /*
50: * The BeOS application object
51: */
52:
53: class UAE : public BApplication {
54: public:
55: UAE();
56: virtual void ArgvReceived(int argc, char **argv);
57: virtual void ReadyToRun(void);
58: virtual bool QuitRequested(void);
59: virtual void AboutRequested(void);
60:
61: private:
62: BBitmap *the_bitmap;
63: UAEWindow *main_window;
64: Emulator *the_emulator;
65: };
66:
67:
68: /*
69: * The window in which the Amiga graphics are displayed, handles I/O
70: */
71:
72: class UAEWindow : public BWindow {
73: public:
74: UAEWindow(BRect frame, BBitmap *bitmap);
75: virtual bool QuitRequested(void);
76: virtual void WindowActivated(bool active);
77:
78: private:
79: BitmapView *main_view;
80: };
81:
82:
83: /*
84: * A simple view class for blitting a bitmap on the screen
85: */
86:
87: class BitmapView : public BView {
88: public:
89: BitmapView(BRect frame, BBitmap *bitmap);
90: virtual void Draw(BRect update);
91: void Draw(BRect from, BRect to);
92:
93: private:
94: BBitmap *the_bitmap;
95: };
96:
97:
98: /*
99: * For running the emulation in its own thread
100: */
101:
102: class Emulator {
103: public:
104: Emulator() {thread_running = FALSE;}
105: void Run(void);
106: void Quit(void);
107:
108: private:
109: static long thread_invoc(Emulator *obj);
110: void thread_func(void);
111:
112: thread_id the_thread;
113: bool thread_running;
114: };
115:
116:
117: // Keyboard and mouse
118: int buttonstate[3];
119: int newmousecounters;
120: int lastmx, lastmy;
121:
122: key_info old_key_info;
123: bool inwindow;
124: bool window_open;
125:
126: // Color map and bitmap
127: xcolnr xcolors[4096];
128: struct vidbuf_description gfxvidinfo;
129:
130: int vsize, hsize, hpixels;
131:
132: BitmapView *bitmap_view;
133: UAEWindow *bitmap_window;
134:
135:
136: // Array for converting Be keycodes to Amiga keycodes
137: int keycode2amiga[128] = {
138: -1, AK_ESC, AK_F1, AK_F2, AK_F3, AK_F4, AK_F5, AK_F6,
139: AK_F7, AK_F8, AK_F9, AK_F10, AK_LALT, AK_mousestuff, AK_RALT, -1,
140:
141: -1, AK_BACKQUOTE, AK_1, AK_2, AK_3, AK_4, AK_5, AK_6,
142: AK_7, AK_8, AK_9, AK_0, AK_MINUS, AK_EQUAL, AK_BS, AK_HELP,
143:
144: AK_NPLPAREN, AK_RAMI, AK_NPLPAREN, AK_NPDIV, AK_NPMUL, AK_NPSUB, AK_TAB, AK_Q,
145: AK_W, AK_E, AK_R, AK_T, AK_Y, AK_U, AK_I, AK_O,
146:
147: AK_P, AK_LBRACKET, AK_RBRACKET, AK_BACKSLASH, AK_DEL, AK_NPRPAREN, AK_LAMI, AK_NP7,
148: AK_NP8, AK_NP9, AK_NPADD, AK_CAPSLOCK, AK_A, AK_S, AK_D, AK_F,
149:
150: AK_G, AK_H, AK_J, AK_K, AK_L, AK_SEMICOLON, AK_QUOTE, AK_RET,
151: AK_NP4, AK_NP5, AK_NP6, AK_LSH, AK_Z, AK_X, AK_C, AK_V,
152:
153: AK_B, AK_N, AK_M, AK_COMMA, AK_PERIOD, AK_SLASH, AK_RSH, AK_UP,
154: AK_NP1, AK_NP2, AK_NP3, AK_ENT, AK_CTRL, AK_LAMI, AK_SPC, AK_RAMI,
155:
156: AK_RALT, AK_LF, AK_DN, AK_RT, AK_NP0, AK_NPDEL, AK_LALT, AK_RALT,
157: AK_LTGT, -1, -1, -1, -1, -1, -1, -1,
158:
159: -1, -1, -1, -1, -1, -1, -1, -1,
160: -1, -1, -1, -1, -1, -1, -1, -1
161: };
162:
163:
164: /*
165: * Create application object and start it
166: */
167:
168: main()
169: {
170: UAE *the_app;
171:
172: the_app = new UAE();
173: the_app->Run();
174: delete the_app;
175:
176: return 0;
177: }
178:
179:
180: /*
181: * UAE Constructor: Initialize member variables
182: */
183:
184: UAE::UAE() : BApplication('UAEm')
185: {
186: the_bitmap = NULL;
187: the_emulator = NULL;
188: main_window = NULL;
189: window_open = FALSE;
190: }
191:
192:
193: /*
194: * Parse command line options
195: */
196:
197: void usage(void)
198: {
199: printf("UAE - The Un*x Amiga emulator\n");
200: printf("Summary of command-line options:\n");
201: printf(" -h : Print help\n");
202: printf(" -m VOLNAME:mount_point : mount file system at <mount point> as AmigaDOS\n"
203: " volume VOLNAME:\n");
204: printf(" -M VOLNAME:mount_point : like -m, but mount read-only\n");
205: printf(" -a : Don't mount the harddisk file automatically.\n"
206: " Useful only for testing.\n");
207: printf(" -s : Emulate 1MB slow memory at 0xC00000\n");
208: printf(" -F n : Emulate n MB fast memory at 0x200000\n");
209: printf(" -f n : Set the frame rate to 1/n\n");
210: printf(" -d : Draw the screen with the right aspect\n");
211: printf(" -D : Start up the built-in debugger\n");
212: printf(" -[0123] file : Use file instead of df[0123].adf as disk image file\n");
213: printf(" -r file : Use file as ROM image instead of kick.rom\n");
214: printf(" -p filename : Use filename to save printer output (may be LPT1: ?)\n");
215: printf(" -J : Fake joystick emulation with the numeric pad.\n");
216: printf(" -g : Turn on gfx-lib replacement.\n");
217: printf(" -d mode : Select resolution with the mode parameter.\n");
218: printf(" -H mode : Set the number of colors with the mode parameter.\n");
219: printf("\n");
220: printf("Valid resolutions: 0 (320x200); 1 (320x240); 2 (320x400); 3 (800x600);\n"
221: " 4 (800x600, correct aspect)\n"
222: "Valid color modes: 0 (256 colors); 1 (32768 colors); 2 (65536 colors)\n"
223: "UAE may choose to ignore the color mode/resolution setting.\n");
224: }
225:
226: void UAE::ArgvReceived(int argc, char **argv)
227: {
228: int c;
229:
230: while(((c = getopt(argc, argv, "Df:gd:hF:asJm:M:0:1:2:3:r:H:p:")) != EOF)) switch(c) {
231: case 'h': usage(); exit(0);
232:
233: case '0': strncpy(df0, optarg, 255); df0[255] = 0; break;
234: case '1': strncpy(df1, optarg, 255); df1[255] = 0; break;
235: case '2': strncpy(df2, optarg, 255); df2[255] = 0; break;
236: case '3': strncpy(df3, optarg, 255); df3[255] = 0; break;
237: case 'r': strncpy(romfile, optarg, 255); romfile[255] = 0; break;
238: case 'p': strncpy(prtname, optarg, 255); prtname[255] = 0; break;
239: case 'm':
240: case 'M':
241: {
242: /* mount file system (repeatable)
243: * syntax: [-m | -M] VOLNAME:/mount_point
244: * example: -M CDROM:/cdrom -m UNIXFS:./disk
245: */
246: static int mount_seen = 0;
247: char buf[256];
248: char *s2;
249: int readonly = (c == 'M');
250:
251: if (mount_seen)
252: fprintf(stderr, "warning: multiple mounts confuse Kickstart 1.3\n");
253: mount_seen = 1;
254: strncpy(buf, optarg, 255); buf[255] = 0;
255: s2 = strchr(buf, ':');
256: if(s2) {
257: *s2++ = '\0';
258: add_filesys_unit(buf, s2, readonly);
259: } else {
260: fprintf(stderr, "Usage: [-m | -M] VOLNAME:/mount_point\n");
261: }
262: }
263: break;
264:
265: case 'f': framerate = atoi(optarg); break;
266: case 'D': use_debugger = 1; break;
267: case 'J': fake_joystick = 1; break;
268: case 'a': automount_uaedev = 0; break;
269: case 's': use_slow_mem = 1; break;
270: case 'g': use_gfxlib = 1; break;
271:
272: case 'F':
273: fastmem_size = atoi(optarg) * 0x100000;
274: if (fastmem_size != 0x100000 && fastmem_size != 0x200000
275: && fastmem_size != 0x400000 && fastmem_size != 0x800000)
276: {
277: fastmem_size = 0;
278: fprintf(stderr, "Unsupported fastmem size!\n");
279: }
280:
281: break;
282:
283: case 'd':
284: screen_res = atoi(optarg);
285: if (screen_res >= 0 && screen_res <= 4) {
286: } else {
287: fprintf(stderr, "Bad video mode selected. Using default.\n");
288: screen_res = 3;
289: }
290: dont_want_aspect = screen_res != 4;
291: use_lores = screen_res < 3;
292: break;
293:
294: case 'H':
295: color_mode = atoi(optarg);
296: if (color_mode < 0 || color_mode > 2) {
297: fprintf(stderr, "Bad color mode selected. Using default.\n");
298: color_mode = 0;
299: }
300: break;
301: }
302: }
303:
304:
305: /*
306: * Arguments processed, create and start emulation
307: */
308:
309: void UAE::ReadyToRun(void)
310: {
311: vsize = dont_want_aspect ? numscrlines : numscrlines*2;
312: hsize = use_lores ? 400 : 800;
313: hpixels = use_lores ? 320 : 796;
314:
315: // Allocate bitmap
316: the_bitmap = new BBitmap(BRect(0, 0, hsize-1, vsize-1), B_COLOR_8_BIT);
317:
318: // Set up vidinfo
319: gfxvidinfo.bufmem = (char *)the_bitmap->Bits();
320: gfxvidinfo.rowbytes = the_bitmap->BytesPerRow();
321: gfxvidinfo.pixbytes = 1;
322: gfxvidinfo.maxblocklines = 100;
323:
324: // Open window
325: main_window = new UAEWindow(BRect(0, 0, hpixels-1, vsize-1), the_bitmap);
326:
327: // Initialize mouse and keyboard variables
328: buttonstate[0] = buttonstate[1] = buttonstate[2] = FALSE;
329: lastmx = lastmy = 0;
330: newmousecounters = FALSE;
331: inwindow = TRUE;
332:
333: // Start emulation
334: the_emulator = new Emulator;
335: the_emulator->Run();
336: }
337:
338:
339: /*
340: * Quit requested (either by menu or by closing the window)
341: */
342:
343: bool UAE::QuitRequested(void)
344: {
345: if (BApplication::QuitRequested()) {
346:
347: // Stop emulation
348: if (the_emulator) {
349: the_emulator->Quit();
350: delete the_emulator;
351: }
352:
353: // Deallocate bitmap
354: if (the_bitmap)
355: delete the_bitmap;
356:
357: return TRUE;
358: }
359: return FALSE;
360: }
361:
362:
363: /*
364: * Display "about" window
365: */
366:
367: void UAE::AboutRequested(void)
368: {
369: char str[256];
370:
371: sprintf(str, "UAE V0.5.3 by Bernd Schmidt\nBeBox port by Christian Bauer");
372: BAlert *the_alert = new BAlert("", str, "OK");
373: the_alert->Go();
374: }
375:
376:
377: /*
378: * UAE Window constructor
379: */
380:
381: UAEWindow::UAEWindow(BRect frame, BBitmap *bitmap) : BWindow(frame, "UAE", B_TITLED_WINDOW, B_NOT_RESIZABLE)
382: {
383: int r, g, b, i;
384:
385: // Move window to right position
386: MoveTo(80, 60);
387:
388: // Create bitmap view
389: Lock();
390: main_view = new BitmapView(frame, bitmap);
391: AddChild(main_view);
392: main_view->GetKeys(&old_key_info, FALSE);
393: Unlock();
394:
395: bitmap_view = main_view;
396: bitmap_window = this;
397:
398: // Initialize xcolors
399: i = 0;
400: for (r=0; r<16; r++) {
401: for (g=0; g<16; g++) {
402: for (b=0; b<16; b++)
403: xcolors[i++] = index_for_color(r<<4 | r, g<<4 | g, b<<4 | b);
404: }
405: }
406:
407: // Show window
408: Show();
409: window_open = TRUE;
410: }
411:
412:
413: /*
414: * Closing the window quits UAE
415: */
416:
417: bool UAEWindow::QuitRequested(void)
418: {
419: window_open = FALSE;
420: be_app->PostMessage(B_QUIT_REQUESTED);
421: return TRUE;
422: }
423:
424:
425: /*
426: * Window was (de)activated
427: */
428:
429: void UAEWindow::WindowActivated(bool active)
430: {
431: inwindow = active;
432: }
433:
434:
435: /*
436: * Bitmap view constructor
437: */
438:
439: BitmapView::BitmapView(BRect frame, BBitmap *bitmap) : BView(frame, "", B_FOLLOW_NONE, B_WILL_DRAW)
440: {
441: the_bitmap = bitmap;
442: }
443:
444:
445: /*
446: * Blit the bitmap
447: */
448:
449: void BitmapView::Draw(BRect update)
450: {
451: DrawBitmap(the_bitmap, update, update);
452: }
453:
454: void BitmapView::Draw(BRect from, BRect to)
455: {
456: DrawBitmap(the_bitmap, from, to);
457: }
458:
459:
460: /*
461: * Start main emulation thread
462: */
463:
464: void Emulator::Run(void)
465: {
466: // Initialize everything
467: produce_sound = FALSE;
468: init_joystick();
469: keybuf_init ();
470: memory_init();
471: custom_init();
472: DISK_init();
473: init_m68k();
474: MC68000_reset();
475:
476: // Start the emulation thread
477: the_thread = spawn_thread(thread_invoc, "UAE 68000", B_NORMAL_PRIORITY, this);
478: resume_thread(the_thread);
479: thread_running = TRUE;
480: }
481:
482:
483: /*
484: * Stop main emulation thread
485: */
486:
487: void Emulator::Quit(void)
488: {
489: // Kill the thread if it is running
490: if (thread_running) {
491: kill_thread(the_thread);
492: thread_running = FALSE;
493: }
494:
495: close_joystick();
496: }
497:
498:
499: /*
500: * The thread's main function
501: */
502:
503: long Emulator::thread_invoc(Emulator *obj)
504: {
505: obj->thread_func();
506: return 0;
507: }
508:
509: void Emulator::thread_func(void)
510: {
511: // This jumps to MC68000_run() and executes the main loop
512: debug();
513: thread_running = FALSE;
514: }
515:
516:
517: /*
518: * Redraw a line
519: */
520:
521: void flush_line(int y)
522: {
523: if (window_open) {
524: bitmap_window->Lock();
525: bitmap_view->Draw(BRect(0, y, hpixels-1, y));
526: bitmap_window->Unlock();
527: }
528: }
529:
530:
531: /*
532: * Redraw a block
533: */
534:
535: void flush_block(int ystart, int ystop)
536: {
537: int xs = use_lores ? prev_max_diwstop - 328 : 0;
538:
539: if (window_open) {
540: bitmap_window->Lock();
541: bitmap_view->Draw(BRect(xs, ystart, hpixels+xs-1, ystop), BRect(0, ystart, hpixels-1, ystop));
542: bitmap_window->Unlock();
543: }
544: }
545:
546:
547: /*
548: * Redraw the screen
549: */
550:
551: void flush_screen(int ystart, int ystop)
552: {
553: }
554:
555:
556: /*
557: * Poll mouse and keyboard
558: */
559:
560: void handle_events(void)
561: {
562: key_info the_key_info;
563: int be_code, be_byte, be_bit, amiga_code;
564: BPoint mouse_point;
565: ulong mouse_buttons;
566:
567: // Keyboard
568: if (window_open && inwindow) {
569: bitmap_window->Lock();
570: bitmap_view->GetKeys(&the_key_info, FALSE);
571: bitmap_window->Unlock();
572:
573: for (be_code=0; be_code<0x80; be_code++) {
574: be_byte = be_code >> 3;
575: be_bit = 1 << (~be_code & 7);
576:
577: // Key state changed?
578: if ((the_key_info.key_states[be_byte] & be_bit)
579: != (old_key_info.key_states[be_byte] & be_bit)) {
580:
581: amiga_code = keycode2amiga[be_code];
582: if (the_key_info.key_states[be_byte] & be_bit) {
583:
584: // Key pressed
585: if (amiga_code == AK_mousestuff)
586: togglemouse();
587: else
588: record_key(amiga_code << 1);
589: } else {
590:
591: // Key released
592: record_key((amiga_code << 1) | 1);
593: }
594: }
595: }
596: old_key_info = the_key_info;
597:
598: // "Affengriff"
599: if ((the_key_info.key_states[0x5c >> 3] & (1 << (~0x5c & 7)))
600: && (the_key_info.key_states[0x5d >> 3] & (1 << (~0x5d & 7)))
601: && (the_key_info.key_states[0x5f >> 3] & (1 << (~0x5f & 7))))
602: MC68000_reset();
603:
604: // Scroll lock toggles inhibit_frame
605: inhibit_frame = the_key_info.key_states[0x0f >> 3] & (1 << (~0x0f & 7));
606: }
607:
608: // Mouse
609: if (window_open && inwindow) {
610: bitmap_window->Lock();
611: bitmap_view->GetMouse(&mouse_point, &mouse_buttons, FALSE);
612: bitmap_window->Unlock();
613: lastmx = mouse_point.x;
614: lastmy = mouse_point.y;
615:
616: buttonstate[0] = mouse_buttons & B_PRIMARY_MOUSE_BUTTON;
617: buttonstate[1] = mouse_buttons & B_TERTIARY_MOUSE_BUTTON;
618: buttonstate[2] = mouse_buttons & B_SECONDARY_MOUSE_BUTTON;
619: }
620: }
621:
622:
623: int debuggable(void)
624: {
625: return TRUE;
626: }
627:
628: int needmousehack(void)
629: {
630: return TRUE;
631: }
632:
633: void LED(int on)
634: {
635: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.