unsigned int get_m68k_cpu_type(char *name) {
for (int i = 0; i < M68K_CPU_TYPES; i++) {
if (strcmp(name, cpu_types[i]) == 0) {
- printf("Set CPU type to %s.\n", cpu_types[i]);
+ printf("[CFG] Set CPU type to %s.\n", cpu_types[i]);
return i + 1;
}
}
- printf ("Invalid CPU type %s specified, defaulting to 68000.\n", name);
+ printf("[CFG] Invalid CPU type %s specified, defaulting to 68000.\n", name);
return M68K_CPU_TYPE_68000;
}
case 'M': ret_int = ret_int * SIZE_MEGA; break;
case 'G': ret_int = ret_int * SIZE_GIGA; break;
default:
- printf("Unknown character %c in hex value.\n", str[i]);
+ printf("[CFG] Unknown character %c in hex value.\n", str[i]);
break;
}
}
index++;
}
if (index == MAX_NUM_MAPPED_ITEMS) {
- printf("Unable to map item, only %d items can be mapped with current binary.\n", MAX_NUM_MAPPED_ITEMS);
+ printf("[CFG] Unable to map item, only %d items can be mapped with current binary.\n", MAX_NUM_MAPPED_ITEMS);
return;
}
switch(type) {
case MAPTYPE_RAM:
- printf("Allocating %d bytes for RAM mapping (%d MB)...\n", size, size / 1024 / 1024);
+ printf("[CFG] Allocating %d bytes for RAM mapping (%d MB)...\n", size, size / 1024 / 1024);
cfg->map_data[index] = (unsigned char *)malloc(size);
if (!cfg->map_data[index]) {
- printf("ERROR: Unable to allocate memory for mapped RAM!\n");
+ printf("[CFG] ERROR: Unable to allocate memory for mapped RAM!\n");
goto mapping_failed;
}
memset(cfg->map_data[index], 0x00, size);
case MAPTYPE_ROM:
in = fopen(filename, "rb");
if (!in) {
- printf("Failed to open file %s for ROM mapping.\n", filename);
+ printf("[CFG] Failed to open file %s for ROM mapping.\n", filename);
goto mapping_failed;
}
fseek(in, 0, SEEK_END);
cfg->map_data[index] = (unsigned char *)calloc(1, cfg->map_size[index]);
cfg->rom_size[index] = (cfg->map_size[index] <= file_size) ? cfg->map_size[index] : file_size;
if (!cfg->map_data[index]) {
- printf("ERROR: Unable to allocate memory for mapped ROM!\n");
+ printf("[CFG] ERROR: Unable to allocate memory for mapped ROM!\n");
goto mapping_failed;
}
memset(cfg->map_data[index], 0x00, cfg->map_size[index]);
break;
}
- printf("[MAP %d] Added %s mapping for range %.8lX-%.8lX ID: %s\n", index, map_type_names[type], cfg->map_offset[index], cfg->map_high[index] - 1, cfg->map_id[index] ? cfg->map_id[index] : "None");
+ printf("[CFG] [MAP %d] Added %s mapping for range %.8lX-%.8lX ID: %s\n", index, map_type_names[type], cfg->map_offset[index], cfg->map_high[index] - 1, cfg->map_id[index] ? cfg->map_id[index] : "None");
if (cfg->map_size[index] == cfg->rom_size[index])
m68k_add_rom_range(cfg->map_offset[index], cfg->map_high[index], cfg->map_data[index]);
struct emulator_config *load_config_file(char *filename) {
FILE *in = fopen(filename, "rb");
if (in == NULL) {
- printf("Failed to open config file %s for reading.\n", filename);
+ printf("[CFG] Failed to open config file %s for reading.\n", filename);
return NULL;
}
parse_line = (char *)calloc(1, 512);
if (!parse_line) {
- printf("Failed to allocate memory for config file line buffer.\n");
+ printf("[CFG] Failed to allocate memory for config file line buffer.\n");
return NULL;
}
cfg = (struct emulator_config *)calloc(1, sizeof(struct emulator_config));
if (!cfg) {
- printf("Failed to allocate memory for temporary emulator config.\n");
+ printf("[CFG] Failed to allocate memory for temporary emulator config.\n");
goto load_failed;
}
mirraddr = get_int(cur_cmd);
break;
default:
- printf("Unknown/unhandled map argument %s on line %d.\n", cur_cmd, cur_line);
+ printf("[CFG] Unknown/unhandled map argument %s on line %d.\n", cur_cmd, cur_line);
break;
}
}
}
case CONFITEM_LOOPCYCLES:
cfg->loop_cycles = get_int(parse_line + str_pos);
- printf("Set CPU loop cycles to %d.\n", cfg->loop_cycles);
+ printf("[CFG] Set CPU loop cycles to %d.\n", cfg->loop_cycles);
break;
case CONFITEM_MOUSE:
get_next_string(parse_line, cur_cmd, &str_pos, ' ');
strcpy(cfg->mouse_file, cur_cmd);
get_next_string(parse_line, cur_cmd, &str_pos, ' ');
cfg->mouse_toggle_key = cur_cmd[0];
+ get_next_string(parse_line, cur_cmd, &str_pos, ' ');
+ cfg->mouse_autoconnect = (strcmp(cur_cmd, "autoconnect") == 0) ? 1 : 0;
cfg->mouse_enabled = 1;
- printf("Enabled mouse event forwarding from file %s, toggle key %c.\n", cfg->mouse_file, cfg->mouse_toggle_key);
+ printf("[CFG] Enabled mouse event forwarding from file %s, toggle key %c.\n", cfg->mouse_file, cfg->mouse_toggle_key);
break;
case CONFITEM_KEYBOARD:
get_next_string(parse_line, cur_cmd, &str_pos, ' ');
- cfg->keyboard_file = (char *)calloc(1, strlen(cur_cmd) + 1);
cfg->keyboard_toggle_key = cur_cmd[0];
- printf("Enabled keyboard event forwarding, toggle key %c.\n", cfg->keyboard_toggle_key);
+ get_next_string(parse_line, cur_cmd, &str_pos, ' ');
+ cfg->keyboard_grab = (strcmp(cur_cmd, "grab") == 0) ? 1 : 0;
+ get_next_string(parse_line, cur_cmd, &str_pos, ' ');
+ cfg->keyboard_autoconnect = (strcmp(cur_cmd, "autoconnect") == 0) ? 1 : 0;
+ printf("[CFG] Enabled keyboard event forwarding, toggle key %c", cfg->keyboard_toggle_key);
+ if (cfg->keyboard_grab)
+ printf(", locking from host when connected");
+ if (cfg->keyboard_autoconnect)
+ printf(", connected to guest at startup");
+ printf(".\n");
break;
case CONFITEM_KBFILE:
get_next_string(parse_line, cur_cmd, &str_pos, ' ');
cfg->keyboard_file = (char *)calloc(1, strlen(cur_cmd) + 1);
strcpy(cfg->keyboard_file, cur_cmd);
- printf("Set keyboard event source file to %s.\n", cfg->keyboard_file);
+ printf("[CFG] Set keyboard event source file to %s.\n", cfg->keyboard_file);
break;
case CONFITEM_PLATFORM: {
char platform_name[128], platform_sub[128];
memset(platform_name, 0x00, 128);
memset(platform_sub, 0x00, 128);
get_next_string(parse_line, platform_name, &str_pos, ' ');
- printf("Setting platform to %s", platform_name);
+ printf("[CFG] Setting platform to %s", platform_name);
get_next_string(parse_line, platform_sub, &str_pos, ' ');
if (strlen(platform_sub))
printf(" (sub: %s)", platform_sub);
}
case CONFITEM_SETVAR: {
if (!cfg->platform) {
- printf("Warning: esetvar used in config file with no platform specified.\n");
+ printf("[CFG] Warning: setvar used in config file with no platform specified.\n");
break;
}
}
case CONFITEM_NONE:
default:
- printf("Unknown config item %s on line %d.\n", cur_cmd, cur_line);
+ printf("[CFG] Unknown config item %s on line %d.\n", cur_cmd, cur_line);
break;
}
- skip_line:;
+ skip_line:
cur_line++;
}
goto load_successful;
extern uint8_t realtime_graphics_debug;
uint8_t realtime_disassembly, int2_enabled = 0;
uint32_t do_disasm = 0, old_level;
-char c = 0, c_code = 0, c_type = 0; // @todo temporary main/cpu_task scope workaround until input moved to a thread
uint32_t last_irq = 8, last_last_irq = 8;
+uint8_t end_signal = 0;
+
char disasm_buf[4096];
#define KICKBASE 0xF80000
// printf("CPU emulation reset.\n");
}
-
if (mouse_hook_enabled && (mouse_extra != 0x00)) {
// mouse wheel events have occurred; unlike l/m/r buttons, these are queued as keypresses, so add to end of buffer
switch (mouse_extra) {
// dampen the scroll wheel until next while loop iteration
mouse_extra = 0x00;
}
+
+ if (end_signal)
+ goto stop_cpu_emulation;
+
goto cpu_loop;
-//stop_cpu_emulation:
+stop_cpu_emulation:
printf("[CPU] End of CPU thread\n");
+ return (void *)NULL;
}
void *keyboard_task() {
- struct pollfd kbdfd[1];
- int kpoll;
+ struct pollfd kbdpoll[1];
+ int kpollrc;
+ char c = 0, c_code = 0, c_type = 0;
+ char grab_message[] = "[KBD] Grabbing keyboard from input layer\n",
+ ungrab_message[] = "[KBD] Ungrabbing keyboard\n";
printf("[KBD] Keyboard thread started\n");
- kbdfd[0].fd = keyboard_fd;
- kbdfd[0].events = POLLIN;
+ // because we permit the keyboard to be grabbed on startup, quickly check if we need to grab it
+ if (kb_hook_enabled && cfg->keyboard_grab) {
+ printf(grab_message);
+ grab_device(keyboard_fd);
+ }
+
+ kbdpoll[0].fd = keyboard_fd;
+ kbdpoll[0].events = POLLIN;
key_loop:
- kpoll = poll(kbdfd, 1, KEY_POLL_INTERVAL_MSEC);
- if ((kpoll > 0) && (kbdfd[0].revents & POLLHUP)) {
+ kpollrc = poll(kbdpoll, 1, KEY_POLL_INTERVAL_MSEC);
+ if ((kpollrc > 0) && (kbdpoll[0].revents & POLLHUP)) {
// in the event that a keyboard is unplugged, keyboard_task will whiz up to 100% utilisation
// this is undesired, so if the keyboard HUPs, end the thread without ending the emulation
printf("[KBD] Keyboard node returned HUP (unplugged?)\n");
goto key_end;
}
- // if kpoll > 0 then it contains number of events to pull, also check if POLLIN is set in revents
- if ((kpoll <= 0) || !(kbdfd[0].revents & POLLIN)) {
+ // if kpollrc > 0 then it contains number of events to pull, also check if POLLIN is set in revents
+ if ((kpollrc <= 0) || !(kbdpoll[0].revents & POLLIN)) {
goto key_loop;
}
while (get_key_char(&c, &c_code, &c_type)) {
if (c && c == cfg->keyboard_toggle_key && !kb_hook_enabled) {
kb_hook_enabled = 1;
- printf("Keyboard hook enabled.\n");
- }
- else if (kb_hook_enabled) {
+ printf("[KBD] Keyboard hook enabled.\n");
+ if (cfg->keyboard_grab) {
+ grab_device(keyboard_fd);
+ printf(grab_message);
+ }
+ } else if (kb_hook_enabled) {
if (c == 0x1B && c_type) {
kb_hook_enabled = 0;
- printf("Keyboard hook disabled.\n");
- }
- else {
+ printf("[KBD] Keyboard hook disabled.\n");
+ if (cfg->keyboard_grab) {
+ release_device(keyboard_fd);
+ printf(ungrab_message);
+ }
+ } else {
if (queue_keypress(c_code, c_type, cfg->platform->id) && int2_enabled && last_irq != 2) {
//last_irq = 0;
//M68K_SET_IRQ(2);
//m68k_pulse_reset();
printf("CPU emulation reset.\n");
}
- // @todo work out how to signal the main process that we want to quit
- // if (c == 'q') {
- // printf("Quitting and exiting emulator.\n");
- // goto stop_cpu_emulation;
- // }
+ if (c == 'q') {
+ printf("Quitting and exiting emulator.\n");
+ end_signal = 1;
+ goto key_end;
+ }
if (c == 'd') {
realtime_disassembly ^= 1;
do_disasm = 1;
key_end:
printf("[KBD] Keyboard thread ending\n");
+ if (cfg->keyboard_grab) {
+ printf(ungrab_message);
+ release_device(keyboard_fd);
+ }
return (void*)NULL;
}
printf("Failed to open keyboard event source.\n");
}
+ if (cfg->mouse_autoconnect)
+ mouse_hook_enabled = 1;
+
+ if (cfg->keyboard_autoconnect)
+ kb_hook_enabled = 1;
+
InitGayle();
signal(SIGINT, sigint_handler);