device(std::size_t screen_width, std::size_t screen_height, std::size_t window_scale) : screen_width_(screen_width), screen_height_(screen_height), window_scale_(window_scale), frame_(screen_width * window_scale, screen_height * window_scale), texture_factory_(), graphics_context_(), offscreen_texture_(texture_factory().create(screen_width, screen_height)), framebuffer_(generate_frame_buffer()) { this->frame_.connect_updating(boost::bind(&device::update, this)); ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, this->framebuffer_); ::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, this->offscreen_texture_.id(), 0); if (::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { throw std::runtime_error("framebuffer is not supported completely"); } ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); }
void process_commands(void) { struct SECommandListNode *temp, *free_node; union SECommand *command; // swap buffers pthread_mutex_lock(&command_queue_mutex); temp = command_read_list; command_read_list = command_write_list; command_write_list = temp; pthread_mutex_unlock(&command_queue_mutex); while (command_read_list != NULL) { command = &(command_read_list->command); switch (command->type) { case UPDATE_OAM : if (command->update_oam.oam_index < NUM_MUNDANE_SPRITES) { oam_registers[command->update_oam.oam_index].enable = command->update_oam.enable; oam_registers[command->update_oam.oam_index].palette = command->update_oam.palette; oam_registers[command->update_oam.oam_index].flip_x = command->update_oam.flip_x; oam_registers[command->update_oam.oam_index].flip_y = command->update_oam.flip_y; oam_registers[command->update_oam.oam_index].x_offset = command->update_oam.x_offset; oam_registers[command->update_oam.oam_index].y_offset = command->update_oam.y_offset; } else if (command->update_oam.oam_index >= INSTANCE_INDEX_MIN && command->update_oam.oam_index < INSTANCE_INDEX_MAX) { // update instace sprite uint oam_index = command->update_oam.oam_index - INSTANCE_INDEX_MIN; memory.instance_oam_registers[oam_index].enable = command->update_oam.enable; memory.instance_oam_registers[oam_index].palette = command->update_oam.palette; memory.instance_oam_registers[oam_index].flip_x = command->update_oam.flip_x; memory.instance_oam_registers[oam_index].flip_y = command->update_oam.flip_y; memory.instance_oam_registers[oam_index].x_offset = command->update_oam.x_offset; memory.instance_oam_registers[oam_index].y_offset = command->update_oam.y_offset; memory.instance_oam_registers[oam_index].sprite_size = command->update_oam.sprite_size; memory.instance_oam_registers[oam_index].sprite = command->update_oam.sprite; memory.instance_oam_registers[oam_index].transpose = command->update_oam.transpose; } // do nothing otherwise break; case(SET_PRIORITY_CTRL): memory.iprctl = command->set_priority_control.iprctl; break; case(UPDATE_CRAM): memory.color_palettes[command->update_cram.cram_index].colors[command->update_cram.palette_index] = (struct PaletteColor) {command->update_cram.red, command->update_cram.green, command->update_cram.blue}; break; case(UPDATE_VRAM): { uint chunk_index = command->update_vram.chunk; uint pixel_x = command->update_vram.pixel_x; uint pixel_y = command->update_vram.pixel_y; if (command->update_vram.chunk < VRAM_CHUNK_GRANDE_BASE) { // INSTANCE CHUNKS memory.instance_chunks[chunk_index].pixel[pixel_x + pixel_y * INSTANCE_BASE_SIZE] = command->update_vram.p_data; } else if (command->update_vram.chunk < VRAM_CHUNK_VRENDE_BASE) { // GRANDE CHUNKS chunk_index -= VRAM_CHUNK_GRANDE_BASE; memory.grande_sprites[chunk_index].pixels[pixel_x + pixel_y * GRANDE_SIZE] = command->update_vram.p_data; } else if (command->update_vram.chunk < VRAM_CHUNK_VENTI_BASE) { // VRENDE CHUNKS chunk_index -= VRAM_CHUNK_VRENDE_BASE; memory.vrende_sprites[chunk_index / 4] .pixels[((chunk_index % 4) / 2) * (2 * GRANDE_SIZE * GRANDE_SIZE) + (chunk_index % 2) * GRANDE_SIZE // align to the 0,0 + (pixel_y * 2 * GRANDE_SIZE) + pixel_x] = command->update_vram.p_data; } else if (command->update_vram.chunk < VRAM_CHUNK_BACKGROUND_BASE) { // VENTI CHUNKS chunk_index -= VRAM_CHUNK_VENTI_BASE; memory.vrende_sprites[chunk_index / 16] .pixels[((chunk_index % 16) / 4) * (4 * GRANDE_SIZE * GRANDE_SIZE) + (chunk_index % 4) * GRANDE_SIZE + (pixel_y * 4 * GRANDE_SIZE) + pixel_x] = command->update_vram.p_data; } else if (command->update_vram.chunk < VRAM_CHUNK_BACKGROUND_MAX) { // BACKGROUND CHUNKS chunk_index -= VRAM_CHUNK_BACKGROUND_BASE; if (chunk_index < 70) { memory.background_sprite.pixels[(chunk_index / 10) * BACKGROUND_WIDTH * GRANDE_SIZE + (chunk_index % 10) * GRANDE_SIZE + pixel_y * BACKGROUND_WIDTH + pixel_x] = command->update_vram.p_data; } else { uint pixel_index = (chunk_index / 10) * BACKGROUND_WIDTH * GRANDE_SIZE + (chunk_index % 5) * 2 * GRANDE_SIZE + pixel_y * BACKGROUND_WIDTH + pixel_x; if (pixel_y >= (GRANDE_SIZE / 2)) { pixel_index -= (GRANDE_SIZE / 2) * BACKGROUND_WIDTH; pixel_index += GRANDE_SIZE; } memory.background_sprite.pixels[pixel_index] = command->update_vram.p_data; } } // else do nothing break; } default: // Do nothing break; } free_node = command_read_list; command_read_list = command_read_list->next_node; free(free_node); } generate_frame_buffer(); }