Compare commits

..

17 Commits

Author SHA1 Message Date
Lephe 3edb80018c
quick fixes and definitely a few bugs in there 2024-03-21 19:08:14 +01:00
Sylvain PILLOT 2e5f99a996
update of README.md 2024-03-21 18:18:32 +01:00
Sylvain PILLOT f4e5b0f91c
addin upscaling now supports usb bulk transfert for screenshot and video capture (of course also text output) 2024-03-21 18:18:29 +01:00
Sylvain PILLOT 9fdd203dbf
bug resolved 2024-03-21 18:14:31 +01:00
Sylvain PILLOT 56fe0dd29c
removed vram switch and timer for fx-as-cg build target 2024-03-21 18:13:51 +01:00
Sylvain PILLOT e5ca6c0fe5
corrected dupdate redirection as per dmode (normal / gray engine) - gray engine now woking on FX9860G_AS_CG target 2024-03-21 18:12:58 +01:00
Sylvain PILLOT 0f3c0ba803
minors fixes 2024-03-21 18:12:58 +01:00
Sylvain PILLOT dceaa2e9cf
[WIP] - conversion of the gray scale engine to the CG for fx_as_cg build target - compiling - linking _ but ony B&W yet 2024-03-21 18:12:58 +01:00
Sylvain PILLOT 87ccadecfd
corrected issue with screen aspect ratio on CG50 during upscaling 2024-03-21 18:12:58 +01:00
Sylvain PILLOT 836706b4dc
[WIP] build-fx-as-cg : upscaling of FX VRAM to CG VRAM + adhoc dupdate 2024-03-21 18:12:58 +01:00
Sylvain PILLOT ff587b6e90
libgint-fxascg - compilation options set to TARGET_FXCG50 2024-03-21 18:12:58 +01:00
Sylvain PILLOT e9ad4e2a79
Start working on libgint-fxascg - compilation options 2024-03-21 18:12:55 +01:00
Lephe b2b1f00d04
fs: take const descriptor in open_generic() 2024-03-19 19:03:33 +01:00
Lephe 5ff6a518f6
gint: memory micro-optimizations 2024-03-19 19:03:17 +01:00
Lephe bc74586a2c
render: parametrize existence of dmode in config.h
This is the first of many steps designed to reduce gint's reliance on
the FX9860G and FXCG50 macros by describing the compile target more
symbolically. The goal is to allow both for g3a compilation of fx-API
code and for a potential CP port.
2024-03-19 18:37:13 +01:00
Lephenixnoir e0ac25fbb0
render: improve implementation of dpoly()
* Honor dwindow settings immediately (avoids useless dline() calls)
* Bound to ymin/ymax instead of doing many useless cut computations
* Remove the need for floating-point operations and division
2024-03-02 23:16:22 +00:00
Sylvain PILLOT b802e8edef
added dpoly() rendering method 2024-03-01 17:37:35 +00:00
23 changed files with 299 additions and 311 deletions

View File

@ -104,10 +104,10 @@ set(SOURCES_COMMON
# Rendering
src/render/dcircle.c
src/render/dellipse.c
src/render/dpoly.c
src/render/dhline.c
src/render/dimage.c
src/render/dline.c
src/render/dpoly.c
src/render/dprint.c
src/render/drect_border.c
src/render/dtext.c
@ -312,14 +312,14 @@ if("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50)
${LINKER_SCRIPTS})
endif()
if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G_AS_CG)
if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G_G3A)
add_compile_options(-DFXCG50)
add_compile_definitions(FX9860G_AS_CG)
set(NAME "gint-fxascg")
set(NAME "gint-fxg3a")
set(LINKER_SCRIPTS
"${CMAKE_CURRENT_BINARY_DIR}/fxcg50.ld"
"${CMAKE_CURRENT_BINARY_DIR}/fxcg50_fastload.ld")
add_library(gint-fxascg STATIC ${SOURCES_COMMON} ${SOURCES_FXASCG} ${ASSETS_FX}
add_library(gint-fxg3a STATIC ${SOURCES_COMMON} ${SOURCES_FXASCG} ${ASSETS_FX}
${LINKER_SCRIPTS})
endif()

View File

@ -16,6 +16,20 @@
0x03f7c0a0 = Commit 3f7c0a0 */
#define GINT_HASH 0x@GINT_GIT_HASH@
/* GINT_HW_{FX,CG}: Identifies the type of hardware running the program. */
#if defined(FX9860G)
# define GINT_HW_FX 1
# define GINT_HW_CG 0
#elif defined(FXCG50) || defined(FX9860G_AS_CG)
# define GINT_HW_FX 0
# define GINT_HW_CG 1
#endif
/* GINT_OS_{FX,CG}: Identifies the type of OS API we're assuming. Currently I
see no reason this would be different from hardware, but who knows. */
#define GINT_OS_FX GINT_HW_FX
#define GINT_OS_CG GINT_HW_CG
/* GINT_NO_OS_STACK: Disables using a chunk of the OS stack as a heap. The top
section covering 355/512 ko is otherwise used. (fx-CG 50) */
#cmakedefine GINT_NO_OS_STACK
@ -41,4 +55,12 @@
/* GINT_USB_DEBUG: Selects whether USB debug functions are enabled */
#cmakedefine GINT_USB_DEBUG
/* GINT_RENDER_DMODE: Selects whether the dmode override is available on
rendering functions. */
#if defined(FX9860G_AS_CG)
# define GINT_RENDER_DMODE 1
#else
# define GINT_RENDER_DMODE GINT_HW_FX
#endif
#endif /* GINT_CONFIG */

View File

@ -15,9 +15,6 @@
extern "C" {
#endif
#include <stdint.h>
#include "attributes.h"
/* gint_call_arg_t: All types of arguments allowed in an indirect call
Because a function call cannot be easily pieced together, there are

View File

@ -13,8 +13,8 @@
extern "C" {
#endif
#include <gint/defs/call.h>
#include <gint/defs/types.h>
#include <gint/defs/call.h>
/* Platform-specific functions include VRAM management and the definition of
the color_t type. */
@ -23,7 +23,7 @@ extern "C" {
#include <gint/display-fx.h>
#endif
#if defined(FXCG50) && !defined(FX9860G_AS_CG)
#if defined(FXCG50) && ! defined(FX9860G_AS_CG)
#include <gint/display-cg.h>
#endif
@ -90,8 +90,8 @@ gint_call_t dupdate_get_hook(void);
to the rectangle spanning from (left,top) included, to (right,bottom)
excluded. The default is from (0,0) to (DWIDTH,DHEIGHT). */
struct dwindow {
int left, top;
int right, bottom;
int left, top;
int right, bottom;
};
extern struct dwindow dwindow;
@ -149,8 +149,8 @@ void drect(int x1, int y1, int x2, int y2, int color);
@fill_color Center color (same values as drect() are allowed)
@border_width Amount of pixels reserved for the border on each side
@border_color Border color (same values as drect() are allowed) */
void drect_border(int x1, int y1, int x2, int y2, int fill_color,
int border_width, int border_color);
void drect_border(int x1, int y1, int x2, int y2,
int fill_color, int border_width, int border_color);
//---
// Point drawing functions
@ -241,78 +241,84 @@ void dcircle(int xm, int ym, int r, int fill_color, int border_color);
@x1 @y1 @x2 @y2 Ellipse's bounding box (both bounds included, like drect())
@fill_color Color of the surface inside the ellipse, C_NONE to disable
@border_color Color of the ellipse itself, C_NONE to disable */
void dellipse(int x1, int y1, int x2, int y2, int fill_color, int border_color);
void dellipse(int x1, int y1, int x2, int y2, int fill_color,
int border_color);
/* dpoly(): Polygone with border
/* dpoly(): Render an arbitrary polygon
This function renders a closed-polygone defined by its vertices coordinates.
Renders the polygon defined by vertices (x[i], y[i]) for 0 < i < N. A fill
color and border color can be specified separately. For filling, N must be
at least 3. For border, N must be at least 2.
@x @y Pointer to arrays containing the x / y coordinates of each
individual vertex
@nbvertices Number of vertices
@fill_color Color of the surface inside the polygone, C_NONE to disable
@border_color Color of the polygon itself, C_NONE to disable */
void dpoly(int *x, int *y, int nbvertices, int fill_color, int border_color);
Note: this is a fairly slow function, not designed for rendering triangles
in 3D games. There are faster methods for that.
@x @y Arrays of vertex coordinates
@N Number of vertices (length of x and y)
@fill_color Color of the polygon's interior, C_NONE to disable
@border_color Color of the polygon's border, C_NONE to disable */
void dpoly(int const *x, int const *y, int N, int fill_color, int border_color);
//---
// Text rendering (topti)
//---
/* font_t: Font data encoded for topti */
typedef struct {
/* Font name (NUL-terminated), NULL if no title */
char const *name;
typedef struct
{
/* Font name (NUL-terminated), NULL if no title */
char const *name;
/* Font shape flags */
uint bold : 1;
uint italic : 1;
uint serif : 1;
uint mono : 1;
uint : 3;
/* Whether data is variable-length (proportional font) */
uint prop : 1;
/* Font shape flags */
uint bold :1;
uint italic :1;
uint serif :1;
uint mono :1;
uint :3;
/* Whether data is variable-length (proportional font) */
uint prop :1;
/* Line height */
uint8_t line_height;
/* Storage height */
uint8_t data_height;
/* Line height */
uint8_t line_height;
/* Storage height */
uint8_t data_height;
/* Number of Unicode blocks */
uint8_t block_count;
/* Number of total glyphs */
uint32_t glyph_count;
/* Number of Unicode blocks */
uint8_t block_count;
/* Number of total glyphs */
uint32_t glyph_count;
/* Character spacing (usually 1) */
uint8_t char_spacing;
/* Character spacing (usually 1) */
uint8_t char_spacing;
uint : 24;
uint :24;
struct {
/* Unicode point of first character in block */
uint start : 20;
/* Length of block */
uint length : 12;
} * blocks;
struct {
/* Unicode point of first character in block */
uint start :20;
/* Length of block */
uint length :12;
} *blocks;
/* Raw glyph data */
uint32_t *data;
/* Raw glyph data */
uint32_t *data;
union {
/* For monospaced fonts */
struct {
/* Width of glyphs */
uint16_t width;
/* Storage size, in longwords, of each glyph */
uint16_t storage_size;
};
/* For proportional fonts */
struct {
/* Storage index to find glyphs quickly */
uint16_t *glyph_index;
/* Width of each individual glyph */
uint8_t *glyph_width;
};
};
union {
/* For monospaced fonts */
struct {
/* Width of glyphs */
uint16_t width;
/* Storage size, in longwords, of each glyph */
uint16_t storage_size;
};
/* For proportional fonts */
struct {
/* Storage index to find glyphs quickly */
uint16_t *glyph_index;
/* Width of each individual glyph */
uint8_t *glyph_width;
};
};
} GPACKED(4) font_t;
@ -390,14 +396,14 @@ char const *drsize(char const *str, font_t const *font, int width, int *w);
and a horizontal alignment option specifies where a given point (x,y) should
be relative to the rendered string. */
enum {
/* Horizontal settings: default in dtext() is DTEXT_LEFT */
DTEXT_LEFT = 0,
DTEXT_CENTER = 1,
DTEXT_RIGHT = 2,
/* Vertical settings: default in dtext() is DTEXT_TOP */
DTEXT_TOP = 0,
DTEXT_MIDDLE = 1,
DTEXT_BOTTOM = 2,
/* Horizontal settings: default in dtext() is DTEXT_LEFT */
DTEXT_LEFT = 0,
DTEXT_CENTER = 1,
DTEXT_RIGHT = 2,
/* Vertical settings: default in dtext() is DTEXT_TOP */
DTEXT_TOP = 0,
DTEXT_MIDDLE = 1,
DTEXT_BOTTOM = 2,
};
/* dtext_opt(): Display a string of text
@ -428,13 +434,12 @@ enum {
@str String to display
@size Maximum number of bytes to display (negative for no limit) */
void dtext_opt(int x, int y, int fg, int bg, int halign, int valign,
char const *str, int size);
char const *str, int size);
/* The last parameter @size was added in gint 2.4; this macro will add it
automatically with a value of -1 if the call is made with only 7 parameters.
This is for backwards compatibility. */
#define dtext_opt8(x, y, fg, bg, h, v, str, sz, ...) \
dtext_opt(x, y, fg, bg, h, v, str, sz)
#define dtext_opt8(x,y,fg,bg,h,v,str,sz,...) dtext_opt(x,y,fg,bg,h,v,str,sz)
#define dtext_opt(...) dtext_opt8(__VA_ARGS__, -1)
/* dtext(): Simple version of dtext_opt() with defaults
@ -449,7 +454,7 @@ void dtext(int x, int y, int fg, char const *str);
dprint_opt(x, y, fg, bg, halign, valign, "A=%d B=%d", A, B); */
void dprint_opt(int x, int y, int fg, int bg, int halign, int valign,
char const *format, ...);
char const *format, ...);
/* dprint(): Simple version of dprint_op() with defaults
Calls dprint_opt() with bg=C_NONE, halign=DTEXT_LEFT and valign=DTEXT_TOP */
@ -494,12 +499,12 @@ void dimage(int x, int y, bopti_image_t const *image);
/* Option values for dsubimage() */
enum {
/* No option */
DIMAGE_NONE = 0x00,
/* Disable clipping, ie. adjustments to the specified subrectangle and
screen location such that any part that overflows from the image or
the screen is ignored. Slightly faster. */
DIMAGE_NOCLIP = 0x01,
/* No option */
DIMAGE_NONE = 0x00,
/* Disable clipping, ie. adjustments to the specified subrectangle and
screen location such that any part that overflows from the image or
the screen is ignored. Slightly faster. */
DIMAGE_NOCLIP = 0x01,
};
/* dsubimage(): Render a section of an image
@ -512,7 +517,7 @@ enum {
@width @height Subrectangle dimensions
@flags OR-combination of DIMAGE_* flags */
void dsubimage(int x, int y, bopti_image_t const *image, int left, int top,
int width, int height, int flags);
int width, int height, int flags);
#ifdef __cplusplus
}

View File

@ -158,7 +158,7 @@ typedef struct {
int8_t queue_next;
int8_t queue_end;
/* Number of events lost because of missing queue space */
uint events_lost;
uint16_t events_lost;
/* Event transforms */
keydev_transform_t tr;
@ -183,9 +183,9 @@ typedef struct {
// <Repeats>
/* Candidate key for repeats (or 0 if no key is candidate yet) */
int rep_key;
int16_t rep_key;
/* Number of repeats already sent */
int rep_count;
int16_t rep_count;
/* Time since key was first pressed (us) */
int rep_time;
/* Delay until next repeat, set by the repeat planner (us) */

View File

@ -78,7 +78,7 @@ void fs_free_descriptor(int fd);
exact file descriptor reuse_fd is used. (This is useful to reopen standard
streams.) In this case, the only possible return values are -1 and reuse_fd
itself. */
int open_generic(fs_descriptor_type_t *type, void *data, int reuse_fd);
int open_generic(fs_descriptor_type_t const *type, void *data, int reuse_fd);
/* fs_path_normalize(): Normalize a path to eliminate ., .. and redundant /

View File

@ -44,12 +44,6 @@ extern usb_interface_t const usb_ff_bulk;
// Sending standard messages
//---
/* usb_fxlink_text(): Send raw text
Send a string; fxlink will display it in the terminal. This can be used to
back stdout/stderr. Sending lots of small messages can be slow; if that's a
problem, fill in message manually. If size is 0, uses strlen(text). */
void usb_fxlink_text(char const *text, int size);
/* usb_fxlink_screenshot(): Take a screenshot
This function sends a copy of the VRAM to fxlink. This is best used just
@ -63,6 +57,27 @@ void usb_fxlink_text(char const *text, int size);
display (it's usually slow and currently not even implemented). */
void usb_fxlink_screenshot(bool onscreen);
#if defined(FX9860G) || defined(FX9860G_AS_CG)
/* usb_fxlink_screenshot_gray(): Take a gray screenshot on fx-9860G
This function is similar to usb_fxlink_screenshot(), but it takes a gray
screenshot. It depends on the gray engine so if you use your add-in will
automatically have the gray engine, that's why it's separate. */
void usb_fxlink_screenshot_gray(bool onscreen);
#endif
/* usb_fxlink_text(): Send raw text
This function sends a string with the "text" type, which fxlink prints on
the terminal. It will send a full fxlink message (with a commit), which is
inefficient if there is a lot of text to send. For better speed, send the
message manually by filling the header and doing the writes and commit
manually.
This function sends the text by blocks of 4 bytes or 2 bytes when alignment
and size allow, and 1 byte otherwise. If size is 0, strlen(text) is used. */
void usb_fxlink_text(char const *text, int size);
/* usb_fxlink_videocapture(): Send a frame for a video recording
This function is essentially the same as usb_fxlink_screenshot(). It sends a
@ -74,12 +89,9 @@ void usb_fxlink_screenshot(bool onscreen);
automatically send new frames to fxlink. */
void usb_fxlink_videocapture(bool onscreen);
#ifdef FX9860G
/* Similar to usb_fxlink_screenshot(), but takes a gray screenshot if the gray
engine is currently running. */
void usb_fxlink_screenshot_gray(bool onscreen);
/* Like usb_fxlink_videocapture(), but uses VRAM data from the gray engine. */
#if defined(FX9860G) || defined(FX9860G_AS_CG)
/* usb_fxlink_videocapture_gray(): Send a gray frame for a video recording
Like usb_fxlink_videocapture(), but uses VRAM data from the gray engine. */
void usb_fxlink_videocapture_gray(bool onscreen);
#endif
@ -156,16 +168,17 @@ int usb_ff_bulk_input(void);
The size of the data to be transferred must be specified upfront, but this
restriction might be lifted in the future. As with the rest of the USB
protocol, all the integer are encoded as *little-endian*. */
typedef struct usb_fxlink_header {
/* Protocol version = 0x00000100 */
uint32_t version;
/* Size of the data to transfer (excluding this header) */
uint32_t size;
/* Size of individual transfers (related to the size of the FIFO) */
uint32_t transfer_size;
/* Application name and message type, UTF-8 (need not be zero-terminated) */
char application[16];
char type[16];
typedef struct usb_fxlink_header
{
/* Protocol version = 0x00000100 */
uint32_t version;
/* Size of the data to transfer (excluding this header) */
uint32_t size;
/* Size of individual transfers (related to the size of the FIFO) */
uint32_t transfer_size;
/* Application name and message type, UTF-8 (need not be zero-terminated) */
char application[16];
char type[16];
} usb_fxlink_header_t;
@ -175,88 +188,28 @@ typedef struct usb_fxlink_header {
exact amount of data that the fxlink message will contain. Returns false if
parameters are invalid or don't fit the fields. */
bool usb_fxlink_fill_header(usb_fxlink_header_t *header,
char const *application, char const *type,
uint32_t data_size);
char const *application, char const *type, uint32_t data_size);
/* Subheader for the fxlink built-in "image" type */
typedef struct {
/* Image size; storage is row-major */
uint32_t width;
uint32_t height;
/* Pixel format, see below */
int pixel_format;
typedef struct
{
/* Image size; storage is row-major */
uint32_t width;
uint32_t height;
/* Pixel format, see below */
int pixel_format;
} usb_fxlink_image_t;
/* Pixel formats */
enum {
/* Image is an array of *big-endian* uint16_t with RGB565 format */
USB_FXLINK_IMAGE_RGB565 = 0,
/* Image is an array of bits in mono format */
USB_FXLINK_IMAGE_MONO,
/* Image is two consecutive mono arrays, one for light, one for dark */
USB_FXLINK_IMAGE_GRAY,
} usb_fxlink_image_format_t;
/* usb_fxlink_screenshot(): Take a screenshot
This function takes a screenshot. If (onscreen = false), it sends the
contents of the VRAM. This mode is best used just before dupdate(), since
the VRAM contents are exactly as they will appear on screen a moment later.
However, this is somewhat unintuitive for interactive GUI as the user has to
press a button after the option is present on-screen, therefore the contents
of the *next* frame are captured.
If (onscreen = true), this function tries to send the pixels that are
currently visible on-screen, with the following heuristic:
* If there is only one VRAM, the VRAM contents are used in the hope they
haven't changed since the last frame was presented with dupdate().
* If there are two VRAMs (on fx-CG 50 or using the gray engine) the contents
of the VRAM not currently being draw to are sent.
This function does not read pixels directly from the display, as this is
usually slow and currently not even implemented. */
void usb_fxlink_screenshot(bool onscreen);
#ifdef FX9860G
/* usb_fxlink_screenshot_gray(): Take a gray screenshot on fx-9860G
This function is similar to usb_fxlink_screenshot(), but it takes a gray
screenshot. It depends on the gray engine so if you use your add-in will
automatically have the gray engine, that's why it's separate. */
void usb_fxlink_screenshot_gray(bool onscreen);
#endif
/* usb_fxlink_text(): Send raw text
This function sends a string with the "text" type, which fxlink prints on
the terminal. It will send a full fxlink message (with a commit), which is
inefficient if there is a lot of text to send. For better speed, send the
message manually by filling the header and doing the writes and commit
manually.
This function sends the text by blocks of 4 bytes or 2 bytes when alignment
and size allow, and 1 byte otherwise. If size is 0, strlen(text) is used. */
void usb_fxlink_text(char const *text, int size);
/* usb_fxlink_videocapture(): Send a frame for a video recording
This function is essentially the same as usb_fxlink_screenshot(). It sends a
capture of the VRAM to fxlink but uses the "video" type, which fxlink
displays in real-time or saves as a video file. The meaning of the onscreen
setting is identical to usb_fxlink_screenshot().
This function can be called with onscreen=false as a dupdate() hook to
automatically send new frames to fxlink. */
void usb_fxlink_videocapture(bool onscreen);
#ifdef FX9860G
/* usb_fxlink_videocapture_gray(): Send a gray frame for a video recording
Like usb_fxlink_videocapture(), but uses VRAM data from the gray engine. */
void usb_fxlink_videocapture_gray(bool onscreen);
#endif
/* Image is an array of *big-endian* uint16_t with RGB565 format */
USB_FXLINK_IMAGE_RGB565 = 0,
/* Image is an array of bits in mono format */
USB_FXLINK_IMAGE_MONO,
/* Image is two consecutive mono arrays, one for light, one for dark */
USB_FXLINK_IMAGE_GRAY,
};
#ifdef __cplusplus
}

View File

@ -42,7 +42,7 @@ void fs_free_descriptor(int fd)
fdtable[fd].data = NULL;
}
int open_generic(fs_descriptor_type_t *type, void *data, int fd)
int open_generic(fs_descriptor_type_t const *type, void *data, int fd)
{
if(!fdtable) {
errno = ENOMEM;
@ -79,7 +79,7 @@ int open_generic(fs_descriptor_type_t *type, void *data, int fd)
/* Standard streams */
static fs_descriptor_type_t devnull = {
static fs_descriptor_type_t const devnull = {
.read = NULL,
.write = NULL,
.lseek = NULL,

View File

@ -11,6 +11,7 @@
#include <stdlib.h>
#include "../render-fx/render-fx.h"
#include "../render/render.h"
/* Three additional video RAMS, allocated statically if --static-gray was set
at configure time, or with malloc() otherwise. */

View File

@ -40,19 +40,19 @@ extern void (*bdtors)(void), (*edtors)(void);
int main(int isappli, int optnum);
/* Whether to restart main through the OS menu rather than returning */
int gint_restart = 0;
int8_t gint_restart = 0;
/* gint_setrestart(): Set whether to restart the add-in after exiting */
void gint_setrestart(int restart)
{
gint_restart = restart;
gint_restart = !!restart;
}
/* Return value of main() */
static int8_t gint_exitcode;
/* Jumping there will properly unwind and leave the add-in (CASIOWIN does not
have an exit syscall and simply wants you to return from main()) */
jmp_buf gint_exitbuf;
/* Return value of main() */
static int gint_exitcode;
/* regcpy(): Copy a memory region using symbol information
@l Source pointer (load address)

View File

@ -17,18 +17,18 @@
#include <string.h>
#include <stdlib.h>
/* Keyboard input device for this Key Scan Interface */
static keydev_t keysc_dev;
/* Keyboard scanner timer */
int16_t keysc_tid = -1;
/* Keyboard scan frequency in Hertz. Start with 128 Hz, this frequency *must
be high* for the keyboard to work! Reading at low frequencies produces a lot
of artifacts. See https://www.casiopeia.net/forum/viewtopic.php?p=20592. */
int keysc_scan_Hz = 128;
int16_t keysc_scan_Hz = 128;
/* Approximation in microseconds, used by the timer and repeat delays */
uint32_t keysc_scan_us = 7812; /* 1000000 / keysc_scan_Hz */
/* Keyboard scanner timer */
int keysc_tid = -1;
/* Keyboard input device for this Key Scan Interface */
static keydev_t keysc_dev;
/* keydev_std(): Standard keyboard input device */
keydev_t *keydev_std(void)
{

View File

@ -1,5 +1,5 @@
#include <gint/display.h>
#include "render-fx.h"
#include "../render/render.h"
/* dclear() - fill the screen with a single color */
void dclear(color_t color)

View File

@ -1,6 +1,6 @@
#include <gint/display.h>
#include <gint/defs/types.h>
#include "render-fx.h"
#include "../render/render.h"
int dgetpixel(int x, int y)
{

View File

@ -1,6 +1,6 @@
#include <gint/display.h>
#include <gint/defs/types.h>
#include "render-fx.h"
#include "../render/render.h"
/* dpixel() - change a pixel's color */
void dpixel(int x, int y, int color)

View File

@ -1,5 +1,6 @@
#include <gint/defs/util.h>
#include <gint/display.h>
#include "../render/render.h"
#include "render-fx.h"
void drect(int x1, int y1, int x2, int y2, int color)

View File

@ -1,4 +1,5 @@
#include <gint/display.h>
#include "../render/render.h"
#include "render-fx.h"
#include "bopti-asm.h"

View File

@ -1,6 +1,6 @@
#include <gint/display.h>
#include <gint/drivers/t6k11.h>
#include "render-fx.h"
#include "../render/render.h"
/* Standard video RAM for fx9860g is 1 bit per pixel */
GSECTION(".bss") GALIGNED(32) static uint32_t fx_vram[256];

View File

@ -50,38 +50,10 @@ void bopti_render_scsp(bopti_image_t const *img, struct rbox *rbox,
uint32_t *v1, uint32_t *v2);
//---
// Alternate rendering modes
// Gray rendering functions for dmode
//---
/* The gray engine overrides the rendering functions by specifying a set of
alternate primitives that are suited to work with two VRAMs. To avoid
linking with them when the gray engine is not used, the display module
exposes a global state in the form of a struct rendering_mode and the gray
engine modifies that state when it runs. */
struct rendering_mode
{
/* Because the gray engine still has business to do after the call to
dgray(DGRAY_OFF), the original dupdate() is made to execute after
the replacement one if the replacement one returns 1. */
int (*dupdate)(void);
/* Area rendering */
void (*dclear)(color_t color);
void (*drect)(int x1, int y1, int x2, int y2, color_t color);
/* Point rendering */
void (*dpixel)(int x, int y, color_t color);
int (*dgetpixel)(int x, int y);
void (*gint_dhline)(int x1, int x2, int y, int color);
void (*gint_dvline)(int y1, int y2, int x, int color);
/* Text and image rendering */
void (*dtext_opt)
(int x, int y, int fg, int bg, int halign, int valign,
char const *str, int size);
void (*dsubimage)
(bopti_image_t const *image, struct rbox *r, int flags);
};
/* The alternate rendering mode pointer (initially NULL)*/
extern struct rendering_mode const *dmode;
struct rbox;
/* These are the corresponding gray rendering functions */
int gupdate(void);
@ -95,9 +67,4 @@ void gtext_opt(int x, int y, int fg, int bg, int halign, int valign,
char const *str, int size);
void gsubimage(bopti_image_t const *image, struct rbox *r, int flags);
/* Short macro to call the alternate rendering function when available */
#define DMODE_OVERRIDE(func, ...) \
if(dmode && dmode->func) { \
return dmode->func(__VA_ARGS__); \
}
#endif /* RENDER_FX */

View File

@ -2,7 +2,7 @@
#include <gint/kmalloc.h>
#include <gint/config.h>
#include <gint/drivers/r61524.h>
#include "../render-fx/render-fx.h"
#include "../render/render.h"
/* The destination VRAM for upscaling + centering + conversion B&W --> 16bits RGB565 */
uint16_t *cg_vram; // set to 0 at initialisation
@ -48,11 +48,11 @@ bool dvram_init( void )
void dgetvram(uint16_t **ptr_vram_1, uint16_t **ptr_vram_2)
{
if(ptr_vram_1) *ptr_vram_1 = &cg_vram;
if(ptr_vram_2) *ptr_vram_2 = &cg_vram;
if(ptr_vram_1) *ptr_vram_1 = cg_vram;
if(ptr_vram_2) *ptr_vram_2 = cg_vram;
}
inline drawupscale( int x, int y, int color )
void drawupscale( int x, int y, int color )
{
int u=y*396*3;
int v=x*3;
@ -134,4 +134,4 @@ void dupdate(void)
gint_call(dupdate_get_hook());
}
__attribute__((alias("dupdate")))
void _WEAK_dupdate(void);
void _WEAK_dupdate(void);

View File

@ -6,9 +6,11 @@
#include <gint/drivers/r61524.h>
#include <gint/gray.h>
#include <gint/display.h>
#include <gint/kmalloc.h>
#include <stdlib.h>
#include "../render/render.h"
#include "../render-fx/render-fx.h"
/* Three additional video RAMS, allocated statically if --static-gray was set
@ -63,7 +65,7 @@ static void gray_quit(void);
static int gray_isinit(void)
{
//return (vrams[0] && vrams[1] && vrams[2] && vrams[3] && timer >= 0);
return (vrams[0] && vrams[1] >= 0);
return (vrams[0] && vrams[1]);
}
@ -192,7 +194,7 @@ int dgray(int mode)
}
/* convert the gray scale into RGB565 and draw in the virutal VRAMthe 3x3 pixels upscaled and centered */
inline gdrawupscale( int x, int y, int color_fx )
void gdrawupscale( int x, int y, int color_fx )
{
int u=y*396*3;
int v=x*3;

View File

@ -2,9 +2,6 @@
#include <gint/defs/util.h>
#include "../render/render.h"
#if defined(FX9860G) || defined(FX9860G_AS_CG)
#include "../render-fx/render-fx.h"
#endif
/* dline(): Bresenham line drawing algorithm
Remotely adapted from MonochromeLib code by Pierre "PerriotLL" Le Gall.
@ -18,19 +15,13 @@ void dline(int x1, int y1, int x2, int y2, int color)
/* Possible optimizations */
if(y1 == y2)
{
#if defined(FX9860G) || defined(FX9860G_AS_CG)
DMODE_OVERRIDE(gint_dhline, x1, x2, y1, color);
#endif
gint_dhline(x1, x2, y1, color);
return;
}
if(x1 == x2)
{
#if defined(FX9860G) || defined(FX9860G_AS_CG)
DMODE_OVERRIDE(gint_dvline, y1, y2, x1, color);
#endif
gint_dvline(y1, y2, x1, color);
return;
}

View File

@ -1,67 +1,67 @@
#include <gint/defs/util.h>
#include <gint/display.h>
#include <stdlib.h>
void dpoly(int *polyX, int *polyY, int polyCorners, int fill_color, int border_color){
static int compare(void const *ptr1, void const *ptr2)
{
return *(int const *)ptr1 - *(int const *)ptr2;
}
if (polyCorners<=2) return;
static void dpoly_fill(int const *x, int const *y, int N, int color)
{
int *nodeX = malloc(N * sizeof *nodeX);
if (fill_color == C_NONE && border_color == C_NONE)
return;
/* Find vertical bounds */
int ymin = y[0], ymax = y[0];
for(int i = 1; i < N; i++)
{
ymin = min(ymin, y[i]);
ymax = max(ymax, y[i]);
}
ymin = max(ymin, dwindow.top);
ymax = min(ymax, dwindow.bottom);
if (fill_color != C_NONE) {
float *nodeX, pixelX, pixelY, swap ;
int i, j, nodes;
nodeX = malloc( polyCorners * sizeof(float));
// Loop through the rows of the image.
for (pixelY=0; pixelY<DHEIGHT; pixelY++) {
// Build a list of nodes.
nodes=0; j=polyCorners-1;
for (i=0; i<polyCorners; i++) {
if ((polyY[i]<(float) pixelY && polyY[j]>=(float) pixelY)
|| (polyY[j]<(float) pixelY && polyY[i]>=(float) pixelY)) {
nodeX[nodes++]=(int) (polyX[i]+(pixelY-polyY[i])/(polyY[j]-polyY[i])*(polyX[j]-polyX[i]));
}
j=i;
}
/* For each row, find vertical cuts from the segments and fill in-between
the cuts. */
for(int pixelY = ymin; pixelY <= ymax; pixelY++) {
// Sort the nodes, via a simple “Bubble” sort.
i=0;
while (i<nodes-1) {
if (nodeX[i]>nodeX[i+1]) {
swap=nodeX[i]; nodeX[i]=nodeX[i+1]; nodeX[i+1]=swap; if (i) i--;
}
else {
i++;
}
}
/* Build a list of nodes */
int nodes = 0;
int j = N - 1;
for(int i = 0; i < N; i++)
{
if((y[i] < pixelY) != (y[j] < pixelY))
nodeX[nodes++] = x[i]+(pixelY-y[i])*(x[j]-x[i])/(y[j]-y[i]);
j = i;
}
// Fill the pixels between node pairs.
for (i=0; i<nodes; i+=2) {
if (nodeX[i ]>=DWIDTH) break;
if (nodeX[i+1]<= 0 ) break;
if (nodeX[i ]< 0 ) nodeX[i ]=0 ;
if (nodeX[i+1]> DWIDTH) nodeX[i+1]=DWIDTH;
//for (pixelX=nodeX[i]; pixelX<nodeX[i+1]; pixelX++) fillPixel(pixelX,pixelY);
dline(nodeX[i], pixelY, nodeX[i+1], pixelY, fill_color);
}
}
/* Sort the cuts' positions */
qsort(nodeX, nodes, sizeof nodeX[0], compare);
free(nodeX);
}
/* Fill the pixels between cut pairs */
for(int i = 0; i < nodes; i += 2)
{
if(nodeX[i] >= dwindow.right || nodeX[i+1] < dwindow.left) break;
nodeX[i] = max(nodeX[i], dwindow.left);
nodeX[i+1] = min(nodeX[i+1], dwindow.right);
dline(nodeX[i], pixelY, nodeX[i+1], pixelY, color);
}
}
if (border_color != C_NONE) {
for (int i = 0; i < polyCorners; i++) {
int px = polyX[i];
int py = polyY[i];
int px2 = polyX[(i + 1) % polyCorners];
int py2 = polyY[(i + 1) % polyCorners];
dline(px, py, px2, py2, border_color);
}
}
free(nodeX);
}
return;
}
static void dpoly_border(int const *x, int const *y, int N, int color)
{
for(int i = 0; i < N - 1; i++)
dline(x[i], y[i], x[i+1], y[i+1], color);
dline(x[N-1], y[N-1], x[0], y[0], color);
}
void dpoly(int const *x, int const *y, int N, int fill_color, int border_color)
{
if(N > 2 && fill_color != C_NONE)
dpoly_fill(x, y, N, fill_color);
if(N >= 2 && border_color != C_NONE)
dpoly_border(x, y, N, border_color);
}

View File

@ -5,6 +5,7 @@
#ifndef RENDER_COMMON
#define RENDER_COMMON
#include <gint/config.h>
#include <gint/display.h>
/* gint_dhline(): Optimized horizontal line
@ -26,4 +27,51 @@ extern font_t const *topti_font;
/* Default font */
extern font_t const *gint_default_font;
//---
// Alternate rendering modes
//---
#if GINT_RENDER_DMODE
/* The gray engine overrides the rendering functions by specifying a set of
alternate primitives that are suited to work with two VRAMs. To avoid
linking with them when the gray engine is not used, the display module
exposes a global state in the form of a struct rendering_mode and the gray
engine modifies that state when it runs. */
struct rbox;
struct rendering_mode
{
/* Because the gray engine still has business to do after the call to
dgray(DGRAY_OFF), the original dupdate() is made to execute after
the replacement one if the replacement one returns 1. */
int (*dupdate)(void);
/* Area rendering */
void (*dclear)(color_t color);
void (*drect)(int x1, int y1, int x2, int y2, color_t color);
/* Point rendering */
void (*dpixel)(int x, int y, color_t color);
int (*dgetpixel)(int x, int y);
void (*gint_dhline)(int x1, int x2, int y, int color);
void (*gint_dvline)(int y1, int y2, int x, int color);
/* Text and image rendering */
void (*dtext_opt)
(int x, int y, int fg, int bg, int halign, int valign,
char const *str, int size);
void (*dsubimage)
(bopti_image_t const *image, struct rbox *r, int flags);
};
/* The alternate rendering mode pointer (initially NULL)*/
extern struct rendering_mode const *dmode;
/* Short macro to call the alternate rendering function when available */
#define DMODE_OVERRIDE(func, ...) \
if(dmode && dmode->func) { \
return dmode->func(__VA_ARGS__); \
}
#else
#define DMODE_OVERRIDE(func, ...)
#endif /* GINT_RENDER_DMODE */
#endif /* RENDER_COMMON */