68478eab4b
but couldn't release immediately since they depended on virtual GPU features which were not yet publicly released in any products. This checkin moves those features from our internal repository to the open source repository. Future development on these tests and examples will take place directly in the open source repository. The primary feature added by this patch is 'Screen Object', a new dynamic display management extension supported by Workstation 7.0 and Fusion 3.0. See the README for a quick explanation.
745 lines
17 KiB
C
745 lines
17 KiB
C
/*
|
|
* This is a modified version of the screen-cursor test, which does
|
|
* not use Screen Object or GMRs. It will run on older versions of the
|
|
* virtual SVGA device.
|
|
*
|
|
* This test doesn't draw anything on the screen, but it still
|
|
* supports the same set of cursors.
|
|
*
|
|
* XXX: Use screen-cursor whenever possible. This test is harder to use
|
|
* and doesn't test as many things.
|
|
*/
|
|
|
|
#include "svga.h"
|
|
#include "intr.h"
|
|
#include "screendraw.h"
|
|
#include "keyboard.h"
|
|
#include "vmbackdoor.h"
|
|
#include "timer.h"
|
|
#include "math.h"
|
|
|
|
|
|
/*
|
|
* Global data
|
|
*/
|
|
|
|
int currentTest = -1;
|
|
|
|
#define FRAME_RATE 60
|
|
|
|
|
|
/*
|
|
* Test Cases
|
|
*/
|
|
|
|
void
|
|
testAlphaArrow(void)
|
|
{
|
|
static const SVGAFifoCmdDefineAlphaCursor cursor = {
|
|
.id = 0,
|
|
.hotspotX = 1,
|
|
.hotspotY = 1,
|
|
.width = 36,
|
|
.height = 51,
|
|
};
|
|
|
|
static const uint32 data[] = {
|
|
# include "rgba_arrow.h"
|
|
};
|
|
|
|
void *fifoData;
|
|
|
|
/*
|
|
* Switch to 8-bit mode. Alpha cursors should work even if the
|
|
* legacy framebuffer is in a low color depth.
|
|
*/
|
|
SVGA_WriteReg(SVGA_REG_BITS_PER_PIXEL, 8);
|
|
|
|
SVGA_BeginDefineAlphaCursor(&cursor, &fifoData);
|
|
memcpy(fifoData, data, sizeof data);
|
|
SVGA_FIFOCommitAll();
|
|
}
|
|
|
|
void
|
|
testGradient(int size)
|
|
{
|
|
const SVGAFifoCmdDefineAlphaCursor cursor = {
|
|
.id = 0,
|
|
.hotspotX = size / 2,
|
|
.hotspotY = size / 2,
|
|
.width = size,
|
|
.height = size,
|
|
};
|
|
|
|
uint32 *data;
|
|
int x, y;
|
|
|
|
SVGA_WriteReg(SVGA_REG_BITS_PER_PIXEL, 8);
|
|
SVGA_BeginDefineAlphaCursor(&cursor, (void**) &data);
|
|
|
|
for (y = 0; y < cursor.height; y++) {
|
|
for (x = 0; x < cursor.width; x++) {
|
|
uint8 alpha = y * 255 / cursor.height;
|
|
|
|
/* Solid white, with pre-multiplied alpha: L = 255 * alpha / 255 */
|
|
uint8 luma = alpha;
|
|
|
|
*(data++) = (alpha << 24) | (luma << 16) | (luma << 8) | luma;
|
|
}
|
|
}
|
|
|
|
SVGA_FIFOCommitAll();
|
|
}
|
|
|
|
void
|
|
testGradient64(void)
|
|
{
|
|
testGradient(64);
|
|
}
|
|
|
|
void
|
|
testGradient180(void)
|
|
{
|
|
testGradient(180);
|
|
}
|
|
|
|
void
|
|
testGradient256(void)
|
|
{
|
|
testGradient(256);
|
|
}
|
|
|
|
void
|
|
testMonochrome(void)
|
|
{
|
|
static const SVGAFifoCmdDefineCursor cursor = {
|
|
.id = 0,
|
|
.hotspotX = 24,
|
|
.hotspotY = 24,
|
|
.width = 48,
|
|
.height = 48,
|
|
.andMaskDepth = 1,
|
|
.xorMaskDepth = 1,
|
|
};
|
|
|
|
static const uint8 data[] = {
|
|
# include "beachball_mono.h"
|
|
};
|
|
|
|
void *andData, *xorData;
|
|
|
|
/*
|
|
* Switch to 32bpp mode, just because we can. Monochrome cursors
|
|
* work in any framebuffer depth.
|
|
*/
|
|
SVGA_WriteReg(SVGA_REG_BITS_PER_PIXEL, 32);
|
|
|
|
SVGA_BeginDefineCursor(&cursor, &andData, &xorData);
|
|
memcpy(andData, data, sizeof data);
|
|
SVGA_FIFOCommitAll();
|
|
}
|
|
|
|
void
|
|
testMonochromeXOR(void)
|
|
{
|
|
static const SVGAFifoCmdDefineCursor cursor = {
|
|
.id = 0,
|
|
.hotspotX = 24,
|
|
.hotspotY = 24,
|
|
.width = 48,
|
|
.height = 48,
|
|
.andMaskDepth = 1,
|
|
.xorMaskDepth = 1,
|
|
};
|
|
|
|
static const uint8 data[] = {
|
|
# include "beachball_mono_xor.h"
|
|
};
|
|
|
|
void *andData, *xorData;
|
|
|
|
SVGA_WriteReg(SVGA_REG_BITS_PER_PIXEL, 32);
|
|
SVGA_BeginDefineCursor(&cursor, &andData, &xorData);
|
|
memcpy(andData, data, sizeof data);
|
|
SVGA_FIFOCommitAll();
|
|
}
|
|
|
|
void
|
|
testMonochromeLarge(void)
|
|
{
|
|
static const SVGAFifoCmdDefineCursor cursor = {
|
|
.id = 0,
|
|
.hotspotX = 50,
|
|
.hotspotY = 50,
|
|
.width = 100,
|
|
.height = 98,
|
|
.andMaskDepth = 1,
|
|
.xorMaskDepth = 1,
|
|
};
|
|
|
|
static const uint8 data[] = {
|
|
# include "chip_mono.h"
|
|
};
|
|
|
|
void *andData, *xorData;
|
|
|
|
/*
|
|
* Switch to 32bpp mode, just because we can. Monochrome cursors
|
|
* work in any framebuffer depth.
|
|
*/
|
|
SVGA_WriteReg(SVGA_REG_BITS_PER_PIXEL, 32);
|
|
|
|
SVGA_BeginDefineCursor(&cursor, &andData, &xorData);
|
|
memcpy(andData, data, sizeof data);
|
|
SVGA_FIFOCommitAll();
|
|
}
|
|
|
|
void
|
|
testANDXOR32(void)
|
|
{
|
|
static const SVGAFifoCmdDefineCursor cursor = {
|
|
.id = 0,
|
|
.hotspotX = 16,
|
|
.hotspotY = 16,
|
|
.width = 32,
|
|
.height = 32,
|
|
.andMaskDepth = 32,
|
|
.xorMaskDepth = 32
|
|
};
|
|
|
|
uint32 *andData, *xorData;
|
|
int x, y;
|
|
|
|
SVGA_WriteReg(SVGA_REG_BITS_PER_PIXEL, 32);
|
|
SVGA_BeginDefineCursor(&cursor, (void**) &andData, (void**) &xorData);
|
|
|
|
for (y = 0; y < cursor.height; y++) {
|
|
for (x = 0; x < cursor.width; x++) {
|
|
|
|
*(andData++) = 0x808080;
|
|
*(xorData++) = y * 127 / cursor.height;
|
|
|
|
}
|
|
}
|
|
|
|
SVGA_FIFOCommitAll();
|
|
}
|
|
|
|
static const uint32 yellowCrabData[] = {
|
|
# include "yellow_crab_rgba.h"
|
|
};
|
|
|
|
void
|
|
buildCrabANDMask(uint8 *andData)
|
|
{
|
|
const uint32 *rgba = yellowCrabData;
|
|
const int width = 48;
|
|
const int height = 50;
|
|
|
|
uint32 andPitch = ((width + 31) / 32) * 4;
|
|
uint8 *andLine;
|
|
int x, y;
|
|
|
|
|
|
for (y = 0; y < height; y++) {
|
|
andLine = andData;
|
|
andData += andPitch;
|
|
memset(andLine, 0, andPitch);
|
|
|
|
for (x = 0; x < width; x++) {
|
|
uint32 color = *(rgba++);
|
|
|
|
*andLine <<= 1;
|
|
|
|
if ((color & 0xFF000000) == 0) {
|
|
/*
|
|
* Transparent pixel
|
|
*/
|
|
*andLine |= 1;
|
|
}
|
|
|
|
if ((x & 7) == 7) {
|
|
andLine++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
testCrabAlpha(void)
|
|
{
|
|
static const SVGAFifoCmdDefineAlphaCursor cursor = {
|
|
.id = 0,
|
|
.hotspotX = 24,
|
|
.hotspotY = 25,
|
|
.width = 48,
|
|
.height = 50,
|
|
};
|
|
|
|
void *fifoData;
|
|
|
|
SVGA_WriteReg(SVGA_REG_BITS_PER_PIXEL, 32);
|
|
SVGA_BeginDefineAlphaCursor(&cursor, &fifoData);
|
|
memcpy(fifoData, yellowCrabData, sizeof yellowCrabData);
|
|
SVGA_FIFOCommitAll();
|
|
}
|
|
|
|
void
|
|
testCrabANDXOR32(void)
|
|
{
|
|
static const SVGAFifoCmdDefineCursor cursor = {
|
|
.id = 0,
|
|
.hotspotX = 24,
|
|
.hotspotY = 25,
|
|
.width = 48,
|
|
.height = 50,
|
|
.andMaskDepth = 1,
|
|
.xorMaskDepth = 32
|
|
};
|
|
|
|
uint8 *andData;
|
|
uint32 *xorData;
|
|
|
|
SVGA_WriteReg(SVGA_REG_BITS_PER_PIXEL, 32);
|
|
SVGA_BeginDefineCursor(&cursor, (void**) &andData, (void**) &xorData);
|
|
|
|
buildCrabANDMask(andData);
|
|
memcpy(xorData, yellowCrabData, sizeof yellowCrabData);
|
|
|
|
SVGA_FIFOCommitAll();
|
|
}
|
|
|
|
void
|
|
testCrabANDXOR16(void)
|
|
{
|
|
static const SVGAFifoCmdDefineCursor cursor = {
|
|
.id = 0,
|
|
.hotspotX = 24,
|
|
.hotspotY = 25,
|
|
.width = 48,
|
|
.height = 50,
|
|
.andMaskDepth = 1,
|
|
.xorMaskDepth = 16
|
|
};
|
|
|
|
const uint32 *rgba = yellowCrabData;
|
|
uint8 *andData;
|
|
uint16 *xorData;
|
|
int x, y;
|
|
|
|
SVGA_WriteReg(SVGA_REG_BITS_PER_PIXEL, 16);
|
|
if (SVGA_ReadReg(SVGA_REG_DEPTH) != 16) {
|
|
Console_Panic("Expected SVGA_REG_DEPTH == 16 for 16bpp mode");
|
|
}
|
|
|
|
SVGA_BeginDefineCursor(&cursor, (void**) &andData, (void**) &xorData);
|
|
|
|
buildCrabANDMask(andData);
|
|
|
|
for (y = 0; y < cursor.height; y++) {
|
|
for (x = 0; x < cursor.width; x++) {
|
|
uint32 color = *(rgba++);
|
|
|
|
/*
|
|
* Convert to RGB 5-6-5
|
|
*/
|
|
|
|
uint8 r = (color >> 19) & 0x1F;
|
|
uint8 g = (color >> 10) & 0x3F;
|
|
uint8 b = (color >> 3) & 0x1F;
|
|
|
|
*(xorData++) = (r << 11) | (g << 5) | b;
|
|
}
|
|
}
|
|
|
|
SVGA_FIFOCommitAll();
|
|
}
|
|
|
|
void
|
|
testCrabANDXOR8(void)
|
|
{
|
|
static const SVGAFifoCmdDefineCursor cursor = {
|
|
.id = 0,
|
|
.hotspotX = 24,
|
|
.hotspotY = 25,
|
|
.width = 48,
|
|
.height = 50,
|
|
.andMaskDepth = 1,
|
|
.xorMaskDepth = 8
|
|
};
|
|
|
|
static const uint8 crabPixels[] = {
|
|
# include "yellow_crab_256_pixels.h"
|
|
};
|
|
|
|
static const uint8 crabColormap[] = {
|
|
# include "yellow_crab_256_colormap.h"
|
|
};
|
|
|
|
uint8 *andData, *xorData;
|
|
int i;
|
|
|
|
SVGA_WriteReg(SVGA_REG_BITS_PER_PIXEL, 8);
|
|
if (SVGA_ReadReg(SVGA_REG_PSEUDOCOLOR) != TRUE) {
|
|
Console_Panic("Expected SVGA_REG_PSUEDOCOLOR == TRUE for 8bpp mode");
|
|
}
|
|
|
|
/*
|
|
* Load the crab's colormap into the SVGA palette registers.
|
|
*/
|
|
for (i = 0; i < arraysize(crabColormap); i++) {
|
|
SVGA_WriteReg(SVGA_PALETTE_BASE + i, crabColormap[i]);
|
|
}
|
|
|
|
SVGA_BeginDefineCursor(&cursor, (void**) &andData, (void**) &xorData);
|
|
buildCrabANDMask(andData);
|
|
memcpy(xorData, crabPixels, sizeof crabPixels);
|
|
SVGA_FIFOCommitAll();
|
|
}
|
|
|
|
void
|
|
createPaletteCursor(void)
|
|
{
|
|
/*
|
|
* Set up a cursor which shows every color in the palette. It has
|
|
* a 1-pixel border of color 255, but every other color forms a
|
|
* 16x16 grid in which each square is a different color. Each grid
|
|
* square is 3x3 pixels.
|
|
*
|
|
* We also take this opportunity to use an 8-bit AND mask, but it's
|
|
* fully opaque (all zeroes).
|
|
*
|
|
* This does mean that to function correctly, this cursor needs
|
|
* color 0 to be black. The SVGA device doesn't specify whether
|
|
* AND/XOR masks are applied before or after pseudocolor emulation,
|
|
* so we need to be okay with either.
|
|
*/
|
|
|
|
static const SVGAFifoCmdDefineCursor cursor = {
|
|
.id = 0,
|
|
.hotspotX = 24,
|
|
.hotspotY = 24,
|
|
.width = 49,
|
|
.height = 49,
|
|
.andMaskDepth = 8,
|
|
.xorMaskDepth = 8
|
|
};
|
|
|
|
uint8 *andData, *xorData;
|
|
uint8 *line;
|
|
int x, y;
|
|
uint32 pitch = roundup(cursor.width, sizeof(uint32)) * sizeof(uint32);
|
|
|
|
SVGA_WriteReg(SVGA_REG_BITS_PER_PIXEL, 8);
|
|
if (SVGA_ReadReg(SVGA_REG_PSEUDOCOLOR) != TRUE) {
|
|
Console_Panic("Expected SVGA_REG_PSUEDOCOLOR == TRUE for 8bpp mode");
|
|
}
|
|
|
|
SVGA_BeginDefineCursor(&cursor, (void**) &andData, (void**) &xorData);
|
|
memset(andData, 0, pitch * cursor.height);
|
|
|
|
for (y = 0; y < cursor.height; y++) {
|
|
line = xorData;
|
|
xorData += pitch;
|
|
|
|
for (x = 0; x < cursor.width; x++) {
|
|
uint8 color;
|
|
|
|
if (y == 0 || x == 0 || y == cursor.height - 1 || x == cursor.width - 1) {
|
|
/* Border color */
|
|
color = 0xFF;
|
|
|
|
} else {
|
|
int row = (y - 1) / 3;
|
|
int column = (x - 1) / 3;
|
|
|
|
color = row * 16 + column;
|
|
}
|
|
|
|
*(line++) = color;
|
|
}
|
|
}
|
|
|
|
SVGA_FIFOCommitAll();
|
|
}
|
|
|
|
void
|
|
animatePalette(void)
|
|
{
|
|
/*
|
|
* Animate the palette. This is stolen from the vbe-palette test...
|
|
*/
|
|
|
|
static int tick = 0;
|
|
int i;
|
|
|
|
/*
|
|
* Let the phase of each color channel slowly drift around.
|
|
*/
|
|
const float rPhase = tick * 0.001;
|
|
const float gPhase = tick * 0.002;
|
|
const float bPhase = tick * 0.003;
|
|
|
|
/*
|
|
* Animate every color except 0 (used for the AND mask) and 255
|
|
* (for the border).
|
|
*/
|
|
|
|
for (i = 1; i < 255; i++) {
|
|
const int x = (i & 0x0F) - 3;
|
|
const int y = (i >> 4) - 3;
|
|
const float t = (x*x + y*y) * 0.05 + tick * 0.02;
|
|
|
|
const uint8 r = sinf(t + rPhase) * 0x7f + 0x80;
|
|
const uint8 g = sinf(t + gPhase) * 0x7f + 0x80;
|
|
const uint8 b = sinf(t + bPhase) * 0x7f + 0x80;
|
|
|
|
SVGA_WriteReg(SVGA_PALETTE_BASE + i * 3 + 0, r);
|
|
SVGA_WriteReg(SVGA_PALETTE_BASE + i * 3 + 1, g);
|
|
SVGA_WriteReg(SVGA_PALETTE_BASE + i * 3 + 2, b);
|
|
}
|
|
|
|
tick++;
|
|
}
|
|
|
|
void
|
|
blit32(const uint32 *src, int srcX, int srcY, int srcWidth,
|
|
uint32 *dest, int destX, int destY, int destWidth,
|
|
int copyWidth, int copyHeight)
|
|
{
|
|
src += srcX + srcY * srcWidth;
|
|
dest += destX + destY * destWidth;
|
|
|
|
while (copyHeight--) {
|
|
memcpy32(dest, src, copyWidth);
|
|
src += srcWidth;
|
|
dest += destWidth;
|
|
}
|
|
}
|
|
|
|
void
|
|
testCursorAnim(void)
|
|
{
|
|
/*
|
|
* Animate a cursor image of a moon orbiting a planet. The cursor
|
|
* hotspot is always centered on the planet, but we dynamically
|
|
* size the cursor according to the bounding box around the planet
|
|
* and moon, and we dynamically adjust the hotspot to keep it
|
|
* centered on the moon.
|
|
*/
|
|
|
|
const int moonWidth = 10;
|
|
const int planetWidth = 20;
|
|
|
|
static int tick = 0;
|
|
float angle = tick * 0.03;
|
|
tick++;
|
|
|
|
const int orbitRadius = 40;
|
|
int orbitX = cosf(angle) * orbitRadius;
|
|
int orbitY = sinf(angle) * orbitRadius;
|
|
|
|
int width, height, planetX, planetY, moonX, moonY;
|
|
|
|
if (orbitX >= 0) {
|
|
width = planetWidth + orbitX;
|
|
planetX = planetWidth/2;
|
|
moonX = planetX + orbitX;
|
|
} else {
|
|
width = planetWidth - orbitX;
|
|
moonX = planetWidth/2;
|
|
planetX = moonX - orbitX;
|
|
}
|
|
|
|
if (orbitY >= 0) {
|
|
height = planetWidth + orbitY;
|
|
planetY = planetWidth/2;
|
|
moonY = planetY + orbitY;
|
|
} else {
|
|
height = planetWidth - orbitY;
|
|
moonY = planetWidth/2;
|
|
planetY = moonY - orbitY;
|
|
}
|
|
|
|
const SVGAFifoCmdDefineAlphaCursor cursor = {
|
|
.id = 0,
|
|
.hotspotX = planetX,
|
|
.hotspotY = planetY,
|
|
.width = width,
|
|
.height = height,
|
|
};
|
|
|
|
uint32 *image;
|
|
|
|
static const uint32 planet[] = {
|
|
# include "planet_rgba.h"
|
|
};
|
|
static const uint32 moon[] = {
|
|
# include "moon_rgba.h"
|
|
};
|
|
|
|
SVGA_WriteReg(SVGA_REG_BITS_PER_PIXEL, 8);
|
|
SVGA_BeginDefineAlphaCursor(&cursor, (void**) &image);
|
|
memset32(image, 0, width * height);
|
|
|
|
blit32(planet, 0, 0, planetWidth,
|
|
image, planetX - planetWidth/2, planetY - planetWidth/2, width,
|
|
planetWidth, planetWidth);
|
|
|
|
blit32(moon, 0, 0, moonWidth,
|
|
image, moonX - moonWidth/2, moonY - moonWidth/2, width,
|
|
moonWidth, moonWidth);
|
|
|
|
SVGA_FIFOCommitAll();
|
|
}
|
|
|
|
|
|
/*
|
|
* gTestCases --
|
|
*
|
|
* Master array of cursor test cases. Each one has a title and a
|
|
* function pointer. The function is run once when a test mode is
|
|
* selected.
|
|
*/
|
|
|
|
struct {
|
|
void (*fn)(void);
|
|
const char *title;
|
|
void (*animateFn)(void);
|
|
} gTestCases[] = {
|
|
{ testAlphaArrow, "Translucent arrow cursor (36x51)" },
|
|
{ testGradient64, "Gradient from transparent white to opaque white (64x64)" },
|
|
{ testGradient180, "Gradient from transparent white to opaque white (180x180)" },
|
|
{ testGradient256, "Gradient from transparent white to opaque white (256x256)" },
|
|
{ testMonochrome, "Monochrome beachball cursor (48x48)" },
|
|
{ testMonochromeXOR, "Monochrome beachball cursor with XOR pixels (48x48)" },
|
|
{ testMonochromeLarge, "Monochrome chip cursor (100x96)" },
|
|
{ testANDXOR32, "AND masks off 7 LSBs, XOR draws blue gradient (32x32)" },
|
|
{ testCrabAlpha, "Yellow crab, alpha blended (48x50)" },
|
|
{ testCrabANDXOR32, "Yellow crab, 1-bit AND, 32-bit XOR (48x50)" },
|
|
{ testCrabANDXOR16, "Yellow crab, 1-bit AND, 16-bit XOR (48x50)" },
|
|
{ testCrabANDXOR8, "Yellow crab, 1-bit AND, 8-bit XOR (48x50)" },
|
|
{ createPaletteCursor, "Palette animation, 8-bit AND/XOR (49x49)", animatePalette },
|
|
{ testCursorAnim, "Animated cursor (variable size and hotspot)", testCursorAnim }
|
|
};
|
|
|
|
|
|
/*
|
|
* selectTest --
|
|
*
|
|
* Switch to a new current test case. Hilight the new test, un-hilight
|
|
* the old one, and call the new test's function.
|
|
*/
|
|
|
|
void
|
|
selectTest(int newTest)
|
|
{
|
|
if (newTest < 0) {
|
|
newTest += arraysize(gTestCases);
|
|
} else if (newTest >= arraysize(gTestCases)) {
|
|
newTest -= arraysize(gTestCases);
|
|
}
|
|
|
|
if (currentTest != newTest) {
|
|
currentTest = newTest;
|
|
gTestCases[newTest].fn();
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* main --
|
|
*
|
|
* Initialization and main loop. This reads a global array of test
|
|
* cases, and presents a menu which cycles through them. The main
|
|
* loop services keyboard and mouse input.
|
|
*/
|
|
|
|
int
|
|
main(void)
|
|
{
|
|
const int screenWidth = 640;
|
|
const int screenHeight = 480;
|
|
|
|
Intr_Init();
|
|
Intr_SetFaultHandlers(SVGA_DefaultFaultHandler);
|
|
|
|
Timer_InitPIT(PIT_HZ / FRAME_RATE);
|
|
Intr_SetMask(PIT_IRQ, TRUE);
|
|
|
|
SVGA_Init();
|
|
|
|
Keyboard_Init();
|
|
VMBackdoor_MouseInit(TRUE);
|
|
SVGA_SetMode(screenWidth, screenHeight, 32);
|
|
|
|
selectTest(0);
|
|
|
|
while (1) {
|
|
int prevTest = currentTest - 1;
|
|
int nextTest = currentTest + 1;
|
|
static VMMousePacket mouseState;
|
|
const int kbdMouseSpeed = 100;
|
|
Bool needCursorUpdate = FALSE;
|
|
|
|
while (Keyboard_IsKeyPressed(KEY_UP)) {
|
|
selectTest(prevTest);
|
|
}
|
|
|
|
while (Keyboard_IsKeyPressed(KEY_DOWN)) {
|
|
selectTest(nextTest);
|
|
}
|
|
|
|
while (VMBackdoor_MouseGetPacket(&mouseState)) {
|
|
needCursorUpdate = TRUE;
|
|
}
|
|
|
|
if (Keyboard_IsKeyPressed('w')) {
|
|
mouseState.y -= kbdMouseSpeed;
|
|
needCursorUpdate = TRUE;
|
|
}
|
|
|
|
if (Keyboard_IsKeyPressed('s')) {
|
|
mouseState.y += kbdMouseSpeed;
|
|
needCursorUpdate = TRUE;
|
|
}
|
|
|
|
if (Keyboard_IsKeyPressed('a')) {
|
|
mouseState.x -= kbdMouseSpeed;
|
|
needCursorUpdate = TRUE;
|
|
}
|
|
|
|
if (Keyboard_IsKeyPressed('d')) {
|
|
mouseState.x += kbdMouseSpeed;
|
|
needCursorUpdate = TRUE;
|
|
}
|
|
|
|
if (needCursorUpdate) {
|
|
/*
|
|
* Fixed-point to pixels.
|
|
*/
|
|
SVGASignedPoint pixelLocation = {
|
|
mouseState.x * screenWidth / 65535,
|
|
mouseState.y * screenHeight / 65535
|
|
};
|
|
SVGA_MoveCursor(TRUE, pixelLocation.x, pixelLocation.y, SVGA_ID_INVALID);
|
|
}
|
|
|
|
/*
|
|
* Some tests are animated...
|
|
*/
|
|
|
|
if (gTestCases[currentTest].animateFn) {
|
|
gTestCases[currentTest].animateFn();
|
|
}
|
|
|
|
/*
|
|
* Wait for the next frame.
|
|
*/
|
|
|
|
Intr_Halt();
|
|
}
|
|
|
|
return 0;
|
|
}
|