161 lines
3.0 KiB
C++
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;
|
|
}
|