From d7cd5f8cef5c1bc1b205400d62eb1efcfa78e60b Mon Sep 17 00:00:00 2001 From: Christophe Meneboeuf Date: Fri, 2 Dec 2016 00:32:53 +0100 Subject: [PATCH] Adding the memory holes --- .gitignore | 5 +++ RgbToHiRes.vcxproj.user | 11 ------- src/HiRes.cpp | 67 +++++++++++++++++++++++++++++++++++++---- src/HiRes.h | 39 +++++++++++++++++++++--- src/Main.cpp | 23 ++++++++++++-- 5 files changed, 121 insertions(+), 24 deletions(-) delete mode 100644 RgbToHiRes.vcxproj.user diff --git a/.gitignore b/.gitignore index eba8f54..466178a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,9 @@ ./x64 ./x86 +./RgbToHiRes.vcxproj.user +*.sln +*.bin +*.asm +**/.vs **/Debug **/Release diff --git a/RgbToHiRes.vcxproj.user b/RgbToHiRes.vcxproj.user deleted file mode 100644 index 26ab88e..0000000 --- a/RgbToHiRes.vcxproj.user +++ /dev/null @@ -1,11 +0,0 @@ - - - - -i D:\Chris.ARES\Dropbox\_Partages\_Macbook\Green.png - WindowsLocalDebugger - - - -i D:\Chris.ARES\Dropbox\_Partages\_Macbook\Green.png - WindowsLocalDebugger - - \ No newline at end of file diff --git a/src/HiRes.cpp b/src/HiRes.cpp index 0392e37..c0a52eb 100644 --- a/src/HiRes.cpp +++ b/src/HiRes.cpp @@ -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::getGroup(const BlockPixel& block) const + pair BlockHr::getGroup(const BlockPixel& block) const { - std::pair groups{ GROUP_1, GROUP_1 }; + pair 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(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(line.second)->emplace_back(BlockHr{}); + } } } - } + unique_ptr> HiRes::getBlob() const + { + auto blob = unique_ptr>{ new array}; + 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; + } + + } \ No newline at end of file diff --git a/src/HiRes.h b/src/HiRes.h index 403aaf9..849c13d 100644 --- a/src/HiRes.h +++ b/src/HiRes.h @@ -3,6 +3,8 @@ #include #include +#include +#include #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::const_iterator begin() const { + return _data.begin(); + } + /// \brief returns the position after the last element + inline std::array::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 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 _data; }; - using LineHr = std::array; - using Blob = std::array; + + static constexpr unsigned NB_BLOCK_PER_LINES = 20u; + static constexpr unsigned NB_LINES_PER_SCREEN = 192u; + using LineHr = std::vector; + using Blob = std::array; + + 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 > 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 _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 _lineOffsets = { + 0x0, 0x400, 0x800, 0xc00, 0x1000, 0x1400, 0x1800, 0x1c00 + }; + std::map _hrOrderedLines; ///< map }; diff --git a/src/Main.cpp b/src/Main.cpp index 547b662..e7cb647 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include @@ -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 imagePath("i", "image", "Image path", true, "", "path_to_image"); + TCLAP::ValueArg imagePath("i", "image", "Source image path", true, "", "path_to_image"); + TCLAP::ValueArg 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(bytes.get()), bytes->size()); + } } //Fatal error