foot/emulator/src/main.cpp
shylie 060ca1d3cd
All checks were successful
Test / build (push) Successful in 8s
Add more tests, prep for graphical output
2025-07-08 11:53:56 -04:00

161 lines
3.0 KiB
C++

#include "foot-emulator.h"
#include <fstream>
#include <iostream>
#include <SDL3/SDL.h>
namespace
{
std::vector<uint16_t> read_file(std::istream& stream)
{
std::vector<uint16_t> buf;
std::streampos pos = stream.tellg();
stream.seekg(0, std::ios::end);
pos = stream.tellg() - pos;
buf.resize(pos / 2);
stream.seekg(0, std::ios::beg);
for (int i = 0; i < buf.size(); i++)
{
char value[2] = {0, 0};
stream.read(value, 2);
buf[i] = (uint16_t(value[0]) << 8) | (uint16_t(value[1]) & 0xFF);
}
return buf;
}
class PrintDevice : public foot::Device
{
public:
PrintDevice() :
Device(1)
{
}
bool update() override
{
uint16_t& value = memory(0);
if (value != 0)
{
std::cout << char(value);
value = 0;
}
return false;
}
};
class MemoryViewDevice : public foot::Device
{
public:
MemoryViewDevice(SDL_Renderer* render, uint8_t width, uint8_t height) :
Device(width * height / 2),
render(render),
texture(SDL_CreateTexture(render, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING, width, height)),
width(width),
height(height)
{}
~MemoryViewDevice()
{
SDL_DestroyTexture(texture);
}
bool update() override
{
int pitch;
uint8_t* pixels;
if (!SDL_LockTexture(texture, nullptr, (void**)&pixels, &pitch))
{
std::cout << SDL_GetError() << std::endl;
}
int idx = 0;
for (int i = 0; i < width / 2; i++)
{
for (int j = 0; j < height; j++)
{
const uint16_t mem = memory(i + j * width / 2);
const uint8_t left = mem & 0xFF;
const uint8_t right = mem >> 8;
pixels[idx + 0] = left;
pixels[idx + 1] = left;
pixels[idx + 2] = left;
pixels[idx + 3] = right;
pixels[idx + 4] = right;
pixels[idx + 5] = right;
idx += 6;
}
}
SDL_UnlockTexture(texture);
SDL_RenderPresent(render);
SDL_Event event;
bool stop = false;
while (SDL_PollEvent(&event))
{
if (event.type == SDL_EVENT_QUIT)
{
stop = true;
}
}
return stop;
}
private:
SDL_Renderer* render;
SDL_Texture* texture;
uint8_t width;
uint8_t height;
};
}
int main(int argc, char** argv)
{
if (argc > 1)
{
constexpr int WIDTH = 64;
constexpr int HEIGHT = 64;
std::ifstream file(argv[1], std::ios::binary);
if (!file.is_open())
{
std::cerr << "Failed to open file: " << argv[1] << std::endl;
return 1;
}
SDL_Window* window;
SDL_Renderer* render;
SDL_Init(SDL_INIT_VIDEO);
SDL_CreateWindowAndRenderer("foot emulator", WIDTH * 4, HEIGHT * 4, 0, &window, &render);
foot::Emulator emu;
emu.map_device(std::make_unique<PrintDevice>());
emu.map_device(std::make_unique<MemoryViewDevice>(render, WIDTH, HEIGHT));
emu.run(read_file(file));
SDL_DestroyRenderer(render);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
else
{
std::cout << "Usage: " << argv[0] << " <filename>" << std::endl;
}
return 1;
}