//Hanlde "all" requests to/from server, pass off to child funcs in // rcon-handlers.c for specific API hooking int root_handler(struct mg_connection *conn, json_t* jreq, json_t* jrsp){ //Get current "action" request json_t* action = json_object_get(jreq,"action"); if (!action){ //no action found, set error handling json_object_set_new(jrsp,"error",json_string("no 'action' key in request (please POST)")); return 400; } //test handler, echos back some basic data about the request if(cmpjstr(action,"version")){ return handle_version(conn,jreq,jrsp); } else if(cmpjstr(action,"api/hotkey")){ return handle_hotkey(jreq,jrsp); } else if(cmpjstr(action,"api/output")){ return handle_output(jreq,jrsp); } else if(cmpjstr(action,"plugin")){ for (size_t i=0; i < rcon_data.plugin_handlers.num; i++){ struct rcon_handler hndl = rcon_data.plugin_handlers.array[i]; if (cmpjstr(json_object_get(jreq,"plugin_action"),hndl.action)){ return hndl.handle_func(conn,jreq,jrsp); } } json_object_set_new(jrsp,"error",json_string("no matching 'plugin_action' found for request.")); return 400; } else { json_object_set_new(jrsp,"error",json_string("no matching 'action' found for request.")); if (jreq){ json_object_set(jrsp, "requestJSON", jreq); } else{ json_object_set_new(jrsp,"requestJSON", json_null()); } return 400; } }
/****** Force the core to sleep ******/ void AGB_core::sleep() { //White out LCD core_cpu.controllers.video.clear_screen_buffer(0xFFFFFFFF); core_cpu.controllers.video.update(); //Wait for L+R+Select input bool l_r_select = false; while(!l_r_select) { SDL_PollEvent(&event); if((event.type == SDL_KEYDOWN) || (event.type == SDL_KEYUP) || (event.type == SDL_JOYBUTTONDOWN) || (event.type == SDL_JOYBUTTONUP) || (event.type == SDL_JOYAXISMOTION) || (event.type == SDL_JOYHATMOTION)) { core_pad.handle_input(event); handle_hotkey(event); } if(((core_pad.key_input & 0x4) == 0) && ((core_pad.key_input & 0x100) == 0) && ((core_pad.key_input & 0x200) == 0)) { l_r_select = true; } SDL_Delay(50); core_cpu.controllers.video.update(); } core_cpu.sleep = false; core_cpu.running = true; }
/****** Run the core in a loop until exit ******/ void AGB_core::run_core() { //Begin running the core while(running) { //Handle SDL Events if((core_cpu.controllers.video.current_scanline == 160) && SDL_PollEvent(&event)) { //X out of a window if(event.type == SDL_QUIT) { stop(); SDL_Quit(); } //Process gamepad or hotkey else if((event.type == SDL_KEYDOWN) || (event.type == SDL_KEYUP) || (event.type == SDL_JOYBUTTONDOWN) || (event.type == SDL_JOYBUTTONUP) || (event.type == SDL_JOYAXISMOTION) || (event.type == SDL_JOYHATMOTION)) { core_pad.handle_input(event); handle_hotkey(event); } } //Run the CPU if(core_cpu.running) { if(db_unit.debug_mode) { debug_step(); } core_cpu.fetch(); core_cpu.decode(); core_cpu.execute(); core_cpu.handle_interrupt(); //Flush pipeline if necessary if(core_cpu.needs_flush) { core_cpu.flush_pipeline(); } //Else update the pipeline and PC else { core_cpu.pipeline_pointer = (core_cpu.pipeline_pointer + 1) % 3; core_cpu.update_pc(); } } //Stop emulation else { stop(); } } //Shutdown core shutdown(); }
/****** Feeds key input from an external source (useful for TAS) ******/ void AGB_core::feed_key_input(int sdl_key, bool pressed) { core_pad.process_keyboard(sdl_key, pressed); handle_hotkey(sdl_key, pressed); }
/****** Run the core in a loop until exit ******/ void AGB_core::run_core() { //Begin running the core while(running) { //Handle SDL Events if((core_cpu.controllers.video.current_scanline == 160) && SDL_PollEvent(&event)) { //X out of a window if(event.type == SDL_QUIT) { stop(); SDL_Quit(); } //Process gamepad or hotkey else if((event.type == SDL_KEYDOWN) || (event.type == SDL_KEYUP) || (event.type == SDL_JOYBUTTONDOWN) || (event.type == SDL_JOYBUTTONUP) || (event.type == SDL_JOYAXISMOTION) || (event.type == SDL_JOYHATMOTION)) { core_pad.handle_input(event); handle_hotkey(event); //Trigger Joypad Interrupt if necessary if(core_pad.joypad_irq) { core_mmu.memory_map[REG_IF] |= 0x1000; } } } //Run the CPU if(core_cpu.running) { //Receive byte from another instance of GBE+ via netplay - Manage sync if(core_cpu.controllers.serial_io.sio_stat.connected) { //Perform syncing operations when hard sync is enabled if(config::netplay_hard_sync) { hard_sync(); } //Receive bytes normally core_cpu.controllers.serial_io.receive_byte(); //Clock SIO //core_cpu.clock_sio(); } //Otherwise, try to run any emulate SIO devices attached to GBE+ else if(core_cpu.controllers.serial_io.sio_stat.emu_device_ready) { core_cpu.clock_emulated_sio_device(); } //Reset system cycles for next instruction core_cpu.system_cycles = 0; if(db_unit.debug_mode) { debug_step(); } core_cpu.fetch(); core_cpu.decode(); core_cpu.execute(); core_cpu.handle_interrupt(); //Flush pipeline if necessary if(core_cpu.needs_flush) { core_cpu.flush_pipeline(); } //Else update the pipeline and PC else { core_cpu.pipeline_pointer = (core_cpu.pipeline_pointer + 1) % 3; core_cpu.update_pc(); } } //Stop emulation else { stop(); } } //Shutdown core shutdown(); }
/****** Run the core in a loop until exit ******/ void SGB_core::run_core() { if(config::gb_type == 2) { core_cpu.reg.a = 0x11; } //Begin running the core while(running) { //Handle SDL Events if((core_cpu.controllers.video.lcd_stat.current_scanline == 144) && SDL_PollEvent(&event)) { //X out of a window if(event.type == SDL_QUIT) { stop(); SDL_Quit(); } //Process gamepad or hotkey else if((event.type == SDL_KEYDOWN) || (event.type == SDL_KEYUP) || (event.type == SDL_JOYBUTTONDOWN) || (event.type == SDL_JOYBUTTONUP) || (event.type == SDL_JOYAXISMOTION) || (event.type == SDL_JOYHATMOTION)) { core_pad.handle_input(event); handle_hotkey(event); //Trigger Joypad Interrupt if necessary if(core_pad.joypad_irq) { core_mmu.memory_map[IF_FLAG] |= 0x10; } } } //Run the CPU if(core_cpu.running) { //Receive byte from another instance of GBE+ via netplay if(core_cpu.controllers.serial_io.sio_stat.connected) { //Perform syncing operations when hard sync is enabled if(config::netplay_hard_sync) { core_cpu.controllers.serial_io.sio_stat.sync_counter += core_cpu.cycles; //Once this Game Boy has reached a specified amount of cycles, freeze until the other Game Boy finished that many cycles if(core_cpu.controllers.serial_io.sio_stat.sync_counter >= core_cpu.controllers.serial_io.sio_stat.sync_clock) { core_cpu.controllers.serial_io.request_sync(); u32 current_time = SDL_GetTicks(); u32 timeout = 0; while(core_cpu.controllers.serial_io.sio_stat.sync) { core_cpu.controllers.serial_io.receive_byte(); //Timeout if 10 seconds passes timeout = SDL_GetTicks(); if((timeout - current_time) >= 10000) { core_cpu.controllers.serial_io.reset(); } } } } //Receive bytes normally core_cpu.controllers.serial_io.receive_byte(); } core_cpu.debug_cycles += core_cpu.cycles; core_cpu.cycles = 0; //Handle Interrupts core_cpu.handle_interrupts(); if(db_unit.debug_mode) { debug_step(); } //Halt CPU if necessary if(core_cpu.halt == true) { //Normal HALT mode if(core_cpu.interrupt || !core_cpu.skip_instruction) { core_cpu.cycles += 4; } //HALT bug else if(core_cpu.skip_instruction) { //Exit HALT mode core_cpu.halt = false; core_cpu.skip_instruction = false; //Execute next opcode, but do not increment PC core_cpu.opcode = core_mmu.read_u8(core_cpu.reg.pc); core_cpu.exec_op(core_cpu.opcode); } } //Process Opcodes else { core_cpu.opcode = core_mmu.read_u8(core_cpu.reg.pc++); core_cpu.exec_op(core_cpu.opcode); } //Update LCD if(core_cpu.double_speed) { core_cpu.controllers.video.step(core_cpu.cycles >> 1); } else { core_cpu.controllers.video.step(core_cpu.cycles); } //Update DIV timer - Every 4 M clocks core_cpu.div_counter += core_cpu.cycles; if(core_cpu.div_counter >= 256) { core_cpu.div_counter -= 256; core_mmu.memory_map[REG_DIV]++; } //Update TIMA timer if(core_mmu.memory_map[REG_TAC] & 0x4) { core_cpu.tima_counter += core_cpu.cycles; switch(core_mmu.memory_map[REG_TAC] & 0x3) { case 0x00: core_cpu.tima_speed = 1024; break; case 0x01: core_cpu.tima_speed = 16; break; case 0x02: core_cpu.tima_speed = 64; break; case 0x03: core_cpu.tima_speed = 256; break; } if(core_cpu.tima_counter >= core_cpu.tima_speed) { core_mmu.memory_map[REG_TIMA]++; core_cpu.tima_counter -= core_cpu.tima_speed; if(core_mmu.memory_map[REG_TIMA] == 0) { core_mmu.memory_map[IF_FLAG] |= 0x04; core_mmu.memory_map[REG_TIMA] = core_mmu.memory_map[REG_TMA]; } } } //Update serial input-output operations if(core_cpu.controllers.serial_io.sio_stat.shifts_left != 0) { core_cpu.controllers.serial_io.sio_stat.shift_counter += core_cpu.cycles; //After SIO clocks, perform SIO operations now if(core_cpu.controllers.serial_io.sio_stat.shift_counter >= core_cpu.controllers.serial_io.sio_stat.shift_clock) { //Shift bit out from SB, transfer it core_mmu.memory_map[REG_SB] <<= 1; core_cpu.controllers.serial_io.sio_stat.shift_counter -= core_cpu.controllers.serial_io.sio_stat.shift_clock; core_cpu.controllers.serial_io.sio_stat.shifts_left--; //Complete the transfer if(core_cpu.controllers.serial_io.sio_stat.shifts_left == 0) { //Reset Bit 7 in SC core_mmu.memory_map[REG_SC] &= ~0x80; core_cpu.controllers.serial_io.sio_stat.active_transfer = false; switch(core_cpu.controllers.serial_io.sio_stat.sio_type) { //Process normal SIO communications case NO_GB_DEVICE: case GB_LINK: //Emulate disconnected link cable (on an internal clock) with no netplay if((core_cpu.controllers.serial_io.sio_stat.internal_clock) && (!config::use_netplay || !core_cpu.controllers.serial_io.sio_stat.connected)) { core_mmu.memory_map[REG_SB] = 0xFF; core_mmu.memory_map[IF_FLAG] |= 0x08; } //Send byte to another instance of GBE+ via netplay if(core_cpu.controllers.serial_io.sio_stat.connected) { core_cpu.controllers.serial_io.send_byte(); } break; //Process GB Printer communications case GB_PRINTER: core_cpu.controllers.serial_io.printer_process(); break; //Process Barcode Boy communications case GB_BARCODE_BOY: core_cpu.controllers.serial_io.barcode_boy_process(); if(core_cpu.controllers.serial_io.barcode_boy.send_data) { core_mmu.memory_map[REG_SB] = core_cpu.controllers.serial_io.barcode_boy.byte; core_mmu.memory_map[IF_FLAG] |= 0x08; } break; //Process Bardigun card scanner communications case GB_BARDIGUN_SCANNER: core_cpu.controllers.serial_io.bardigun_process(); break; } } } } }