diff --git a/basic/test.bsc b/basic/test.bsc index 6e8ab1b51..eec06269b 100644 --- a/basic/test.bsc +++ b/basic/test.bsc @@ -2,6 +2,7 @@ ' BASIC Mouse cursor manipulation ' mouse show +cls:line 0,0 ink 3 to 100,100 mouse to 260,180 repeat b = mouse(x,y,s) diff --git a/emulator/src/core/sys_debugger.cpp b/emulator/src/core/sys_debugger.cpp index 7d397ad9f..755e525a7 100644 --- a/emulator/src/core/sys_debugger.cpp +++ b/emulator/src/core/sys_debugger.cpp @@ -158,7 +158,10 @@ void DBGXRender(int *address,int showDisplay) { } const uint8_t *cursorImage; uint16_t cursorX,cursorY; - if (MSEGetCursorDrawInformation(&cursorImage,&cursorX,&cursorY)) { + uint8_t xHit,yHit; + if (MSEGetCursorDrawInformation(&cursorX,&cursorY)) { + cursorImage = CURGetCurrent(&xHit,&yHit); + cursorX -= xHit;cursorY -= yHit; uint8_t w = 16,h = 16; if (cursorX + 16 >= 320) w = 320-cursorX; if (cursorY + 16 >= 240) h = 240-cursorY; diff --git a/firmware/common/include/common.h b/firmware/common/include/common.h index 2bfda39f1..b284f513e 100644 --- a/firmware/common/include/common.h +++ b/firmware/common/include/common.h @@ -48,6 +48,7 @@ #include "interface/graphics.h" #include "interface/console.h" #include "interface/mouse.h" +#include "interface/cursor.h" #include "interface/timer.h" #include "interface/sound.h" #include "interface/memory.h" diff --git a/firmware/common/include/interface/cursor.h b/firmware/common/include/interface/cursor.h new file mode 100644 index 000000000..04318f19e --- /dev/null +++ b/firmware/common/include/interface/cursor.h @@ -0,0 +1,28 @@ +// *************************************************************************************** +// *************************************************************************************** +// +// Name : cursor.h +// Authors : Paul Robson (paul@robsons.org.uk) +// Date : 13th April 2024 +// Reviewed : No +// Purpose : Cursor header +// +// *************************************************************************************** +// *************************************************************************************** + +#ifndef _CURSOR_H +#define _CURSOR_H + +void CURInitialise(void); +const uint8_t *CURGetCurrent(uint8_t *xHit,uint8_t *yHit); +bool CURSetCurrent(uint8_t cursorID); + + +#endif + +// *************************************************************************************** +// +// Date Revision +// ==== ======== +// +// *************************************************************************************** diff --git a/firmware/common/include/interface/mouse.h b/firmware/common/include/interface/mouse.h index bdc34fe88..c4b05d8f0 100644 --- a/firmware/common/include/interface/mouse.h +++ b/firmware/common/include/interface/mouse.h @@ -10,8 +10,8 @@ // *************************************************************************************** // *************************************************************************************** -#ifndef _CURSOR_H -#define _CURSOR_H +#ifndef _MOUSE_H +#define _MOUSE_H void MSEInitialise(void); void MSESetPosition(uint16_t x, uint16_t y); @@ -19,7 +19,7 @@ void MSEOffsetPosition(int8_t dx, int8_t dy); void MSEUpdateScrollWheel(int8_t ds); void MSEUpdateButtonState(uint8_t buttonState); void MSEGetState(uint16_t *pX, uint16_t *pY, uint8_t *pButtonState, uint8_t *pScrollWheelState); -bool MSEGetCursorDrawInformation(const uint8_t **pData, uint16_t *pX, uint16_t *pY); +bool MSEGetCursorDrawInformation(uint16_t *pX, uint16_t *pY); void MSESetVisible(bool isVisible); void MSEEnableMouse(void); bool MSEMousePresent(void); diff --git a/firmware/common/scripts/cursors.py b/firmware/common/scripts/cursors.py index aa1980787..6b4db5938 100644 --- a/firmware/common/scripts/cursors.py +++ b/firmware/common/scripts/cursors.py @@ -3,32 +3,45 @@ # # Name : cursors.py # Authors : Paul Robson (paul@robsons.org.uk) -# Date : 21st March 2024 +# Date : 13th April 2024 # Reviewed : No -# Purpose : Converts cursors to data (monochrome only at present) +# Purpose : Converts cursors to data (2nd version) # # *************************************************************************************** # *************************************************************************************** import re,os,sys -from PIL import Image - - -class Cursor(object): - def __init__(self,imageFile,xClick,yClick): - self.click = (xClick,yClick) - self.image = Image.open("scripts"+os.sep+"cursors"+os.sep+imageFile) - assert self.image.size == (16,16) - self.imageData = [0xFF] * 256 - self.name = imageFile[:-4].lower() - for x in range(0,16): - for y in range(0,16): - p = self.image.getpixel((x,y)) - if p[3] > 128: - self.imageData[x+y*16] = 7 if p[0]+p[1]+p[2] > 512 else 0 - ib = ",".join([str(x) for x in self.imageData]) - print("static const uint8_t {1}_cursor_data[] = {{ {0}}};\n".format(ib,self.name)) - -cursors = [] -print("//\n//\tThis file is automatically generated.\n//") -Cursor("default.png",0,0) + +def convert(n): + n = n & 0x0F + return 0xFF if n == 0 else n + +src = [x for x in open("scripts/cursors/graphics.gfx","rb").read(-1)] +assert src[0] == 1 and src[1] == 0 and src[3] == 0 +cursorCount = src[2] + +print("//\n//\tThis file is automatically generated\n//\n") + +print("#define CURSOR_IMAGE_COUNT ({0})\n".format(cursorCount)) + +cursorData = [] +for c in src[256:]: + cursorData.append(convert(c >> 4)) + cursorData.append(convert(c)) + +print("const uint8_t cursor_data[] = {") +print(",".join([str(x) for x in cursorData])) +print("};\n") + +hitPoint = [] +for i in range(0,cursorCount): + hp = [8,8] + if i == 0: + hp = [4,0] + if i == 4 or i == 9: + hp = [4,4] + hitPoint += hp +print("const uint8_t cursor_hitPoint[] = {") +print(",".join([str(x) for x in hitPoint])) +print("};\n") + diff --git a/firmware/common/scripts/cursors/Makefile b/firmware/common/scripts/cursors/Makefile new file mode 100644 index 000000000..aa0d3b5e2 --- /dev/null +++ b/firmware/common/scripts/cursors/Makefile @@ -0,0 +1,23 @@ +# *************************************************************************************** +# *************************************************************************************** +# +# Name : Makefile +# Author : Paul Robson (paul@robsons.org.uk) +# Date : 20th November 2023 +# Reviewed : No +# Purpose : Main firmware makefile, most of the work is done by CMake. +# +# *************************************************************************************** +# *************************************************************************************** + +ifeq ($(OS),Windows_NT) +#is this really needed? WSL2 is the 2023. +include ..\..\..\..\build_env\common.make +else +include ../../../../build_env/common.make +endif + +all: + + $(PYTHON) $(BINDIR)makeimg.zip + diff --git a/firmware/common/scripts/cursors/default.png b/firmware/common/scripts/cursors/default.png deleted file mode 100644 index 09fac7758..000000000 Binary files a/firmware/common/scripts/cursors/default.png and /dev/null differ diff --git a/firmware/common/scripts/cursors/graphics.gfx b/firmware/common/scripts/cursors/graphics.gfx new file mode 100644 index 000000000..652329884 Binary files /dev/null and b/firmware/common/scripts/cursors/graphics.gfx differ diff --git a/firmware/common/scripts/cursors/sprite_16.png b/firmware/common/scripts/cursors/sprite_16.png new file mode 100644 index 000000000..fee2812e3 Binary files /dev/null and b/firmware/common/scripts/cursors/sprite_16.png differ diff --git a/firmware/common/scripts/cursors/sprite_32.png b/firmware/common/scripts/cursors/sprite_32.png new file mode 100644 index 000000000..31814a5a8 Binary files /dev/null and b/firmware/common/scripts/cursors/sprite_32.png differ diff --git a/firmware/common/scripts/cursors/tile_16.png b/firmware/common/scripts/cursors/tile_16.png new file mode 100644 index 000000000..4207d4ace Binary files /dev/null and b/firmware/common/scripts/cursors/tile_16.png differ diff --git a/firmware/common/sources/interface/cursor.cpp b/firmware/common/sources/interface/cursor.cpp new file mode 100644 index 000000000..e2dd96ca9 --- /dev/null +++ b/firmware/common/sources/interface/cursor.cpp @@ -0,0 +1,56 @@ +// *************************************************************************************** +// *************************************************************************************** +// +// Name : cursor.cpp +// Authors : Paul Robson (paul@robsons.org.uk) +// Date : 13th April 2024 +// Reviewed : No +// Purpose : Cursor Repository. +// +// *************************************************************************************** +// *************************************************************************************** + +#include "common.h" +#include "data/cursors.h" +static uint8_t currentCursor; + +// *************************************************************************************** +// +// Initialise cursors +// +// *************************************************************************************** + +void CURInitialise(void) { + currentCursor = 0; +} + +// *************************************************************************************** +// +// Get current cursor +// +// *************************************************************************************** + +const uint8_t *CURGetCurrent(uint8_t *xHit,uint8_t *yHit) { + if (xHit != NULL) *xHit = cursor_hitPoint[currentCursor*2]; + if (yHit != NULL) *yHit = cursor_hitPoint[currentCursor*2+1]; + return cursor_data+currentCursor*256; +} + +// *************************************************************************************** +// +// Set current cursor +// +// *************************************************************************************** + +bool CURSetCurrent(uint8_t cursorID) { + bool isOk = cursorID < CURSOR_IMAGE_COUNT; // Number of cursors + currentCursor = isOk ? cursorID : 0; // Bad value sets default + return !isOk; // Return false on error +} + +// *************************************************************************************** +// +// Date Revision +// ==== ======== +// +// *************************************************************************************** diff --git a/firmware/common/sources/interface/dispatch.cpp b/firmware/common/sources/interface/dispatch.cpp index cc69489e2..d1f994d64 100644 --- a/firmware/common/sources/interface/dispatch.cpp +++ b/firmware/common/sources/interface/dispatch.cpp @@ -75,6 +75,7 @@ void DSPReset(void) { const char bootString[] = PROMPT; MEMInitialiseMemory(); // Set up memory, load kernel ROM MSEInitialise(); // Mouse first, before starting graphics. + CURInitialise(); GFXSetMode(0); // Initialise graphics SPRReset(); // Reset sprites. LOGDrawLogo(); // Draw logo diff --git a/firmware/common/sources/interface/mouse.cpp b/firmware/common/sources/interface/mouse.cpp index 5eb4191c9..7d7ccf472 100644 --- a/firmware/common/sources/interface/mouse.cpp +++ b/firmware/common/sources/interface/mouse.cpp @@ -91,8 +91,7 @@ void MSESetVisible(bool isVisible) { // // *************************************************************************************** -bool MSEGetCursorDrawInformation(const uint8_t **pData, uint16_t *pX, uint16_t *pY) { - *pData = default_cursor_data; // Just one cursor +bool MSEGetCursorDrawInformation(uint16_t *pX, uint16_t *pY) { *pX = xCursor; *pY = yCursor; // This is top left - so crosshairs will need adjusting for example. return isCursorVisible && xCursor < gMode.xGSize && yCursor < gMode.yGSize; // On and on screen. } diff --git a/firmware/sources/hardware/dvi_320x240x256.cpp b/firmware/sources/hardware/dvi_320x240x256.cpp index f4674a0a8..cc553fed5 100644 --- a/firmware/sources/hardware/dvi_320x240x256.cpp +++ b/firmware/sources/hardware/dvi_320x240x256.cpp @@ -70,8 +70,11 @@ static void __not_in_flash_func(_scanline_callback)(void) { if (lineCounter == FRAME_HEIGHT) { frameCounter++; lineCounter = 0; - cursorEnabled = MSEGetCursorDrawInformation(&cursorImage, // Get cursor info this frame. - &xCursor,&yCursor); + uint8_t xHit,yHit; + cursorEnabled = MSEGetCursorDrawInformation(&xCursor,&yCursor); // Get cursor info this frame. + cursorImage = CURGetCurrent(&xHit,&yHit); + xCursor -= xHit;yCursor -= yHit; + if (cursorEnabled) { // If enabled work out physical drawing height. wCursor = hCursor = 16; // Could be partially drawn. if (xCursor + 16 >= 320) wCursor = 320-xCursor; @@ -84,12 +87,14 @@ static void __not_in_flash_func(_scanline_callback)(void) { *scanline++ = palette[*screenPos++]; // convert using palette => buffer. } if (cursorEnabled && lineCounter>=yCursor && lineCounter= 0 && xCursor < 320-16) { // On Screen ? + const uint8_t *cursorData = cursorImage + (lineCounter-yCursor) * 16; + cursline += xCursor; // Position on this line. + for (uint16_t i = 0;i < wCursor;i++) { // Each pixel. + uint8_t pixel = *cursorData++; + if (pixel != 0xFF) *cursline = palette[pixel]; // Check for transparency + cursline++; + } } } }