Ejemplo n.º 1
0
 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();
}