home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD1.iso / Emulatoren / UAE061.LZH / uae-0.6.1 / bebox.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-28  |  13.4 KB  |  648 lines

  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.     gfxvidinfo.maxlinetoscr = 0;
  324.         gfxvidinfo.x_adjust = 0;
  325.         gfxvidinfo.maxline = 100000; /* ??? */
  326.  
  327.     // Open window
  328.     main_window = new UAEWindow(BRect(0, 0, hpixels-1, vsize-1), the_bitmap);
  329.  
  330.     // Initialize mouse and keyboard variables
  331.     buttonstate[0] = buttonstate[1] = buttonstate[2] = FALSE;
  332.     lastmx = lastmy = 0;
  333.     newmousecounters = FALSE;
  334.     inwindow = TRUE;
  335.  
  336.     // Start emulation
  337.     the_emulator = new Emulator;
  338.     the_emulator->Run();
  339. }
  340.  
  341.  
  342. /*
  343.  *  Quit requested (either by menu or by closing the window)
  344.  */
  345.  
  346. bool UAE::QuitRequested(void)
  347. {
  348.     if (BApplication::QuitRequested()) {
  349.  
  350.         // Stop emulation
  351.         if (the_emulator) {
  352.             the_emulator->Quit();
  353.             delete the_emulator;
  354.         }
  355.  
  356.         // Deallocate bitmap
  357.         if (the_bitmap)
  358.             delete the_bitmap;
  359.  
  360.         return TRUE;
  361.     }
  362.     return FALSE;
  363. }
  364.  
  365.  
  366. /*
  367.  *  Display "about" window
  368.  */
  369.  
  370. void UAE::AboutRequested(void)
  371. {
  372.     char str[256];
  373.  
  374.     sprintf(str, "UAE V0.5.3 by Bernd Schmidt\nBeBox port by Christian Bauer");
  375.     BAlert *the_alert = new BAlert("", str, "OK");
  376.     the_alert->Go();
  377. }
  378.  
  379.  
  380. /*
  381.  *  UAE Window constructor
  382.  */
  383.  
  384. UAEWindow::UAEWindow(BRect frame, BBitmap *bitmap) : BWindow(frame, "UAE", B_TITLED_WINDOW, B_NOT_RESIZABLE)
  385. {
  386.     int r, g, b, i;
  387.  
  388.     // Move window to right position
  389.     MoveTo(80, 60);
  390.  
  391.     // Create bitmap view
  392.     Lock();
  393.     main_view = new BitmapView(frame, bitmap);
  394.     AddChild(main_view);
  395.     main_view->GetKeys(&old_key_info, FALSE);
  396.     Unlock();
  397.  
  398.     bitmap_view = main_view;
  399.     bitmap_window = this;
  400.  
  401.     // Initialize xcolors
  402.     i = 0;
  403.     for (r=0; r<16; r++) {
  404.         for (g=0; g<16; g++) {
  405.             for (b=0; b<16; b++)
  406.                 xcolors[i++] = index_for_color(r<<4 | r, g<<4 | g, b<<4 | b);
  407.         }
  408.     }
  409.  
  410.     // Show window
  411.     Show();
  412.     window_open = TRUE;
  413. }
  414.  
  415.  
  416. /*
  417.  *  Closing the window quits UAE
  418.  */
  419.  
  420. bool UAEWindow::QuitRequested(void)
  421. {
  422.     window_open = FALSE;
  423.     be_app->PostMessage(B_QUIT_REQUESTED);
  424.     return TRUE;
  425. }
  426.  
  427.  
  428. /*
  429.  *  Window was (de)activated
  430.  */
  431.  
  432. void UAEWindow::WindowActivated(bool active)
  433. {
  434.     inwindow = active;
  435. }
  436.  
  437.  
  438. /*
  439.  *  Bitmap view constructor
  440.  */
  441.  
  442. BitmapView::BitmapView(BRect frame, BBitmap *bitmap) : BView(frame, "", B_FOLLOW_NONE, B_WILL_DRAW)
  443. {
  444.     the_bitmap = bitmap;
  445. }
  446.  
  447.  
  448. /*
  449.  *  Blit the bitmap
  450.  */
  451.  
  452. void BitmapView::Draw(BRect update)
  453. {
  454.     DrawBitmap(the_bitmap, update, update);
  455. }
  456.  
  457. void BitmapView::Draw(BRect from, BRect to)
  458. {
  459.     DrawBitmap(the_bitmap, from, to);
  460. }
  461.  
  462.  
  463. /*
  464.  *  Start main emulation thread
  465.  */
  466.  
  467. void Emulator::Run(void)
  468. {
  469.     // Initialize everything    
  470.     produce_sound = FALSE;
  471.     init_joystick();
  472.     keybuf_init ();    
  473.     memory_init();
  474.     custom_init();
  475.     DISK_init();
  476.     init_m68k();
  477.     MC68000_reset();
  478.  
  479.     // Start the emulation thread
  480.     the_thread = spawn_thread(thread_invoc, "UAE 68000", B_NORMAL_PRIORITY, this);
  481.     resume_thread(the_thread);
  482.     thread_running = TRUE;
  483. }
  484.  
  485.  
  486. /*
  487.  *  Stop main emulation thread
  488.  */
  489.  
  490. void Emulator::Quit(void)
  491. {
  492.     // Kill the thread if it is running
  493.     if (thread_running) {
  494.         kill_thread(the_thread);
  495.         thread_running = FALSE;
  496.     }
  497.  
  498.     close_joystick();
  499. }
  500.  
  501.  
  502. /*
  503.  *  The thread's main function
  504.  */
  505.  
  506. long Emulator::thread_invoc(Emulator *obj)
  507. {
  508.     obj->thread_func();
  509.     return 0;
  510. }
  511.  
  512. void Emulator::thread_func(void)
  513. {
  514.     // This jumps to MC68000_run() and executes the main loop
  515.     debug();
  516.     thread_running = FALSE;
  517. }
  518.  
  519.  
  520. /*
  521.  *  Redraw a line
  522.  */
  523.  
  524. void flush_line(int y)
  525. {
  526.     if (window_open) {
  527.         bitmap_window->Lock();
  528.         bitmap_view->Draw(BRect(0, y, hpixels-1, y));
  529.         bitmap_window->Unlock();
  530.     }
  531. }
  532.  
  533.  
  534. /*
  535.  *  Redraw a block
  536.  */
  537.  
  538. void flush_block(int ystart, int ystop)
  539. {
  540.     int xs = use_lores ? prev_max_diwstop - 328 : 0;
  541.  
  542.     if (window_open) {
  543.         bitmap_window->Lock();
  544.         bitmap_view->Draw(BRect(xs, ystart, hpixels+xs-1, ystop), BRect(0, ystart, hpixels-1, ystop));
  545.         bitmap_window->Unlock();
  546.     }
  547. }
  548.  
  549.  
  550. /*
  551.  *  Redraw the screen
  552.  */
  553.  
  554. void flush_screen(int ystart, int ystop)
  555. {
  556. }
  557.  
  558.  
  559. /*
  560.  *  Poll mouse and keyboard
  561.  */
  562.  
  563. void handle_events(void)
  564. {
  565.     key_info the_key_info;
  566.     int be_code, be_byte, be_bit, amiga_code;
  567.     BPoint mouse_point;
  568.     ulong mouse_buttons;
  569.  
  570.     // Keyboard
  571.     if (window_open && inwindow) {
  572.         bitmap_window->Lock();
  573.         bitmap_view->GetKeys(&the_key_info, FALSE);
  574.         bitmap_window->Unlock();
  575.  
  576.         for (be_code=0; be_code<0x80; be_code++) {
  577.             be_byte = be_code >> 3;
  578.             be_bit = 1 << (~be_code & 7);
  579.  
  580.             // Key state changed?
  581.             if ((the_key_info.key_states[be_byte] & be_bit)
  582.                  != (old_key_info.key_states[be_byte] & be_bit)) {
  583.  
  584.                 amiga_code = keycode2amiga[be_code];
  585.                 if (the_key_info.key_states[be_byte] & be_bit) {
  586.  
  587.                     // Key pressed
  588.                     if (amiga_code == AK_mousestuff)
  589.                         togglemouse();
  590.                     else
  591.                         record_key(amiga_code << 1);
  592.                 } else {
  593.  
  594.                     // Key released
  595.                     record_key((amiga_code << 1) | 1);
  596.                 }
  597.             }
  598.         }        
  599.         old_key_info = the_key_info;
  600.  
  601.         // "Affengriff"
  602.         if ((the_key_info.key_states[0x5c >> 3] & (1 << (~0x5c & 7)))
  603.          && (the_key_info.key_states[0x5d >> 3] & (1 << (~0x5d & 7)))
  604.          && (the_key_info.key_states[0x5f >> 3] & (1 << (~0x5f & 7))))
  605.             MC68000_reset();
  606.  
  607.         // Scroll lock toggles inhibit_frame
  608.         inhibit_frame = the_key_info.key_states[0x0f >> 3] & (1 << (~0x0f & 7));
  609.     }
  610.  
  611.     // Mouse
  612.     if (window_open && inwindow) {
  613.         bitmap_window->Lock();
  614.         bitmap_view->GetMouse(&mouse_point, &mouse_buttons, FALSE);
  615.         bitmap_window->Unlock();
  616.         lastmx = mouse_point.x;
  617.         lastmy = mouse_point.y;
  618.  
  619.         buttonstate[0] = mouse_buttons & B_PRIMARY_MOUSE_BUTTON;
  620.         buttonstate[1] = mouse_buttons & B_TERTIARY_MOUSE_BUTTON;
  621.         buttonstate[2] = mouse_buttons & B_SECONDARY_MOUSE_BUTTON;
  622.     }
  623. }
  624.  
  625.  
  626. int debuggable(void)
  627. {
  628.     return TRUE;
  629. }
  630.  
  631. int needmousehack(void)
  632. {
  633.     return TRUE;
  634. }
  635.  
  636. void LED(int on)
  637. {
  638. }
  639.  
  640. void calc_adjustment(void)
  641. {
  642.     gfxvidinfo.x_adjust = 0;
  643. }
  644.  
  645. void target_specific_usage(void)
  646. {
  647. }
  648.