140 lines
2.8 KiB
C
140 lines
2.8 KiB
C
#include <SDL2/SDL.h>
|
|
#include <vhex/display.h>
|
|
#include <vhex/display/interface.h>
|
|
#include <vhex/driver.h>
|
|
|
|
/* Literal error message printed to stderr, evaluates to 1 for a combined
|
|
return/exit() call */
|
|
#define err(fmt, ...) ({ \
|
|
fprintf(stderr, "error: " fmt "\n", ##__VA_ARGS__); \
|
|
1; \
|
|
})
|
|
|
|
static SDL_Window *__sdl_window = NULL;
|
|
|
|
__attribute__((destructor))
|
|
void quit(void)
|
|
{
|
|
if(__sdl_window != NULL) {
|
|
SDL_DestroyWindow(__sdl_window);
|
|
__sdl_window = NULL;
|
|
}
|
|
}
|
|
|
|
//---
|
|
// Driver primitives
|
|
//---
|
|
|
|
uint32_t vhex_vram[(396*224) / 2];
|
|
|
|
/* sdl_frame_start() - prepar the screen and reset surfaces */
|
|
int sdl_frame_start(dsurface_t *surface)
|
|
{
|
|
surface->vram = (void*)vhex_vram;
|
|
surface->width = 396;
|
|
surface->height = 224;
|
|
surface->x1 = 0;
|
|
surface->y1 = 0;
|
|
surface->x2 = 395;
|
|
surface->y2 = 223;
|
|
return (0);
|
|
}
|
|
|
|
/* sdl_frame_frag_next() : update the next fragment */
|
|
int sdl_frame_frag_next(dsurface_t *surface)
|
|
{
|
|
(void)surface;
|
|
return -1;
|
|
}
|
|
|
|
/* sdl_frame_frag_send() : send fragment to the screen */
|
|
int sdl_frame_frag_send(dsurface_t *surface)
|
|
{
|
|
|
|
SDL_SetWindowSize(__sdl_window, 396, 224);
|
|
SDL_Surface *src = SDL_CreateRGBSurface(
|
|
0, 396, 224, 24,
|
|
0x000000ff, 0x0000ff00, 0x0000ff00, 0
|
|
);
|
|
|
|
uint16_t *vram = surface->vram;
|
|
uint8_t *display = src->pixels;
|
|
for (int i = 0; i < 396 * 224; ++i){
|
|
display[(i * 3) + 0] = (((vram[i] & 0xf800) >> 11) * 255) / 31;
|
|
display[(i * 3) + 1] = (((vram[i] & 0x07e0) >> 5) * 255) / 63;
|
|
display[(i * 3) + 2] = (((vram[i] & 0x001f) >> 0) * 255) / 31;
|
|
}
|
|
|
|
SDL_Surface *dst = SDL_GetWindowSurface(__sdl_window);
|
|
SDL_BlitSurface(src, NULL, dst, NULL);
|
|
SDL_FreeSurface(src);
|
|
|
|
SDL_UpdateWindowSurface(__sdl_window);
|
|
return 0;
|
|
}
|
|
|
|
/* sdl_frame_end() : destructor */
|
|
int sdl_frame_end(dsurface_t *surface)
|
|
{
|
|
(void)surface;
|
|
return 0;
|
|
}
|
|
|
|
//---
|
|
// Driver context management
|
|
//---
|
|
|
|
static int __sdl_configure(void)
|
|
{
|
|
if(!SDL_WasInit(SDL_INIT_VIDEO)) {
|
|
int rc = SDL_Init(SDL_INIT_VIDEO);
|
|
if(rc < 0)
|
|
return err("Cannot initialize SDL: %s\n", SDL_GetError());
|
|
}
|
|
|
|
__sdl_window = SDL_CreateWindow(
|
|
"vxKernel",
|
|
SDL_WINDOWPOS_CENTERED,
|
|
SDL_WINDOWPOS_CENTERED,
|
|
396,
|
|
224,
|
|
0
|
|
);
|
|
return 0;
|
|
}
|
|
|
|
static void __sdl_hsave(void)
|
|
{
|
|
// Nothing to do, this is a fake driver
|
|
;
|
|
}
|
|
|
|
static void __sdl_hrestore(void)
|
|
{
|
|
// Nothing to do, this is a fake driver
|
|
;
|
|
}
|
|
|
|
|
|
struct vhex_driver drv_sdl = {
|
|
.name = "SDL",
|
|
.hsave = (void*)&__sdl_hsave,
|
|
.hrestore = (void*)&__sdl_hrestore,
|
|
.configure = (void*)&__sdl_configure,
|
|
.state_size = 4,
|
|
.flags = {
|
|
.DISPLAY = 1,
|
|
.SHARED = 0,
|
|
.UNUSED = 0,
|
|
},
|
|
.module_data = &(struct dstack_drv_interface){
|
|
.frame_start = &sdl_frame_start,
|
|
.frame_frag_next = &sdl_frame_frag_next,
|
|
.frame_frag_send = &sdl_frame_frag_send,
|
|
.frame_end = &sdl_frame_end,
|
|
.display_width = 396,
|
|
.display_height = 224
|
|
}
|
|
};
|
|
VHEX_DECLARE_DRIVER(16, drv_sdl);
|