void emu_loop(bool reset) { if (reset) { emu_reset(); } exiting = false; #ifdef __EMSCRIPTEN__ emscripten_set_main_loop(emu_inner_loop, -1, 1); #else while (!exiting) { if (cpu_events & EVENT_RESET) { cpu_events = EVENT_NONE; gui_console_printf("CPU Reset triggered..."); emu_reset(); } if (cpu_events & EVENT_DEBUG_STEP) { cpu_events = EVENT_NONE; debugger(DBG_STEP, 0); } sched_process_pending_events(); if (cycle_count_delta < 0) { cpu_execute(); // execute instructions with available clock cycles } else { QThread::yieldCurrentThread(); } } emu_cleanup(); #endif }
bool EmuThread::stop() { exiting = true; paused = false; setTurboMode(true); if(!this->wait(200)) { terminate(); if(!this->wait(200)) return false; } emu_cleanup(); return true; }
void emu_loop(bool reset) { if (reset) { emu_reset(); } exiting = false; emulationPaused = false; #ifdef __EMSCRIPTEN__ emscripten_set_main_loop(emu_main_loop_inner, 0, 1); #else while (!exiting) { emu_main_loop_inner(); } #endif emu_cleanup(); }
bool emu_start() { bool ret = false; long lSize; asic_init(); if (rom_image == NULL) { gui_console_printf("No ROM image specified."); } else { FILE *rom = fopen_utf8(rom_image, "rb"); do { if (rom) { uint16_t field_type; const uint8_t *outer; const uint8_t *current; const uint8_t *data; uint32_t outer_field_size; uint32_t data_field_size; ti_device_type device_type; uint32_t offset; // Get ROM file size if (fseek(rom, 0L, SEEK_END) < 0) { break; } lSize = ftell(rom); if (lSize < 0) { break; } if (fseek(rom, 0L, SEEK_SET) < 0) { break; } // Read whole ROM. if (fread(asic.mem->flash.block, 1, lSize, rom) < (size_t)lSize) { break; } // Parse certificate fields to determine model. //device_type = (ti_device_type)(asic.mem->flash.block[0x20017]); // We've heard of the OS base being at 0x30000 on at least one calculator. for (offset = 0x20000U; offset < 0x40000U; offset += 0x10000U) { outer = asic.mem->flash.block; // Outer 0x800(0) field. if (cert_field_get(outer + offset, asic.mem->flash.size - offset, &field_type, &outer, &outer_field_size)) { break; } if (field_type != 0x800F /*|| field_type == 0x800D || field_type == 0x800E*/) { continue; } //fprintf(stderr, "outer: %p\t%04X\t%p\t%u\n", asic.mem->flash.block, field_type, outer, outer_field_size); // Inner 0x801(0) field: calculator model if (cert_field_get(outer, outer_field_size, &field_type, &data, &data_field_size)) { break; } //fprintf(stderr, "inner 1: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size); if (field_type != 0x8012 || data[0] != 0x13) { break; } // Inner 0x802(0) field: skip. data_field_size = outer_field_size - (data + data_field_size - outer); data = outer; if (cert_field_next(&data, &data_field_size)) { break; } //fprintf(stderr, "data: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size); current = data; if (cert_field_get(current, data_field_size, &field_type, &data, &data_field_size)) { break; } //fprintf(stderr, "inner 2: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size); if (field_type != 0x8021) { break; } // Inner 0x803(0) field: skip. data_field_size = outer_field_size - (data + data_field_size - outer); data = current; if (cert_field_next(&data, &data_field_size)) { break; } current = data; //fprintf(stderr, "data: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size); if (cert_field_get(current, data_field_size, &field_type, &data, &data_field_size)) { break; } //fprintf(stderr, "inner 3: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size); if (field_type != 0x8032) { break; } // Inner 0x80A(0) field: skip. data_field_size = outer_field_size - (data + data_field_size - outer); data = current; if (cert_field_next(&data, &data_field_size)) { break; } current = data; //fprintf(stderr, "data: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size); if (cert_field_get(current, data_field_size, &field_type, &data, &data_field_size)) { break; } //fprintf(stderr, "inner 4: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size); if (field_type != 0x80A1) { break; } // Inner 0x80C(0) field: keep. data_field_size = outer_field_size - (data + data_field_size - outer); data = current; if (cert_field_next(&data, &data_field_size)) { break; } current = data; //fprintf(stderr, "data: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size); if (cert_field_get(current, data_field_size, &field_type, &data, &data_field_size)) { break; } //fprintf(stderr, "inner 5: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size); if (field_type != 0x80C2) { break; } //fprintf(stderr, "Found calculator type %02X\n", data[1]); if (data[1] != 0 && data[1] != 1) { break; } device_type = (ti_device_type)(data[1]); // If we come here, we've found something. ret = true; break; } if (ret) { control.device_type = device_type; asic.device_type = device_type; } } } while(0); if (!ret) { gui_console_printf("Error opening ROM image.\n", rom_image); emu_cleanup(); } if (rom) { fclose(rom); } } return ret; }
bool emu_start(const char *romImage, const char *savedImage) { bool ret = false; long lSize; FILE *imageFile = NULL; gui_set_busy(true); do { if(savedImage != NULL) { emu_image_t *image; imageFile = fopen_utf8(savedImage, "rb"); if (!imageFile) { break; } if (fseek(imageFile, 0L, SEEK_END) < 0) { break; } lSize = ftell(imageFile); if (lSize < 0) { break; } if (fseek(imageFile, 0L, SEEK_SET) < 0) { break; } if((size_t)lSize < sizeof(emu_image_t)) { break; } image = (emu_image_t*)malloc(lSize); if(!image) { break; } if(fread(image, lSize, 1, imageFile) != 1) { free(image); break; } sched_reset(); sched.items[SCHED_THROTTLE].clock = CLOCK_27M; sched.items[SCHED_THROTTLE].proc = throttle_interval_event; asic_init(); asic_reset(); if(image->version != imageVersion || !asic_restore(image)) { emu_cleanup(); free(image); break; } free(image); ret = true; } else { asic_init(); if (romImage == NULL) { gui_console_printf("[CEmu] No ROM image specified.\n"); break; } else { FILE *romFile = fopen_utf8(romImage, "rb"); do { if (romFile) { uint16_t field_type; const uint8_t *outer; const uint8_t *current; const uint8_t *data; uint32_t outer_field_size; uint32_t data_field_size; ti_device_t device_type; uint32_t offset; /* Get ROM file size */ if (fseek(romFile, 0L, SEEK_END) < 0) { break; } lSize = ftell(romFile); if (lSize < 0) { break; } if (fseek(romFile, 0L, SEEK_SET) < 0) { break; } /* Read whole ROM. */ if (fread(mem.flash.block, 1, lSize, romFile) < (size_t)lSize) { break; } if (mem.flash.block[0x7E] == 0xFE) { break; } /* Parse certificate fields to determine model. */ /* device_type = (ti_device_type)(asic.mem->flash.block[0x20017]); */ /* We've heard of the OS base being at 0x30000 on at least one calculator. */ for (offset = 0x20000U; offset < 0x40000U; offset += 0x10000U) { outer = mem.flash.block; /* Outer 0x800(0) field. */ if (cert_field_get(outer + offset, mem.flash.size - offset, &field_type, &outer, &outer_field_size)) { break; } if (field_type != 0x800F /*|| field_type == 0x800D || field_type == 0x800E*/) { continue; } /*fprintf(stderr, "outer: %p\t%04X\t%p\t%u\n", asic.mem->flash.block, field_type, outer, outer_field_size);*/ /* Inner 0x801(0) field: calculator model */ if (cert_field_get(outer, outer_field_size, &field_type, &data, &data_field_size)) { break; } /*fprintf(stderr, "inner 1: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);*/ if (field_type != 0x8012 || data[0] != 0x13) { break; } /* Inner 0x802(0) field: skip. */ data_field_size = outer_field_size - (data + data_field_size - outer); data = outer; if (cert_field_next(&data, &data_field_size)) { break; } /*fprintf(stderr, "data: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);*/ current = data; if (cert_field_get(current, data_field_size, &field_type, &data, &data_field_size)) { break; } /*fprintf(stderr, "inner 2: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);*/ if (field_type != 0x8021) { break; } /* Inner 0x803(0) field: skip. */ data_field_size = outer_field_size - (data + data_field_size - outer); data = current; if (cert_field_next(&data, &data_field_size)) { break; } current = data; /*fprintf(stderr, "data: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);*/ if (cert_field_get(current, data_field_size, &field_type, &data, &data_field_size)) { break; } /*fprintf(stderr, "inner 3: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);*/ if (field_type != 0x8032) { break; } /* Inner 0x80A(0) field: skip. */ data_field_size = outer_field_size - (data + data_field_size - outer); data = current; if (cert_field_next(&data, &data_field_size)) { break; } current = data; /*fprintf(stderr, "data: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);*/ if (cert_field_get(current, data_field_size, &field_type, &data, &data_field_size)) { break; } /*fprintf(stderr, "inner 4: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);*/ if (field_type != 0x80A1) { break; } /* Inner 0x80C(0) field: keep. */ data_field_size = outer_field_size - (data + data_field_size - outer); data = current; if (cert_field_next(&data, &data_field_size)) { break; } current = data; /*fprintf(stderr, "data: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);*/ if (cert_field_get(current, data_field_size, &field_type, &data, &data_field_size)) { break; } /*fprintf(stderr, "inner 5: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);*/ if (field_type != 0x80C2) { break; } /*fprintf(stderr, "Found calculator type %02X\n", data[1]);*/ if (data[1] != 0 && data[1] != 1) { break; } device_type = (ti_device_t)(data[1]); /* If we come here, we've found something. */ ret = true; break; } if (ret) { set_device_type(device_type); } } } while(0); if (romFile) { fclose(romFile); } } } } while(0); if (imageFile) { fclose(imageFile); } if (!ret) { gui_console_printf("[CEmu] Error opening image (Corrupted certificate?)\n"); emu_cleanup(); } gui_set_busy(false); return ret; }
bool emu_start(unsigned int port_gdb, unsigned int port_rdbg, const char *snapshot_file) { gui_busy_raii gui_busy; if(snapshot_file) { // Open snapshot size_t snapshot_size = gzip_filesize(snapshot_file); if(snapshot_size < sizeof(emu_snapshot)) return false; FILE *fp = fopen_utf8(snapshot_file, "rb"); if(!fp) return false; int dupfd = dup(fileno(fp)); fclose(fp); fp = nullptr; // gzdopen takes ownership of the fd gzFile gzf = gzdopen(dupfd, "r"); if(!gzf) { close(dupfd); return false; } auto snapshot = (struct emu_snapshot *) malloc(snapshot_size); if(!snapshot) { gzclose(gzf); return false; } if((size_t) gzread(gzf, snapshot, snapshot_size) != snapshot_size) { gzclose(gzf); free(snapshot); return false; } gzclose(gzf); //sched_reset(); sched.items[SCHED_THROTTLE].clock = CLOCK_27M; sched.items[SCHED_THROTTLE].proc = throttle_interval_event; // TODO: Max length path_boot1 = std::string(snapshot->path_boot1); path_flash = std::string(snapshot->path_flash); // TODO: Pass snapshot_size to flash_resume to avoid reading after the buffer // Resume components uint32_t sdram_size; if(snapshot->sig != SNAPSHOT_SIG || snapshot->version != SNAPSHOT_VER || !flash_resume(snapshot) || !flash_read_settings(&sdram_size, &product, &features, &asic_user_flags) || !cpu_resume(snapshot) || !memory_resume(snapshot) || !sched_resume(snapshot)) { emu_cleanup(); free(snapshot); return false; } free(snapshot); } else { if (!flash_open(path_flash.c_str())) return false; uint32_t sdram_size; flash_read_settings(&sdram_size, &product, &features, &asic_user_flags); flash_set_bootorder(boot_order); if(!memory_initialize(sdram_size)) { emu_cleanup(); return false; } } if(debug_on_start) cpu_events |= EVENT_DEBUG_STEP; uint8_t *rom = mem_areas[0].ptr; memset(rom, -1, 0x80000); for (int i = 0x00000; i < 0x80000; i += 4) RAM_FLAGS(&rom[i]) = RF_READ_ONLY; /* Load the ROM */ FILE *f = fopen_utf8(path_boot1.c_str(), "rb"); if (!f) { gui_perror(path_boot1.c_str()); emu_cleanup(); return false; } (void)fread(rom, 1, 0x80000, f); fclose(f); #ifndef NO_TRANSLATION if(!translate_init()) { gui_debug_printf("Could not init JIT, disabling translation.\n"); do_translate = false; } #endif addr_cache_init(); throttle_timer_on(); if(port_gdb) gdbstub_init(port_gdb); if(port_rdbg) rdebug_bind(port_rdbg); usblink_queue_reset(); if(!snapshot_file) emu_reset(); return true; }