Пример #1
0
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
}
Пример #2
0
bool EmuThread::stop()
{
    exiting = true;
    paused = false;
    setTurboMode(true);
    if(!this->wait(200))
    {
        terminate();
        if(!this->wait(200))
            return false;
    }

    emu_cleanup();
    return true;
}
Пример #3
0
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();
}
Пример #4
0
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;
}
Пример #5
0
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;
}
Пример #6
0
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;
}