#include "io_device.hpp" #include #include #include #include #include #include #include #include #include using namespace vc5; namespace { bool sdl_is_initialized = false; struct Char { explicit constexpr Char(char ch, uint64_t data) : ch(ch) , data(data) { } auto to_u64() const -> uint64_t { return data; } char ch; uint64_t data; }; constexpr auto charset = std::array { Char(' ', 0x0000000000000000), Char('A', 0x66667E66667E1800), Char('B', 0x7C7E667C667E7800), Char('C', 0x3C7E6060607E3C00), Char('D', 0x7C7E6666667E7C00), Char('E', 0x7E7E607E607E7E00), Char('F', 0x60607878607E7E00), Char('G', 0x7E7E666E607E7E00), Char('H', 0x6666667E7E666600), Char('I', 0x7E7E1818187E7E00), Char('J', 0x3C7E6606067E7E00), Char('K', 0x666E7C7C6E666600), Char('L', 0x7E7E606060606000), Char('M', 0xC3C3C3C3DBFFE700), Char('N', 0x6666666E7E766600), Char('O', 0x3C66666666663C00), Char('P', 0x60607C7E667C7C00), Char('Q', 0x3F7E6E66667E3C00), Char('R', 0x666C7C7E667E7C00), Char('S', 0x3C66063C60663C00), Char('T', 0x18181818187E7E00), Char('U', 0x3C7E666666666600), Char('V', 0x183C7E6666666600), Char('W', 0xE7FFDBDBC3C3C300), Char('X', 0x6666663C3C666600), Char('Y', 0x181818183C666600), Char('Z', 0x7E7E30180C7E7E00), }; } auto IoDevice::create(int ch_size, int ch_width, int ch_height) -> std::expected, std::string> { auto profile = ScreenProfile(ch_size, ch_width, ch_height); auto px_width= profile.px_width; auto px_height = profile.px_height; if (!sdl_is_initialized) { if (SDL_Init(SDL_INIT_VIDEO) != 0) { return std::unexpected(SDL_GetError()); } } SDL_Window* window; SDL_Renderer* renderer; if (SDL_CreateWindowAndRenderer(px_width, px_height, 0, &window, &renderer) != 0) { return std::unexpected(SDL_GetError()); } SDL_Texture* texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STREAMING, px_width, px_height); if (texture == nullptr) { return std::unexpected(SDL_GetError()); } SDL_RenderPresent(renderer); return std::make_unique(profile, window, renderer, texture); } IoDevice::~IoDevice() { auto lock = std::lock_guard(mx); SDL_DestroyTexture(m_texture); SDL_DestroyRenderer(m_renderer); SDL_DestroyWindow(m_window); if (sdl_is_initialized) { SDL_Quit(); } } auto IoDevice::set_char(uint16_t offset, uint8_t value) -> std::expected { auto lock = std::lock_guard(mx); auto it = std::find_if(charset.begin(), charset.end(), [&](Char ch) { return ch.ch == value; }); uint64_t char_data = it->to_u64(); SDL_Color* buffer; int pitch; int res = SDL_LockTexture(m_texture, NULL, (void**)&buffer, &pitch); if (res != 0) { return std::unexpected(SDL_GetError()); } auto [ch_size, ch_width, ch_height, px_width, px_height] = m_profile; std::println("ch_size = {}, ch_width = {}, ch_height = {}, px_width = {}, px_height = {}", ch_size, ch_width, ch_height, px_width, px_height); for (int ch_y = 0; ch_y < 8; ++ch_y) { for (int ch_x = 0; ch_x < 8; ++ch_x) { bool ch = char_data >> (ch_y * 8 + (8 - ch_x - 1)) & 1; for (int px_y = 0; px_y < ch_size; ++px_y) { for (int px_x = 0; px_x < ch_size; ++px_x) { int x = (offset % 4 * ch_size + ch_x) * 4 + px_x; int y = (offset / 4 * ch_size + ch_y) * 4 + px_y; buffer[y * px_width + x] = ch ? SDL_Color { 0xff, 0xff, 0xff, 0xff } : SDL_Color { 0x00, 0x00, 0x00, 0xff }; } } } } SDL_UnlockTexture(m_texture); SDL_RenderCopy(m_renderer, m_texture, NULL, NULL); SDL_RenderPresent(m_renderer); return {}; }