258 lines
8.8 KiB
C++
258 lines
8.8 KiB
C++
#include <SDL2/SDL.h>
|
|
#include <string.h>
|
|
#include "font.h"
|
|
#include "error.h"
|
|
|
|
#define VDP_CMD_LOCATE 0
|
|
#define VDP_CMD_PRINT 1
|
|
#define VDP_CMD_PUTCHAR 2
|
|
#define VDP_CMD_SETCHAR 3
|
|
#define VDP_CMD_PUTSPRITE 4
|
|
#define VDP_CMD_SETSPRITE 5
|
|
#define VDP_CMD_FLIP 6
|
|
#define VDP_CMD_COLOR 7
|
|
#define VDP_CMD_BORDER 8
|
|
#define VDP_CMD_CLRSCR 9
|
|
#define VDP_CMD_MOVE 10
|
|
#define VDP_CMD_GETCHAR 11
|
|
#define VDP_CMD_GETCOLOR 12
|
|
#define VDP_CMD_PUTCOLOR 13
|
|
|
|
struct t_sprite {
|
|
Uint8 x = 0;
|
|
Uint8 y = 0;
|
|
Uint8 tile = 32;
|
|
Uint8 col = 1;
|
|
};
|
|
|
|
static SDL_Window* sdlWindow = NULL;
|
|
static SDL_Renderer* sdlRenderer = NULL;
|
|
static SDL_Texture* sdlTexture = NULL;
|
|
static SDL_Rect src, dst;
|
|
static bool fullscreen = false;
|
|
|
|
static t_sprite sprites[32];
|
|
|
|
static Uint8 screen_map[16 * 12];
|
|
static Uint8 screen_color[16 * 12];
|
|
//Uint8 char_map[256 * 8];
|
|
static Uint8 screen_buffer[128 * 96 * 4];
|
|
static Uint8 cursor_x = 0;
|
|
static Uint8 cursor_y = 0;
|
|
|
|
static Uint8 color = 0x24;
|
|
static Uint8 border = 0x02;
|
|
static Uint8 data_stack[256];
|
|
static int data_stack_pos = 0;
|
|
|
|
static Uint8 palette[16][4] = {
|
|
{ 255, 0, 0, 255 },
|
|
{ 0, 255, 0, 255 },
|
|
{ 0, 0, 255, 255 },
|
|
{ 255, 0, 255, 255 },
|
|
{ 255, 255, 0, 255 },
|
|
{ 0, 255, 255, 255 },
|
|
{ 255, 255, 255, 255 },
|
|
{ 0, 0, 0, 255 },
|
|
{ 128, 0, 0, 255 },
|
|
{ 0, 128, 0, 255 },
|
|
{ 0, 0, 128, 255 },
|
|
{ 128, 0, 128, 255 },
|
|
{ 128, 128, 0, 255 },
|
|
{ 0, 128, 128, 255 },
|
|
{ 128, 128, 128, 255 },
|
|
{ 0, 0, 0, 255 },
|
|
};
|
|
|
|
void vdp_flip();
|
|
|
|
void vdp_init() {
|
|
SDL_Init(SDL_INIT_EVERYTHING);
|
|
sdlWindow = SDL_CreateWindow("PaCo", 160, SDL_WINDOWPOS_UNDEFINED, 608, 480, fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_SHOWN);
|
|
sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, SDL_RENDERER_PRESENTVSYNC);
|
|
SDL_RenderSetLogicalSize(sdlRenderer, 152, 120);
|
|
SDL_SetRenderDrawColor(sdlRenderer, palette[border][0], palette[border][1], palette[border][2], palette[border][3]);
|
|
sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STATIC, 128, 128);
|
|
SDL_ShowCursor(fullscreen ? 0 : 1);
|
|
|
|
src.x = src.y = 0;
|
|
dst.x = dst.y = 12;
|
|
src.w = dst.w = 128;
|
|
src.h = dst.h = 96;
|
|
|
|
for (int i = 0; i < 16 * 12; i++) screen_map[i] = 32;
|
|
for (int i = 0; i < 16 * 12; i++) screen_color[i] = color;
|
|
|
|
if (error_raised()) {
|
|
error_print(screen_map);
|
|
border = 0;
|
|
vdp_flip();
|
|
}
|
|
}
|
|
|
|
void vdp_quit() {
|
|
SDL_DestroyTexture(sdlTexture);
|
|
SDL_DestroyRenderer(sdlRenderer);
|
|
SDL_DestroyWindow(sdlWindow);
|
|
SDL_Quit();
|
|
}
|
|
|
|
void vdp_flip() {
|
|
Uint8* sb = screen_buffer;
|
|
Uint8* sm = screen_map;
|
|
Uint8* sc = screen_color;
|
|
for (int y = 0; y < 12; y++) {
|
|
for (int x = 0; x < 16; x++) {
|
|
Uint8* cm = &char_map[*sm << 3];
|
|
Uint8* sbt = sb;
|
|
for (int l = 0; l < 8; l++) {
|
|
if (*cm & 128) memcpy(sbt, palette[*sc & 0x0F], 4); else memcpy(sbt, palette[*sc >> 4], 4); sbt += 4;
|
|
if (*cm & 64) memcpy(sbt, palette[*sc & 0x0F], 4); else memcpy(sbt, palette[*sc >> 4], 4); sbt += 4;
|
|
if (*cm & 32) memcpy(sbt, palette[*sc & 0x0F], 4); else memcpy(sbt, palette[*sc >> 4], 4); sbt += 4;
|
|
if (*cm & 16) memcpy(sbt, palette[*sc & 0x0F], 4); else memcpy(sbt, palette[*sc >> 4], 4); sbt += 4;
|
|
if (*cm & 8) memcpy(sbt, palette[*sc & 0x0F], 4); else memcpy(sbt, palette[*sc >> 4], 4); sbt += 4;
|
|
if (*cm & 4) memcpy(sbt, palette[*sc & 0x0F], 4); else memcpy(sbt, palette[*sc >> 4], 4); sbt += 4;
|
|
if (*cm & 2) memcpy(sbt, palette[*sc & 0x0F], 4); else memcpy(sbt, palette[*sc >> 4], 4); sbt += 4;
|
|
if (*cm & 1) memcpy(sbt, palette[*sc & 0x0F], 4); else memcpy(sbt, palette[*sc >> 4], 4); sbt += (512-32+4);
|
|
cm++;
|
|
}
|
|
sm++; sc++; sb += 32;
|
|
}
|
|
sb += 3584; //3584;
|
|
}
|
|
for (int i = 0; i < 32; i++) {
|
|
Uint8* cm = &char_map[sprites[i].tile << 3];
|
|
Uint8 x = sprites[i].x;
|
|
Uint8 y = sprites[i].y;
|
|
Uint8 col = sprites[i].col;
|
|
Uint8* sbt = &screen_buffer[((x - 8) * 4) + ((y - 8) * 128 * 4)];
|
|
for (int l = 0; l < 8; l++) {
|
|
if (y >= 8 && y < 104) {
|
|
if (((x + 0) >= 8) && ((x + 0) < 136) && (*cm & 128)) memcpy(sbt, palette[col & 0x0F], 4); sbt += 4;
|
|
if (((x + 1) >= 8) && ((x + 1) < 136) && (*cm & 64)) memcpy(sbt, palette[col & 0x0F], 4); sbt += 4;
|
|
if (((x + 2) >= 8) && ((x + 2) < 136) && (*cm & 32)) memcpy(sbt, palette[col & 0x0F], 4); sbt += 4;
|
|
if (((x + 3) >= 8) && ((x + 3) < 136) && (*cm & 16)) memcpy(sbt, palette[col & 0x0F], 4); sbt += 4;
|
|
if (((x + 4) >= 8) && ((x + 4) < 136) && (*cm & 8)) memcpy(sbt, palette[col & 0x0F], 4); sbt += 4;
|
|
if (((x + 5) >= 8) && ((x + 5) < 136) && (*cm & 4)) memcpy(sbt, palette[col & 0x0F], 4); sbt += 4;
|
|
if (((x + 6) >= 8) && ((x + 6) < 136) && (*cm & 2)) memcpy(sbt, palette[col & 0x0F], 4); sbt += 4;
|
|
if (((x + 7) >= 8) && ((x + 7) < 136) && (*cm & 1)) memcpy(sbt, palette[col & 0x0F], 4); sbt += (512 - 32 + 4);
|
|
} else {
|
|
sbt += 512;
|
|
}
|
|
cm++; y++;
|
|
}
|
|
}
|
|
SDL_UpdateTexture(sdlTexture, NULL, screen_buffer, 128 * sizeof(Uint32));
|
|
SDL_RenderClear(sdlRenderer);
|
|
SDL_RenderCopy(sdlRenderer, sdlTexture, &src, &dst);
|
|
SDL_RenderPresent(sdlRenderer);
|
|
}
|
|
|
|
void vdp_switch_fullscreen() {
|
|
SDL_SetWindowFullscreen(sdlWindow, fullscreen ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP);
|
|
fullscreen = !fullscreen;
|
|
SDL_DestroyRenderer(sdlRenderer);
|
|
sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, SDL_RENDERER_PRESENTVSYNC);
|
|
SDL_RenderSetLogicalSize(sdlRenderer, 152, 120);
|
|
SDL_ShowCursor(fullscreen ? 0 : 1);
|
|
SDL_DestroyTexture(sdlTexture);
|
|
sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STATIC, 128, 128);
|
|
}
|
|
|
|
void vdp_data_out(const unsigned char& value) {
|
|
data_stack[data_stack_pos++] = value;
|
|
}
|
|
|
|
void vdp_cmd_out(const unsigned char& value) {
|
|
Uint8 n;
|
|
switch (value) {
|
|
case VDP_CMD_LOCATE:
|
|
cursor_x = data_stack[--data_stack_pos]; cursor_y = data_stack[--data_stack_pos]; break;
|
|
case VDP_CMD_MOVE:
|
|
cursor_x += data_stack[--data_stack_pos]; cursor_y += data_stack[--data_stack_pos]; break;
|
|
case VDP_CMD_PRINT:
|
|
for (int i = data_stack_pos-1; i >= 0; i--) {
|
|
screen_map[cursor_x + (cursor_y << 4)] = data_stack[i];
|
|
screen_color[cursor_x + (cursor_y << 4)] = color;
|
|
cursor_x++; if (cursor_x == 16) { cursor_x = 0; cursor_y++; }
|
|
}
|
|
break;
|
|
case VDP_CMD_PUTCHAR:
|
|
cursor_x = data_stack[data_stack_pos - 1];
|
|
cursor_y = data_stack[data_stack_pos - 2];
|
|
screen_map[cursor_x + (cursor_y << 4)] = data_stack[data_stack_pos-3];
|
|
break;
|
|
case VDP_CMD_PUTCOLOR:
|
|
cursor_x = data_stack[data_stack_pos - 1];
|
|
cursor_y = data_stack[data_stack_pos - 2];
|
|
screen_color[cursor_x + (cursor_y << 4)] = data_stack[data_stack_pos - 3];
|
|
break;
|
|
case VDP_CMD_GETCHAR:
|
|
data_stack[0] = screen_map[data_stack[1] + (data_stack[0] << 4)];
|
|
break;
|
|
case VDP_CMD_GETCOLOR:
|
|
data_stack[0] = screen_color[data_stack[1] + (data_stack[0] << 4)];
|
|
break;
|
|
case VDP_CMD_SETCHAR:
|
|
n = data_stack[data_stack_pos - 1];
|
|
char_map[(n << 3)] = data_stack[data_stack_pos - 2];
|
|
char_map[(n << 3) + 1] = data_stack[data_stack_pos - 3];
|
|
char_map[(n << 3) + 2] = data_stack[data_stack_pos - 4];
|
|
char_map[(n << 3) + 3] = data_stack[data_stack_pos - 5];
|
|
char_map[(n << 3) + 4] = data_stack[data_stack_pos - 6];
|
|
char_map[(n << 3) + 5] = data_stack[data_stack_pos - 7];
|
|
char_map[(n << 3) + 6] = data_stack[data_stack_pos - 8];
|
|
char_map[(n << 3) + 7] = data_stack[data_stack_pos - 9];
|
|
break;
|
|
case VDP_CMD_PUTSPRITE:
|
|
n = data_stack[data_stack_pos - 1];
|
|
sprites[n].x = data_stack[data_stack_pos - 2];
|
|
sprites[n].y = data_stack[data_stack_pos - 3];
|
|
break;
|
|
case VDP_CMD_SETSPRITE:
|
|
n = data_stack[data_stack_pos - 1];
|
|
sprites[n].tile = data_stack[data_stack_pos - 2];
|
|
sprites[n].col = data_stack[data_stack_pos - 3] & 0xF;
|
|
break;
|
|
case VDP_CMD_FLIP:
|
|
vdp_flip(); break;
|
|
case VDP_CMD_COLOR:
|
|
color = data_stack[0];
|
|
break;
|
|
case VDP_CMD_BORDER:
|
|
border = data_stack[0] & 0xF;
|
|
SDL_SetRenderDrawColor(sdlRenderer, palette[border][0], palette[border][1], palette[border][2], palette[border][3]);
|
|
break;
|
|
case VDP_CMD_CLRSCR:
|
|
for (int i = 0; i < 16 * 12; i++) screen_map[i] = 32;
|
|
for (int i = 0; i < 16 * 12; i++) screen_color[i] = color;
|
|
break;
|
|
}
|
|
data_stack_pos = 0;
|
|
}
|
|
|
|
unsigned char vdp_in() {
|
|
return data_stack[0];
|
|
}
|
|
|
|
/*int main(int argc, char* argv[]) {
|
|
static bool should_quit = false;
|
|
static SDL_Event sdlEvent;
|
|
|
|
while (!should_quit) {
|
|
just_pressed = SDL_SCANCODE_UNKNOWN;
|
|
while (SDL_PollEvent(&sdlEvent)) {
|
|
if (sdlEvent.type == SDL_QUIT) { should_quit = true; break; }
|
|
else if (sdlEvent.type == SDL_KEYDOWN) {
|
|
//anyKey = true;
|
|
just_pressed = sdlEvent.key.keysym.scancode;
|
|
if (sdlEvent.key.keysym.scancode == SDL_SCANCODE_ESCAPE) { should_quit = true; }
|
|
}
|
|
}
|
|
//if (!should_quit) should_quit = currentLoop();
|
|
}
|
|
|
|
vbm_quit();
|
|
return 0;
|
|
}*/
|