mirror of
https://github.com/Pixinn/Rgb2Hires.git
synced 2025-01-08 17:29:39 +00:00
Adding the memory holes
This commit is contained in:
parent
6b68e7bc84
commit
d7cd5f8cef
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,4 +1,9 @@
|
||||
./x64
|
||||
./x86
|
||||
./RgbToHiRes.vcxproj.user
|
||||
*.sln
|
||||
*.bin
|
||||
*.asm
|
||||
**/.vs
|
||||
**/Debug
|
||||
**/Release
|
||||
|
@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LocalDebuggerCommandArguments>-i D:\Chris.ARES\Dropbox\_Partages\_Macbook\Green.png</LocalDebuggerCommandArguments>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LocalDebuggerCommandArguments>-i D:\Chris.ARES\Dropbox\_Partages\_Macbook\Green.png</LocalDebuggerCommandArguments>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
</Project>
|
@ -9,6 +9,8 @@ using namespace std;
|
||||
namespace RgbToHires {
|
||||
|
||||
|
||||
/************************* CLASS BlockHr **********************/
|
||||
|
||||
BlockHr::BlockHr()
|
||||
{
|
||||
_data[0] = 0;
|
||||
@ -37,9 +39,9 @@ namespace RgbToHires {
|
||||
}
|
||||
|
||||
|
||||
std::pair<BlockHr::eColorGroup, BlockHr::eColorGroup> BlockHr::getGroup(const BlockPixel& block) const
|
||||
pair<BlockHr::eColorGroup, BlockHr::eColorGroup> BlockHr::getGroup(const BlockPixel& block) const
|
||||
{
|
||||
std::pair<eColorGroup, eColorGroup> groups{ GROUP_1, GROUP_1 };
|
||||
pair<eColorGroup, eColorGroup> groups{ GROUP_1, GROUP_1 };
|
||||
//1st block group, including the last semi-pixel
|
||||
for (auto i = 0u; i < 4u; ++i) {
|
||||
if (block[i] == GREEN || block[i] == VIOLET) {
|
||||
@ -86,25 +88,78 @@ namespace RgbToHires {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/************************* CLASS HiRes **********************/
|
||||
|
||||
|
||||
|
||||
|
||||
HiRes::HiRes(const ImageQuantized& source)
|
||||
{
|
||||
auto pixel_src = source.getConstPixels(0u, 0u, WIDTH, HEIGHT);
|
||||
|
||||
//Filling the storage with BlockHrs
|
||||
for (auto& line : _blob) {
|
||||
for (auto& block : line) {
|
||||
line.reserve(NB_BLOCK_PER_LINES);
|
||||
//Useful data
|
||||
for (auto blockNr = 0u; blockNr < NB_BLOCK_PER_LINES; ++blockNr ) {
|
||||
BlockPixel blockPxRgb;
|
||||
for (auto& pxRgb : blockPxRgb) {
|
||||
pxRgb = *pixel_src++;
|
||||
}
|
||||
block = BlockHr{ blockPxRgb };
|
||||
line.emplace_back(BlockHr{ blockPxRgb });
|
||||
}
|
||||
}
|
||||
//Constructing the map used to interleave the lines
|
||||
auto i = 0u;
|
||||
for (const auto& line : _blob) {
|
||||
auto addr_interleaved = _lineAdresses[i / 8] + _lineOffsets[i % 8];
|
||||
_hrOrderedLines.insert(pair<const uint16_t, const LineHr*>(addr_interleaved, &line));
|
||||
++i;
|
||||
}
|
||||
//Adding the 8 byte "memory holes"
|
||||
for (auto line : _hrOrderedLines) {
|
||||
if ((line.first & 0xFF) == 0x50 || (line.first & 0xFF) == 0xD0) {
|
||||
for (auto i = 0u; i < 4u; ++i) {
|
||||
const_cast<LineHr*>(line.second)->emplace_back(BlockHr{});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
unique_ptr<array<uint8_t, HiRes::FRAME_SIZE>> HiRes::getBlob() const
|
||||
{
|
||||
auto blob = unique_ptr<array<uint8_t, FRAME_SIZE>>{ new array<uint8_t, FRAME_SIZE>};
|
||||
auto byte_blob = begin(*blob);
|
||||
for (const auto& line : _hrOrderedLines) {
|
||||
for (const auto& block : *(line.second)) {
|
||||
for (const auto byte_block : block) {
|
||||
*byte_blob++ = byte_block;
|
||||
}
|
||||
}
|
||||
}
|
||||
return blob;
|
||||
}
|
||||
|
||||
|
||||
|
||||
string HiRes::getAsm() const
|
||||
{
|
||||
string assembly{ "Picture:\n" };
|
||||
for (const auto& line : _hrOrderedLines) {
|
||||
assembly += "\t.byte\t";
|
||||
for (const auto& block : *(line.second)) {
|
||||
for (const auto byte : block) {
|
||||
assembly += to_string(byte) + ", ";
|
||||
}
|
||||
}
|
||||
assembly.pop_back(); //removing the last coma
|
||||
assembly.pop_back();
|
||||
assembly += "\n";
|
||||
}
|
||||
return assembly;
|
||||
}
|
||||
|
||||
|
||||
}
|
39
src/HiRes.h
39
src/HiRes.h
@ -3,6 +3,8 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
@ -18,14 +20,21 @@ namespace RgbToHires {
|
||||
BlockHr();
|
||||
/// \brief Construction from 7 pixels
|
||||
BlockHr(const BlockPixel& );
|
||||
/// \brief returns the position of the first element
|
||||
inline std::array<uint8_t, 2>::const_iterator begin() const {
|
||||
return _data.begin();
|
||||
}
|
||||
/// \brief returns the position after the last element
|
||||
inline std::array<uint8_t, 2>::const_iterator end() const {
|
||||
return _data.end();
|
||||
}
|
||||
private:
|
||||
/// \brief color group as defined in Apple's documentation
|
||||
enum eColorGroup {
|
||||
GROUP_1,
|
||||
GROUP_2
|
||||
};
|
||||
/// \brief Returns the color group of these two pixel blocks
|
||||
/// Works on double blocks instead of single blocks
|
||||
/// \brief Returns the color group of these two 3.5 pixel blocks
|
||||
std::pair<eColorGroup, eColorGroup> getGroup(const BlockPixel&) const;
|
||||
/// \brief Returns the bit pait corresponding to the given color
|
||||
uint8_t getDibit(const Magick::Color&) const;
|
||||
@ -33,18 +42,38 @@ namespace RgbToHires {
|
||||
std::array<uint8_t, 2> _data;
|
||||
};
|
||||
|
||||
using LineHr = std::array<BlockHr, 10>;
|
||||
using Blob = std::array<LineHr, 192>;
|
||||
|
||||
static constexpr unsigned NB_BLOCK_PER_LINES = 20u;
|
||||
static constexpr unsigned NB_LINES_PER_SCREEN = 192u;
|
||||
using LineHr = std::vector<BlockHr>;
|
||||
using Blob = std::array<LineHr, NB_LINES_PER_SCREEN>;
|
||||
|
||||
|
||||
|
||||
class HiRes
|
||||
{
|
||||
public:
|
||||
static constexpr unsigned FRAME_SIZE = 192 * 40 + 512; ///< Frame size in byte
|
||||
|
||||
HiRes(const ImageQuantized&);
|
||||
~HiRes() = default;
|
||||
|
||||
/// \brief Returns the binary hires picture
|
||||
std::unique_ptr <std::array<uint8_t, FRAME_SIZE>> getBlob() const;
|
||||
/// \brief Returns asm code corresponding to the image in memory (CA65 format)
|
||||
std::string getAsm() const;
|
||||
|
||||
private:
|
||||
Blob _blob; ///< A frame ordered buffer of hires data
|
||||
Blob _blob; ///< A frame ordered buffer of hires data
|
||||
static constexpr std::array<const uint16_t, 192 / 8> _lineAdresses = {
|
||||
0x2000, 0x2080, 0x2100, 0x2180, 0x2200, 0x2280, 0x2300, 0x2380,
|
||||
0x2028, 0x20a8, 0x2128, 0x21a8, 0x2228, 0x22a8, 0x2328, 0x23a8,
|
||||
0x2050, 0x20d0, 0x2150, 0x21d0, 0x2250, 0x22d0, 0x2350, 0x23d0
|
||||
};
|
||||
static constexpr std::array<const uint16_t, 8> _lineOffsets = {
|
||||
0x0, 0x400, 0x800, 0xc00, 0x1000, 0x1400, 0x1800, 0x1c00
|
||||
};
|
||||
std::map<const uint16_t, const LineHr*> _hrOrderedLines; ///< map<adress,line's data>
|
||||
};
|
||||
|
||||
|
||||
|
23
src/Main.cpp
23
src/Main.cpp
@ -1,6 +1,7 @@
|
||||
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include <Magick++.h>
|
||||
@ -19,16 +20,25 @@ inline bool exists(const std::string& path)
|
||||
return (stat(path.c_str(), &buffer) == 0);
|
||||
}
|
||||
|
||||
/// \brief Program entry point
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
Magick::InitializeMagick(*argv);
|
||||
|
||||
//Parsing command line
|
||||
TCLAP::CmdLine cmd("rgbtohires", ' ', "0");
|
||||
TCLAP::ValueArg<string> imagePath("i", "image", "Image path", true, "", "path_to_image");
|
||||
TCLAP::ValueArg<string> imagePath("i", "image", "Source image path", true, "", "path_to_image");
|
||||
TCLAP::ValueArg<string> outputPath("o", "output", "Output path", true, "", "path_to_output");
|
||||
TCLAP::SwitchArg assembly("a", "asm", "Output asm format");
|
||||
cmd.add(imagePath);
|
||||
cmd.add(outputPath);
|
||||
cmd.add(assembly);
|
||||
cmd.parse(argc, argv);
|
||||
|
||||
if (imagePath.getValue().size() == 0 || outputPath.getValue().size() == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
try {
|
||||
const auto filepath = imagePath.getValue();
|
||||
if (!exists(filepath)) {
|
||||
@ -36,7 +46,16 @@ int main( int argc, char *argv[] )
|
||||
}
|
||||
const auto imageRgb = Magick::Image{ filepath };
|
||||
auto imageQuantized = ImageQuantized{ imageRgb };
|
||||
const auto imageHiRes = HiRes{ imageQuantized };
|
||||
const auto imageHiRes = HiRes{ imageQuantized };
|
||||
if (assembly.getValue() == true) { //Ouput in ASM
|
||||
ofstream output(outputPath.getValue());
|
||||
output << imageHiRes.getAsm();
|
||||
}
|
||||
else { //Binary output
|
||||
ofstream output(outputPath.getValue(), ios::binary);
|
||||
const auto bytes = imageHiRes.getBlob();
|
||||
output.write(reinterpret_cast<const char*>(bytes.get()), bytes->size());
|
||||
}
|
||||
}
|
||||
|
||||
//Fatal error
|
||||
|
Loading…
Reference in New Issue
Block a user