void vm_op_fire(vm_t* vm) { static int screen_id = -1; uint16_t count = vm_hw_count(vm), i = 0; hw_t* device; if (screen_id == -1) { for (i = 0; i < count; i++) { device = vm_hw_get_device(vm, i); if (device != NULL && device->id == 0x7349F615) { vm->registers[REG_A] = 0; vm->registers[REG_B] = 0x1000; vm_hw_interrupt(vm, i); vm->registers[REG_A] = 1; vm->registers[REG_B] = 0x1000 + 0x17F; vm_hw_interrupt(vm, i); screen_id = i; break; } } } if (vm->fire_cycles < vm->fire_cycles_target) { vm->fire_cycles++; return; } else { uint16_t pos = 0x1000, length = 0, fill = 0, idx = 0; vm->fire_cycles = 0; vm->fire_cycles_target = DCPU_TICKS_KHZ * 1000; while (pos < 0x1000 + 0x300) { length = rand() % 100; fill = rand() % 0x10000; for (idx = 0; idx < length; idx++) { vm->ram[pos + idx] = fill; vm_hook_fire(vm, pos + idx, HOOK_ON_WRITE, NULL); } if (pos + length < pos) break; pos += length; } } }
void vm_hw_lem1802_interrupt(vm_t* vm, void* ud) { struct lem1802_hardware* hw = (struct lem1802_hardware*)ud; uint16_t requested_action = vm->registers[REG_A]; uint16_t val_b = vm->registers[REG_B]; uint16_t idx = 0; uint32_t store; switch (requested_action) { case LEM1802_MEM_MAP_SCREEN: printd(LEVEL_DEBUG, "LEM1802 SCREEN MAPPED: %u.\n", val_b); vm_hw_lem1802_mem_set_screen(hw, val_b); vm_hook_fire(hw->vm, hw->hw_id, HOOK_ON_HARDWARE_CHANGE, hw); hw->screen_was_updated = 1; break; case LEM1802_MEM_MAP_FONT: printd(LEVEL_DEBUG, "LEM1802 FONT MAPPED.\n"); vm_hw_lem1802_mem_set_font(hw, val_b); hw->screen_was_updated = 1; break; case LEM1802_MEM_MAP_PALETTE: printd(LEVEL_DEBUG, "LEM1802 PALETTE MAPPED.\n"); vm_hw_lem1802_mem_set_palette(hw, val_b); hw->screen_was_updated = 1; hw->border_was_updated = 1; break; case LEM1802_SET_BORDER_COLOR: printd(LEVEL_DEBUG, "LEM1802 BORDER SET.\n"); vm_hw_lem1802_set_border(hw, val_b); break; case LEM1802_MEM_DUMP_FONT: printd(LEVEL_DEBUG, "LEM1802 DUMP FONT.\n"); vm->sleep_cycles += 256; for (idx = 0; idx < 128; idx++) { store = vm_hw_lem1802_mem_get_font_default_representation(idx); vm->ram[val_b + idx * 2] = (uint16_t)(store >> 16); vm->ram[val_b + idx * 2 + 1] = (uint16_t)((store << 16) >> 16); } break; case LEM1802_MEM_DUMP_PALETTE: printd(LEVEL_DEBUG, "LEM1802 DUMP PALETTE.\n"); vm->sleep_cycles += 16; vm_hw_lem1802_mem_dump_default_palette(vm, val_b); break; } }
void vm_hw_lem1802_init(vm_t* vm) { struct lem1802_hardware* hw; hw = malloc(sizeof(struct lem1802_hardware)); hw->cycle_hook = 0; hw->write_hook = 0; hw->break_hook = 0; hw->vm = vm; // setting up some status values hw->blink_status = 1; hw->blink_tick = 0; hw->border_color = 0; // hw->border_was_updated = 1; hw->screen_was_updated = 1; hw->texture_has_changed = 1; hw->window_closed = 0; hw->context = NULL; // Set up the LEM1802 hardware information. hw->device.id = LEM1802_ID; hw->device.version = LEM1802_VERSION; hw->device.manufacturer = LEM1802_MANUFACTURER; hw->device.handler = &vm_hw_lem1802_interrupt; hw->device.free_handler = &vm_hw_lem1802_free; // set userdata to lem1820 struct hw->device.userdata = hw; // register hooks and hw hw->cycle_hook = vm_hook_register(vm, &vm_hw_lem1802_cycle, HOOK_ON_60HZ, hw); hw->write_hook = vm_hook_register(vm, &vm_hw_lem1802_write, HOOK_ON_WRITE, hw); hw->break_hook = vm_hook_register(vm, &vm_hw_lem1802_break, HOOK_ON_BREAK, hw); hw->hw_id = vm_hw_register(vm, &hw->device); hw->glfw_texture = malloc(HW_LEM1802_SCREEN_TEXTURE_MEM_SIZE); // Initialize the memory for LEM1802. vm_hw_lem1802_mem_init(hw); // Init GLFW and OpenGL vm_hw_lem1802_init_glfw(hw); // Set up the keyboard. vm_hw_keyboard_init(vm); glfwSetKeyCallback(&vm_hw_keyboard_handle_key); glfwSetCharCallback(&vm_hw_keyboard_handle_char); vm_hook_fire(hw->vm, hw->hw_id, HOOK_ON_HARDWARE_CHANGE, hw); }
void vm_op_radiation(vm_t* vm) { if (vm->radiation_cycles < vm->radiation_cycles_target) { vm->radiation_cycles++; return; } else { uint16_t pos = rand() % 0x10000, bit = rand() % 15; vm->radiation_cycles = 0; vm->radiation_cycles_target = DCPU_TICKS_KHZ * vm->radiation_factor * (rand() % 10); vm->ram[pos] = vm->ram[pos] ^ (1 << bit); vm_hook_fire(vm, pos, HOOK_ON_WRITE, NULL); } }
void vm_hook_break(vm_t* vm) { vm_hook_fire(vm, 0, HOOK_ON_BREAK); }