Files
Sprinter-SDCC/tests/gfx_mous/gfx_mous.c
T
snark13 737c974400 Add mdview markdown viewer, reorganize tests/examples and libc layout
- Split tests/ (libc feature tests) and examples/ (real apps); shared
  app.mk in repo root, was examples/example.mk
- libc/io/* split into libc/{conio,env,errno,file,mouse,string,sys,
  time,video}/ — clearer module boundaries
- New examples/mdview/: markdown viewer (Phases 1-5 + light nested
  lists). Headers (H1-H4), HR, ulist/olist/quote with nesting via
  leading spaces, fenced code blocks, inline emphasis (bold/italic/
  underscore/code), wrap/unwrap mode with soft wrap (F2), horizontal
  pan (← →) with '>' truncation indicator
- libc additions: scroll() in conio (ESTEX SCROLL), strlwr/strupr,
  gets() test
- Makefile updates across tests/ for the new shared app.mk path

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-04 22:23:36 +03:00

170 lines
5.3 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* gfx_mouse_test — exercises the graphics-mode mouse cursor API:
* $09 LOAD CURSOR — install a custom cursor bitmap
* $81 CHANGE VIDEO MODE — let the driver re-sync after switching modes
* $0B RETURN CURSOR — read the cursor back (may be a stub in MAME)
*
* Flow:
* 1. Init the mouse driver in text mode.
* 2. Switch to 320x256x256, notify the driver.
* 3. Build an 8x8 cursor — solid white border + transparent middle —
* and load it. Show it. Move the mouse to verify it tracks.
* 4. Press a key: query the driver's view of the cursor and dump the
* result so we can compare against what we loaded.
* 5. Hide cursor, return to text mode, print the round-trip dump.
*
* The driver's bitmap format is undocumented — best guess is one byte
* per pixel (palette index, with 0 meaning transparent). We load 0xFF
* for opaque cells and 0 for transparent so the cursor stands out
* against any background.
*/
#include <stdio.h>
#include <conio.h>
#include <mouse.h>
#include <gfx.h>
#include <stdint.h>
#define CURSOR_W 12
#define CURSOR_H 12
#define CURSOR_BUF_BYTES (CURSOR_W * CURSOR_H)
/* Cursor format (verified empirically 2026-05-31):
* ONE BYTE per pixel — row-major, width*height bytes total.
* 0xFF = transparent (background shows through)
* any other byte = palette index (drawn opaque)
*
* Cursor bitmap lives in a dedicated video bank, not the 0x50 page used
* by gfx_clear256 / gfx_putpixel256 — that's why 0xFF reads as transparent
* even though in the main visible page 0xFF is a regular colour.
*/
static uint8_t cursor_bitmap[CURSOR_BUF_BYTES];
static uint8_t roundtrip_buf[CURSOR_BUF_BYTES];
static uint8_t palette[256 * 4];
/* Arrow shape, 1 byte per pixel. Each cell is either:
* _ transparent (0xFF, lets the background through)
* O black solid pixel (0x00)
* W white solid pixel (0xFF would mean transparent, so use 0xFF
* palette entry by hand if you want a white pixel — for the
* default greyscale palette in this demo, W = bright grey 0xE0)
*
* Feel free to edit the 12×12 grid below to draw a nicer cursor. */
#define _ 0xFF
#define O 0x00
#define W 0xE0
static const uint8_t cursor_arrow[CURSOR_BUF_BYTES] = {
O,_,_,_,_,_,_,_,_,_,_,_,
O,O,_,_,_,_,_,_,_,_,_,_,
O,W,O,_,_,_,_,_,_,_,_,_,
O,W,W,O,_,_,_,_,_,_,_,_,
O,W,W,W,O,_,_,_,_,_,_,_,
O,W,W,W,W,O,_,_,_,_,_,_,
O,W,W,W,W,W,O,_,_,_,_,_,
O,W,W,W,O,O,O,O,_,_,_,_,
O,O,O,W,O,_,_,_,_,_,_,_,
O,_,_,O,W,O,_,_,_,_,_,_,
_,_,_,O,W,O,_,_,_,_,_,_,
_,_,_,_,O,O,_,_,_,_,_,_,
};
#undef _
#undef O
#undef W
static void make_palette(void)
{
for (int i = 0; i < 256; i++) {
palette[i*4+0] = (uint8_t)i;
palette[i*4+1] = (uint8_t)i;
palette[i*4+2] = (uint8_t)i;
palette[i*4+3] = 0;
}
}
/* Copy the arrow pattern into our scratch (one place for the driver
* to point IX at). */
static void build_cursor(void)
{
for (int i = 0; i < CURSOR_BUF_BYTES; i++)
cursor_bitmap[i] = cursor_arrow[i];
}
static void wait_key(void)
{
while (!kbhit()) { /* spin */ }
(void)getch();
}
int main(void)
{
textattr(COLOR(COLOR_LIGHTGRAY, COLOR_BLACK));
clrscr();
cputs("gfx_mouse_test\r\n");
if (mouse_init() < 0) {
cputs("mouse_init failed - no driver\r\n");
return 1;
}
mouse_set_sensitivity(2, 2);
/* --- enter graphics, load custom cursor, then show -------------- */
make_palette();
build_cursor();
uint8_t prev = gfx_init(GFX_MODE_320x256x256, 0);
gfx_pal_load(0, 0, 0, palette);
gfx_clear256(0x40); /* dim grey background */
/* Coordinate grid every 32 px so the cursor position reads easily. */
for (int x = 0; x < GFX_WIDTH; x += 32) gfx_vline256(x, 0, GFX_HEIGHT, 0x80);
for (int y = 0; y < GFX_HEIGHT; y += 32) gfx_hline256(0, y, GFX_WIDTH, 0x80);
mouse_video_mode_changed(GFX_MODE_320x256x256);
mouse_bounds_x(0, GFX_WIDTH - 1);
mouse_bounds_y(0, GFX_HEIGHT - 1);
mouse_cursor_t custom = {
.image = cursor_bitmap,
.width = CURSOR_W,
.height = CURSOR_H,
.hot_x = 0,
.hot_y = 0,
};
mouse_load_cursor(&custom);
mouse_show();
wait_key();
/* --- query driver to see what it has now ------------------------ */
mouse_cursor_t readback = {
.image = roundtrip_buf,
.width = 0, .height = 0, .hot_x = 0, .hot_y = 0,
};
mouse_get_cursor(&readback);
mouse_hide();
gfx_done(prev);
mouse_video_mode_changed(prev); /* tell driver we're back */
/* --- back in text mode: report what the driver returned --------- */
textattr(COLOR(COLOR_LIGHTGRAY, COLOR_BLACK));
clrscr();
cprintf("loaded : %ux%u hot (%u,%u)\r\n",
CURSOR_W, CURSOR_H, 0, 0);
cprintf("read back: %ux%u hot (%u,%u)\r\n",
readback.width, readback.height, readback.hot_x, readback.hot_y);
uint16_t n = (uint16_t)readback.width * (uint16_t)readback.height;
if (n > CURSOR_BUF_BYTES) n = CURSOR_BUF_BYTES;
cprintf("bitmap (%u bytes):\r\n", n);
for (uint16_t i = 0; i < n; i++) {
cprintf("%02X ", roundtrip_buf[i]);
if ((i % readback.width) == readback.width - 1) cputs("\r\n");
}
cputs("\r\n");
cputs("press any key to exit");
wait_key();
return 0;
}