-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
83 additions
and
146 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
{ | ||
"dependencies": [ | ||
"catch2", | ||
"trompeloeil" | ||
"trompeloeil", | ||
"cxxopts" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,92 +1,102 @@ | ||
#include <cstdlib> | ||
#include <memory> | ||
#include <array> | ||
#include <vector> | ||
#include <iostream> | ||
#include <fstream> | ||
#include <string_view> | ||
#include <format> | ||
#include <optional> | ||
#include <vectrexia.h> | ||
#include "gif.h" | ||
#include "getopt.h" | ||
#include <cxxopts.hpp> | ||
|
||
constexpr size_t ROM_SIZE = 65536; | ||
constexpr size_t MAX_FILENAME_SIZE = 2000; | ||
|
||
std::unique_ptr<Vectrex> vectrex = std::make_unique<Vectrex>(); | ||
std::array<uint8_t , FRAME_WIDTH * FRAME_HEIGHT * 4> gif_buffer{}; | ||
std::array<uint8_t, FRAME_WIDTH * FRAME_HEIGHT * 4> gif_buffer{}; | ||
|
||
int main(int argc, char *argv[]) | ||
{ | ||
int c = 0; | ||
int ch = 0; | ||
int r = 0; | ||
long skipframes = 0; | ||
long outframes = 1000; | ||
FILE *romfile; | ||
char giffilename[2000]{}; | ||
uint8_t rombuffer[65536]{}; | ||
GifWriter gw = {}; | ||
|
||
opterr = 0; | ||
while ((c = getopt(argc, argv, "s:n:")) != -1) { | ||
switch (c) { | ||
case 's':skipframes = strtol(optarg, nullptr, 10); | ||
break; | ||
case 'n':outframes = strtol(optarg, nullptr, 10); | ||
break; | ||
default:abort(); | ||
long skipframes = 0; | ||
long outframes = 1000; | ||
std::array<uint8_t, ROM_SIZE> rombuffer{}; | ||
GifWriter gw{}; | ||
|
||
// Parse command line arguments using cxxopts | ||
cxxopts::Options options("vectgif", "Generate a GIF from a Vectrex ROM"); | ||
options.add_options() | ||
("s,skipframes", "Number of frames to skip", cxxopts::value<long>()->default_value("0")) | ||
("n,outframes", "Number of output frames", cxxopts::value<long>()->default_value("1000")) | ||
("rom", "ROM file", cxxopts::value<std::string>()) | ||
("gif", "GIF output file", cxxopts::value<std::string>()->default_value("")); | ||
|
||
auto result = options.parse(argc, argv); | ||
|
||
skipframes = result["skipframes"].as<long>(); | ||
outframes = result["outframes"].as<long>(); | ||
|
||
if (!result.count("rom")) { | ||
std::cerr << "vectgif: usage: vectgif <rom> [gif]\n"; | ||
return 1; | ||
} | ||
} | ||
|
||
auto nargs = (argc - optind); | ||
if (nargs < 1 || nargs > 2) { | ||
fprintf(stderr, "vectgif: usage: vectgif <rom> [gif]\n"); | ||
return 1; | ||
} | ||
|
||
// load the ROM file | ||
printf("[ROM]: loading ROM \"%s\"\n", argv[optind]); | ||
romfile = fopen(argv[optind], "rb"); | ||
std::string rom_filename = result["rom"].as<std::string>(); | ||
std::string giffilename; | ||
if (result.count("gif") && !result["gif"].as<std::string>().empty()) { | ||
giffilename = result["gif"].as<std::string>(); | ||
} else { | ||
giffilename = std::format("{}.gif", rom_filename); | ||
} | ||
|
||
while( ( ch = fgetc(romfile) ) != EOF && r < 65536) { | ||
rombuffer[r++] = static_cast<uint8_t>(ch); | ||
} | ||
fclose(romfile); | ||
// Load the ROM file | ||
std::ifstream romfile(rom_filename, std::ios::binary); | ||
if (!romfile) { | ||
std::cerr << "[ROM]: Failed to open ROM file " << rom_filename << "\n"; | ||
return 1; | ||
} | ||
|
||
printf("[ROM]: size = %d\n", r); | ||
std::cout << std::format("[ROM]: loading ROM \"{}\"\n", rom_filename); | ||
romfile.read(reinterpret_cast<char*>(rombuffer.data()), ROM_SIZE); | ||
auto r = static_cast<size_t>(romfile.gcount()); | ||
romfile.close(); | ||
|
||
if (!vectrex->LoadCartridge(rombuffer, static_cast<size_t>(r))) { | ||
printf("Failed to load the ROM file\n"); | ||
return 1; | ||
} | ||
std::cout << std::format("[ROM]: size = {}\n", r); | ||
|
||
if (nargs == 1) { | ||
snprintf(giffilename, sizeof(giffilename), "%s.gif", argv[optind]); | ||
} | ||
else { | ||
snprintf(giffilename, sizeof(giffilename), "%s", argv[optind + 1]); | ||
} | ||
if (!vectrex->LoadCartridge(rombuffer.data(), r)) { | ||
std::cerr << "Failed to load the ROM file\n"; | ||
return 1; | ||
} | ||
|
||
GifBegin(&gw, giffilename, FRAME_WIDTH, FRAME_HEIGHT, 2, 8, false); | ||
GifBegin(&gw, giffilename.c_str(), FRAME_WIDTH, FRAME_HEIGHT, 2, 8, false); | ||
|
||
vectrex->Reset(); | ||
vectrex->Reset(); | ||
|
||
vectrex->SetPlayerOne(0x80, 0x80, 1, 1, 1, 1); | ||
vectrex->SetPlayerTwo(0x80, 0x80, 1, 1, 1, 1); | ||
vectrex->SetPlayerOne(0x80, 0x80, 1, 1, 1, 1); | ||
vectrex->SetPlayerTwo(0x80, 0x80, 1, 1, 1, 1); | ||
|
||
for (int frame = 0; frame < outframes; frame++) { | ||
for (int s = 0; s < skipframes+1; s++) { | ||
vectrex->Run(30000); | ||
} | ||
for (int frame = 0; frame < outframes; frame++) { | ||
for (int s = 0; s < skipframes + 1; s++) { | ||
vectrex->Run(30000); | ||
} | ||
|
||
auto framebuffer = vectrex->getFramebuffer(); | ||
auto framebuffer = vectrex->getFramebuffer(); | ||
|
||
auto gb = gif_buffer.begin(); | ||
for (auto &fb : *framebuffer) { | ||
*++gb = static_cast<uint8_t>(fb.value * 0xffu); | ||
*++gb = static_cast<uint8_t>(fb.value * 0xffu); | ||
*++gb = static_cast<uint8_t>(fb.value * 0xffu); | ||
*++gb = static_cast<uint8_t>(fb.value * 0xffu); | ||
} | ||
GifWriteFrame(&gw, gif_buffer.data(), FRAME_WIDTH, FRAME_HEIGHT, 2); | ||
if (frame % 100 == 0) { | ||
printf("[VECTREX] frame = %d\n", frame); | ||
auto gb = gif_buffer.begin(); | ||
for (const auto &fb : *framebuffer) { | ||
*gb++ = static_cast<uint8_t>(fb.value * 0xffu); | ||
*gb++ = static_cast<uint8_t>(fb.value * 0xffu); | ||
*gb++ = static_cast<uint8_t>(fb.value * 0xffu); | ||
*gb++ = static_cast<uint8_t>(fb.value * 0xffu); | ||
} | ||
GifWriteFrame(&gw, gif_buffer.data(), FRAME_WIDTH, FRAME_HEIGHT, 2); | ||
if (frame % 100 == 0) { | ||
std::cout << std::format("[VECTREX] frame = {}\n", frame); | ||
} | ||
} | ||
} | ||
|
||
GifEnd(&gw); | ||
GifEnd(&gw); | ||
|
||
return 0; | ||
return 0; | ||
} |