--- uae/src/bebox.cpp 2018/04/24 16:38:39 1.1.1.1 +++ uae/src/bebox.cpp 2018/04/24 16:39:06 1.1.1.2 @@ -2,43 +2,108 @@ * UAE - The Un*x Amiga Emulator * * BeBox port specific stuff - * - * (c) 1996 Christian Bauer + * + * (c) 1996-1997 Christian Bauer * (c) 1996 Patrick Hanevold */ -#define VersionStr "0.6.4" - #include #include #include +#include #include #include +#include #include #include #include +#include #define __STDC__ 1 #define __GNU_LIBRARY__ #include #undef __GNU_LIBRARY__ #undef __STDC__ -#ifndef __bebox__ -#error Compiling bebox.cpp, but __bebox__ unset. -#endif - #include "bebox.h" -extern void deinit_sound(void); + +// Messages +const ulong MSG_INSERT_DF0 = 'idf0'; +const ulong MSG_EJECT_DF0 = 'edf0'; +const ulong MSG_INSERT_DF1 = 'idf1'; +const ulong MSG_EJECT_DF1 = 'edf1'; +const ulong MSG_INSERT_DF2 = 'idf2'; +const ulong MSG_EJECT_DF2 = 'edf2'; +const ulong MSG_INSERT_DF3 = 'idf3'; +const ulong MSG_EJECT_DF3 = 'edf3'; +const ulong MSG_FR1 = 'mfr1'; +const ulong MSG_FR2 = 'mfr2'; +const ulong MSG_FR3 = 'mfr3'; +const ulong MSG_FR4 = 'mfr4'; +const ulong MSG_FR5 = 'mfr5'; +const ulong MSG_FR6 = 'mfr6'; +const ulong MSG_FR7 = 'mfr7'; +const ulong MSG_RESET = 'rset'; +const ulong MSG_DEBUG = 'dbug'; +const ulong MSG_REDRAW = 'draw'; + + +// LED colors +const rgb_color PowerDark = {0x40, 0x00, 0x00, 0}; +const rgb_color PowerLight = {0xff, 0x00, 0x00, 0}; +const rgb_color DriveDark = {0x00, 0x40, 0x00, 0}; +const rgb_color DriveLight = {0x00, 0xff, 0x00, 0}; + + +// Variables +static UAE *the_app; +static BitmapView *bitmap_view; +static UAEWindow *bitmap_window; +static bool reset_thyself = FALSE; + +static key_info old_key_info; +static bool window_open; +static bool LEDs[4]; + +static int the_argc; +static char **the_argv; + +static BJoystick *joy; + + +// Array for converting Be keycodes to Amiga keycodes +int keycode2amiga[128] = { + -1, AK_ESC, AK_F1, AK_F2, AK_F3, AK_F4, AK_F5, AK_F6, + AK_F7, AK_F8, AK_F9, AK_F10, -1, AK_mousestuff, -1, -1, + + -1, AK_BACKQUOTE, AK_1, AK_2, AK_3, AK_4, AK_5, AK_6, + AK_7, AK_8, AK_9, AK_0, AK_MINUS, AK_EQUAL, AK_BS, AK_HELP, + + AK_NPLPAREN, AK_NPRPAREN, -1, AK_NPDIV, AK_NPMUL, AK_NPSUB, AK_TAB, AK_Q, + AK_W, AK_E, AK_R, AK_T, AK_Y, AK_U, AK_I, AK_O, + + AK_P, AK_LBRACKET, AK_RBRACKET, AK_BACKSLASH, AK_DEL, AK_LALT, AK_RALT, AK_NP7, + AK_NP8, AK_NP9, AK_NPADD, AK_CAPSLOCK, AK_A, AK_S, AK_D, AK_F, + + AK_G, AK_H, AK_J, AK_K, AK_L, AK_SEMICOLON, AK_QUOTE, AK_RET, + AK_NP4, AK_NP5, AK_NP6, AK_LSH, AK_Z, AK_X, AK_C, AK_V, + + AK_B, AK_N, AK_M, AK_COMMA, AK_PERIOD, AK_SLASH, AK_RSH, AK_UP, + AK_NP1, AK_NP2, AK_NP3, AK_ENT, AK_CTRL, AK_LAMI, AK_SPC, AK_RAMI, + + AK_RALT, AK_LF, AK_DN, AK_RT, AK_NP0, AK_NPDEL, AK_LALT, AK_RALT, + AK_LTGT, -1, -1, -1, -1, -1, -1, -1, + + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 +}; /* * Create application object and start it */ -UAE *the_app; - main() { the_app = new UAE(); @@ -56,55 +121,33 @@ main() UAE::UAE() : BApplication('UAEm') { the_bitmap = NULL; - the_emulator = NULL; main_window = NULL; window_open = FALSE; -// Init Key events - CurentEvent = (Event*)malloc(sizeof(Event)); - LastEvent=CurentEvent; - CurentEvent->Age=0; - CurentEvent->Next=0; } + +/* + * Copy command line arguments + */ + void UAE::ArgvReceived(int argc, char **argv) { - parse_cmdline(argc,argv); + the_argc = argc; + the_argv = new char *[argc]; + for (int i=0; iBits(); - gfxvidinfo.rowbytes = the_bitmap->BytesPerRow(); - gfxvidinfo.pixbytes = 1; - gfxvidinfo.maxblocklines = 100; - gfxvidinfo.maxlinetoscr = 0; - gfxvidinfo.x_adjust = 0; - gfxvidinfo.maxline = 100000; /* ??? */ - - // Open window - main_window = new UAEWindow(BRect(0, 0, hpixels-1, vsize+B_MENU_BAR_HEIGHT), the_bitmap); - - // Initialize mouse and keyboard variables - buttonstate[0] = buttonstate[1] = buttonstate[2] = FALSE; - lastmx = lastmy = 0; - newmousecounters = FALSE; - inwindow = TRUE; - - // Start emulation - the_emulator = new Emulator; - the_emulator->Run(); + // Start the emulation thread + the_thread = spawn_thread(thread_func, "UAE 68000", B_NORMAL_PRIORITY, this); + resume_thread(the_thread); } @@ -114,21 +157,25 @@ void UAE::ReadyToRun(void) bool UAE::QuitRequested(void) { - if (BApplication::QuitRequested()) { + // Quit the thread + long l; + quit_program = 1; + regs.spcflags |= SPCFLAG_BRK; + wait_for_thread(the_thread, &l); - // Stop emulation - if (the_emulator) { - the_emulator->Quit(); - delete the_emulator; - } + return TRUE; +} - // Deallocate bitmap - if (the_bitmap) - delete the_bitmap; - return TRUE; - } - return FALSE; +/* + * The thread's main function + */ + +long UAE::thread_func(void *obj) +{ + real_main(the_argc, the_argv); + close_sound(); + return 0; } @@ -140,244 +187,237 @@ void UAE::AboutRequested(void) { char str[256]; - sprintf(str, " Un*x Amiga Emulator V"VersionStr"\n" - " by Bernd Schmidt\n" - " BeBox port by Christian Bauer\n" - "Additional porting by Patrick Hanevold"); + sprintf(str, " Un*x Amiga Emulator V%d.%d.%d\n" + " by Bernd Schmidt\n" + " BeBox port by Christian Bauer\n" + "Additional porting by Patrick Hanevold", UAEMAJOR, UAEMINOR, UAEURSAMINOR); BAlert *the_alert = new BAlert("", str, "OK"); the_alert->Go(); } -//void UAE::MessageReceived(BMessage *Msg) -//{ -// switch(Msg->what) -// { -// default: -// BApplication::MessageReceived(Msg); -// } -//} - -char *DiskName[4]; -char *FileName[4]; -int FloppyN; - -void UAE::RefsReceived(BMessage *Msg) -{ - ulong type; - long count; - BFile *File; - BDirectory *dir,*dir2; - char FileNm[256]; // = (char*)Msg->FindString("filename"); - char Path1[512]=""; - char Path2[512]=""; - int err; - - Msg->GetInfo("refs",&type,&count); - for(long n=--count;n>=0;n--){ - record_ref item = Msg->FindRef("refs",n); - if(item.database>=0 && item.record>=0){ - if(does_ref_conform(item,"File")){ - File = new BFile; - File->SetRef(item); - File->GetName(FileNm); - DiskName[FloppyN]=FileNm; - File->GetName(Path2); - dir = new BDirectory; - dir2 = new BDirectory; - err = File->GetParent(dir); - while(err == B_NO_ERROR) - { - dir->GetName(Path1); - if(strlen(Path2)) - { - strcat(Path1,"/"); - strcat(Path1,Path2); - } - strcpy(Path2,Path1); - err = dir->GetParent(dir2); - if(err==B_NO_ERROR) dir->SetRef(dir2->Record()->Ref()); - } - strcpy(Path1,"/"); - strcat(Path1,Path2); -// strcpy(FileName[FloppyN],Path1); - FileName[FloppyN]=Path1; - disk_eject(FloppyN); - disk_insert(FloppyN,Path1); - delete(dir); - delete(dir2); - delete(File); - } - //else BRecord *rec = new BRecord(item); - } - } -} -void UAE::FilePanelClosed(BMessage *Msg) +/* + * Run file panel for floppy disk image selection + */ + +void UAEWindow::request_floppy(char *title, int drive_num) { + BMessage *sendmsg = new BMessage(B_REFS_RECEIVED); + sendmsg->AddLong("uae_drive_num", drive_num); + be_app->RunFilePanel(title, "Insert", NULL, FALSE, sendmsg); } -void UAE::RequestFile(char *Title,int Drive) + +/* + * File panel reply + */ + +void UAE::RefsReceived(BMessage *msg) { - FloppyN=Drive; - RunFilePanel(Title,"Insert","Eject",FALSE,NULL); + ulong type; + long count; + char path[512]; + + // Find drive number (default is 0) + int drive_num = msg->FindLong("uae_drive_num"); + + // Find path of file + msg->GetInfo("refs", &type, &count); + for (int i=--count; i>=0; i--) { + record_ref item = msg->FindRef("refs", i); + if (item.database >= 0 && item.record >= 0 && does_ref_conform(item, "File")) { + BFile *file = new BFile; + file->SetRef(item); + file->GetPath(path, 511); + + // Eject old disk, then insert new one + disk_eject(drive_num); + disk_insert(drive_num, path); + delete file; + } + } } + /* * UAE Window constructor */ -LEDView *PowerLED,*DriveLED; +LEDView *PowerLED, *DriveLED[4]; -#define M_DF0 'MDF0' -#define M_DF1 'MDF1' -#define M_DF2 'MDF2' -#define M_DF3 'MDF3' -#define M_FR1 'MFR1' -#define M_FR2 'MFR2' -#define M_FR3 'MFR3' -#define M_FR4 'MFR4' -#define M_FR5 'MFR5' -#define M_FR6 'MFR6' -#define M_FR7 'MFR7' - -UAEWindow::UAEWindow(BRect frame, BBitmap *bitmap) : BWindow(frame,"UAE "VersionStr, B_TITLED_WINDOW, B_NOT_RESIZABLE|B_NOT_ZOOMABLE) -{ - BRect MenuRect = Bounds(); - BRect PowerRect = Bounds(); - BRect DriveRect = Bounds(); - BRect MeterRect = Bounds(); - MenuRect.bottom = MenuRect.top + B_MENU_BAR_HEIGHT; - MenuRect.right -= 8; - DriveRect.bottom = MenuRect.bottom; - DriveRect.left = MenuRect.right+1; - DriveRect.right = DriveRect.left+3; - PowerRect.bottom = MenuRect.bottom; - PowerRect.left = DriveRect.right+1; - PowerRect.right = PowerRect.left+3; - MeterRect.left += 50; - MeterRect.right -= 15; - MeterRect.top += 5; - MeterRect.bottom = B_MENU_BAR_HEIGHT-5; - - BView *DriveView = new BView(DriveRect,"",B_FOLLOW_NONE, B_WILL_DRAW); - - BMenuBar *MenuBar = new BMenuBar(MenuRect,"MenuBar",B_FOLLOW_LEFT_RIGHT|B_FOLLOW_TOP, B_ITEMS_IN_ROW, FALSE); - - BMenu *Menu; - BMenu *SubMenu; - BMenuItem *DriveItem[4],*RateItem[7]; - - DiskName[0]=df0; - DiskName[1]=df1; - DiskName[2]=df2; - DiskName[3]=df3; - Menu = new BMenu("Amiga", B_ITEMS_IN_COLUMN); MenuBar->AddItem(Menu); - SubMenu = new BMenu("Floppy", B_ITEMS_IN_COLUMN); Menu->AddItem(SubMenu); - DriveItem[0] = new BMenuItem(DiskName[0], new BMessage(M_DF0), NULL); SubMenu->AddItem(DriveItem[0]); - DriveItem[1] = new BMenuItem(DiskName[1], new BMessage(M_DF1), NULL); SubMenu->AddItem(DriveItem[1]); - DriveItem[2] = new BMenuItem(DiskName[2], new BMessage(M_DF2), NULL); SubMenu->AddItem(DriveItem[2]); - DriveItem[3] = new BMenuItem(DiskName[3], new BMessage(M_DF3), NULL); SubMenu->AddItem(DriveItem[3]); - SubMenu = new BMenu("Framerate", B_ITEMS_IN_COLUMN); Menu->AddItem(SubMenu); - SubMenu->SetRadioMode(TRUE); - RateItem[0] = new BMenuItem("1/1", new BMessage(M_FR1), NULL); SubMenu->AddItem(RateItem[0]); - RateItem[1] = new BMenuItem("1/2", new BMessage(M_FR2), NULL); SubMenu->AddItem(RateItem[1]); - RateItem[2] = new BMenuItem("1/3", new BMessage(M_FR3), NULL); SubMenu->AddItem(RateItem[2]); - RateItem[3] = new BMenuItem("1/4", new BMessage(M_FR4), NULL); SubMenu->AddItem(RateItem[3]); - RateItem[4] = new BMenuItem("1/5", new BMessage(M_FR5), NULL); SubMenu->AddItem(RateItem[4]); - RateItem[5] = new BMenuItem("1/6", new BMessage(M_FR6), NULL); SubMenu->AddItem(RateItem[5]); - RateItem[6] = new BMenuItem("1/7", new BMessage(M_FR7), NULL); SubMenu->AddItem(RateItem[6]); - RateItem[3]->SetMarked(TRUE); +UAEWindow::UAEWindow(BRect frame, BBitmap *bitmap) : BWindow(frame,"UAE", B_TITLED_WINDOW, B_NOT_RESIZABLE|B_NOT_ZOOMABLE) +{ + int i; + // Move window to right position + Lock(); + MoveTo(80, 80); + + // Set up menus + BMenuBar *MenuBar = new BMenuBar(Bounds(), "", B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP, B_ITEMS_IN_ROW, TRUE); + + BMenu *Menu; + BMenu *SubMenu; + BMenuItem *RateItem[7]; + + Menu = new BMenu("Amiga"); MenuBar->AddItem(Menu); + SubMenu = new BMenu("Framerate"); Menu->AddItem(SubMenu); + SubMenu->SetRadioMode(TRUE); + RateItem[0] = new BMenuItem("1/1", new BMessage(MSG_FR1)); SubMenu->AddItem(RateItem[0]); + RateItem[1] = new BMenuItem("1/2", new BMessage(MSG_FR2)); SubMenu->AddItem(RateItem[1]); + RateItem[2] = new BMenuItem("1/3", new BMessage(MSG_FR3)); SubMenu->AddItem(RateItem[2]); + RateItem[3] = new BMenuItem("1/4", new BMessage(MSG_FR4)); SubMenu->AddItem(RateItem[3]); + RateItem[4] = new BMenuItem("1/5", new BMessage(MSG_FR5)); SubMenu->AddItem(RateItem[4]); + RateItem[5] = new BMenuItem("1/6", new BMessage(MSG_FR6)); SubMenu->AddItem(RateItem[5]); + RateItem[6] = new BMenuItem("1/7", new BMessage(MSG_FR7)); SubMenu->AddItem(RateItem[6]); + Menu->AddItem(new BMenuItem("Reset", new BMessage(MSG_RESET))); + Menu->AddItem(new BMenuItem("Debugger", new BMessage(MSG_DEBUG))); + Menu = new BMenu("Floppy"); MenuBar->AddItem(Menu); + SubMenu = new BMenu("DF0:"); Menu->AddItem(SubMenu); + SubMenu->AddItem(new BMenuItem("Insert...", new BMessage(MSG_INSERT_DF0))); + SubMenu->AddItem(new BMenuItem("Eject", new BMessage(MSG_EJECT_DF0))); + SubMenu = new BMenu("DF1:"); Menu->AddItem(SubMenu); + SubMenu->AddItem(new BMenuItem("Insert...", new BMessage(MSG_INSERT_DF1))); + SubMenu->AddItem(new BMenuItem("Eject", new BMessage(MSG_EJECT_DF1))); + SubMenu = new BMenu("DF2:"); Menu->AddItem(SubMenu); + SubMenu->AddItem(new BMenuItem("Insert...", new BMessage(MSG_INSERT_DF2))); + SubMenu->AddItem(new BMenuItem("Eject", new BMessage(MSG_EJECT_DF2))); + SubMenu = new BMenu("DF3:"); Menu->AddItem(SubMenu); + SubMenu->AddItem(new BMenuItem("Insert...", new BMessage(MSG_INSERT_DF3))); + SubMenu->AddItem(new BMenuItem("Eject", new BMessage(MSG_EJECT_DF3))); + RateItem[0]->SetMarked(TRUE); AddChild(MenuBar); -// AddChild(DriveView); -// Lock(); -// DriveView->SetHighColor(0xff,0,0); -// DriveView->FillRect(DriveRect,B_SOLID_HIGH); -// Unlock(); - -// SetPulseRate(500000.0/100.0); - - DriveLED = new LEDView(DriveRect,0xff,0x80,0,0x80,0x40,0); - AddChild(DriveLED); - PowerLED = new LEDView(PowerRect,0,0xe0,0,0,0xb0,0); - AddChild(PowerLED); - MeterView *Meter = new MeterView(MeterRect); - AddChild(Meter); - int r, g, b, i; + // Resize window to fit menu bar + MenuBar->ResizeBy(-5*4, 0); // Make room for LEDs + BRect MenuRect = MenuBar->Frame(); + ResizeBy(0, MenuRect.bottom + 1); + SetDiscipline(FALSE); - // Move window to right position - MoveTo(80, 60); + // Create LEDs + BRect PowerRect = Bounds(); + PowerRect.bottom = MenuRect.bottom; + PowerRect.left = MenuRect.right+1; + PowerRect.right = PowerRect.left+3; + PowerLED = new LEDView(PowerRect, PowerLight, PowerDark); + AddChild(PowerLED); + + BRect DriveRect = PowerRect; + for (i=0; i<4; i++) { + DriveRect.left += 4; + DriveRect.right += 4; + DriveLED[i] = new LEDView(DriveRect, DriveLight, DriveDark); + AddChild(DriveLED[i]); + } // Create bitmap view - Lock(); - frame.Set(0,B_MENU_BAR_HEIGHT+1,hsize-1,vsize+B_MENU_BAR_HEIGHT); - main_view = new BitmapView(frame, bitmap); + BRect BitmapRect = frame; + BitmapRect.OffsetTo(0, MenuRect.bottom + 1); + main_view = new BitmapView(BitmapRect, bitmap); AddChild(main_view); main_view->MakeFocus(); main_view->GetKeys(&old_key_info, FALSE); - Unlock(); bitmap_view = main_view; bitmap_window = this; // Initialize xcolors i = 0; - for (r=0; r<16; r++) { - for (g=0; g<16; g++) { - for (b=0; b<16; b++) + for (int r=0; r<16; r++) { + for (int g=0; g<16; g++) { + for (int b=0; b<16; b++) xcolors[i++] = index_for_color(r<<4 | r, g<<4 | g, b<<4 | b); } } // Show window + Unlock(); Show(); window_open = TRUE; } -void UAEWindow::MessageReceived(BMessage *Msg) + +/* + * Message received + */ + +void UAEWindow::MessageReceived(BMessage *msg) { - switch(Msg->what) - { - case M_DF0: - the_app->RequestFile("Insert floppy in DF0:",0); - break; - case M_DF1: - the_app->RequestFile("Insert floppy in DF1:",1); - break; - case M_DF2: - the_app->RequestFile("Insert floppy in DF2:",2); - break; - case M_DF3: - the_app->RequestFile("Insert floppy in DF3:",3); - break; - case M_FR1: - framerate = 1; - break; - case M_FR2: - framerate = 2; - break; - case M_FR3: - framerate = 3; - break; - case M_FR4: - framerate = 4; - break; - case M_FR5: - framerate = 5; - break; - case M_FR6: - framerate = 6; - break; - case M_FR7: - framerate = 7; - break; - default: - printf("Err\n"); - BWindow::MessageReceived(Msg); + BMessage *msg2; + + switch(msg->what) { + case MSG_INSERT_DF0: + request_floppy("Insert floppy in DF0:", 0); + break; + case MSG_EJECT_DF0: + disk_eject(0); + break; + case MSG_INSERT_DF1: + request_floppy("Insert floppy in DF1:", 1); + break; + case MSG_EJECT_DF1: + disk_eject(1); + break; + case MSG_INSERT_DF2: + request_floppy("Insert floppy in DF2:", 2); + break; + case MSG_EJECT_DF2: + disk_eject(2); + break; + case MSG_INSERT_DF3: + request_floppy("Insert floppy in DF3:", 3); + break; + case MSG_EJECT_DF3: + disk_eject(3); + break; + + case MSG_FR1: + framerate = 1; + break; + case MSG_FR2: + framerate = 2; + break; + case MSG_FR3: + framerate = 3; + break; + case MSG_FR4: + framerate = 4; + break; + case MSG_FR5: + framerate = 5; + break; + case MSG_FR6: + framerate = 6; + break; + case MSG_FR7: + framerate = 7; + break; + + case MSG_RESET: + reset_thyself = TRUE; + break; + + case MSG_DEBUG: + activate_debugger(); + break; + + case MSG_REDRAW: + MessageQueue()->Lock(); + while ((msg2 = MessageQueue()->FindMessage(MSG_REDRAW, 0)) != NULL) + MessageQueue()->RemoveMessage(msg2); + MessageQueue()->Unlock(); + Lock(); + main_view->Draw(BRect(0, 0, gfx_requested_width-1, gfx_requested_height-1)); + Unlock(); + break; + + default: + BWindow::MessageReceived(msg); + break; } } + /* * Closing the window quits UAE */ @@ -386,20 +426,11 @@ bool UAEWindow::QuitRequested(void) { window_open = FALSE; be_app->PostMessage(B_QUIT_REQUESTED); - return TRUE; + return FALSE; } /* - * Window was (de)activated - */ - -void UAEWindow::WindowActivated(bool active) -{ - inwindow = active; -} - -/* * Bitmap view constructor */ @@ -415,11 +446,7 @@ BitmapView::BitmapView(BRect frame, BBit void BitmapView::Draw(BRect update) { - int xs = use_lores ? prev_max_diwstop - 328 : 0; - BRect from=update; - from.left+=xs; - from.right+=xs; - DrawBitmap(the_bitmap, from, update); + DrawBitmap(the_bitmap, update, update); } void BitmapView::Draw(BRect from, BRect to) @@ -427,252 +454,166 @@ void BitmapView::Draw(BRect from, BRect DrawBitmap(the_bitmap, from, to); } -//char KeyState[256]; -char RawKeys[128]={ -// 0 1 2 3 4 5 6 7 8 9 A B C D E F -/* 00 */ 0, 0, 0, 0, 0, 0, 0, 0, AK_BS,AK_TAB,AK_RET,0, 0, 0, 0, 0, -/* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, AK_ESC, 0, 0, 0, 0, -/* 20 */ AK_SPC,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, AK_NPADD, 0, AK_NPSUB,0, 0, -/* 30 */ AK_0, AK_1,AK_2,AK_3,AK_4,AK_5,AK_6,AK_7,AK_8, AK_9, 0, AK_SEMICOLON,0, 0, 0, 0, -/* 40 */ 0, AK_A,AK_B,AK_C,AK_D,AK_E,AK_F,AK_G,AK_H, AK_I, AK_J, AK_K, AK_L, AK_M, AK_N,AK_O, -/* 50 */ AK_P, AK_Q,AK_R,AK_S,AK_T,AK_U,AK_V,AK_W,AK_X, AK_Y, AK_Z, 0, AK_BACKSLASH,0, 0, 0, -/* 60 */ 0, AK_A,AK_B,AK_C,AK_D,AK_E,AK_F,AK_G,AK_H, AK_I, AK_J, AK_K, AK_L, AK_M, AK_N,AK_O, -/* 70 */ AK_P, AK_Q,AK_R,AK_S,AK_T,AK_U,AK_V,AK_W,AK_X, AK_Y, AK_Z, 0, 0, 0, 0, AK_DEL}; - -void BitmapView::KeyDown(ulong aChar) -{ -// printf("$%x\n",aChar); -/* - Event *NewEvent=(Event*)malloc(sizeof(Event)); - NewEvent->Next=0; - NewEvent->Age=3; - if((aChar>0x40)&&(aChar<0x5b)){ - NewEvent->Key=AK_LSH; - LastEvent->Next=NewEvent; - LastEvent=NewEvent; - NewEvent=(Event*)malloc(sizeof(Event)); - NewEvent->Next=0; - NewEvent->Age=3; - NewEvent->Key=RawKeys[aChar]; - LastEvent->Next=NewEvent; - LastEvent=NewEvent; - NewEvent=(Event*)malloc(sizeof(Event)); - NewEvent->Next=0; - NewEvent->Age=3; - NewEvent->Key=AK_LSH; - }else{ - switch(aChar) - { - case 0x3a: - NewEvent->Key=AK_LSH; - LastEvent->Next=NewEvent; - LastEvent=NewEvent; - NewEvent=(Event*)malloc(sizeof(Event)); - NewEvent->Next=0; - NewEvent->Age=3; - NewEvent->Key=AK_SEMICOLON; - LastEvent->Next=NewEvent; - LastEvent=NewEvent; - NewEvent=(Event*)malloc(sizeof(Event)); - NewEvent->Next=0; - NewEvent->Age=3; - NewEvent->Key=AK_LSH; - break; - default: - NewEvent->Key=RawKeys[aChar]; - } - } - LastEvent->Next=NewEvent; - LastEvent=NewEvent; -*/ -} /* - * LED + * Key pressed */ -LEDView::LEDView(BRect frame, int aR, int aG, int aB, int iR, int iG, int iB) : BView(frame,"", B_FOLLOW_NONE, B_WILL_DRAW) +void BitmapView::KeyDown(ulong aChar) { - ActiveColor.R=aR; - ActiveColor.G=aG; - ActiveColor.B=aB; - IdleColor.R=iR; - IdleColor.G=iG; - IdleColor.B=iB; - State = FALSE; + // Break key jumps into debugger + if (aChar == B_FUNCTION_KEY && Window()->CurrentMessage()->FindLong("key") == B_PAUSE_KEY) + activate_debugger(); } -void LEDView::AttachedToWindow(void) -{ - bounds = Bounds(); -} -void LEDView::Draw(BRect update) -{ - Refresh(); -} +/* + * Mouse moved + */ -void LEDView::SetState(bool NewState) +void BitmapView::MouseMoved(BPoint point, ulong transit, BMessage *message) { - if(NewState!=State) - { - State = NewState; - Refresh(); + newmousecounters = 0; + switch (transit) { + case B_ENTERED_VIEW: + newmousecounters = 1; + lastmx = point.x; + lastmy = point.y; + break; + case B_EXITED_VIEW: + break; + case B_INSIDE_VIEW: + lastmx = point.x; + lastmy = point.y; + break; } } -void LEDView::Refresh(void) -{ - Window()->Lock(); - if(State) SetHighColor(ActiveColor.R,ActiveColor.G,ActiveColor.B); - else SetHighColor(IdleColor.R,IdleColor.G,IdleColor.B); - FillRect(bounds); - Window()->Unlock(); -} /* - * Meter + * LED */ -MeterView::MeterView(BRect frame) : BView(frame,"", B_FOLLOW_NONE, B_WILL_DRAW|B_PULSE_NEEDED) -{ -} - -void MeterView::AttachedToWindow(void) +LEDView::LEDView(BRect frame, rgb_color active, rgb_color idle) : BView(frame, "", B_FOLLOW_NONE, B_WILL_DRAW) { + active_color = active; + idle_color = idle; + state = FALSE; + SetViewColor(idle_color); + SetHighColor(idle_color); bounds = Bounds(); } -void MeterView::Draw(BRect) +void LEDView::Draw(BRect update) { - Refresh(); + FillRect(bounds); } -void MeterView::Pulse(void) +void LEDView::SetState(bool new_state) { - Refresh(); + if (new_state != state) { + state = new_state; + Window()->Lock(); + if (state) { + SetViewColor(active_color); + SetHighColor(active_color); + } else { + SetViewColor(idle_color); + SetHighColor(idle_color); + } + Draw(bounds); + Window()->Unlock(); + } } -void MeterView::Refresh(void) -{ - ulong Speed=frametime/timeframes; - int Frames=Speed/20+1; - BRect Fine=bounds; - Fine.left=Fine.right-(bounds.right-bounds.left)/Frames; - Fine.right=Fine.left+(Speed-20*(Frames-1))*((bounds.right-bounds.left)/Frames)/20; - Window()->Lock(); - SetHighColor(0,0,0); - FillRect(bounds); - SetHighColor(255,0,0); - FillRect(Fine); - int R=255-200/Frames; - for(int n=Frames-1; n; n--){ - R-=200/Frames; - SetHighColor(R,0,0); - Fine.left=(n-1)*((bounds.right-bounds.left)/Frames); - Fine.right=n*((bounds.right-bounds.left)/Frames); - FillRect(Fine); - } - Window()->Unlock(); -} /* - * Start main emulation thread - */ - -void Emulator::Run(void) -{ - // Initialize everything - produce_sound = TRUE; - init_sound(); - gui_init(); - init_joystick(); - keybuf_init (); - memory_init(); - custom_init(); - DISK_init(); - init_m68k(); - MC68000_reset(); + * Redraw a line + */ - // Start the emulation thread - the_thread = spawn_thread(thread_invoc, "UAE 68000", B_NORMAL_PRIORITY, this); - resume_thread(the_thread); - thread_running = TRUE; +void flush_line(int y) +{ + if (window_open) { + bitmap_window->Lock(); + bitmap_view->Draw(BRect(0, y, gfx_requested_width-1, y)); + bitmap_window->Unlock(); + } } /* - * Stop main emulation thread + * Redraw a block */ -void Emulator::Quit(void) +void flush_block(int ystart, int ystop) { - // Kill the thread if it is running - if (thread_running) { - kill_thread(the_thread); - thread_running = FALSE; - } - - close_joystick(); - deinit_sound(); } /* - * The thread's main function + * Redraw the screen */ -long Emulator::thread_invoc(void *data) //Emulator *obj) -{ - Emulator *obj = (Emulator*)data; - obj->thread_func(); - return 0; -} - -void Emulator::thread_func(void) +void flush_screen(int ystart, int ystop) { - // This jumps to MC68000_run() and executes the main loop - debug(); - thread_running = FALSE; + if (window_open) + bitmap_window->PostMessage(new BMessage(MSG_REDRAW)); } /* - * Redraw a line + * Init graphics */ -void flush_line(int y) +int graphics_init(void) { - if (window_open) { - bitmap_window->Lock(); - bitmap_view->Draw(BRect(0, y, hpixels+-1, y)); - bitmap_window->Unlock(); - } + return the_app->GraphicsInit(); } +int UAE::GraphicsInit(void) +{ + if (gfx_requested_width < 320) + gfx_requested_width = 320; + if (gfx_requested_height < 200) + gfx_requested_height = 200; -/* - * Redraw a block - */ + gfxvidinfo.maxlinetoscr = gfx_requested_width; + gfxvidinfo.maxline = gfx_requested_height; -void flush_block(int ystart, int ystop) -{ - int xs = use_lores ? prev_max_diwstop - 328 : 0; + // Allocate bitmap + the_bitmap = new BBitmap(BRect(0, 0, gfx_requested_width-1, gfx_requested_height-1), B_COLOR_8_BIT); - if (window_open) { - bitmap_window->Lock(); - bitmap_view->Draw(BRect(xs, ystart, hpixels+xs-1, ystop), BRect(0, ystart, hpixels-1, ystop)); - bitmap_window->Unlock(); - } + // Set up vidinfo + gfxvidinfo.pixbytes = 1; + gfxvidinfo.rowbytes = the_bitmap->BytesPerRow(); + gfxvidinfo.bufmem = (char *)the_bitmap->Bits(); + gfxvidinfo.maxblocklines = 100; /* whatever... */ + + // Open window + main_window = new UAEWindow(BRect(0, 0, gfx_requested_width-1, gfx_requested_height-1), the_bitmap); + + // Initialize mouse and keyboard variables + buttonstate[0] = buttonstate[1] = buttonstate[2] = 0; + lastmx = lastmy = 0; + newmousecounters = 0; + + return TRUE; } /* - * Redraw the screen + * Exit graphics */ -void flush_screen(int ystart, int ystop) +void graphics_leave(void) +{ + the_app->GraphicsLeave(); +} + +void UAE::GraphicsLeave(void) { + // Deallocate bitmap + delete the_bitmap; } @@ -687,80 +628,61 @@ void handle_events(void) BPoint mouse_point; ulong mouse_buttons; - // Keyboard - if (window_open && inwindow) { + if (reset_thyself) { + m68k_reset(); + reset_thyself = FALSE; + } + + // Redraw drive LEDs + for (int i=0; i<4; i++) + DriveLED[i]->SetState(LEDs[i]); + + if (window_open && bitmap_window->IsActive()) { + bitmap_window->Lock(); bitmap_view->GetKeys(&the_key_info, FALSE); + bitmap_view->GetMouse(&mouse_point, &mouse_buttons, FALSE); bitmap_window->Unlock(); - for (be_code=0; be_code<0x80; be_code++) { - be_byte = be_code >> 3; - be_bit = 1 << (~be_code & 7); - - // Key state changed? - if ((the_key_info.key_states[be_byte] & be_bit) - != (old_key_info.key_states[be_byte] & be_bit)) { - - amiga_code = keycode2amiga[be_code]; - if (the_key_info.key_states[be_byte] & be_bit) { - - // Key pressed - if (amiga_code == AK_mousestuff) - togglemouse(); - else - printf("Key\n"); - record_key(amiga_code << 1); - } else { + // Keyboard + if (memcmp(the_key_info.key_states, old_key_info.key_states, sizeof(the_key_info.key_states))) { + for (be_code=0; be_code<0x80; be_code++) { + be_byte = be_code >> 3; + be_bit = 1 << (~be_code & 7); + + // Key state changed? + if ((the_key_info.key_states[be_byte] & be_bit) + != (old_key_info.key_states[be_byte] & be_bit)) { + + amiga_code = keycode2amiga[be_code]; + if (the_key_info.key_states[be_byte] & be_bit) { + + // Key pressed + if (amiga_code == AK_mousestuff) + togglemouse(); + else + record_key(amiga_code << 1); + } else { - // Key released - record_key((amiga_code << 1) | 1); + // Key released + record_key((amiga_code << 1) | 1); + } } - } - } - old_key_info = the_key_info; + } + old_key_info = the_key_info; + } // "Affengriff" if ((the_key_info.key_states[0x5c >> 3] & (1 << (~0x5c & 7))) && (the_key_info.key_states[0x5d >> 3] & (1 << (~0x5d & 7))) && (the_key_info.key_states[0x5f >> 3] & (1 << (~0x5f & 7)))) - MC68000_reset(); + m68k_reset(); // Scroll lock toggles inhibit_frame inhibit_frame = the_key_info.key_states[0x0f >> 3] & (1 << (~0x0f & 7)); -/* - static bool ShiftState=FALSE; - if(CurentEvent->Age){ - if(CurentEvent->Key==AK_LSH){ - CurentEvent->Age--; - if(CurentEvent->Age==2){ - if(ShiftState) {record_key((AK_LSH<<1)|1); ShiftState=FALSE; printf("ShU\n");} - else {record_key(AK_LSH<<1); ShiftState=TRUE; printf("ShD\n");} - } - }else{ - CurentEvent->Age--; - if(CurentEvent->Age==2) record_key(CurentEvent->Key<<1); - if(CurentEvent->Age==0) record_key((CurentEvent->Key<<1)|1); - } - } - else{ - if(CurentEvent->Next) - { - Event *TrashEvent=CurentEvent; - CurentEvent=CurentEvent->Next; - free(TrashEvent); - } - } -*/ - } - // Mouse - if (window_open && inwindow) { - bitmap_window->Lock(); - bitmap_view->GetMouse(&mouse_point, &mouse_buttons, FALSE); - bitmap_window->Unlock(); - lastmx = mouse_point.x; - lastmy = mouse_point.y; - if(lastmx>=0&&lastmy>=0&&lastmx= 0 && mouse_point.y >= 0 && mouse_point.x < gfx_requested_width && mouse_point.y < gfx_requested_height) { buttonstate[0] = mouse_buttons & B_PRIMARY_MOUSE_BUTTON; buttonstate[1] = mouse_buttons & B_TERTIARY_MOUSE_BUTTON; buttonstate[2] = mouse_buttons & B_SECONDARY_MOUSE_BUTTON; @@ -768,65 +690,230 @@ void handle_events(void) } } -int debuggable(void) + +/* + * Joystick routines + */ + +void read_joystick(UWORD *dir, int *button) { - return TRUE; + static int joy_minx = 32767, joy_maxx = 0, + joy_miny = 32767, joy_maxy = 0; + int left = 0, right = 0, top = 0, bot = 0; + + *dir = 0; + *button = 0; + + if (joy->Update() != B_ERROR) { + if (joy->horizontal > joy_maxx) + joy_maxx = joy->horizontal; + if (joy->horizontal < joy_minx) + joy_minx = joy->horizontal; + if (joy->vertical > joy_maxy) + joy_maxy = joy->vertical; + if (joy->vertical < joy_miny) + joy_miny = joy->vertical; + + if (joy_maxx-joy_minx < 100 || joy_maxy-joy_miny < 100) + return; + + if (joy->horizontal < (joy_minx + (joy_maxx-joy_minx)/3)) + right = 1; + else if (joy->horizontal > (joy_minx + 2*(joy_maxx-joy_minx)/3)) + left = 1; + + if (joy->vertical < (joy_miny + (joy_maxy-joy_miny)/3)) + bot = 1; + else if (joy->vertical > (joy_miny + 2*(joy_maxy-joy_miny)/3)) + top = 1; + + if (left) top = !top; + if (right) bot = !bot; + *dir = bot | (right << 1) | (top << 8) | (left << 9); + *button = !joy->button1; + } } -int needmousehack(void) +void init_joystick(void) { - return TRUE; + joy = new BJoystick(); + joy->Open("joystick1"); } -void LED(int on) +void close_joystick(void) { -// printf("PowerLED: %d\n",on); - PowerLED->SetState((bool)~on); + joy->Close(); + delete joy; } -bool LEDs[4]; -void gui_led(int led, int on) +/* + * Sound routines + */ + +#ifndef DONT_WANT_SOUND +extern "C" { +extern UWORD *sndbuffer; +extern UWORD *bufpt; +extern int sound_available; +extern int smplcnt; +extern int sndbufsize; +extern int init_sound(void); +extern void flush_sound_buffer(void); +extern void init_sound_table8(void); +extern void init_sound_table16(void); +extern void sample8_handler(void); +extern void sample16_handler(void); +}; + +static UBYTE *buffers[2] = {NULL, NULL}; +static int buf_num; +static BAudioSubscriber *the_sub; +static bool sound_ready = FALSE; +static sem_id sound_sync_sem; + +bool stream_func(void *arg, char *buf, long count); + +int init_sound(void) { - if(led<4) - { - LEDs[led]=on; - DriveLED->SetState(LEDs[0]|LEDs[1]|LEDs[2]|LEDs[3]); -// printf("DriveLeds: %d,%d,%d,%d\n",LEDs[0],LEDs[1],LEDs[2],LEDs[3]); + sound_sync_sem = create_sem(0, "UAE Sound Sync Semaphore"); + the_sub = new BAudioSubscriber("UAE DAC subscriber"); + + if (!produce_sound) + return 0; + sound_ready = the_sub->Subscribe(B_DAC_STREAM, the_sub->ID(), FALSE) == B_NO_ERROR; + if (!sound_ready) + return 0; + + if (sound_desired_bsiz == 0) + sound_desired_bsiz = sound_desired_freq / 50 * 2; + sndbufsize = sound_desired_bsiz; + buffers[0] = new UBYTE[sndbufsize]; + buffers[1] = new UBYTE[sndbufsize]; + memset(buffers[0], 0, sndbufsize); + memset(buffers[1], 0, sndbufsize); + buf_num = 0; + sndbufpt = sndbuffer = (UWORD *)buffers[buf_num]; + + eventtab[ev_sample].evtime = (long)maxhpos * maxvpos * 50 / sound_desired_freq; + init_sound_table16(); + eventtab[ev_sample].handler = sample16_handler; + + sound_available = 1; + + the_sub->SetDACSampleInfo(2, 1, B_BIG_ENDIAN, B_LINEAR_SAMPLES); + the_sub->SetSamplingRate(sound_desired_freq); + the_sub->EnterStream(NULL, TRUE, NULL, stream_func, NULL, TRUE); + the_sub->SetStreamBuffers(sound_desired_bsiz, 4); + return 1; +} + +void close_sound(void) +{ + if (sound_ready) { + the_sub->ExitStream(TRUE); + the_sub->SetStreamBuffers(4096, 8); + the_sub->Unsubscribe(); + sound_ready = FALSE; } + delete the_sub; + + delete_sem(sound_sync_sem); + + delete buffers[0]; + delete buffers[1]; +} + +void flush_sound_buffer(void) +{ + if (sound_ready) { + long l; + get_sem_count(sound_sync_sem, &l); + if (l > 0) + acquire_sem_etc(sound_sync_sem, l+1, 0, 0); + else + acquire_sem(sound_sync_sem); + } + + sndbufpt = sndbuffer = (UWORD *)buffers[buf_num]; + buf_num ^= 1; +} + +bool stream_func(void *arg, char *buf, long count) +{ + memcpy(buf, buffers[buf_num], count); + release_sem(sound_sync_sem); + return TRUE; +} +#else +int init_sound(void) +{ + produce_sound = 0; + return 0; +} + +void close_sound(void) +{ +} +#endif + + +/* + * Misc routines + */ + +int debuggable(void) +{ + return TRUE; +} + +int needmousehack(void) +{ + return TRUE; } -void calc_adjustment(void) +void LED(int on) { - gfxvidinfo.x_adjust = 0; + PowerLED->SetState(!on); } void target_specific_usage(void) { + printf(" -S n : Sound emulation accuracy (n = 0, 1, 2 or 3)\n" + " For sound emulation, n = 2 is recommended\n"); + printf(" -R n : Use n Hz to output sound. Common values are\n" + " 22050 Hz or 44100 Hz\n"); + printf(" -B n : Use a sound buffer of n bytes (use small\n" + " values on fast machines)\n"); } -int quit_program; +void setup_brkhandler(void) +{ +} -static void sigchldhandler(int foo) +void gui_led(int led, int on) { + if (led > 0 && led < 5) + LEDs[led-1] = on; } int gui_init(void) { - LEDs[0]=LEDs[1]=LEDs[2]=LEDs[3]=FALSE; - quit_program = 0; - return 0; + LEDs[0] = LEDs[1] = LEDs[2] = LEDs[3] = FALSE; + quit_program = 0; + return 0; } void gui_exit(void) { } -//void gui_led(int led, int on) -//{ -//} +int gui_update(void) +{ + return 0; +} -void gui_filename(int num, char *name) +void gui_filename(int num, const char *name) { }