From 6c5075bc99ba07f46562f7f10db14e153d7a93ec Mon Sep 17 00:00:00 2001 From: jhansen Date: Mon, 26 Apr 2010 21:49:44 +0000 Subject: git-svn-id: https://mindboards.svn.sourceforge.net/svnroot/mindboards/lms_nbcnxc_128/trunk@6 c9361245-7fe8-9947-84e8-057757c4e366 --- AT91SAM7S256/Source/c_cmd_drawing.inc | 1713 +++++++++++++++++++++++++++------ 1 file changed, 1428 insertions(+), 285 deletions(-) (limited to 'AT91SAM7S256/Source/c_cmd_drawing.inc') diff --git a/AT91SAM7S256/Source/c_cmd_drawing.inc b/AT91SAM7S256/Source/c_cmd_drawing.inc index 0132d44..a8b5d86 100644 --- a/AT91SAM7S256/Source/c_cmd_drawing.inc +++ b/AT91SAM7S256/Source/c_cmd_drawing.inc @@ -12,12 +12,17 @@ // 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)) //------------------------------------------------------------------ @@ -30,7 +35,7 @@ void cCmdRestoreDefaultScreen(void); //------------------------------------------------------------------ // cCmdDrawString - Draw string to display buffer -void cCmdDrawString(UBYTE *pString, ULONG X, ULONG Y); +void cCmdDrawString(UBYTE *pString, ULONG X, ULONG Y, UBYTE InvertMode, UBYTE LogicalMode, UBYTE FillMode); // OP codes supported by RIC files enum { @@ -42,17 +47,70 @@ enum { IMG_LINE_ID = 5, IMG_RECTANGLE_ID = 6, IMG_CIRCLE_ID = 7, - IMG_NUMBOX_ID = 8 + 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 & 0x000F) +#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 -#define DRAW_OPT_CLEAR_WHOLE_SCREEN (0x0001) -#define DRAW_OPT_CLEAR_EXCEPT_STATUS_SCREEN (0x0002) -#define DRAW_OPT_CLEAR_MODE(_v) ((_v) & 0x0003) +// (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 + +#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 @@ -63,7 +121,8 @@ enum { // Screen Modes for SetScreenMode function enum { - RESTORE_NXT_SCREEN = 0 + RESTORE_NXT_SCREEN = 0, + CLEAR_NXT_SCREEN = 1 }; #define IMG_COMMON_FIELDS UWORD OpSize; UWORD OpCode; @@ -118,7 +177,7 @@ typedef struct typedef struct { IMG_COMMON_FIELDS - UWORD CopyOptions; // Copy, CopyNot, Or, BitClear; + 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 @@ -164,6 +223,23 @@ typedef struct 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; @@ -175,22 +251,47 @@ typedef union 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; -SWORD gPassedVarsCount; +SLONG * gpPassedImgVars = NULL; +SWORD gPassedVarsCount = 0; // Private Prototypes -void cCmdDrawLine(SLONG x1, SLONG y1, SLONG x2, SLONG y2); -void cCmdDrawRect(SLONG left, SLONG bottom, SLONG width, SLONG hieght); +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); +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); + IMG_OP_SPRITE * pSprite, + UBYTE InvertMode, UBYTE LogicalMode, UBYTE FillMode); SLONG cCmdResolveValue(SWORD Value); -void cCmdSetPixel(SLONG X, SLONG Y, ULONG Val); +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 @@ -202,18 +303,10 @@ void cCmdSetPixel(SLONG X, SLONG Y, ULONG Val); NXT_STATUS cCmdWrapDrawText(UBYTE * ArgV[]) { IMG_PT * pPt = (IMG_PT*) ArgV[1]; - ArgV[2] = (UBYTE*)cCmdDVPtr(*(DV_INDEX *)(ArgV[2])); //Resolve array argument - - cCmdClearScreenIfNeeded(*(ULONG*)ArgV[3]); - - // Display the String - cCmdDrawString(ArgV[2], (UBYTE)pPt->X, (UBYTE)(pPt->Y)); - pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND); - + cCmdDrawTextHelper(*(ULONG*)ArgV[3], ArgV[2], pPt); // Set return value *((SBYTE*)(ArgV[0])) = NO_ERR; - return NO_ERR; } @@ -225,11 +318,14 @@ NXT_STATUS cCmdWrapDrawText(UBYTE * ArgV[]) NXT_STATUS cCmdWrapDrawPoint(UBYTE * ArgV[]) { IMG_PT * pPt = (IMG_PT*) ArgV[1]; + ULONG DrawOptions = *(ULONG*)ArgV[2]; + UBYTE pixelMode, fillMode; - cCmdClearScreenIfNeeded(*(ULONG*)ArgV[2]); + cCmdClearScreenIfNeeded(DrawOptions); - // Display the String - cCmdSetPixel(pPt->X, pPt->Y, TRUE); + // Display the Pixel + if (cCmdResolveDrawingMode(DrawOptions, &pixelMode, &fillMode)) + cCmdSetPixel(pPt->X, pPt->Y, pixelMode); pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND); @@ -249,10 +345,13 @@ 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(*(ULONG*)ArgV[3]); + cCmdClearScreenIfNeeded(DrawOptions); - cCmdDrawLine(pPt1->X, pPt1->Y, pPt2->X, pPt2->Y); + if (cCmdResolveDrawingMode(DrawOptions, &pixelMode, &fillMode)) + cCmdDrawLine(pPt1->X, pPt1->Y, pPt2->X, pPt2->Y, pixelMode); pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND); @@ -270,66 +369,18 @@ NXT_STATUS cCmdWrapDrawLine(UBYTE * ArgV[]) //ArgV[3]: Options (ULONG) NXT_STATUS cCmdWrapDrawCircle(UBYTE * ArgV[]) { - SLONG x, x1, y1, y, dp, delta; IMG_PT * pPt = (IMG_PT*) ArgV[1]; SLONG radius = *(UBYTE*)ArgV[2]; - - cCmdClearScreenIfNeeded(*(ULONG*)ArgV[3]); - - x1 = pPt->X; - y1 = pPt->Y; - x = 0; - y = radius; - dp=2*(1-radius); - while(y >= 0) - { - cCmdSetPixel((x+x1), (y+y1), TRUE); - cCmdSetPixel((-x+x1),(-y+y1), TRUE); - cCmdSetPixel((x+x1), (-y+y1), TRUE); - cCmdSetPixel((-x+x1),(y+y1), TRUE); - if(dp<0) - { - delta = 2*dp + 2*y - 1; - if (delta > 0) - { - x++; - y--; - dp += 2*x - 2*y + 2; - } - else - { - x++; - dp += 2*x + 1; - } - } - else if (dp > 0) - { - delta = 2*dp - 2*x - 1; - if (delta > 0) - { - y--; - dp += 1 - 2*y; - } - else - { - x++; - y--; - dp += 2*x - 2*y + 2; - } - } - else - { - x++; - y--; - dp += 2*x - 2*y +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; } @@ -343,10 +394,13 @@ 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(*(ULONG*)ArgV[3]); + cCmdClearScreenIfNeeded(DrawOptions); - cCmdDrawRect(pPt1->X, pPt1->Y, pPt2->X, pPt2->Y); + if (cCmdResolveDrawingMode(DrawOptions, &pixelMode, &fillMode)) + cCmdDrawRect(pPt1->X, pPt1->Y, pPt2->X, pPt2->Y, pixelMode, fillMode); pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND); @@ -356,6 +410,66 @@ NXT_STATUS cCmdWrapDrawRect(UBYTE * ArgV[]) 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; + + //Resolve array argument + IMG_PT * Points = (IMG_PT*)cCmdDVPtr(*(DV_INDEX *)(ArgV[1])); + UWORD polyCorners = DV_ARRAY[*(DV_INDEX *)(ArgV[1])].Count; + if (polyCorners <= MAX_CORNERS) { + + cCmdClearScreenIfNeeded(DrawOptions); + + if (cCmdResolveDrawingMode(DrawOptions, &pixelMode, &fillMode)) + cCmdDrawPolygon(Points, polyCorners, pixelMode, fillMode); + + pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND); + + // Set return value + *((SBYTE*)(ArgV[0])) = NO_ERR; + + return NO_ERR; + } + else { + // Set return value + *((SBYTE*)(ArgV[0])) = ERR_INSTR; + + return ERR_INSTR; + } +} + +//----------------------------------------------------------------- +//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) { @@ -375,12 +489,17 @@ void cCmdSetIMGData(ULONG DataAddr, IMG_OP_UNION * pSprite) //----------------------------------------------------------------- SLONG cCmdResolveValue(SWORD Value) { - if (!IMG_SYMB_USEARGS(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; @@ -428,252 +547,829 @@ SLONG cCmdResolveValue(SWORD Value) } -//----------------------------------------------------------------- -//cCmdWrapDrawGraphic -//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[]) +NXT_STATUS cCmdDrawPictureHelper(IMG_OP_UNION** ppImage, IMG_PT* pPoint, SLONG* pVars, ULONG DataSize, ULONG Options) { - SBYTE * pReturnVal = (SBYTE*)(ArgV[0]); - LOADER_STATUS LStatus; - NXT_STATUS DStatus = NO_ERR; - ULONG DataSize; - SLONG OpSize; - IMG_PT Pt; // Where to draw the picture at (up and to the right) - UBYTE ImageHandle; - IMG_OP_UNION * pImage; - - //Resolve array argument - ArgV[2] = (UBYTE*)cCmdDVPtr(*(DV_INDEX *)(ArgV[2])); - ArgV[3] = (UBYTE*)cCmdDVPtr(*(DV_INDEX *)(ArgV[3])); - - cCmdClearScreenIfNeeded(*(ULONG*)ArgV[4]); - - //Open the file in memory map mode. return if failure. - LStatus = pMapLoader->pFunc(OPENREADLINEAR, ArgV[2], (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) + 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)) { - *pReturnVal = (SBYTE)(LOADER_ERR_BYTE(LStatus)); - return (NO_ERR); - } - //Else, start interpretting the file - else - { - // Read the ArgV params, Clear the data table. - Pt = *(IMG_PT*)ArgV[1]; - //!!! Unsafe assumption that array is non-empty. Should check and avoid using pointer if empty. - gpPassedImgVars = (SLONG*)ArgV[3]; - memset(gpImgData,0,sizeof(gpImgData)); - - // 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) { - // Setup to look at an opcode, make sure it looke reasonable. - if (DataSize < sizeof(IMG_OP_CORE)) + case IMG_SPRITE_ID: { - DStatus = ERR_FILE; - break; // Too small to look at, somethings wrong. + if (OpSize >= sizeof(IMG_OP_SPRITE)) + cCmdSetIMGData(pImage->Sprite.DataAddr, pImage); } - OpSize = pImage->Core.OpSize + sizeof(UWORD); - if (OpSize & 0x01) + break; + + case IMG_VARMAP_ID: { - DStatus = ERR_FILE; - break; // Odd sizes not allowed. + if (OpSize >= sizeof(IMG_OP_VARMAP)) + cCmdSetIMGData(pImage->VarMap.DataAddr, pImage); } + break; - switch(pImage->Core.OpCode) + case IMG_COPYBITS_ID: { - case IMG_SPRITE_ID: + if (OpSize >= sizeof(IMG_OP_COPYBITS)) { - if (OpSize >= sizeof(IMG_OP_SPRITE)) - cCmdSetIMGData(pImage->Sprite.DataAddr, pImage); + 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; + } + break; - case IMG_VARMAP_ID: + case IMG_LINE_ID: + { + if (OpSize >= sizeof(IMG_OP_LINE)) { - if (OpSize >= sizeof(IMG_OP_VARMAP)) - cCmdSetIMGData(pImage->VarMap.DataAddr, pImage); + 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; + } + break; - case IMG_COPYBITS_ID: + case IMG_RECTANGLE_ID: + { + if (OpSize >= sizeof(IMG_OP_RECT)) { - if (OpSize >= sizeof(IMG_OP_COPYBITS)) - { - IMG_OP_COPYBITS * pCB = &(pImage->CopyBits); - 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))); - } + 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; + } + break; - case IMG_LINE_ID: + case IMG_CIRCLE_ID: + { + if (OpSize >= sizeof(IMG_OP_CIRCLE)) { - if (OpSize >= sizeof(IMG_OP_LINE)) - { - IMG_OP_LINE * pL = &(pImage->Line); - 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) - ); - } + 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; + } + break; - case IMG_RECTANGLE_ID: + case IMG_PIXEL_ID: + { + if (OpSize >= sizeof(IMG_OP_PIXEL)) { - if (OpSize >= sizeof(IMG_OP_LINE)) - { - IMG_OP_RECT * pL = &(pImage->Rect); - cCmdDrawRect( - (SWORD)(cCmdResolveValue(pL->Pt.X)+Pt.X), - (SWORD)(cCmdResolveValue(pL->Pt.Y)+Pt.Y), - (SWORD)(cCmdResolveValue(pL->Width)), - (SWORD)(cCmdResolveValue(pL->Height)) + 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; + } + break; - case IMG_PIXEL_ID: + case IMG_NUMBOX_ID: + { + if (OpSize >= sizeof(IMG_OP_NUMBOX)) { - if (OpSize >= sizeof(IMG_OP_PIXEL)) - { - cCmdSetPixel( - (cCmdResolveValue(pImage->Pixel.Pt.X) + Pt.X), - (cCmdResolveValue(pImage->Pixel.Pt.Y) + Pt.Y), - TRUE); - } + 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; + } + break; - case IMG_NUMBOX_ID: + case IMG_ELLIPSE_ID: + { + if (OpSize >= sizeof(IMG_OP_ELLIPSE)) { - if (OpSize >= sizeof(IMG_OP_NUMBOX)) - { - UBYTE NumStr[20]; - IMG_OP_NUMBOX * pNB = &(pImage->NumBox); - sprintf((PSZ)NumStr, "%d", cCmdResolveValue(pNB->Value)); - cCmdDrawString( - NumStr, - (UBYTE) (cCmdResolveValue(pNB->Pt.X) + Pt.X), - (UBYTE) (cCmdResolveValue(pNB->Pt.Y) + Pt.Y)); - } + 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; + } + break; - case IMG_DESCRIPTION_ID: + case IMG_POLYGON_ID: + { + if (OpSize >= sizeof(IMG_OP_POLYGON)) { - //No-op + IMG_OP_POLYGON * pP = &(pImage->Polygon); + cCmdResolveDrawingMode(pP->CopyOptions, &pixelMode, &fillMode); //JJR + // resolve all the values in the struct + 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); } - break; + } + break; - default: + case IMG_DESCRIPTION_ID: + { + switch( pImage->Desc.Options ) { - //Unrecognized opcode, pass an error back to the user. - DStatus = ERR_FILE; + 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; } + break; - DataSize -= OpSize; - pImage = (IMG_OP_UNION*) ((UBYTE*)pImage + OpSize); + default: + { + //Unrecognized opcode, pass an error back to the user. + DStatus = ERR_FILE; + } + break; } - pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND); + DataSize -= OpSize; + pImage = (IMG_OP_UNION*) ((UBYTE*)pImage + OpSize); } + gpPassedImgVars = NULL; + memset(gpImgData,0,sizeof(gpImgData)); + pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND); + return DStatus; +} - // Set return value, close file and return - *pReturnVal = 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); } //----------------------------------------------------------------- -// cCmdDrawLine - draw a line. All clipping is done by the set pixel function. +//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) -{ - 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 (;;) + 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) { - cCmdSetPixel(x, y, TRUE); - if (x==x2) - return; - if (d>=0) - { - y += sy; - d -= ax; - } - x += sx; - d += ay; + if (dx && dy) + y1 = y1 + (((0-x1)*dy)/dx); + x1 = 0; } - } - else - { /* y dominant */ - d = ax-(ay>>1); - for (;;) + //Trim x2 end: + if (x2 > DISPLAY_WIDTH-1) { - cCmdSetPixel(x, y, TRUE); - if (y==y2) - return; - if (d>=0) + 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; + 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; } - y += sy; - d += ax; } } } //----------------------------------------------------------------- -// cCmdDrawRect - draw a rectangle. All clipping is done by the set pixel function. +// cCmdDrawRect - draw a rectangle. void cCmdDrawRect( SLONG left, SLONG bottom, SLONG width, - SLONG height) + 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) { - SLONG right = left + width; - SLONG top = bottom + height; + 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++; + } - // Draw the four line segments - cCmdDrawLine(left, top, right, top); - cCmdDrawLine(right, top, right, bottom); - cCmdDrawLine(right, bottom, left, bottom); - cCmdDrawLine(left, bottom, left, top); + // 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) @@ -750,17 +1447,56 @@ void cCmdCopyBitMapBits( for (dy = dst_y; dy > last_y; dy--) { sx = src_x; - bit_y = masks[7 - (dy & 0x07)]; - not_bit_y = ~ bit_y; + bit_y = masks[7 - (dy & 0x07)]; + // not_bit_y = ~ bit_y; //JJR pDstByte = pFirstDstByte; pLastDstByte = pDstByte + (last_x - dst_x); for (; pDstByte < pLastDstByte; pDstByte++) { - if ( *(pSrcByte + (sx >> 3)) & masks[sx & 0x07] ){ - *pDstByte |= bit_y; - } else { - *pDstByte &= not_bit_y; + //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; @@ -772,15 +1508,15 @@ void cCmdCopyBitMapBits( } //----------------------------------------------------------------- -// cCmdSetPixel - Set or clear a pixel based on Val -void cCmdSetPixel(SLONG X, SLONG Y, ULONG Val) +// cCmdSetPixel - Set, clear or invert a pixel based on PixelMode +void cCmdSetPixel(SLONG X, SLONG Y, ULONG PixelMode) { Y = TRANSLATE_Y(Y); - pMapDisplay->pFunc(DISPLAY_PIXEL, (UBYTE)Val, (UBYTE)X, (UBYTE)Y, 0, 0); + if (X>=0 && X=0 && YpFunc(DISPLAY_PIXEL, (UBYTE)PixelMode, (UBYTE)X, (UBYTE)Y, 0, 0); } - //----------------------------------------------------------------- //cCmdWrapSetScreenMode //ArgV[0]: (Function return) Status code, SBYTE @@ -791,27 +1527,68 @@ NXT_STATUS cCmdWrapSetScreenMode(UBYTE * ArgV[]) 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; } -//------------------------------------------------------------------ -// cCmdClearScreenIfNeeded - Clear entire sceen buffer if explicitly requested or implicitly required. -void cCmdClearScreenIfNeeded(ULONG DrawOptions) +void cDirtyDisplay(ULONG* DrawOptions) { - //If we are the first drawing command, clear the screen and record that we've done so + //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; - - //Override DrawOptions because we have to clear anyway - DrawOptions = DRAW_OPT_CLEAR_WHOLE_SCREEN; + + 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 (DRAW_OPT_CLEAR_MODE(DrawOptions)) + if (cCmdResolveClearScreenMode(DrawOptions)) { pMapDisplay->pFunc(DISPLAY_ERASE_ALL, 0, 0, 0, 0, 0); @@ -827,10 +1604,12 @@ void cCmdClearScreenIfNeeded(ULONG DrawOptions) // 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) +//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; @@ -868,7 +1647,37 @@ void cCmdDrawString(UBYTE *pString, ULONG X, ULONG Y) pSource = (UBYTE*)&(pFont->Data[Item * FontWidth]); while (FontWidth--) { - *pDestination = *pSource; +//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++; } @@ -879,7 +1688,7 @@ void cCmdDrawString(UBYTE *pString, ULONG X, ULONG Y) //------------------------------------------------------------------ // cCmdRestoreDefaultScreen - Restore to Default 'Running' screen -void cCmdRestoreDefaultScreen(void) +__ramfunc void cCmdRestoreDefaultScreen(void) { //If this program has taken over the display, reset it for the UI if (VarsCmd.DirtyDisplay == TRUE) @@ -891,4 +1700,338 @@ void cCmdRestoreDefaultScreen(void) 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++; + } +} + -- cgit v1.2.3