// // Date init 14.12.2004 // // Revision date $Date:: 8/26/05 4:17p $ // // Filename $Workfile:: c_cmd.c $ // // Version $Revision:: 35 $ // // Archive $Archive:: /LMS2006/Sys01/Main/Firmware/Source/c_cmd_drawing.c $ // // Platform C // #define MAX_CORNERS 128 //absolute value of a #define ABS(a) (((a)<0) ? -(a) : (a)) //take binary sign of a, either -1, or 1 if >= 0 #define SGN(a) (((a)<0) ? -1 : 1) #define MAX(a,b) (((a>b) ? (a) : (b))) #define MIN(a,b) (((aNormal)) //------------------------------------------------------------------ // cCmdClearScreenIfNeeded - Clear entire sceen buffer if explicitly requested or implicitly required. void cCmdClearScreenIfNeeded(ULONG DrawOptions); //------------------------------------------------------------------ // cCmdRestorDefaultScreen - Restore screen to default 'Running' screen void cCmdRestoreDefaultScreen(void); //------------------------------------------------------------------ // cCmdDrawString - Draw string to display buffer void cCmdDrawString(UBYTE *pString, ULONG X, ULONG Y, UBYTE InvertMode, UBYTE LogicalMode, UBYTE FillMode); // OP codes supported by RIC files enum { IMG_DESCRIPTION_ID = 0, // Ignored at this time IMG_SPRITE_ID = 1, IMG_VARMAP_ID = 2, IMG_COPYBITS_ID = 3, IMG_PIXEL_ID = 4, IMG_LINE_ID = 5, IMG_RECTANGLE_ID = 6, IMG_CIRCLE_ID = 7, IMG_NUMBOX_ID = 8, IMG_ELLIPSE_ID = 9, IMG_POLYGON_ID = 10 }; #define IMG_SYMB_USEARGS(_v) (_v & (SWORD)0xF000) #define IMG_SYMB_MAP(_v) ((_v & 0x0F00) >> 8) #define IMG_SYMB_ARG(_v) (_v & 0x00FF) //JJR //#define DRAW_OPT_CLEAR_PIXELS (0x0004) //#define SET_PIXELS(_v) (((_v) & DRAW_OPT_CLEAR_PIXELS) ? FALSE : TRUE) // DrawingOptions // (and CopyOptions) // - parameter used within byte code drawing operations // - now unified with 'CopyOptions' parameter in RIC files // Bits 0 & 1 (values 0,1,2,3) control screen clearing behaviour (Not within RIC files). // Bit 2 (value 4) controls the NOT operation, i.e. draw in white or invert text/graphics. // Bits 3 & 4 (values 0,8,16,24) control pixel logical combinations (COPY/AND/OR/XOR). // Bit 5 (value 32) controls shape filling, or overrides text/graphic bitmaps with set pixels. // These may be ORed together for the full instruction. // These operations are resolved into the separate, common parameters // defined in 'c_display.iom' before any drawing function is called. // Note that when drawing a RIC file, the initial 'DrawingOptions' parameter // supplied in the drawing instruction controls screen clearing, but nothing else. // The 'CopyOptions' parameter from each instruction in the RIC file then controls // graphic operations, but the screen-clearing bits are ignored. #define DRAW_OPT_NORMAL (0x0000) #define DRAW_OPT_LOGICAL_COPY (0x0000) #define DRAW_OPT_CLEAR_WHOLE_SCREEN (0x0001) #define DRAW_OPT_CLEAR_EXCEPT_STATUS_SCREEN (0x0002) #define DRAW_OPT_INVERT (0x0004) #define DRAW_OPT_LOGICAL_AND (0x0008) #define DRAW_OPT_LOGICAL_OR (0x0010) #define DRAW_OPT_LOGICAL_XOR (0x0018) #define DRAW_OPT_FILL_SHAPE (0x0020) // Combined parameter masks: #define DRAW_OPT_CLEAR_SCREEN_MODES (0x0003) #define DRAW_OPT_LOGICAL_OPERATIONS (0x0018) #define DRAW_OPT_FONT_DIRECTIONS (0x01C0) #define DRAW_OPT_FONT_WRAP (0x0200) #define DRAW_OPT_FONT_DIR_L2RB (0x0000) // Font left to right bottom align #define DRAW_OPT_FONT_DIR_L2RT (0x0040) // Font left to right top align #define DRAW_OPT_FONT_DIR_R2LB (0x0080) // Font right to left bottom align #define DRAW_OPT_FONT_DIR_R2LT (0x00C0) // Font right to left top align #define DRAW_OPT_FONT_DIR_B2TL (0x0100) // Font bottom to top left align #define DRAW_OPT_FONT_DIR_B2TR (0x0140) // Font bottom to top right align #define DRAW_OPT_FONT_DIR_T2BL (0x0180) // Font top to bottom left align #define DRAW_OPT_FONT_DIR_T2BR (0x01C0) // Font top to bottom right align // new constant for polyline vs polygon #define DRAW_OPT_POLYGON_POLYLINE (0x0400) #define DESC_FONTOUT 0x8001 // ID for new font out function // CopyOptions, as originally defined for RIC files, now equate to: // COPY = 0 = 0x00 = DRAW_OPT_NORMAL = Copy all bits, solid and clear // COPY_NOT = 4 = 0x04 = DRAW_OPT_INVERT = Copy all bits, but invert bitmap images first // OR = 16 = 0x10 = DRAW_OPT_LOGICAL_OR = Copy solid bits, ignore clear bits // BIT_CLEAR = 12 = 0x0C = DRAW_OPT_INVERT + DRAW_OPT_LOGICAL_AND = Erase screen for solid bits, ignore clear bits //JJR // Clear Before Drawing Modes for Draw functions enum { DO_NOT_CLEAR = 0, CLEAR_B4_DRAW = 1 }; // Screen Modes for SetScreenMode function enum { RESTORE_NXT_SCREEN = 0, CLEAR_NXT_SCREEN = 1 }; #define IMG_COMMON_FIELDS UWORD OpSize; UWORD OpCode; #define TRANSLATE_Y(_y) ((DISPLAY_HEIGHT-1) - (_y)) typedef struct { SWORD X, Y; } IMG_PT; typedef struct { IMG_PT Pt; SWORD Width, Height; } IMG_RECT; typedef struct { IMG_COMMON_FIELDS } IMG_OP_CORE; typedef struct { IMG_COMMON_FIELDS UWORD Options; UWORD Width; UWORD Height; } IMG_OP_DESCRIPTION; typedef struct { IMG_COMMON_FIELDS UWORD DataAddr; //Address sprite handle will be stored in. UWORD Rows; //Second deminsion of the array below. UWORD RowBytes; //The actual size of the following array. Must be even. UBYTE Bytes[2]; //Minimum of two for alignment purposes } IMG_OP_SPRITE; typedef struct { IMG_COMMON_FIELDS UWORD DataAddr; //Address sprite handle will be stored in. UWORD MapCount; //The actual size of the following array. Must be even. struct { //Minimum of two for alignment purposes UWORD Domain; UWORD Range; } MapElt[1]; } IMG_OP_VARMAP; typedef struct { IMG_COMMON_FIELDS UWORD CopyOptions; // Copy, CopyNot, Or, BitClear; //JJR ,Xor; UWORD DataAddr; // Address of an already defined sprite IMG_RECT Src; // Source rectangle IMG_PT Dst; // Destination left top } IMG_OP_COPYBITS; typedef struct { IMG_COMMON_FIELDS UWORD CopyOptions; IMG_PT Pt; UWORD Value; // typically mapped to an argument } IMG_OP_PIXEL; typedef struct { IMG_COMMON_FIELDS UWORD CopyOptions; IMG_PT Pt1; IMG_PT Pt2; } IMG_OP_LINE; typedef struct { IMG_COMMON_FIELDS UWORD CopyOptions; IMG_PT Pt; SWORD Width, Height; } IMG_OP_RECT; typedef struct { IMG_COMMON_FIELDS UWORD CopyOptions; IMG_PT Pt; UWORD Radius; } IMG_OP_CIRCLE; typedef struct { IMG_COMMON_FIELDS UWORD CopyOptions; IMG_PT Pt; UWORD Value; // typically mapped to an argument } IMG_OP_NUMBOX; typedef struct { IMG_COMMON_FIELDS UWORD CopyOptions; IMG_PT Pt; UWORD Radius1; UWORD Radius2; } IMG_OP_ELLIPSE; typedef struct { IMG_COMMON_FIELDS UWORD CopyOptions; UWORD Count; //The actual size of the following array. IMG_PT Points[3]; //Minimum of 3 for polygon } IMG_OP_POLYGON; typedef union { IMG_OP_CORE Core; IMG_OP_DESCRIPTION Desc; IMG_OP_SPRITE Sprite; IMG_OP_VARMAP VarMap; IMG_OP_COPYBITS CopyBits; IMG_OP_PIXEL Pixel; IMG_OP_LINE Line; IMG_OP_RECT Rect; IMG_OP_CIRCLE Circle; IMG_OP_NUMBOX NumBox; IMG_OP_ELLIPSE Ellipse; IMG_OP_POLYGON Polygon; } IMG_OP_UNION; // Variables for DrawImage #define IMG_MAX_DATA 11 IMG_OP_UNION * gpImgData[IMG_MAX_DATA]; SLONG * gpPassedImgVars = NULL; SWORD gPassedVarsCount = 0; // Private Prototypes void cCmdDrawLine(SLONG x1, SLONG y1, SLONG x2, SLONG y2, UBYTE PixelMode); void cCmdDrawRect(SLONG left, SLONG bottom, SLONG width, SLONG height, UBYTE PixelMode, UBYTE FillMode); void cCmdDrawCircle(SLONG cx, SLONG cy, SLONG radius, UBYTE PixelMode, UBYTE FillMode); void cCmdDrawPolygon(IMG_PT* points, UWORD polyCorners, UBYTE PixelMode, UBYTE FillMode, UBYTE bLine); void cCmdDrawEllipse(SWORD cx, SWORD cy, SWORD a, SWORD b, UBYTE PixelMode, UBYTE FillMode); void cCmdCopyBitMapBits(SLONG dst_x, SLONG dst_y, SLONG src_x, SLONG src_y, SLONG src_width, SLONG src_height, IMG_OP_SPRITE * pSprite, UBYTE InvertMode, UBYTE LogicalMode, UBYTE FillMode); SLONG cCmdResolveValue(SWORD Value); void cCmdSetPixel(SLONG X, SLONG Y, ULONG PixelMode); UBYTE cCmdResolveDrawingMode(UWORD DrawingOptions, UBYTE* pPixelMode, UBYTE* pFillMode); void cCmdResolveBitmapMode(UWORD DrawingOptions, UBYTE* pInvertMode, UBYTE* pLogicalMode, UBYTE* pFillMode); UBYTE cCmdResolveClearScreenMode(UWORD DrawingOptions); void cCmdResolveFontOptions(UWORD DrawingOptions, UBYTE* pFontDir, UBYTE* pFontWrap); void cCmdDrawFont(IMG_OP_SPRITE *pSprite, SLONG sW, SLONG sH, SLONG startx, SLONG starty, UBYTE fontDir, UBYTE fontWrap, UBYTE invertMode, UBYTE logicalMode, UBYTE fillMode); void cCmdDrawTextHelper(ULONG DrawOptions, UBYTE *pString, IMG_PT * pPt) { UBYTE invertMode, logicalMode, fillMode; cCmdClearScreenIfNeeded(DrawOptions); // Display the String cCmdResolveBitmapMode(DrawOptions, &invertMode, &logicalMode, &fillMode); cCmdDrawString(pString, (UBYTE)pPt->X, (UBYTE)pPt->Y, invertMode, logicalMode, fillMode); pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND); } //----------------------------------------------------------------- //cCmdWrapDrawText //ArgV[0]: (Function return) Status byte, SBYTE //ArgV[1]: Location (IMG_PT *) //ArgV[2]: Text (CStr) //ArgV[3]: Options (ULONG) // NXT_STATUS cCmdWrapDrawText(UBYTE * ArgV[]) { IMG_PT * pPt = (IMG_PT*) ArgV[1]; ArgV[2] = (UBYTE*)cCmdDVPtr(*(DV_INDEX *)(ArgV[2])); //Resolve array argument cCmdDrawTextHelper(*(ULONG*)ArgV[3], ArgV[2], pPt); // Set return value *((SBYTE*)(ArgV[0])) = NO_ERR; return NO_ERR; } //----------------------------------------------------------------- //cCmdWrapDrawPoint //ArgV[0]: (Function return) Status byte, SBYTE //ArgV[1]: Location (IMG_PT *) //ArgV[2]: Options (ULONG) NXT_STATUS cCmdWrapDrawPoint(UBYTE * ArgV[]) { IMG_PT * pPt = (IMG_PT*) ArgV[1]; ULONG DrawOptions = *(ULONG*)ArgV[2]; UBYTE pixelMode, fillMode; cCmdClearScreenIfNeeded(DrawOptions); // Display the Pixel if (cCmdResolveDrawingMode(DrawOptions, &pixelMode, &fillMode)) cCmdSetPixel(pPt->X, pPt->Y, pixelMode); pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND); // Set return value *((SBYTE*)(ArgV[0])) = NO_ERR; return NO_ERR; } //----------------------------------------------------------------- //cCmdWrapDrawLine //ArgV[0]: (Function return) Status byte, SBYTE //ArgV[1]: Start Location (IMG_PT *) //ArgV[2]: End Location (IMG_PT *) //ArgV[3]: Options (ULONG) NXT_STATUS cCmdWrapDrawLine(UBYTE * ArgV[]) { IMG_PT * pPt1 = (IMG_PT*) ArgV[1]; IMG_PT * pPt2 = (IMG_PT*) ArgV[2]; ULONG DrawOptions = *(ULONG*)ArgV[3]; UBYTE pixelMode, fillMode; cCmdClearScreenIfNeeded(DrawOptions); if (cCmdResolveDrawingMode(DrawOptions, &pixelMode, &fillMode)) cCmdDrawLine(pPt1->X, pPt1->Y, pPt2->X, pPt2->Y, pixelMode); pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND); // Set return value *((SBYTE*)(ArgV[0])) = NO_ERR; return NO_ERR; } //----------------------------------------------------------------- //cCmdWrapDrawCircle //ArgV[0]: (Function return) Status byte, SBYTE //ArgV[1]: Start Location (IMG_PT *) //ArgV[2]: Radius (U8) //ArgV[3]: Options (ULONG) NXT_STATUS cCmdWrapDrawCircle(UBYTE * ArgV[]) { IMG_PT * pPt = (IMG_PT*) ArgV[1]; SLONG radius = *(UBYTE*)ArgV[2]; ULONG DrawOptions = *(ULONG*)ArgV[3]; UBYTE pixelMode, fillMode; cCmdClearScreenIfNeeded(DrawOptions); if (cCmdResolveDrawingMode(DrawOptions, &pixelMode, &fillMode)) cCmdDrawCircle(pPt->X, pPt->Y, radius, pixelMode, fillMode); pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND); // Set return value *((SBYTE*)(ArgV[0])) = NO_ERR; return NO_ERR; } //----------------------------------------------------------------- //cCmdWrapDrawRect //ArgV[0]: (Function return) Status byte, SBYTE //ArgV[1]: TopLeft (IMG_PT *) //ArgV[2]: BottomRight (IMG_PT *) //ArgV[3]: Options (ULONG) NXT_STATUS cCmdWrapDrawRect(UBYTE * ArgV[]) { IMG_PT * pPt1 = (IMG_PT*) ArgV[1]; IMG_PT * pPt2 = (IMG_PT*) ArgV[2]; // Second point is actually (width, height) ULONG DrawOptions = *(ULONG*)ArgV[3]; UBYTE pixelMode, fillMode; cCmdClearScreenIfNeeded(DrawOptions); if (cCmdResolveDrawingMode(DrawOptions, &pixelMode, &fillMode)) cCmdDrawRect(pPt1->X, pPt1->Y, pPt2->X, pPt2->Y, pixelMode, fillMode); pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND); // Set return value *((SBYTE*)(ArgV[0])) = NO_ERR; return NO_ERR; } //----------------------------------------------------------------- //cCmdWrapDrawPolygon //ArgV[0]: (Function return) Status byte, SBYTE //ArgV[1]: Points IMG_PT[] //ArgV[2]: Options (ULONG) NXT_STATUS cCmdWrapDrawPolygon(UBYTE * ArgV[]) { ULONG DrawOptions = *(ULONG*)ArgV[2]; UBYTE pixelMode, fillMode, bLine; //Resolve array argument IMG_PT * Points = (IMG_PT*)cCmdDVPtr(*(DV_INDEX *)(ArgV[1])); UWORD polyCorners = DV_ARRAY[*(DV_INDEX *)(ArgV[1])].Count; cCmdClearScreenIfNeeded(DrawOptions); bLine = (DrawOptions & DRAW_OPT_POLYGON_POLYLINE) ? 1 : 0; if (cCmdResolveDrawingMode(DrawOptions, &pixelMode, &fillMode)) { if (fillMode == DRAW_SHAPE_FILLED && polyCorners > MAX_CORNERS) { // Set return value *((SBYTE*)(ArgV[0])) = ERR_INSTR; return ERR_INSTR; } else cCmdDrawPolygon(Points, polyCorners, pixelMode, fillMode, bLine); } pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND); // Set return value *((SBYTE*)(ArgV[0])) = NO_ERR; return NO_ERR; } //----------------------------------------------------------------- //cCmdWrapDrawEllipse //ArgV[0]: (Function return) Status byte, SBYTE //ArgV[1]: Start Location (IMG_PT *) //ArgV[2]: Radius1 (U8) //ArgV[3]: Radius2 (U8) //ArgV[4]: Options (ULONG) NXT_STATUS cCmdWrapDrawEllipse(UBYTE * ArgV[]) { IMG_PT * pPt = (IMG_PT*) ArgV[1]; SWORD radius1 = *(UBYTE*)ArgV[2]; SWORD radius2 = *(UBYTE*)ArgV[3]; ULONG DrawOptions = *(ULONG*)ArgV[4]; UBYTE pixelMode, fillMode; cCmdClearScreenIfNeeded(DrawOptions); if (cCmdResolveDrawingMode(DrawOptions, &pixelMode, &fillMode)) cCmdDrawEllipse(pPt->X, pPt->Y, radius1, radius2, pixelMode, fillMode); pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND); // Set return value *((SBYTE*)(ArgV[0])) = NO_ERR; return NO_ERR; } //----------------------------------------------------------------- IMG_OP_UNION * cCmdGetIMGData(ULONG DataAddr) { if (DataAddr >= IMG_MAX_DATA) return NULL; else return gpImgData[DataAddr]; } //----------------------------------------------------------------- void cCmdSetIMGData(ULONG DataAddr, IMG_OP_UNION * pSprite) { if ((DataAddr >= 1) && (DataAddr < IMG_MAX_DATA)) gpImgData[DataAddr] = pSprite; } //----------------------------------------------------------------- SLONG cCmdResolveValue(SWORD Value) { if (!IMG_SYMB_USEARGS(Value) || !gpPassedImgVars || (gPassedVarsCount == 0)) { return Value; } else { // if we try to access a variable beyond the end of the array we provided // then just return the original value if (IMG_SYMB_ARG(Value) >= gPassedVarsCount) return Value; IMG_OP_VARMAP * pVarMap; SLONG Arg; pVarMap = (IMG_OP_VARMAP *) cCmdGetIMGData((SWORD)IMG_SYMB_MAP(Value)); Arg = gpPassedImgVars[IMG_SYMB_ARG(Value)]; if (!pVarMap) { // No map, this implies a 1:1 mapping. return Arg; } else { // Scan through the list finding the pair the Arg lies between // Then linearly interpolate the mapping. SLONG i, DCur, RCur, DSpread, VSpread, RSpread; SLONG Count = pVarMap->MapCount; SLONG DPrev = pVarMap->MapElt[0].Domain; SLONG RPrev = pVarMap->MapElt[0].Range; if (Arg <= DPrev) { // Too small, map it to the first point return RPrev; } for (i = 1; i < Count; i++) { DCur = pVarMap->MapElt[i].Domain; RCur = pVarMap->MapElt[i].Range; if (Arg < DCur) { DSpread = DCur - DPrev; VSpread = Arg - DPrev; RSpread = RCur - RPrev; // Found the point and mapped, it return. return (RPrev+((VSpread*RSpread)/DSpread)); } DPrev = DCur; RPrev = RCur; } // If we get this far then it is too large, map it to the last point. return RCur; } } } NXT_STATUS cCmdDrawPictureHelper(IMG_OP_UNION** ppImage, IMG_PT* pPoint, SLONG* pVars, ULONG DataSize, ULONG Options) { SLONG OpSize; UBYTE gFillMode, gInvertMode, gLogicalMode, gFontDir, gFontWrap; UBYTE pixelMode, fillMode; UBYTE invertMode, logicalMode; IMG_PT Pt; // Where to draw the picture at (up and to the right) NXT_STATUS DStatus = NO_ERR; IMG_OP_UNION* pImage = *ppImage; // Read the params, Clear the data table. Pt = *pPoint; gpPassedImgVars = pVars; memset(gpImgData,0,sizeof(gpImgData)); cCmdClearScreenIfNeeded(Options); cCmdResolveBitmapMode(Options, &gInvertMode, &gLogicalMode, &gFillMode); cCmdResolveFontOptions(Options, &gFontDir, &gFontWrap); // Run through the op codes. while(!IS_ERR(DStatus)) { // Setup to look at an opcode, make sure it looke reasonable. if (DataSize < sizeof(IMG_OP_CORE)) { DStatus = ERR_FILE; break; // Too small to look at, somethings wrong. } OpSize = pImage->Core.OpSize + sizeof(UWORD); if (OpSize & 0x01) { DStatus = ERR_FILE; break; // Odd sizes not allowed. } switch(pImage->Core.OpCode) { case IMG_SPRITE_ID: { if (OpSize >= sizeof(IMG_OP_SPRITE)) cCmdSetIMGData(pImage->Sprite.DataAddr, pImage); } break; case IMG_VARMAP_ID: { if (OpSize >= sizeof(IMG_OP_VARMAP)) cCmdSetIMGData(pImage->VarMap.DataAddr, pImage); } break; case IMG_COPYBITS_ID: { if (OpSize >= sizeof(IMG_OP_COPYBITS)) { IMG_OP_COPYBITS * pCB = &(pImage->CopyBits); cCmdResolveBitmapMode(pCB->CopyOptions, &invertMode, &logicalMode, &fillMode); cCmdCopyBitMapBits( (cCmdResolveValue(pCB->Dst.X) + Pt.X), (cCmdResolveValue(pCB->Dst.Y) + Pt.Y), cCmdResolveValue((pCB->Src.Pt.X)), cCmdResolveValue((pCB->Src.Pt.Y)), cCmdResolveValue((pCB->Src.Width)), cCmdResolveValue((pCB->Src.Height)), (IMG_OP_SPRITE*)cCmdGetIMGData(cCmdResolveValue(pCB->DataAddr)), invertMode, logicalMode, fillMode); } } break; case IMG_LINE_ID: { if (OpSize >= sizeof(IMG_OP_LINE)) { IMG_OP_LINE * pL = &(pImage->Line); cCmdResolveDrawingMode(pL->CopyOptions, &pixelMode, &fillMode); //JJR cCmdDrawLine( (cCmdResolveValue(pL->Pt1.X)+Pt.X), (cCmdResolveValue(pL->Pt1.Y)+Pt.Y), (cCmdResolveValue(pL->Pt2.X)+Pt.X), (cCmdResolveValue(pL->Pt2.Y)+Pt.Y), pixelMode //JJR ); } } break; case IMG_RECTANGLE_ID: { if (OpSize >= sizeof(IMG_OP_RECT)) { IMG_OP_RECT * pR = &(pImage->Rect); cCmdResolveDrawingMode(pR->CopyOptions, &pixelMode, &fillMode); //JJR cCmdDrawRect( (SWORD)(cCmdResolveValue(pR->Pt.X)+Pt.X), (SWORD)(cCmdResolveValue(pR->Pt.Y)+Pt.Y), (SWORD)(cCmdResolveValue(pR->Width)), (SWORD)(cCmdResolveValue(pR->Height)), pixelMode, fillMode //JJR ); } } break; case IMG_CIRCLE_ID: { if (OpSize >= sizeof(IMG_OP_CIRCLE)) { IMG_OP_CIRCLE * pC = &(pImage->Circle); cCmdResolveDrawingMode(pC->CopyOptions, &pixelMode, &fillMode); //JJR cCmdDrawCircle( (SWORD)(cCmdResolveValue(pC->Pt.X)+Pt.X), (SWORD)(cCmdResolveValue(pC->Pt.Y)+Pt.Y), (SWORD)(cCmdResolveValue(pC->Radius)), pixelMode, fillMode //JJR ); } } break; case IMG_PIXEL_ID: { if (OpSize >= sizeof(IMG_OP_PIXEL)) { cCmdResolveDrawingMode(pImage->Pixel.CopyOptions, &pixelMode, &fillMode); //JJR cCmdSetPixel( (cCmdResolveValue(pImage->Pixel.Pt.X) + Pt.X), (cCmdResolveValue(pImage->Pixel.Pt.Y) + Pt.Y), pixelMode //JJR ); } } break; case IMG_NUMBOX_ID: { if (OpSize >= sizeof(IMG_OP_NUMBOX)) { UBYTE NumStr[20]; IMG_OP_NUMBOX * pNB = &(pImage->NumBox); sprintf((PSZ)NumStr, "%d", cCmdResolveValue(pNB->Value)); cCmdResolveBitmapMode(pNB->CopyOptions, &invertMode, &logicalMode, &fillMode); cCmdDrawString( NumStr, (UBYTE) (cCmdResolveValue(pNB->Pt.X) + Pt.X), (UBYTE) (cCmdResolveValue(pNB->Pt.Y) + Pt.Y), invertMode, logicalMode, fillMode //JJR ); } } break; case IMG_ELLIPSE_ID: { if (OpSize >= sizeof(IMG_OP_ELLIPSE)) { IMG_OP_ELLIPSE * pE = &(pImage->Ellipse); cCmdResolveDrawingMode(pE->CopyOptions, &pixelMode, &fillMode); //JJR cCmdDrawEllipse( (SWORD)(cCmdResolveValue(pE->Pt.X)+Pt.X), (SWORD)(cCmdResolveValue(pE->Pt.Y)+Pt.Y), (SWORD)(cCmdResolveValue(pE->Radius1)), (SWORD)(cCmdResolveValue(pE->Radius2)), pixelMode, fillMode //JJR ); } } break; case IMG_POLYGON_ID: { if (OpSize >= sizeof(IMG_OP_POLYGON)) { IMG_OP_POLYGON * pP = &(pImage->Polygon); UBYTE bLine = (pP->CopyOptions & DRAW_OPT_POLYGON_POLYLINE) ? 1 : 0; cCmdResolveDrawingMode(pP->CopyOptions, &pixelMode, &fillMode); //JJR // resolve all the values in the struct if (fillMode != DRAW_SHAPE_FILLED || pP->Count <= MAX_CORNERS) { for(int i=0;iCount; i++) { pP->Points[i].X = (SWORD)(cCmdResolveValue(pP->Points[i].X)+Pt.X); pP->Points[i].Y = (SWORD)(cCmdResolveValue(pP->Points[i].Y)+Pt.Y); } cCmdDrawPolygon(pP->Points, pP->Count, pixelMode, fillMode, bLine); } } } break; case IMG_DESCRIPTION_ID: { switch( pImage->Desc.Options ) { case DESC_FONTOUT : cCmdDrawFont((IMG_OP_SPRITE*)cCmdGetIMGData(1), pImage->Desc.Width, pImage->Desc.Height, Pt.X, Pt.Y, gFontDir, gFontWrap, gInvertMode, gLogicalMode, gFillMode); break; } } break; default: { //Unrecognized opcode, pass an error back to the user. DStatus = ERR_FILE; } break; } DataSize -= OpSize; pImage = (IMG_OP_UNION*) ((UBYTE*)pImage + OpSize); } gpPassedImgVars = NULL; memset(gpImgData,0,sizeof(gpImgData)); pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND); return DStatus; } void cCmdDrawPictureFromFile(UBYTE *pFilename, IMG_PT* pPoint, SLONG* pVars, ULONG Options, SBYTE * pReturnVal) { LOADER_STATUS LStatus; ULONG DataSize; UBYTE ImageHandle; IMG_OP_UNION * pImage; //Open the file in memory map mode. return if failure. LStatus = pMapLoader->pFunc(OPENREADLINEAR, pFilename, (UBYTE*)(&pImage), &DataSize); ImageHandle = LOADER_HANDLE(LStatus); //If error opening file, give up and write loader status back to user. if (LOADER_ERR(LStatus) != SUCCESS || pImage == NULL) { *pReturnVal = (SBYTE)(LOADER_ERR_BYTE(LStatus)); return; } //Else, start interpretting the file else { *pReturnVal = cCmdDrawPictureHelper(&pImage, pPoint, pVars, DataSize, Options); } pMapLoader->pFunc(CLOSE, &ImageHandle, NULL, NULL); } //----------------------------------------------------------------- //cCmdWrapDrawPicture //ArgV[0]: (Function return) Status Byte, SBYTE //ArgV[1]: Left Top (IMG_PT *) //ArgV[2]: Filename, CStr //ArgV[3]: Variables, array of I32 //ArgV[4]: Options (ULONG) NXT_STATUS cCmdWrapDrawPicture(UBYTE * ArgV[]) { SBYTE * pReturnVal = (SBYTE *)ArgV[0]; IMG_PT* pPt = (IMG_PT*)ArgV[1]; ULONG Options = *(ULONG *)ArgV[4]; // count the variables gPassedVarsCount = DV_ARRAY[*(DV_INDEX *)(ArgV[3])].Count; //Resolve array argument ArgV[2] = (UBYTE*)cCmdDVPtr(*(DV_INDEX *)(ArgV[2])); ArgV[3] = (UBYTE*)cCmdDVPtr(*(DV_INDEX *)(ArgV[3])); cCmdDrawPictureFromFile((UBYTE *)ArgV[2], pPt, (SLONG *)ArgV[3], Options, pReturnVal); return (NO_ERR); } //----------------------------------------------------------------- //cCmdWrapDrawPictureArray //ArgV[0]: (Function return) Status Byte, SBYTE //ArgV[1]: Left Top (IMG_PT *) //ArgV[2]: Data, array of U8 //ArgV[3]: Variables, array of I32 //ArgV[4]: Options (ULONG) NXT_STATUS cCmdWrapDrawPictureArray(UBYTE * ArgV[]) { SBYTE * pReturnVal = (SBYTE *)ArgV[0]; IMG_PT* pPt = (IMG_PT *)ArgV[1]; DV_INDEX DVIndex = *(DV_INDEX*)ArgV[2]; ULONG Options = *(ULONG *)ArgV[4]; ULONG DataSize = DV_ARRAY[DVIndex].Count; IMG_OP_UNION* pImage; // count the variables gPassedVarsCount = DV_ARRAY[*(DV_INDEX *)(ArgV[3])].Count; //Resolve array argument pImage = (IMG_OP_UNION*)cCmdDVPtr(DVIndex); ArgV[3] = (UBYTE*)cCmdDVPtr(*(DV_INDEX *)(ArgV[3])); // pVar *pReturnVal = cCmdDrawPictureHelper((IMG_OP_UNION**)&pImage, pPt, (SLONG*)ArgV[3], DataSize, Options); return (NO_ERR); } //----------------------------------------------------------------- //cCmdWrapDrawFont //ArgV[0]: (Function return) Status Byte, SBYTE //ArgV[1]: Left Top (IMG_PT *) //ArgV[2]: FontFilename, CStr //ArgV[3]: Text, CStr //ArgV[4]: Options (ULONG) NXT_STATUS cCmdWrapDrawFont(UBYTE * ArgV[]) { SBYTE * pReturnVal = (SBYTE *)ArgV[0]; IMG_PT * pPt = (IMG_PT*)ArgV[1]; ULONG Options = *(ULONG *)ArgV[4]; // count the number of characters gPassedVarsCount = DV_ARRAY[*(DV_INDEX *)(ArgV[3])].Count; //Resolve array arguments ArgV[2] = (UBYTE*)cCmdDVPtr(*(DV_INDEX *)(ArgV[2])); ArgV[3] = (UBYTE*)cCmdDVPtr(*(DV_INDEX *)(ArgV[3])); if (strlen((PSZ)ArgV[2]) == 0) { // if font filename is empty then use draw text instead cCmdDrawTextHelper(Options, ArgV[3], pPt); // Set return value *pReturnVal = NO_ERR; return NO_ERR; } else { // count the variables gPassedVarsCount = MIN(strlen((PSZ)ArgV[3]), 256); // copy data from input string into SLONG* array SLONG Vars[256]; for(int i=0; i<256;i++) { if (i < gPassedVarsCount) Vars[i] = ArgV[3][i]; else Vars[i] = 0; } cCmdDrawPictureFromFile((UBYTE *)ArgV[2], pPt, (SLONG*)Vars, Options, pReturnVal); return (NO_ERR); } } //----------------------------------------------------------------- // cCmdDrawLine - draw a line. Line is clipped to screen boundaries. void cCmdDrawLine( SLONG x1, SLONG y1, SLONG x2, SLONG y2, UBYTE PixelMode) //JJR { SLONG tx, ty; //JJR SLONG dx, dy; //JJR dx = x2-x1; //JJR dy = y2-y1; //JJR //Clip line ends vertically - easier if y1 y2) {tx=x1; x1=x2; x2=tx; ty=y1; y1=y2; y2=ty;} //Is line completely off screen? if (y2<0 || y1>=DISPLAY_HEIGHT) return; //Trim y1 end: if (y1 < 0) { if (dx && dy) x1 = x1 + (((0-y1)*dx)/dy); y1 = 0; } //Trim y2 end: if (y2 > DISPLAY_HEIGHT-1) { if (dx && dy) x2 = x2 - (((y2-(DISPLAY_HEIGHT-1))*dx)/dy); y2 = DISPLAY_HEIGHT-1; } //Clip horizontally - easier if x1 x2) {tx=x1; x1=x2; x2=tx; ty=y1; y1=y2; y2=ty;} //Is line completely off screen? if (x2<0 || x1>=DISPLAY_WIDTH) return; //Trim x1 end: if (x1 < 0) { if (dx && dy) y1 = y1 + (((0-x1)*dy)/dx); x1 = 0; } //Trim x2 end: if (x2 > DISPLAY_WIDTH-1) { if (dx && dy) y2 = y2 - (((x2-(DISPLAY_WIDTH-1))*dy)/dx); x2 = DISPLAY_WIDTH-1; } if (x1 == x2) { // vertical line or a single point if (y1 == y2) //cCmdSetPixel(x1, y1, Set); //JJR pMapDisplay->pFunc(DISPLAY_PIXEL, (UBYTE)PixelMode, (UBYTE)x1, (UBYTE)TRANSLATE_Y(y1), 0, 0); //JJR else { //pMapDisplay->pFunc(DISPLAY_VERTICAL_LINE, Set, x1, TRANSLATE_Y(y1), 0, TRANSLATE_Y(y2)); //JJR pMapDisplay->pFunc(DISPLAY_VERTICAL_LINE, PixelMode, x1, TRANSLATE_Y(y1), 0, TRANSLATE_Y(y2)); //JJR } } else if (y1 == y2) { // horizontal line (single point already dealt with) pMapDisplay->pFunc(DISPLAY_HORIZONTAL_LINE, PixelMode, x1, TRANSLATE_Y(y1), x2, 0); //JJR } else { SLONG d,x,y,ax,ay,sx,sy,dx,dy; // Initialize variables dx = x2-x1; ax = ABS(dx)<<1; sx = SGN(dx); dy = y2-y1; ay = ABS(dy)<<1; sy = SGN(dy); x = x1; y = y1; if (ax>ay) { // x dominant d = ay-(ax>>1); for (;;) { //cCmdSetPixel(x, y, Set); //JJR pMapDisplay->pFunc(DISPLAY_PIXEL, (UBYTE)PixelMode, (UBYTE)x, (UBYTE)TRANSLATE_Y(y), 0, 0); //JJR if (x==x2) return; if (d>=0) { y += sy; d -= ax; } x += sx; d += ay; } } else { // y dominant d = ax-(ay>>1); for (;;) { //cCmdSetPixel(x, y, Set); //JJR pMapDisplay->pFunc(DISPLAY_PIXEL, (UBYTE)PixelMode, (UBYTE)x, (UBYTE)TRANSLATE_Y(y), 0, 0); //JJR if (y==y2) return; if (d>=0) { x += sx; d -= ay; } y += sy; d += ax; } } } } //----------------------------------------------------------------- // cCmdDrawRect - draw a rectangle. void cCmdDrawRect( SLONG left, SLONG bottom, SLONG width, SLONG height, UBYTE PixelMode, //JJR UBYTE FillMode) //JJR { SLONG x1, y1; SLONG x2, y2; SLONG t; x1 = left; x2 = left + width; /* if (width > 0) x2 = left + width - 1; else if (width < 0) x2 = left + width + 1; else x2 = x1; */ y1 = bottom; y2 = bottom + height; /* if (height > 0) y2 = bottom + height - 1; else if (height < 0) y2 = bottom + height + 1; else y2 = y1; */ if (x1>x2) {t = x1; x1 = x2; x2 = t;} if (y1>y2) {t = y1; y1 = y2; y2 = t;} if (y2 == y1 || x2 == x1) { // height == 0 so draw a single pixel horizontal line OR // width == 0 so draw a single pixel vertical line cCmdDrawLine(x1, y1, x2, y2, PixelMode); return; } // rectangle has abs(width) or abs(height) >= 1 if (FillMode == DRAW_SHAPE_FILLED) { if (x2<0 || y2<0 || x1>DISPLAY_WIDTH-1 || y1>DISPLAY_HEIGHT-1) return; if (x1<0) x1=0; if (y1<0) y1=0; if (x2>DISPLAY_WIDTH-1) x2=DISPLAY_WIDTH-1; if (y2>DISPLAY_HEIGHT-1) y2=DISPLAY_HEIGHT-1; pMapDisplay->pFunc(DISPLAY_FILL_REGION, PixelMode, x1, TRANSLATE_Y(y2), x2-x1+1, y2-y1+1); } else { //Use the full line drawing functions rather than horizontal/vertical //functions so these get clipped properly. These will fall straight //through to the faster functions anyway. //Also don't re-draw parts of slim rectangles since XOR might be on. cCmdDrawLine(x1, y1, x2, y1, PixelMode); if (y2>y1) { cCmdDrawLine(x1, y2, x2, y2, PixelMode); if (y2 > y1+1) { cCmdDrawLine(x2, y1+1, x2, y2-1, PixelMode); if (x2>x1) cCmdDrawLine(x1, y1+1, x1, y2-1, PixelMode); } } } } void cCmdDrawPolygon(IMG_PT* points, UWORD polyCorners, UBYTE PixelMode, UBYTE FillMode, UBYTE bLine) { // the fill mode overrides the polyline vs polygon setting if (FillMode == DRAW_SHAPE_FILLED) { int nodes; int nodeX[MAX_CORNERS]; int pixelY; int i, j; int swap; int IMAGE_TOP = -1; int IMAGE_BOTTOM = 1024; int IMAGE_RIGHT = -1; int IMAGE_LEFT = 1024; // calculate maximum and minimum X and Y coordinate values for(i=0;iIMAGE_TOP) IMAGE_TOP = tmpY; if (tmpYIMAGE_RIGHT) IMAGE_RIGHT = tmpX; if (tmpX=pixelY) || (pJ.Y=pixelY)) { nodeX[nodes++]=(pI.X+(pixelY-pI.Y)*(pJ.X-pI.X)/(pJ.Y-pI.Y)); } j=i; } // Sort the nodes, via a simple “Bubble” sort. i=0; while (inodeX[i+1]) { swap=nodeX[i]; nodeX[i]=nodeX[i+1]; nodeX[i+1]=swap; if (i) i--; } else i++; } // Fill the pixels between node pairs. for (i=0; i=IMAGE_RIGHT) break; if (nodeX[i+1]> IMAGE_LEFT) { if (nodeX[i ]< IMAGE_LEFT) nodeX[i ]=IMAGE_LEFT; if (nodeX[i+1]> IMAGE_RIGHT) nodeX[i+1]=IMAGE_RIGHT; cCmdDrawLine(nodeX[i], pixelY, nodeX[i+1], pixelY, PixelMode); } } } } else { // for(int i = 0, j = polyCorners-1; i=0 && x<=a) { if (FillMode != DRAW_SHAPE_FILLED) { cCmdSetPixel(xc+x, yc+y, PixelMode); if (x!=0 || y!=0) cCmdSetPixel(xc-x, yc-y, PixelMode); if (x!=0 && y!=0) { cCmdSetPixel(xc+x, yc-y, PixelMode); cCmdSetPixel(xc-x, yc+y, PixelMode); } } if (t + b2*x <= crit1 || /* e(x+1,y-1/2) <= 0 */ t + a2*y <= crit3) /* e(x+1/2,y) <= 0 */ { if (FillMode == DRAW_SHAPE_FILLED) { if (height == 1) ; /* draw nothing */ else if (ry*2+1 > (height-1)*2) { cCmdDrawRect(xc-rx, yc-ry, width-1, height-1, PixelMode, FillMode); cCmdDrawRect(xc-rx, yc+ry, width-1, -(height-1), PixelMode, FillMode); ry -= height-1; height = 1; } else { cCmdDrawRect(xc-rx, yc-ry, width-1, ry*2, PixelMode, FillMode); ry -= ry; height = 1; } rx++; width += 2; } x++; dxt += d2xt; t += dxt; } else if (t - a2*y > crit2) /* e(x+1/2,y-1) > 0 */ { y--; dyt += d2yt; t += dyt; if (FillMode == DRAW_SHAPE_FILLED) height++; } else { if (FillMode == DRAW_SHAPE_FILLED) { if (ry*2+1 > height*2) { cCmdDrawRect(xc-rx, yc-ry, width-1, height-1, PixelMode, FillMode); cCmdDrawRect(xc-rx, yc+ry, width-1, -(height-1), PixelMode, FillMode); } else { cCmdDrawRect(xc-rx, yc-ry, width-1, ry*2, PixelMode, FillMode); } width += 2; ry -= height; height = 1; rx++; } x++; dxt += d2xt; t += dxt; y--; dyt += d2yt; t += dyt; } } if (FillMode == DRAW_SHAPE_FILLED) { if (ry > height) { cCmdDrawRect(xc-rx, yc-ry, width-1, height-1, PixelMode, FillMode); cCmdDrawRect(xc-rx, yc+ry, width-1, -(height-1), PixelMode, FillMode); } else { cCmdDrawRect(xc-rx, yc-ry, width-1, ry*2, PixelMode, FillMode); } } } //----------------------------------------------------------------- // cCmdDrawCircle - draw a circle. All clipping is done by the set pixel function. //void cCmdDrawCircle(SLONG cx, SLONG cy, SLONG radius, UBYTE Set) //JJR void cCmdDrawCircle(SLONG cx, SLONG cy, SLONG radius, UBYTE PixelMode, UBYTE FillMode) //JJR { cCmdDrawEllipse(cx, cy, radius, radius, PixelMode, FillMode); } /* //----------------------------------------------------------------- // cCmdDrawCircle - draw a circle. All clipping is done by the set pixel function. //void cCmdDrawCircle(SLONG cx, SLONG cy, SLONG radius, UBYTE Set) //JJR void cCmdDrawCircle(SLONG cx, SLONG cy, SLONG radius, UBYTE PixelMode, UBYTE FillMode) //JJR { SLONG f, ddF_x, ddF_y, x, y; SLONG ox, oy; //JJR f = 1 - radius; ddF_x = 0; ddF_y = -2 * radius; x = 0; y = abs(radius); //JJR //JJR if (y==0) { cCmdSetPixel(cx, cy + radius, PixelMode); return; } if (FillMode == DRAW_SHAPE_FILLED) { cCmdDrawLine(cx-radius, cy, cx+radius, cy, PixelMode); } else { cCmdSetPixel(cx + radius, cy, PixelMode); cCmdSetPixel(cx - radius, cy, PixelMode); } if (FillMode != DRAW_SHAPE_FILLED || y==1) { cCmdSetPixel(cx, cy + radius, PixelMode); cCmdSetPixel(cx, cy - radius, PixelMode); } if (y==1) return; while (x < y) { ox = x; //JJR oy = y; //JJR if(f >= 0) { y--; ddF_y += 2; f += ddF_y; } x++; ddF_x += 2; f += ddF_x + 1; //JJR //Need to avoid duplicating pixels if drawing with XOR: if (FillMode == DRAW_SHAPE_FILLED) { //Fill by drawing successive horizontal lines above and below //a horizontal centre line. if (x <= y) { cCmdDrawLine(cx-y, cy+x, cx+y, cy+x, PixelMode); cCmdDrawLine(cx-y, cy-x, cx+y, cy-x, PixelMode); } //Only draw horizontal lines from the top and bottom if: //i. The line doesn't overlap with the one just drawn, and the top // curve has just stepped down a pixel or: //ii. A line wasn't just drawn and the loop is about to exit. if ((xy && oxOpCode!=IMG_SPRITE_ID) return; pDstBytes = DISP_BUFFER_P; // Clip the edges. Modify the source and width as well. if (dst_x < 0) { // bounds check start of x trim = (0 - dst_x); dst_x = 0; src_x += trim; src_width -= trim; } last_x = dst_x + src_width; if (last_x > DISPLAY_WIDTH) // bound check end of x last_x = DISPLAY_WIDTH; if (dst_y < 0) { // bound check start of y trim = (0 - dst_y); dst_y = 0; src_y += trim; // fix up source as well since we are clipping the start of the loop src_height -= trim; } last_y = dst_y + src_height; if (last_y > DISPLAY_HEIGHT) // bound check end of y last_y = DISPLAY_HEIGHT; // Convert the 0,0 bottom left origin to the top left 0,0 used by the actual // buffer last_y = TRANSLATE_Y(last_y); dst_y = TRANSLATE_Y(dst_y); // The last row is the top most scan line in the LCD Buffer // so limit if the copy would copy into memory before the buffer. // The first row copied will be the one closest to the bottom of the LCD // If that is off screen then limit as well and adjust the start point on the start // Copy bits top to top moving down. sy = src_y; rowbytes = pSprite->RowBytes; pSrcByte = pSprite->Bytes + ((pSprite->Rows - 1 - sy) * rowbytes); pFirstDstByte = pDstBytes + ((dst_y >> 3) * DISPLAY_REALWIDTH) + dst_x; for (dy = dst_y; dy > last_y; dy--) { sx = src_x; bit_y = masks[7 - (dy & 0x07)]; // not_bit_y = ~ bit_y; //JJR pDstByte = pFirstDstByte; pLastDstByte = pDstByte + (last_x - dst_x); for (; pDstByte < pLastDstByte; pDstByte++) { //Read source byte: //If fill mode is on, pretend the source bitmap is solid: if (FillMode==DRAW_SHAPE_FILLED) srcByte = 0xff; else srcByte = *(pSrcByte + (sx >> 3)); //JJR //If invert mode is on, invert the source byte: if (InvertMode==DRAW_BITMAP_INVERT) srcByte = ~srcByte; //JJR //Test the pixel in the source byte: if ( srcByte & masks[sx & 0x07] ) //JJR { //If pixel is set in source image: switch (LogicalMode) { case DRAW_LOGICAL_AND: break; case DRAW_LOGICAL_XOR: *pDstByte ^= bit_y; break; case DRAW_LOGICAL_OR: case DRAW_LOGICAL_COPY: default: *pDstByte |= bit_y; break; } } else { //If pixel is clear in source image: switch (LogicalMode) { case DRAW_LOGICAL_OR: case DRAW_LOGICAL_XOR: break; case DRAW_LOGICAL_AND: case DRAW_LOGICAL_COPY: default: *pDstByte &= ~bit_y; break; } } //JJR sx ++; } pSrcByte -= rowbytes; sy ++; if ((dy & 0x07) == 0) // bump back the scan line start point at rollover pFirstDstByte -= DISPLAY_REALWIDTH; } } //----------------------------------------------------------------- // cCmdSetPixel - Set, clear or invert a pixel based on PixelMode void cCmdSetPixel(SLONG X, SLONG Y, ULONG PixelMode) { Y = TRANSLATE_Y(Y); if (X>=0 && X=0 && YpFunc(DISPLAY_PIXEL, (UBYTE)PixelMode, (UBYTE)X, (UBYTE)Y, 0, 0); } //----------------------------------------------------------------- //cCmdWrapSetScreenMode //ArgV[0]: (Function return) Status code, SBYTE //ArgV[1]: ScreenMode ULONG NXT_STATUS cCmdWrapSetScreenMode(UBYTE * ArgV[]) { ULONG ScreenMode = (ULONG)(*ArgV[1]); if (ScreenMode == RESTORE_NXT_SCREEN) { cCmdRestoreDefaultScreen(); } else if (ScreenMode == CLEAR_NXT_SCREEN) { pMapDisplay->pFunc(DISPLAY_ERASE_ALL, 0, 0, 0, 0, 0); } // Set return value *(SBYTE*)(ArgV[0]) = NO_ERR; return NO_ERR; } void cDirtyDisplay(ULONG* DrawOptions) { //If we are the first drawing command mark the display as dirty if (VarsCmd.DirtyDisplay == FALSE) { VarsCmd.DirtyDisplay = TRUE; pMapUi->Flags &= ~UI_ENABLE_STATUS_UPDATE; if (DrawOptions) { //Override DrawOptions because we have to clear anyway *DrawOptions = DRAW_OPT_CLEAR_WHOLE_SCREEN; } } } // //cCmdWrapDisplayExecuteFunction //ArgV[0]: (return) Status byte, SBYTE //ArgV[1]: UBYTE Cmd //ArgV[2]: UBYTE On //ArgV[3]: UBYTE X1 //ArgV[4]: UBYTE Y1 //ArgV[5]: UBYTE X2 //ArgV[6]: UBYTE Y2 // NXT_STATUS cCmdWrapDisplayExecuteFunction(UBYTE * ArgV[]) { cDirtyDisplay(NULL); UBYTE Cmd = *(UBYTE*)(ArgV[1]); UBYTE Y1 = *(UBYTE*)(ArgV[4]); UBYTE Y2 = *(UBYTE*)(ArgV[6]); if (Cmd != DISPLAY_CHAR) Y1 = TRANSLATE_Y(Y1); if (Cmd == DISPLAY_VERTICAL_LINE) Y2 = TRANSLATE_Y(Y2); pMapDisplay->pFunc(Cmd, *(UBYTE*)(ArgV[2]), *(UBYTE*)(ArgV[3]), Y1, *(UBYTE*)(ArgV[5]), Y2); *(SBYTE*)(ArgV[0]) = NO_ERR; return (NO_ERR); } //------------------------------------------------------------------ // cCmdClearScreenIfNeeded - Clear entire sceen buffer if explicitly requested or implicitly required. void cCmdClearScreenIfNeeded(ULONG DrawOptions) { cDirtyDisplay(&DrawOptions); if (cCmdResolveClearScreenMode(DrawOptions)) { pMapDisplay->pFunc(DISPLAY_ERASE_ALL, 0, 0, 0, 0, 0); //Clear UpdateMask to kill any pending updates pMapDisplay->UpdateMask = 0; } return; } //------------------------------------------------------------------ // cCmdDrawString - Draw string to display buffer // Properly uses 'Normal' display buffer to avoid conflicts with popup buffer // Clips text at bottom and right hand edges of the screen buffer //!!! Function copied and modified from cDisplayString //void cCmdDrawString(UBYTE *pString, ULONG X, ULONG Y) //JJR void cCmdDrawString(UBYTE *pString, ULONG X, ULONG Y, UBYTE InvertMode, UBYTE LogicalMode, UBYTE FillMode) //JJR { UBYTE *pSource; UBYTE *pDestination; UBYTE a; FONT *pFont; ULONG FontWidth; ULONG Items; ULONG Item; ULONG Line; //Get current font information pFont = pMapDisplay->pFont; Items = pFont->ItemsX * pFont->ItemsY; //Invert Y coordinate to match display buffer Y = TRANSLATE_Y(Y); Line = (Y & 0xF8) / 8; //If text line is out of bounds, do nothing. if (Line >= TEXTLINES) return; //Calculate pointer to first byte of drawing destination pDestination = &(DISP_BUFFER_P[Line * DISPLAY_WIDTH + X]); while (*pString) { FontWidth = pFont->ItemPixelsX; //Calculate X coordinate of the right edge of this character. //If it will extend past the right edge, clip the string. X += FontWidth; if (X >= DISPLAY_WIDTH) break; //If Item is defined by the font, display it. Else, ignore it. Item = *pString - ' '; if (Item < Items) { pSource = (UBYTE*)&(pFont->Data[Item * FontWidth]); while (FontWidth--) { //JJR // *pDestination = *pSource; //Fetch a byte from the source bitmap: //If fill mode is on, pretend the source bitmap is solid: if (FillMode==DRAW_SHAPE_FILLED) a = 0xff; else a = *pSource; //Implement bitmap invert mode: if (InvertMode==DRAW_BITMAP_INVERT) a = ~a; //Implement bitmap logical mode when writing on screen: switch (LogicalMode) { case DRAW_LOGICAL_OR: *pDestination |= a; break; case DRAW_LOGICAL_AND: *pDestination &= a; break; case DRAW_LOGICAL_XOR: *pDestination ^= a; break; case DRAW_LOGICAL_COPY: default: *pDestination = a; break; } //JJR pDestination++; pSource++; } } pString++; } } //------------------------------------------------------------------ // cCmdRestoreDefaultScreen - Restore to Default 'Running' screen void cCmdRestoreDefaultScreen(void) { //If this program has taken over the display, reset it for the UI if (VarsCmd.DirtyDisplay == TRUE) { VarsCmd.DirtyDisplay = FALSE; pMapDisplay->pFunc(DISPLAY_ERASE_ALL, 0, 0, 0, 0, 0); pMapDisplay->UpdateMask = SCREEN_BIT(SCREEN_BACKGROUND); pMapUi->Flags |= UI_ENABLE_STATUS_UPDATE | UI_REDRAW_STATUS; } // restore default display state pMapDisplay->Display = (UBYTE*)pMapDisplay->Normal; pMapDisplay->Flags = DISPLAY_REFRESH | DISPLAY_ON; } //------------------------------------------------------------------ // cCmdResolveDrawingMode - extract the parameters that affect pixel, line and shape // drawing from the 'DrawingOptions' or 'CopyOptions' parameter. // Return FALSE for combinations that do nothing. UBYTE cCmdResolveDrawingMode(UWORD DrawingOptions, UBYTE* pPixelMode, UBYTE* pFillMode) { DrawingOptions = cCmdResolveValue(DrawingOptions); // Extract shape fill option: if (DrawingOptions & DRAW_OPT_FILL_SHAPE) *pFillMode = DRAW_SHAPE_FILLED; else *pFillMode = DRAW_SHAPE_HOLLOW; // Extract pixel drawing options: if (DrawingOptions & DRAW_OPT_INVERT) { //Drawing with white pixels: switch (DrawingOptions & DRAW_OPT_LOGICAL_OPERATIONS) { //Only these cases do anything: case DRAW_OPT_LOGICAL_COPY: case DRAW_OPT_LOGICAL_AND: *pPixelMode = DRAW_PIXELS_CLEAR; return TRUE; default: break; } } else { //Drawing with black pixels: switch (DrawingOptions & DRAW_OPT_LOGICAL_OPERATIONS) { //Only these cases do anything: case DRAW_OPT_LOGICAL_COPY: case DRAW_OPT_LOGICAL_OR: *pPixelMode = DRAW_PIXELS_SET; return TRUE; case DRAW_OPT_LOGICAL_XOR: *pPixelMode = DRAW_PIXELS_INVERT; return TRUE; default: break; } } // If no operation is required, set defaults and return FALSE. // e.g. 'AND' on its own is meaningless for line drawing, // 'INVERT + OR' and 'INVERT + XOR' do nothing either. *pPixelMode = DRAW_PIXELS_SET; *pFillMode = DRAW_SHAPE_HOLLOW; return FALSE; } //------------------------------------------------------------------ // cCmdResolveBitmapMode - extract the parameters that affect bitmap and text // drawing from the 'DrawingOptions' or 'CopyOptions' parameter. void cCmdResolveBitmapMode(UWORD DrawingOptions, UBYTE* pInvertMode, UBYTE* pLogicalMode, UBYTE* pFillMode) { DrawingOptions = cCmdResolveValue(DrawingOptions); //Extract bitmap inversion mode: if (DrawingOptions & DRAW_OPT_INVERT) *pInvertMode = DRAW_BITMAP_INVERT; else *pInvertMode = DRAW_BITMAP_PLAIN; //Extract bitmap logical operation: switch (DrawingOptions & DRAW_OPT_LOGICAL_OPERATIONS) { case DRAW_OPT_LOGICAL_OR: *pLogicalMode = DRAW_LOGICAL_OR; break; case DRAW_OPT_LOGICAL_AND: *pLogicalMode = DRAW_LOGICAL_AND; break; case DRAW_OPT_LOGICAL_XOR: *pLogicalMode = DRAW_LOGICAL_XOR; break; case DRAW_OPT_LOGICAL_COPY: default: *pLogicalMode = DRAW_LOGICAL_COPY; break; } // Extract shape fill option (overrides source bitmap with all pixels set): if (DrawingOptions & DRAW_OPT_FILL_SHAPE) *pFillMode = DRAW_SHAPE_FILLED; else *pFillMode = DRAW_SHAPE_HOLLOW; } //------------------------------------------------------------------ // cCmdResolveFontOptions - extract the parameters that affect custom RIC font drawing // drawing from the 'DrawingOptions' parameter. void cCmdResolveFontOptions(UWORD DrawingOptions, UBYTE* pFontDir, UBYTE* pFontWrap) { //Extract bitmap inversion mode: if (DrawingOptions & DRAW_OPT_FONT_WRAP) *pFontWrap = DRAW_FONT_WRAP_ON; else *pFontWrap = DRAW_FONT_WRAP_OFF; //Extract bitmap logical operation: switch (DrawingOptions & DRAW_OPT_FONT_DIRECTIONS) { case DRAW_OPT_FONT_DIR_L2RB: *pFontDir = DRAW_FONT_DIR_L2RB; break; case DRAW_OPT_FONT_DIR_L2RT: *pFontDir = DRAW_FONT_DIR_L2RT; break; case DRAW_OPT_FONT_DIR_R2LB: *pFontDir = DRAW_FONT_DIR_R2LB; break; case DRAW_OPT_FONT_DIR_R2LT: *pFontDir = DRAW_FONT_DIR_R2LT; break; case DRAW_OPT_FONT_DIR_B2TL: *pFontDir = DRAW_FONT_DIR_B2TL; break; case DRAW_OPT_FONT_DIR_B2TR: *pFontDir = DRAW_FONT_DIR_B2TR; break; case DRAW_OPT_FONT_DIR_T2BL: *pFontDir = DRAW_FONT_DIR_T2BL; break; case DRAW_OPT_FONT_DIR_T2BR: *pFontDir = DRAW_FONT_DIR_T2BR; break; default: *pFontDir = DRAW_FONT_DIR_L2RB; break; } } //------------------------------------------------------------------ // cCmdResolveClearScreenMode - extract the parameters that affect screen clearing // from the 'DrawingOptions' parameter. UBYTE cCmdResolveClearScreenMode(UWORD DrawingOptions) { if (DrawingOptions & DRAW_OPT_CLEAR_SCREEN_MODES) return TRUE; else return FALSE; } //JJR void cCmdDrawFont(IMG_OP_SPRITE *pSprite, SLONG sW, SLONG sH, SLONG startx, SLONG starty, UBYTE fontDir, UBYTE fontWrap, UBYTE invertMode, UBYTE logicalMode, UBYTE fillMode) { SWORD index; // index on id for output SWORD xpos; // x-position for next output SWORD ypos; // y-position for next output SLONG sourcex; // X-Pos of pattern inside bitmap SLONG sourcey; // Y-Pos of pattern inside bitmap SLONG sourcew; // Width of pattern inside bitmap SLONG sourceh; // Height of pattern inside bitmap int destx; // X-Destination position on screen int desty; // Y-Destination position on screen SWORD stdw; // Standard font width SWORD stdh; // Standard font height if (!gpPassedImgVars) // exit early if we do not have parameters return; stdw = MIN( sW, DISPLAY_WIDTH ); // calculate the standard width stdh = MIN( sH, DISPLAY_HEIGHT ); // calculate the standard height index=0; // Reset the start position xpos=startx; // Initial start position X ypos=starty; // Initial start position Y while( index < gPassedVarsCount ) { // terminate the loop at our first null if (gpPassedImgVars[index] == 0) break; sourcex=cCmdResolveValue(0xF200|index); // Get dynamic xpos of pattern sourcey=cCmdResolveValue(0xF300|index); // Get dynamic ypos of pattern sourcew=cCmdResolveValue(0xF400|index); // Get dynamic width of pattern sourceh=cCmdResolveValue(0xF500|index); // Get dynamic height of pattern //--Calculate the rectangle for source (inside the sprite) and destination //--on the screen (related to the fontdirection) for performing the //--BitCopy function switch( fontDir ) { case DRAW_FONT_DIR_L2RB : // Left to right with bottom align---------------- if( fontWrap ) { if( ( xpos + sourcew ) > DISPLAY_WIDTH ) { xpos = startx; ypos -= stdh; } } destx = xpos; desty = ypos; xpos = xpos + sourcew; break; case DRAW_FONT_DIR_L2RT : // Left to right with align to top---------------- if( fontWrap ) { if( ( xpos + sourcew ) > DISPLAY_WIDTH ) { xpos = startx; ypos += stdh; } } destx = xpos; desty = ypos - sourceh + 1; xpos = xpos + sourcew; break; case DRAW_FONT_DIR_R2LB : // Right to left with align to bottom------------- if( fontWrap ) { if( ( xpos - sourcew ) < 0 ) { xpos = startx; ypos -= stdh; } } destx = xpos - sourcew + 1; desty = ypos; xpos = xpos - sourcew; break; case DRAW_FONT_DIR_R2LT : // Right to left with align to top---------------- if( fontWrap ) { if( ( xpos - sourcew ) < 0 ) { xpos = startx; ypos += stdh; } } destx = xpos - sourcew + 1; desty = ypos - sourceh + 1; xpos = xpos - sourcew; break; case DRAW_FONT_DIR_B2TL : // Bottom to top with allign to left-------------- if( fontWrap ) { if( ( ypos + sourceh ) > DISPLAY_HEIGHT ) { xpos += stdw; ypos = starty; } } destx = xpos; desty = ypos; ypos = ypos + sourceh; break; case DRAW_FONT_DIR_B2TR : // Bottom to top with allign to right------------- if( fontWrap ) { if( ( ypos + sourceh ) > DISPLAY_HEIGHT ) { xpos -= stdw; ypos = starty; } } destx = xpos - sourcew + 1; desty = ypos; ypos = ypos + sourceh; break; case DRAW_FONT_DIR_T2BL : // Top to bottom with allign to right------------- if( fontWrap ) { if( ( ypos - sourceh ) < 0 ) { xpos += stdw; ypos = starty; } } destx = xpos; desty = ypos - sourceh + 1; ypos = ypos - sourceh; break; case DRAW_FONT_DIR_T2BR : // Top to bottom with allign to right------------- if( fontWrap ) { if( ( ypos - sourceh ) < 0 ) { xpos -= stdw; ypos = starty; } } destx = xpos - sourcew + 1; desty = ypos - sourceh + 1; ypos = ypos - sourceh; break; } //--Output of the calculated pattern to the screen------------------------ cCmdCopyBitMapBits(destx, desty, sourcex, sourcey, sourcew, sourceh, pSprite, invertMode, logicalMode, fillMode); // move on to next character index++; } }