aboutsummaryrefslogtreecommitdiff
path: root/AT91SAM7S256/Source/c_cmd_drawing.inc
diff options
context:
space:
mode:
Diffstat (limited to 'AT91SAM7S256/Source/c_cmd_drawing.inc')
-rw-r--r--AT91SAM7S256/Source/c_cmd_drawing.inc894
1 files changed, 894 insertions, 0 deletions
diff --git a/AT91SAM7S256/Source/c_cmd_drawing.inc b/AT91SAM7S256/Source/c_cmd_drawing.inc
new file mode 100644
index 0000000..0132d44
--- /dev/null
+++ b/AT91SAM7S256/Source/c_cmd_drawing.inc
@@ -0,0 +1,894 @@
+//
+// 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
+//
+
+//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 DISP_BUFFER_P ((UBYTE*)&(pMapDisplay->Normal))
+
+//------------------------------------------------------------------
+// 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);
+
+// 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
+};
+
+#define IMG_SYMB_USEARGS(_v) (_v & (SWORD)0xF000)
+#define IMG_SYMB_MAP(_v) ((_v & 0x0F00) >> 8)
+#define IMG_SYMB_ARG(_v) (_v & 0x000F)
+
+// DrawingOptions
+#define DRAW_OPT_CLEAR_WHOLE_SCREEN (0x0001)
+#define DRAW_OPT_CLEAR_EXCEPT_STATUS_SCREEN (0x0002)
+#define DRAW_OPT_CLEAR_MODE(_v) ((_v) & 0x0003)
+
+
+// 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
+};
+
+#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;
+ 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 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_UNION;
+
+// Variables for DrawImage
+#define IMG_MAX_DATA 11
+IMG_OP_UNION * gpImgData[IMG_MAX_DATA];
+SLONG * gpPassedImgVars;
+SWORD gPassedVarsCount;
+
+// Private Prototypes
+void cCmdDrawLine(SLONG x1, SLONG y1, SLONG x2, SLONG y2);
+void cCmdDrawRect(SLONG left, SLONG bottom, SLONG width, SLONG hieght);
+void cCmdCopyBitMapBits(SLONG dst_x, SLONG dst_y,
+ SLONG src_x, SLONG src_y, SLONG src_width, SLONG src_height,
+ IMG_OP_SPRITE * pSprite);
+SLONG cCmdResolveValue(SWORD Value);
+void cCmdSetPixel(SLONG X, SLONG Y, ULONG Val);
+
+//-----------------------------------------------------------------
+//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
+
+ cCmdClearScreenIfNeeded(*(ULONG*)ArgV[3]);
+
+ // Display the String
+ cCmdDrawString(ArgV[2], (UBYTE)pPt->X, (UBYTE)(pPt->Y));
+ pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND);
+
+ // 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];
+
+ cCmdClearScreenIfNeeded(*(ULONG*)ArgV[2]);
+
+ // Display the String
+ cCmdSetPixel(pPt->X, pPt->Y, TRUE);
+
+ 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];
+
+ cCmdClearScreenIfNeeded(*(ULONG*)ArgV[3]);
+
+ cCmdDrawLine(pPt1->X, pPt1->Y, pPt2->X, pPt2->Y);
+
+ 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[])
+{
+ 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;
+ }
+ }
+
+ 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)
+
+ cCmdClearScreenIfNeeded(*(ULONG*)ArgV[3]);
+
+ cCmdDrawRect(pPt1->X, pPt1->Y, pPt2->X, pPt2->Y);
+
+ 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))
+ {
+ return Value;
+ }
+ else
+ {
+ 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;
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------
+//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[])
+{
+ 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)
+ {
+ *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)
+ {
+ 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);
+ 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)));
+ }
+ }
+ break;
+
+ case IMG_LINE_ID:
+ {
+ 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)
+ );
+ }
+ }
+ break;
+
+ case IMG_RECTANGLE_ID:
+ {
+ 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))
+ );
+ }
+ }
+ break;
+
+ case IMG_PIXEL_ID:
+ {
+ if (OpSize >= sizeof(IMG_OP_PIXEL))
+ {
+ cCmdSetPixel(
+ (cCmdResolveValue(pImage->Pixel.Pt.X) + Pt.X),
+ (cCmdResolveValue(pImage->Pixel.Pt.Y) + Pt.Y),
+ TRUE);
+ }
+ }
+ 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));
+ cCmdDrawString(
+ NumStr,
+ (UBYTE) (cCmdResolveValue(pNB->Pt.X) + Pt.X),
+ (UBYTE) (cCmdResolveValue(pNB->Pt.Y) + Pt.Y));
+ }
+ }
+ break;
+
+ case IMG_DESCRIPTION_ID:
+ {
+ //No-op
+ }
+ break;
+
+ default:
+ {
+ //Unrecognized opcode, pass an error back to the user.
+ DStatus = ERR_FILE;
+ }
+ break;
+ }
+
+ DataSize -= OpSize;
+ pImage = (IMG_OP_UNION*) ((UBYTE*)pImage + OpSize);
+ }
+
+ pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND);
+ }
+
+ // Set return value, close file and return
+ *pReturnVal = DStatus;
+ pMapLoader->pFunc(CLOSE, &ImageHandle, NULL, NULL);
+ return (NO_ERR);
+}
+
+//-----------------------------------------------------------------
+// cCmdDrawLine - draw a line. All clipping is done by the set pixel function.
+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 (;;)
+ {
+ cCmdSetPixel(x, y, TRUE);
+ 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, TRUE);
+ if (y==y2)
+ return;
+ if (d>=0)
+ {
+ x += sx;
+ d -= ay;
+ }
+ y += sy;
+ d += ax;
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------
+// cCmdDrawRect - draw a rectangle. All clipping is done by the set pixel function.
+void cCmdDrawRect(
+ SLONG left,
+ SLONG bottom,
+ SLONG width,
+ SLONG height)
+{
+ SLONG right = left + width;
+ SLONG top = bottom + height;
+
+ // 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);
+}
+
+
+#ifndef DISPLAY_REALWIDTH
+ #define DISPLAY_REALWIDTH DISPLAY_WIDTH
+#endif
+//-----------------------------------------------------------------
+//cCmdCopyBitMapBits
+void cCmdCopyBitMapBits(
+ SLONG dst_x, // left pixel on LCD
+ SLONG dst_y, // bottom pixel on LCD
+ SLONG src_x, // starting pixel x coordinate from source map
+ SLONG src_y, // starting pixel y coordinate from source map
+ SLONG src_width, // width in pixels to the right (negative implies to the left)
+ SLONG src_height, // height in pixels down (negative implies down)
+ IMG_OP_SPRITE * pSprite)
+{
+ SLONG dy; // Location in the destination pixmap , the screen that is
+ SLONG sx;
+ SLONG sy; // Location in the source pixmap.
+ SLONG trim, last_x, last_y, rowbytes;
+ UBYTE *pSrcByte;
+ UBYTE *pDstBytes;
+ UBYTE *pDstByte, *pFirstDstByte;
+ UBYTE *pLastDstByte;
+ UBYTE bit_y, not_bit_y;
+ UBYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
+
+ // Data in the image file is row major 8 pixels per byte.top row first.
+ // src and dst coordinates treat the bottom left most pixel as (0,0)
+
+ if (!pSprite || pSprite->OpCode!=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;
+ 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;
+ }
+ sx ++;
+ }
+ pSrcByte -= rowbytes;
+ sy ++;
+ if ((dy & 0x07) == 0) // bump back the scan line start point at rollover
+ pFirstDstByte -= DISPLAY_REALWIDTH;
+ }
+
+}
+
+//-----------------------------------------------------------------
+// cCmdSetPixel - Set or clear a pixel based on Val
+void cCmdSetPixel(SLONG X, SLONG Y, ULONG Val)
+{
+ Y = TRANSLATE_Y(Y);
+
+ pMapDisplay->pFunc(DISPLAY_PIXEL, (UBYTE)Val, (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();
+ }
+
+ // 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)
+{
+ //If we are the first drawing command, clear the screen and record that we've done so
+ 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 (DRAW_OPT_CLEAR_MODE(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)
+{
+ UBYTE *pSource;
+ UBYTE *pDestination;
+ 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--)
+ {
+ *pDestination = *pSource;
+ 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;
+ }
+}