///////////////////////////////////////////////////////////////////////////// // // EpdBinary.cpp : implementation for compressed EPD classes // // Written by Thomas F. Mooney, III (tfm3@teleproc.com) // Copyright © 1999. // // This code may be used in compiled form in any way you desire. This // file may be redistributed unmodified by any means PROVIDING it is // not sold for profit without the authors written consent, and // providing that this notice and the authors name is included. If // the source code in this file is used in any commercial application // then acknowledgement must be made to the author of this file // (in whatever form you wish). // // This file is provided "as is" with no expressed or implied warranty. // The author accepts no liability if it causes any damage to your // computer, data, etc. // // Please report any bugs/anomalies/suggestions to the author via the // e-mail address listed above. // ///////////////////////////////////////////////////////////////////////////// static char Copyright[] = "Copyright © 1999 - TeleProcess Management, Inc."; #include "EpdBinary.h" #include const char EpdBinary::BitsOnInByte[256] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, /* 0 - 15 */ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, /* 16 - 31 */ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, /* 32 - 47 */ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 48 - 63 */ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, /* 64 - 79 */ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 80 - 95 */ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 96 - 111 */ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 112 - 127 */ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, /* 128 - 143 */ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 144 - 159 */ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 160 - 175 */ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 176 - 191 */ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 192 - 207 */ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 208 - 223 */ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 224 - 239 */ 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 /* 240 - 255 */ }; // EpdBinary() default contructor initializes sets all member // variables to their initial state. EpdBinary::EpdBinary() { EPD StringEpd; StringEpd = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq -"; CompressString(StringEpd); ConstructorHelper(); } // EpdBinary() copy contructor initializes sets all member // variables to the same state as the copied object. EpdBinary::EpdBinary(const EpdBinary& OldEpd) { memcpy(m_Buffer, OldEpd.m_Buffer, EPD_BINARY_LENGTH); ConstructorHelper(); // This is my evil doings... -DRC } // EpdBinary() constructor which uses an existing compressed // EPD for initialization. EpdBinary::EpdBinary(const char* OldEpdChar) { memcpy(m_Buffer, OldEpdChar, EPD_BINARY_LENGTH); ConstructorHelper(); // This is my evil doings... -DRC } // EpdBinary() constructor which uses text EPD for initialization. // Essentially this acts as a text EPD to compressed EPD convertor. EpdBinary::EpdBinary(const EPD& StringEpd) { CompressString(StringEpd); ConstructorHelper(); // This is my evil doings... -DRC } // Initialize the chess program helper fields... // All the constuctors need this. // This is my evil doings... -DRC void EpdBinary::ConstructorHelper() { e.ce=0; e.acd=0; e.pm=NULL; e.bm=NULL; e.am=NULL; } // Set the predicted move field // This is my evil doings... -DRC void EpdBinary::SetPM(char *pm) { if (pm && strlen(pm) > 0) { e.pm = new char[strlen(pm)+1]; strcpy(e.pm, pm); } } // This is my evil doings... -DRC // Set the best move field void EpdBinary::SetBM(char *bm) { if (bm && strlen(bm) > 0) { e.bm = new char[strlen(bm)+1]; strcpy(e.bm, bm); } } // This is my evil doings... -DRC // Set the avoid move field void EpdBinary::SetAM(char *am) { if (am && strlen(am) > 0) { e.am = new char[strlen(am)+1]; strcpy(e.am, am); } } // ~EpdBinary() default destructor. // The deletion of string objests is my evil doings... -DRC EpdBinary::~EpdBinary() { if (e.pm) { delete[] e.pm; e.pm = NULL; } if (e.bm) { delete[] e.bm; e.bm = NULL; } if (e.am) { delete[] e.am; e.am = NULL; } } // Assignment operator copies one object to another. EpdBinary& EpdBinary::operator=(const EpdBinary& OldEpd) { if (&OldEpd != this) { memcpy(m_Buffer, OldEpd.m_Buffer, EPD_BINARY_LENGTH); } return *this; } // Comparison operator indicates relative value. bool EpdBinary::operator==(const EpdBinary& OldEpd) { if (memcmp(m_Buffer, OldEpd.m_Buffer, EPD_BINARY_LENGTH) == 0) { return true; } else { return false; } } // Comparison operator indicates relative value. bool EpdBinary::operator>(const EpdBinary& OldEpd) { if (memcmp(m_Buffer, OldEpd.m_Buffer, EPD_BINARY_LENGTH) > 0) { return true; } else { return false; } } // Comparison operator indicates relative value. bool EpdBinary::operator>=(const EpdBinary& OldEpd) { if (memcmp(m_Buffer, OldEpd.m_Buffer, EPD_BINARY_LENGTH) >= 0) { return true; } else { return false; } } // Comparison operator indicates relative value. bool EpdBinary::operator<(const EpdBinary& OldEpd) { if (memcmp(m_Buffer, OldEpd.m_Buffer, EPD_BINARY_LENGTH) < 0) { return true; } else { return false; } } // Comparison operator indicates relative value. bool EpdBinary::operator<=(const EpdBinary& OldEpd) { if (memcmp(m_Buffer, OldEpd.m_Buffer, EPD_BINARY_LENGTH) <= 0) { return true; } else { return false; } } // Operator for casting to char*. Note that we make a copy // of the member variable and return a pointer to the copy. // This protects against the user modifying the member variable. EpdBinary::operator char*() { static char Buffer[EPD_BINARY_LENGTH]; memcpy(Buffer, m_Buffer, EPD_BINARY_LENGTH); return Buffer; } // GetEpd returns a string version of the compressed EPD. By // providing this function we have implemented and binary->text // EPD convertor. EPD EpdBinary::GetEpd() { // First expand bits to bytes for easier access char ExpandedBuffer[EPD_BINARY_LENGTH * 8]; char* pSource; char* pTarget; int nCount = 0; char cSource; memset(ExpandedBuffer, 0, sizeof(ExpandedBuffer)); pSource = m_Buffer; pTarget = ExpandedBuffer; while (nCount < EPD_BINARY_LENGTH) { cSource = *pSource; int nBits = 0; while (nBits < 8) { if ((cSource & '\x0080') != 0) { *pTarget = '\x01'; } else { *pTarget = '\x00'; } cSource <<= 1; pTarget++; nBits++; } pSource++; nCount++; } // Now go through the binary data converting it to its text // equivalent. Note that some pieces have double meaning. Rooks // can indicate castle status, the white king indicates which // side moves next, there is a special pawn to indicate en passant. EPD Epd; std::string PiecePlacement = ""; std::string ActiveColor = "?"; std::string CastleAvailability; std::string EnPassantTarget = "-"; bool bWhiteToMove = true; bool bWhiteMayCastleKingside = false; bool bWhiteMayCastleQueenside = false; bool bBlackMayCastleKingside = false; bool bBlackMayCastleQueenside = false; char* pBoard; char* pPiece; char cFile; char cRank; int nEmptySquares = 0; char FormatBuffer[32]; pBoard = &ExpandedBuffer[0]; pPiece = &ExpandedBuffer[64]; cRank = RankBase + (RankCount - 1); while (cRank >= RankBase) { cFile = FileBase; while (cFile < (FileBase + FileCount)) { if (*pBoard == '\x00') { nEmptySquares++; } else { if (nEmptySquares > 0) { sprintf(FormatBuffer, "%d", nEmptySquares); PiecePlacement += FormatBuffer; nEmptySquares = 0; } if (memcmp(pPiece, BinaryWhitePawn, sizeof(BinaryWhitePawn)) == 0) { PiecePlacement += "P"; } else if (memcmp(pPiece, BinaryBlackPawn, sizeof(BinaryBlackPawn)) == 0) { PiecePlacement += "p"; } else if (memcmp(pPiece, BinaryWhiteBishop, sizeof(BinaryWhiteBishop)) == 0) { PiecePlacement += "B"; } else if (memcmp(pPiece, BinaryBlackBishop, sizeof(BinaryBlackBishop)) == 0) { PiecePlacement += "b"; } else if (memcmp(pPiece, BinaryWhiteKnight, sizeof(BinaryWhiteKnight)) == 0) { PiecePlacement += "N"; } else if (memcmp(pPiece, BinaryBlackKnight, sizeof(BinaryBlackKnight)) == 0) { PiecePlacement += "n"; } else if (memcmp(pPiece, BinaryWhiteRook, sizeof(BinaryWhiteRook)) == 0) { PiecePlacement += "R"; } else if (memcmp(pPiece, BinaryBlackRook, sizeof(BinaryBlackRook)) == 0) { PiecePlacement += "r"; } else if (memcmp(pPiece, BinaryWhiteRookMayCastle, sizeof(BinaryWhiteRook)) == 0) { PiecePlacement += "R"; if (cFile == FileBase) { bWhiteMayCastleQueenside = true; } else { bWhiteMayCastleKingside = true; } } else if (memcmp(pPiece, BinaryBlackRookMayCastle, sizeof(BinaryBlackRook)) == 0) { PiecePlacement += "r"; if (cFile == FileBase) { bBlackMayCastleQueenside = true; } else { bBlackMayCastleKingside = true; } } else if (memcmp(pPiece, BinaryWhiteQueen, sizeof(BinaryWhiteQueen)) == 0) { PiecePlacement += "Q"; } else if (memcmp(pPiece, BinaryBlackQueen, sizeof(BinaryBlackQueen)) == 0) { PiecePlacement += "q"; } else if (memcmp(pPiece, BinaryWhiteKingWhiteToMove, sizeof(BinaryWhiteKingWhiteToMove)) == 0) { PiecePlacement += "K"; bWhiteToMove = true; } else if (memcmp(pPiece, BinaryWhiteKingBlackToMove, sizeof(BinaryWhiteKingBlackToMove)) == 0) { PiecePlacement += "K"; bWhiteToMove = false; } else if (memcmp(pPiece, BinaryBlackKing, sizeof(BinaryBlackKing)) == 0) { PiecePlacement += "k"; } else if (memcmp(pPiece, BinaryEpPawn, sizeof(BinaryEpPawn)) == 0) { if (cRank == '4') { PiecePlacement += "P"; EnPassantTarget = cFile; EnPassantTarget += cRank - 1; } else { PiecePlacement += "p"; EnPassantTarget = cFile; EnPassantTarget += cRank + 1; } } else { assert(false); // should never happen } pPiece += sizeof(BinaryBlackKing); } pBoard++; cFile++; } if (nEmptySquares > 0) { sprintf(FormatBuffer, "%d", nEmptySquares); PiecePlacement += FormatBuffer; nEmptySquares = 0; } if (cRank > RankBase) { PiecePlacement += "/"; } cRank--; } if (bWhiteToMove) { ActiveColor = "w"; } else { ActiveColor = "b"; } if ((!bWhiteMayCastleKingside) && (!bWhiteMayCastleQueenside) && (!bBlackMayCastleKingside) && (!bBlackMayCastleQueenside)) { CastleAvailability = "-"; } else { CastleAvailability = ""; if (bWhiteMayCastleKingside) { CastleAvailability += "K"; } if (bWhiteMayCastleQueenside) { CastleAvailability += "Q"; } if (bBlackMayCastleKingside) { CastleAvailability += "k"; } if (bBlackMayCastleQueenside) { CastleAvailability += "q"; } } // Finally, assemble the string EPD. Epd = PiecePlacement + " " + ActiveColor + " " + CastleAvailability + " " + EnPassantTarget; return Epd; } void EpdBinary::CompressString(const EPD& StringEpd) { EPD EpdCopy = StringEpd; memset(m_Buffer, 0, EPD_BINARY_LENGTH); char ExpandedBuffer[EPD_BINARY_LENGTH * 8]; char* pBoard = ExpandedBuffer; char* pPiece = pBoard + 64; memset(ExpandedBuffer, 0, sizeof(ExpandedBuffer)); // Get ready to parse supplied EPD char* pPiecePlacement = NULL; std::string PiecePlacement; char* pActiveColor = NULL; bool bWhiteToMove; char* pCastleAvailability = NULL; bool bWhiteMayCastleKingside = false; bool bWhiteMayCastleQueenside = false; bool bBlackMayCastleKingside = false; bool bBlackMayCastleQueenside = false; char* pEnPassantTarget = NULL; char cEnPassantFile; char cEnPassantRank; char pszWhiteSpace[] = " \t\v\r\n"; bool bEpdValid = true; // Parse supplied EPD, check for missing pieces as we go pPiecePlacement = strtok(EpdCopy.begin(), pszWhiteSpace); if (pPiecePlacement != NULL) { pActiveColor = strtok(NULL, pszWhiteSpace); if (pActiveColor != NULL) { pCastleAvailability = strtok(NULL, pszWhiteSpace); if (pCastleAvailability != NULL) { pEnPassantTarget = strtok(NULL, pszWhiteSpace); if (pEnPassantTarget == NULL) { bEpdValid = false; } } else { bEpdValid = false; } } else { bEpdValid = false; } } else { bEpdValid = false; } if (bEpdValid) { if (*pActiveColor == 'w') { bWhiteToMove = true; } else if (*pActiveColor == 'b') { bWhiteToMove = false; } else { bEpdValid = false; } while ((*pCastleAvailability != '-') && (*pCastleAvailability != '\0')) { if (*pCastleAvailability == 'K') { bWhiteMayCastleKingside = true; } else if (*pCastleAvailability == 'Q') { bWhiteMayCastleQueenside = true; } else if (*pCastleAvailability == 'k') { bBlackMayCastleKingside = true; } else if (*pCastleAvailability == 'q') { bBlackMayCastleQueenside = true; } else { bEpdValid = false; } pCastleAvailability++; } if (*pEnPassantTarget == '-') { cEnPassantFile = 0; cEnPassantRank = 0; } else { cEnPassantFile = *pEnPassantTarget; cEnPassantRank = *(pEnPassantTarget + 1); } // Break the piece placement data down into ranks and // then break the ranks down into empty squares and // pieces. PiecePlacement = pPiecePlacement; std::list RankList; std::list::iterator pRank; std::string Rank; char pszSlash[] = "/"; char* pParseRank = NULL; int nIndex; int nSize; char cRankItem; int nRankWidth; int nEmptySquares; char cFile; char cRank; pParseRank = strtok(PiecePlacement.begin(), pszSlash); while (pParseRank != NULL) { RankList.push_back(pParseRank); pParseRank = strtok(NULL, pszSlash); } if (RankList.size() == 8) { pRank = RankList.begin(); cRank = RankBase + (RankCount - 1); while ((pRank != RankList.end()) && (pBoard < ExpandedBuffer + sizeof(ExpandedBuffer)) && (pPiece < ExpandedBuffer + sizeof(ExpandedBuffer))) { Rank = *pRank; nSize = Rank.size(); nIndex = 0; nRankWidth = 0; cFile = FileBase; while (nIndex < nSize) { cRankItem = Rank[nIndex]; if ((cRankItem >= '1') && (cRankItem <= '8')) { nEmptySquares = cRankItem - '0'; nRankWidth += nEmptySquares; cFile += nEmptySquares; pBoard += nEmptySquares; } else if ((pBoard >= ExpandedBuffer + sizeof(ExpandedBuffer)) || (pPiece >= ExpandedBuffer + sizeof(ExpandedBuffer))) { bEpdValid = false; break; } else if (cRankItem == 'p') { nRankWidth++; *pBoard = '\x01'; pBoard++; if ((cFile == cEnPassantFile) && (cRank == cEnPassantRank - 1)) { memcpy(pPiece, BinaryEpPawn, sizeof(BinaryEpPawn)); pPiece += sizeof(BinaryEpPawn); } else { memcpy(pPiece, BinaryBlackPawn, sizeof(BinaryBlackPawn)); pPiece += sizeof(BinaryBlackPawn); } cFile++; } else if (cRankItem == 'P') { nRankWidth++; *pBoard = '\x01'; pBoard++; if ((cFile == cEnPassantFile) && (cRank == cEnPassantRank + 1)) { memcpy(pPiece, BinaryEpPawn, sizeof(BinaryEpPawn)); pPiece += sizeof(BinaryEpPawn); } else { memcpy(pPiece, BinaryWhitePawn, sizeof(BinaryWhitePawn)); pPiece += sizeof(BinaryWhitePawn); } cFile++; } else if (cRankItem == 'b') { nRankWidth++; *pBoard = '\x01'; pBoard++; memcpy(pPiece, BinaryBlackBishop, sizeof(BinaryBlackBishop)); pPiece += sizeof(BinaryBlackBishop); cFile++; } else if (cRankItem == 'B') { nRankWidth++; *pBoard = '\x01'; pBoard++; memcpy(pPiece, BinaryWhiteBishop, sizeof(BinaryWhiteBishop)); pPiece += sizeof(BinaryWhiteBishop); cFile++; } else if (cRankItem == 'n') { nRankWidth++; *pBoard = '\x01'; pBoard++; memcpy(pPiece, BinaryBlackKnight, sizeof(BinaryBlackKnight)); pPiece += sizeof(BinaryBlackKnight); cFile++; } else if (cRankItem == 'N') { nRankWidth++; *pBoard = '\x01'; pBoard++; memcpy(pPiece, BinaryWhiteKnight, sizeof(BinaryWhiteKnight)); pPiece += sizeof(BinaryWhiteKnight); cFile++; } else if (cRankItem == 'r') { nRankWidth++; *pBoard = '\x01'; pBoard++; if ((cFile == 'a') && (cRank == '8') && (bBlackMayCastleQueenside)) { memcpy(pPiece, BinaryBlackRookMayCastle, sizeof(BinaryBlackRookMayCastle)); pPiece += sizeof(BinaryBlackRookMayCastle); } else if ((cFile == 'h') && (cRank == '8') && (bBlackMayCastleKingside)) { memcpy(pPiece, BinaryBlackRookMayCastle, sizeof(BinaryBlackRookMayCastle)); pPiece += sizeof(BinaryBlackRookMayCastle); } else { memcpy(pPiece, BinaryBlackRook, sizeof(BinaryBlackRook)); pPiece += sizeof(BinaryBlackRook); } cFile++; } else if (cRankItem == 'R') { nRankWidth++; *pBoard = '\x01'; pBoard++; if ((cFile == 'a') && (cRank == '1') && (bWhiteMayCastleQueenside)) { memcpy(pPiece, BinaryWhiteRookMayCastle, sizeof(BinaryWhiteRookMayCastle)); pPiece += sizeof(BinaryWhiteRookMayCastle); } else if ((cFile == 'h') && (cRank == '1') && (bWhiteMayCastleKingside)) { memcpy(pPiece, BinaryWhiteRookMayCastle, sizeof(BinaryWhiteRookMayCastle)); pPiece += sizeof(BinaryWhiteRookMayCastle); } else { memcpy(pPiece, BinaryWhiteRook, sizeof(BinaryWhiteRook)); pPiece += sizeof(BinaryWhiteRook); } cFile++; } else if (cRankItem == 'q') { nRankWidth++; *pBoard = '\x01'; pBoard++; memcpy(pPiece, BinaryBlackQueen, sizeof(BinaryBlackQueen)); pPiece += sizeof(BinaryBlackQueen); cFile++; } else if (cRankItem == 'Q') { nRankWidth++; *pBoard = '\x01'; pBoard++; memcpy(pPiece, BinaryWhiteQueen, sizeof(BinaryWhiteQueen)); pPiece += sizeof(BinaryWhiteQueen); cFile++; } else if (cRankItem == 'k') { nRankWidth++; *pBoard = '\x01'; pBoard++; memcpy(pPiece, BinaryBlackKing, sizeof(BinaryBlackKing)); pPiece += sizeof(BinaryBlackKing); cFile++; } else if (cRankItem == 'K') { nRankWidth++; *pBoard = '\x01'; pBoard++; if (bWhiteToMove) { memcpy(pPiece, BinaryWhiteKingWhiteToMove, sizeof(BinaryWhiteKingWhiteToMove)); pPiece += sizeof(BinaryWhiteKingWhiteToMove); } else { memcpy(pPiece, BinaryWhiteKingBlackToMove, sizeof(BinaryWhiteKingBlackToMove)); pPiece += sizeof(BinaryWhiteKingBlackToMove); } cFile++; } else { bEpdValid = false; break; } nIndex++; } if (bEpdValid) { if (nRankWidth != 8) { bEpdValid = false; break; } } else { break; } cRank--; pRank++; } } else { bEpdValid = false; } } // If we've still got a valid EPD, compress the results // into our member variable. if (bEpdValid) { char* pSource; char* pTarget; int nCount; char cTarget; pSource = ExpandedBuffer; pTarget = m_Buffer; nCount = 0; while (nCount < sizeof(m_Buffer)) { int nBits; nBits = 0; cTarget = '\x00'; while (nBits < 8) { cTarget <<= 1; if (*pSource != '\x00') { cTarget ^= '\x01'; } pSource++; nBits++; } *pTarget = cTarget; pTarget++; nCount++; } } } int EpdBinary::GetPieceCount(void) { int count; unsigned char *Ptr = (unsigned char *) m_Buffer; count = BitsOnInByte[Ptr[0]] + BitsOnInByte[Ptr[1]] + BitsOnInByte[Ptr[2]] + BitsOnInByte[Ptr[3]] + BitsOnInByte[Ptr[4]] + BitsOnInByte[Ptr[5]] + BitsOnInByte[Ptr[6]] + BitsOnInByte[Ptr[7]]; return count; } // BUGBUG DRC: The stuff below is a horrible hack, purely in the name of expediency. // Thomas Mooney is responsible for none of it, and I am responsible for all of it. - dcorbit // Forgive me Thomas, for I have Kludged. int EpdBinary::SaveToFile(FILE *f) { if (f) { int count; epd_solid es = {0}; es.ce = e.ce; es.acd = e.acd; if (e.bm) strncpy(es.bm, e.bm, sizeof(es.bm)); if (e.am) strncpy(es.am, e.am, sizeof(es.am)); if (e.pm) strncpy(es.pm, e.pm, sizeof(es.pm)); count = fwrite(&es.ce, sizeof(es.ce), 1, f) + fwrite(&es.acd, sizeof(es.acd), 1, f) + fwrite(&es.am, sizeof(es.am), 1, f) + fwrite(&es.bm, sizeof(es.bm), 1, f) + fwrite(&es.pm, sizeof(es.pm), 1, f) + fwrite(m_Buffer, EPD_BINARY_LENGTH, 1, f); if (count == 6) return EPD_STATUS_SUCCESS; else return EPD_STATUS_FAILURE; } else return EPD_STATUS_FAILURE; } int EpdBinary::GetFromFile(epd_solid &es, char *edata, FILE *f) { int count = 0; if (f) { count = fread(&es.ce, sizeof(es.ce), 1, f) + fread(&es.acd, sizeof(es.acd), 1, f) + fread(&es.am, sizeof(es.am), 1, f) + fread(&es.bm, sizeof(es.bm), 1, f) + fread(&es.pm, sizeof(es.pm), 1, f) + fread(edata, EPD_BINARY_LENGTH, 1, f); } if (count == 6) return EPD_STATUS_SUCCESS; else return EPD_STATUS_FAILURE; } // Dann's horrible hack constuctor. Forgive me Thomas, for I have Kludged. EpdBinary::EpdBinary(epd_solid &es, char *edata) { memcpy(m_Buffer, edata, EPD_BINARY_LENGTH); SetCE(es.ce); SetACD(es.acd); SetPM(es.pm); SetBM(es.bm); SetAM(es.am); }