#include "common.h"

#ifdef HAS_IOE

#include "device/mmio.h"
#include "device/port-io.h"
#include <SDL2/SDL.h>

#define VMEM 0x40000
#define SCREEN_PORT 0x100
#define SCREEN_H 300
#define SCREEN_W 400

static SDL_Window *window;
static SDL_Renderer *renderer;
static SDL_Texture *texture;

static uint32_t (*vmem) [SCREEN_W];
static uint32_t *screensize_port_base;

inline void SDL_ErrorCheck(int ret) {
#ifdef DEBUG
  if(ret != 0) {
    rlib::println("SDL_Error: ret=", ret, ", GETERR=", SDL_GetError());
  }
#endif
}

static void init_vga_impl() {
  SDL_ErrorCheck(SDL_Init(SDL_INIT_VIDEO));
  SDL_ErrorCheck(SDL_CreateWindowAndRenderer(SCREEN_W * 2, SCREEN_H * 2, 0, &window, &renderer));
  SDL_SetWindowTitle(window, "NEMU");
  texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888,
      SDL_TEXTUREACCESS_STATIC, SCREEN_W, SCREEN_H);

  screensize_port_base = reinterpret_cast<decltype(screensize_port_base)>(add_pio_map(SCREEN_PORT, 4, nullptr));
  *screensize_port_base = ((SCREEN_W) << 16) | (SCREEN_H);
  vmem = reinterpret_cast<decltype(vmem)>(add_mmio_map(VMEM, 0x80000, nullptr));
}

void update_screen() {
#ifndef DISABLE_MMIO
#ifdef ENABLE_ASYNC_RENDER
  if(window == nullptr) init_vga_impl();
#endif
  SDL_ErrorCheck(SDL_UpdateTexture(texture, NULL, vmem, SCREEN_W * sizeof(vmem[0][0])));
  SDL_ErrorCheck(SDL_RenderClear(renderer));
  SDL_ErrorCheck(SDL_RenderCopy(renderer, texture, NULL, NULL));
  SDL_RenderPresent(renderer);
#endif
}

void init_vga() {
#ifdef ENABLE_ASYNC_RENDER
  // Because of fucking SDL design, vga_init should be done in updating thread.
  // Do nothing in main thread.
#else
  init_vga_impl();
#endif
}

#endif	/* HAS_IOE */
