#ifndef INC_6502_C_VICII_HPP #define INC_6502_C_VICII_HPP #include "6502.hpp" #include namespace vicii { enum struct Colors : std::uint8_t { black = 0, white = 1, red = 2, cyan = 3, violet = 4, green = 5, blue = 6, yellow = 7, orange = 8, brown = 9, light_red = 10, dark_grey = 11, grey = 12, light_green = 13, light_blue = 14, light_grey = 15 }; [[maybe_unused]] static void decrement_border_color() { mos6502::poke(0xd020, mos6502::peek(0xd020) - 1); } static void increment_border_color() { mos6502::poke(0xd020, mos6502::peek(0xd020) + 1); } static void putc(geometry::point location, std::uint8_t c, Colors color) { const auto offset = static_cast(location.y * 40 + location.x); const auto start = static_cast(0x400 + offset); mos6502::poke(start, c); mos6502::poke(offset + 0xD800, static_cast(color)); } static std::uint8_t getc(geometry::point location) { const auto start = static_cast(0x400 + (location.y * 40 + location.x)); return mos6502::peek(start); } static void invertc(geometry::point location) { const auto start = static_cast(0x400 + (location.y * 40 + location.x)); mos6502::memory_loc(start) += 128; } static void put_hex(geometry::point start, uint8_t value, Colors color) { const auto put_nibble = [color](geometry::point location, std::uint8_t nibble) { if (nibble <= 9) { putc(location, nibble + 48, color); } else { putc(location, nibble - 9, color); } }; put_nibble(start + geometry::point{ 1, 0 }, 0xF & value); put_nibble(start , 0xF & (value >> 4)); } static void put_hex(geometry::point location, std::uint16_t value, Colors color) { put_hex(location, static_cast(0xFF & (value >> 8)), color); put_hex(location + geometry::point{ 2, 0 }, static_cast(0xFF & value), color); } static void put_graphic(geometry::point location, const auto &graphic) { for (const auto &p : graphic.size()) { putc(p + location, graphic[p], Colors::white); } } static void put_graphic(geometry::point location, const auto &graphic) requires requires { graphic.colors[{0, 0}]; } { for (const auto &p : graphic.data.size()) { putc(p + location, graphic.data[p], static_cast(graphic.colors[p])); } } static void cls() { for (std::uint16_t i = 0x400; i < 0x400 + 1000; ++i) { mos6502::poke(i, 32); } } struct Screen { void load(geometry::point location, auto &s) { for (const auto &p : s.size()) { s[p] = getc(p + location); } } void hide(auto &s) { if (s.is_shown) { put_graphic(s.location, s.saved_background); s.is_shown = false; } } void show(geometry::point loc, auto &s) { if (s.is_shown) { put_graphic(s.location, s.saved_background); } s.is_shown = true; s.location = loc; load(loc, s.saved_background); put_graphic(loc, s.graphic); } }; void draw_vline(geometry::point begin, const geometry::point end, Colors c) { while (begin < end) { putc(begin, 93, c); begin = begin + geometry::point{ 0, 1 }; } } void draw_hline(geometry::point begin, const geometry::point end, Colors c) { while (begin < end) { putc(begin, 67, c); begin = begin + geometry::point{1,0}; } } void draw_box(geometry::rect geo, Colors color) { putc(geo.top_left(), 85, color); putc(geo.top_right(), 73, color); putc(geo.bottom_right(), 75, color); putc(geo.bottom_left(), 74, color); draw_hline(geo.top_left() + geometry::point{1,0}, geo.top_right(), color); draw_hline(geo.bottom_left() + geometry::point{ 1, 0 }, geo.bottom_right(), color); draw_vline(geo.top_left() + geometry::point{ 0, 1 }, geo.bottom_left(), color); draw_vline(geo.top_right() + geometry::point{ 0, 1 }, geo.bottom_right(), color); } }// namespace vicii #endif// INC_6502_C_VICII_HPP