/* * CiderPress * Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved. * See the file LICENSE for distribution terms. */ /* * Convert the various Super HiRes formats. */ #ifndef REFORMAT_SUPERHIRES_H #define REFORMAT_SUPERHIRES_H #include "ReformatBase.h" /* * Reformat SHR images (abstract base class). * * THOUGHT: add a "convert single line" function that copies to bytes or * RGBTRIPLEs or whatever. Use it in the usual functions and for converting * odd-sized APF-format images. Args are the bits for the line, 320/640 mode * for source-pixel interpretation, and the color palette for that line. We * need to orient less on the format we're converting *to* (e.g. 320/640x200) * and more on what we're converting *from* (arbitrary sized image with * certain GS-specific characteristics). */ class ReformatSHR : public ReformatGraphics { public: enum { kNumLines = 200, kPixelBytesPerLine = 160, kNumColorTables = 16, kNumEntriesPerColorTable = 16, kColorTableEntrySize = 2, kOutputWidth = 640, // use pixel-doubling so we can get both kOutputHeight = 400, // 320 and 640 modes kTotalSize = 32768, kMaxPixelsPerScan = 1280, // allow up to 1280x1024 kMaxScanLines = 1024, // in APF images kSCBColorTableMask = 0x0f, kSCBFillMode = 0x20, kSCBInterrupts = 0x40, kSCBNumPixels = 0x80, // 0=320, 1=640 }; /* * This holds one SHR screen; the size must be 32768 bytes. */ typedef struct SHRScreen { uint8_t pixels[kNumLines * kPixelBytesPerLine]; uint8_t scb[kNumLines]; uint8_t reserved[256 - kNumLines]; uint8_t colorTable[kNumColorTables * kNumEntriesPerColorTable * kColorTableEntrySize]; } SHRScreen; /* convert 0RGB into (R,G,B) */ void GSColor(int color, RGBTRIPLE* pTriple) { pTriple->rgbtRed = ((color >> 8) & 0x0f) * 17; pTriple->rgbtGreen = ((color >> 4) & 0x0f) * 17; pTriple->rgbtBlue = (color & 0x0f) * 17; } void GSColor(int color, RGBQUAD* pQuad) { pQuad->rgbRed = ((color >> 8) & 0x0f) * 17; pQuad->rgbGreen = ((color >> 4) & 0x0f) * 17; pQuad->rgbBlue = (color & 0x0f) * 17; pQuad->rgbReserved = 0; } /* 16 palettes of 16 colors */ RGBQUAD fColorTables[kNumColorTables][kNumEntriesPerColorTable]; /* * Convert a SHRScreen struct to a 256-color DIB. * * This is a reasonably generic routine shared by SHR functions. */ MyDIBitmap* SHRScreenToBitmap8(const SHRScreen* pScreen); /* * Convert tables of SHR data to an 8bpp bitmap. The expectation is * that we double-up 320-mode pixels and double the height, so the * output for a standard SHR image will be a 640x400 bitmap. * * "pPixels" is the 2-bit or 4-bit pixel data. * "pSCB" points to an array of SCB values, one per scan line. * "pColorTable" points to an array of 16 color tables (16 entries each). * "bytesPerLine" is the number of whole bytes per line. * "numScanLines" is the number of scan lines. * "outputWidthPix" is the width, in pixels (640 for full screen). * "outputHeightPix" is the height, in pixels (400 for full screen). * * If the source material has an odd width, part of the last byte will * be empty. */ MyDIBitmap* SHRDataToBitmap8(const uint8_t* pPixels, const uint8_t* pSCB, const uint8_t* pColorTable, unsigned int bytesPerLine, unsigned int numScanLines, unsigned int outputWidthPix, unsigned int outputHeightPix); }; /* * Reformat an unpacked SHR graphic into a bitmap. */ class ReformatUnpackedSHR : public ReformatSHR { public: ReformatUnpackedSHR(void) {} virtual ~ReformatUnpackedSHR(void) {} virtual void Examine(ReformatHolder* pHolder) override; virtual int Process(const ReformatHolder* pHolder, ReformatHolder::ReformatID id, ReformatHolder::ReformatPart part, ReformatOutput* pOutput) override; private: SHRScreen fScreen; }; /* * Reformat an unpacked ".APP" SHR graphic from John Elway Quarterback GS * into a bitmap. (Implementing this was trivial if slightly silly.) */ class ReformatJEQSHR : public ReformatSHR { public: ReformatJEQSHR(void) {} virtual ~ReformatJEQSHR(void) {} virtual void Examine(ReformatHolder* pHolder) override; virtual int Process(const ReformatHolder* pHolder, ReformatHolder::ReformatID id, ReformatHolder::ReformatPart part, ReformatOutput* pOutput) override; private: enum { kExpectedLen = 32288 }; SHRScreen fScreen; }; /* * Reformat a Paintworks SHR graphic ($c0/0000) into a bitmap. */ class ReformatPaintworksSHR : public ReformatSHR { public: ReformatPaintworksSHR(void) {} virtual ~ReformatPaintworksSHR(void) {} virtual void Examine(ReformatHolder* pHolder) override; virtual int Process(const ReformatHolder* pHolder, ReformatHolder::ReformatID id, ReformatHolder::ReformatPart part, ReformatOutput* pOutput) override; private: enum { kMinSize = 223 }; //SHRScreen fScreen; }; /* * Reformat a packed SHR graphic ($c0/0001) into a bitmap. */ class ReformatPackedSHR : public ReformatSHR { public: ReformatPackedSHR(void) {} virtual ~ReformatPackedSHR(void) {} virtual void Examine(ReformatHolder* pHolder) override; virtual int Process(const ReformatHolder* pHolder, ReformatHolder::ReformatID id, ReformatHolder::ReformatPart part, ReformatOutput* pOutput) override; private: SHRScreen fScreen; }; /* * Reformat an Apple-Preferred Format SHR graphic ($c0/0002) into a bitmap. * * The graphic could be a standard SHR image, a larger or smaller than normal * SHR image, or a 3200-color image. */ class ReformatAPFSHR : public ReformatSHR { public: ReformatAPFSHR(void) : fNonStandard(false), fPixelStore(NULL), fSCBStore(NULL) {} virtual ~ReformatAPFSHR(void) { if (fPixelStore != NULL && fPixelStore != fScreen.pixels) delete[] fPixelStore; if (fSCBStore != NULL && fSCBStore != fScreen.scb) delete[] fSCBStore; } virtual void Examine(ReformatHolder* pHolder) override; virtual int Process(const ReformatHolder* pHolder, ReformatHolder::ReformatID id, ReformatHolder::ReformatPart part, ReformatOutput* pOutput) override; private: int UnpackMain(const uint8_t* srcPtr, long srcLen); int UnpackMultipal(uint8_t* dstPtr, const uint8_t* srcPtr, long srcLen); void UnpackNote(const uint8_t* srcPtr, long srcLen); /* use this for standard-sized images */ SHRScreen fScreen; /* set for non-standard images */ bool fNonStandard; /* use this for non-standard-sized images */ uint8_t* fPixelStore; uint8_t* fSCBStore; unsigned int fNumScanLines; // #of scan lines in image unsigned int fPixelsPerScanLine; unsigned int fPixelBytesPerLine; unsigned int fOutputWidth; unsigned int fOutputHeight; // scan lines * 2 }; /* * Reformat a 3200-color SHR graphic into a bitmap. */ class Reformat3200SHR : public ReformatSHR { public: Reformat3200SHR(void) {} virtual ~Reformat3200SHR(void) {} // alternate construction, used by APFSHR Reformat3200SHR(SHRScreen* pScreen, uint8_t* multiPal) { memcpy(&fScreen, pScreen, sizeof(fScreen)); memcpy(fExtColorTable, multiPal, sizeof(fExtColorTable)); } virtual void Examine(ReformatHolder* pHolder) override; virtual int Process(const ReformatHolder* pHolder, ReformatHolder::ReformatID id, ReformatHolder::ReformatPart part, ReformatOutput* pOutput) override; MyDIBitmap* SHR3200ToBitmap24(void); protected: enum { kExtNumColorTables = kNumLines, kExtTotalSize = 38400, }; SHRScreen fScreen; // only "pixels" is valid /* this holds the 200 color tables, with the entries switched to normal */ uint8_t fExtColorTable[kExtNumColorTables * kNumEntriesPerColorTable * kColorTableEntrySize]; }; /* * Reformat a packed 3200-color SHR graphic. */ class Reformat3201SHR : public Reformat3200SHR { public: Reformat3201SHR(void) {} virtual ~Reformat3201SHR(void) {} virtual void Examine(ReformatHolder* pHolder) override; virtual int Process(const ReformatHolder* pHolder, ReformatHolder::ReformatID id, ReformatHolder::ReformatPart part, ReformatOutput* pOutput) override; }; /* * Generic DreamGrafix code. */ class DreamGrafix { public: DreamGrafix(void) : fWidth(0), fHeight(0), fNumColors(0) {} ~DreamGrafix(void) {} /* * Scan the file. If it's a DreamGrafix image, extract values from the * header fields and return "true". */ bool ScanDreamGrafix(ReformatHolder* pHolder); /* * Unpack a DreamGrafix SHR image compressed with LZW. */ bool UnpackDG(const uint8_t* srcBuf, long srcLen, ReformatSHR::SHRScreen* pScreen, uint8_t* extColorTable); int fWidth; int fHeight; int fNumColors; private: static int UnpackLZW(const uint8_t* srcBuf, long srcLen, uint8_t* dstBuf, long dstLen); enum { kHeaderOffset = 17 }; }; /* * Reformat a DreamGrafix 256-color SHR graphic. */ class ReformatDG256SHR : public ReformatSHR { public: ReformatDG256SHR(void) {} virtual ~ReformatDG256SHR(void) {} virtual void Examine(ReformatHolder* pHolder) override; virtual int Process(const ReformatHolder* pHolder, ReformatHolder::ReformatID id, ReformatHolder::ReformatPart part, ReformatOutput* pOutput) override; private: DreamGrafix fDG; SHRScreen fScreen; }; /* * Reformat a DreamGrafix 3200-color SHR graphic. */ class ReformatDG3200SHR : public Reformat3200SHR { public: ReformatDG3200SHR(void) {} virtual ~ReformatDG3200SHR(void) {} virtual void Examine(ReformatHolder* pHolder) override; virtual int Process(const ReformatHolder* pHolder, ReformatHolder::ReformatID id, ReformatHolder::ReformatPart part, ReformatOutput* pOutput) override; private: DreamGrafix fDG; }; #endif /*REFORMAT_SUPERHIRES_H*/