#include //#define STB_IMAGE_IMPLEMENTATION //#include "stb_image.h" #include #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; }*/