int test_status() { asic_t *asic = asic_init(TI83p, NULL); z80iodevice_t status = init_status(asic); // Test battery status asic->battery = BATTERIES_GOOD; asic->battery_remove_check = 0; uint8_t value = status.read_in(status.device); if (!(value & 1)) { asic_free(asic); return 1; } // Test flash asic->mmu->flash_unlocked = 1; value = status.read_in(status.device); if (!(value & 4)) { asic_free(asic); return 1; } asic->mmu->flash_unlocked = 0; value = status.read_in(status.device); if (value & 4) { asic_free(asic); return 1; } asic_free(asic); return 0; }
int test_link_assist_rx() { asic_t *asic = asic_init(TI83pSE, NULL); z80iodevice_t link_assist_rx_read = asic->cpu->devices[0x0A]; z80iodevice_t link_assist_status = asic->cpu->devices[0x09]; link_state_t *state = link_assist_rx_read.device; if (!link_recv_byte(asic, 0xBE)) { asic_free(asic); return 1; } if (link_recv_byte(asic, 0xEF)) { asic_free(asic); return 2; } uint8_t status = link_assist_status.read_in(state); if (status != state->assist.status.u8 || !state->assist.status.rx_ready || !state->assist.status.int_rx_ready) { return 3; } uint8_t val = link_assist_rx_read.read_in(state); if (val != 0xBE) { return 4; } status = link_assist_status.read_in(state); if (status != state->assist.status.u8 || state->assist.status.rx_ready || state->assist.status.int_rx_ready) { return 5; } return 0; }
int test_LDDR() { asic_t *device = asic_init(TI83p, NULL); uint8_t test[] = { 0xED, 0xB8 }; // LDDR device->cpu->registers.HL = 0xC004; device->cpu->registers.DE = 0xD004; device->cpu->registers.BC = 5; cpu_write_byte(device->cpu, 0xC000, 0x11); cpu_write_byte(device->cpu, 0xC001, 0x22); cpu_write_byte(device->cpu, 0xC002, 0x33); cpu_write_byte(device->cpu, 0xC003, 0x44); cpu_write_byte(device->cpu, 0xC004, 0x55); flash(device, test, sizeof(test)); int cycles = cpu_execute(device->cpu, 100); if (cpu_read_byte(device->cpu, 0xD000) != 0x11 || cpu_read_byte(device->cpu, 0xD001) != 0x22 || cpu_read_byte(device->cpu, 0xD002) != 0x33 || cpu_read_byte(device->cpu, 0xD003) != 0x44 || cpu_read_byte(device->cpu, 0xD004) != 0x55 || device->cpu->registers.HL != 0xBFFF || device->cpu->registers.DE != 0xCFFF || device->cpu->registers.BC != 0 || cycles != 0) { asic_free(device); return 1; } asic_free(device); return 0; }
int test_CPD() { asic_t *device = asic_init(TI83p, NULL); uint8_t test[] = { 0xED, 0xA9 }; // CPD device->cpu->registers.HL = 0xC002; device->cpu->registers.BC = 5; device->cpu->registers.A = 0x11; cpu_write_byte(device->cpu, 0xC000, 0x11); cpu_write_byte(device->cpu, 0xC001, 0x22); cpu_write_byte(device->cpu, 0xC002, 0x33); flash(device, test, sizeof(test)); int cycles = cpu_execute(device->cpu, 16); if (device->cpu->registers.flags.Z != 0 || device->cpu->registers.HL != 0xC001 || device->cpu->registers.BC != 4 || cycles != 0) { asic_free(device); return 1; } device->cpu->registers.PC = 0; cpu_execute(device->cpu, 16); device->cpu->registers.PC = 0; cpu_execute(device->cpu, 16); if (device->cpu->registers.flags.Z != 1 || device->cpu->registers.HL != 0xBFFF || device->cpu->registers.BC != 2) { asic_free(device); return 1; } asic_free(device); return 0; }
int hardware_sys_init() { /* Setup ASIC stuff */ asic_init(); /* VBlank multiplexer */ vblank_init(); initted = 1; return 0; }
int test_memorymapping_others() { asic_t *asic = asic_init(TI84p, NULL); memory_mapping_state_t *state = asic->cpu->devices[0x04].device; state->ram_bank_page = 1; state->bank_a_page = 0; state->bank_a_flash = 0; reload_mapping(state); ti_write_byte(asic->mmu, 0x4000, 0x12); if (asic->mmu->ram[0] != 0x12) { asic_free(asic); return 1; } asic->mmu->ram[0x4000] = 0x34; if (ti_read_byte(asic->mmu, 0xC000) != 0x34) { asic_free(asic); return 2; } state->map_mode = 1; state->bank_a_page = 0; state->bank_a_flash = 0; state->bank_b_page = 0; state->bank_b_flash = 0; reload_mapping(state); if (ti_read_byte(asic->mmu, 0x4000) != 0x12) { asic_free(asic); return 3; } if (ti_read_byte(asic->mmu, 0x8000) != 0x34) { asic_free(asic); return 4; } if (ti_read_byte(asic->mmu, 0xC000) != 0x12) { asic_free(asic); return 5; } return 0; }
int test_link_port() { asic_t *asic = asic_init(TI83p, NULL); z80iodevice_t link = asic->cpu->devices[0x00]; link_state_t *state = link.device; uint8_t value = link.read_in(state); if (value != 0) { asic_free(asic); return 1; } link.write_out(state, 0x01); value = link.read_in(state); if (value != 0x11) { asic_free(asic); return 2; } return 0; }
int test_CPDR() { asic_t *device = asic_init(TI83p); uint8_t test[] = { 0xED, 0xB9 }; // CPDR device->cpu->registers.HL = 0xC004; device->cpu->registers.BC = 5; device->cpu->registers.A = 0x33; cpu_write_byte(device->cpu, 0xC001, 0x22); cpu_write_byte(device->cpu, 0xC002, 0x33); cpu_write_byte(device->cpu, 0xC003, 0x44); cpu_write_byte(device->cpu, 0xC004, 0x55); flash(device, test, sizeof(test)); int cycles = cpu_execute(device->cpu, 58); if (device->cpu->registers.HL != 0xC001 || device->cpu->registers.BC != 2 || cycles != 0) { asic_free(device); return 1; } asic_free(device); return 0; }
int test_link_assist_tx() { asic_t *asic = asic_init(TI83pSE, NULL); z80iodevice_t link_assist_tx_read = asic->cpu->devices[0x0D]; z80iodevice_t link_assist_status = asic->cpu->devices[0x09]; link_state_t *state = link_assist_tx_read.device; if (link_read_tx_buffer(asic) != EOF) { asic_free(asic); return 1; } uint8_t status = link_assist_status.read_in(state); if (status != state->assist.status.u8 || !state->assist.status.tx_ready || !state->assist.status.int_tx_ready) { return 2; } link_assist_tx_read.write_out(state, 0xDE); status = link_assist_status.read_in(state); if (status != state->assist.status.u8 || state->assist.status.tx_ready || state->assist.status.int_tx_ready) { return 3; } if (link_read_tx_buffer(asic) != 0xDE) { return 4; } status = link_assist_status.read_in(state); if (status != state->assist.status.u8 || !state->assist.status.tx_ready || !state->assist.status.int_tx_ready) { return 5; } return 0; }
int test_LDI() { asic_t *device = asic_init(TI83p); uint8_t test[] = { 0xED, 0xA0 }; // LDI device->cpu->registers.HL = 0xC000; device->cpu->registers.DE = 0xD000; device->cpu->registers.BC = 5; cpu_write_byte(device->cpu, 0xC000, 0x11); cpu_write_byte(device->cpu, 0xC001, 0x22); cpu_write_byte(device->cpu, 0xC002, 0x33); cpu_write_byte(device->cpu, 0xC003, 0x44); cpu_write_byte(device->cpu, 0xC004, 0x55); flash(device, test, sizeof(test)); int cycles = cpu_execute(device->cpu, 16); if (cpu_read_byte(device->cpu, 0xD000) != 0x11 || device->cpu->registers.HL != 0xC001 || device->cpu->registers.DE != 0xD001 || device->cpu->registers.BC != 4 || cycles != 0) { asic_free(device); return 1; } asic_free(device); return 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; }
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; }