[WIP] - conversion of the gray scale engine to the CG for fx_as_cg build target - compiling - linking _ but ony B&W yet

This commit is contained in:
Sylvain PILLOT 2023-03-16 22:28:28 +01:00
parent 469be10609
commit a41c44988b
2 changed files with 354 additions and 1 deletions

View File

@ -243,7 +243,7 @@ set(SOURCES_CG
set(SOURCES_FXASCG
# Gray engine
src/gray/engine.c
src/gray/engine_fxascg.c
src/gray/gclear.c
src/gray/ggetpixel.c
src/gray/gint_gline.c

353
src/gray/engine_fxascg.c Normal file
View File

@ -0,0 +1,353 @@
//---
// gint:gray:engine - Core gray engine
//---
#include <gint/defs/types.h>
#include <gint/drivers/r61524.h>
#include <gint/gray.h>
#include <gint/display.h>
#include <gint/timer.h>
#include <stdlib.h>
#include "../render-fx/render-fx.h"
/* Three additional video RAMS, allocated statically if --static-gray was set
at configure time, or with malloc() otherwise. */
#ifdef GINT_STATIC_GRAY
GBSS static uint32_t gvrams[3][256];
#endif
uint16_t *cg_vram_gray;
/* Four VRAMs: two to draw and two to display */
static uint32_t *vrams[4] = { NULL, NULL, NULL, NULL };
/* Current VRAM pair used for drawing; the value can either be 0 (draws to
VRAMs 0 and 1) or 2 (draws to VRAMs 2 and 3). */
static int volatile st = 0;
/* Timer ID, always equal to GRAY_TIMER except if initialization fails */
static int timer = -1;
/* Whether the engine is scheduled to run at the next frame */
static int runs = 0;
/* Underlying timer, set to count at P_phi/64 */
#define GRAY_TIMER 0
#define GRAY_CLOCK TIMER_Pphi_64
/* Delays of the light and dark frames for the above setting */
GBSS static int delays[2];
/* The alternate rendering mode structure used to override d*() */
static struct rendering_mode const gray_mode = {
.dupdate = gupdate,
.dclear = gclear,
.drect = grect,
.dpixel = gpixel,
.dgetpixel = ggetpixel,
.gint_dhline = gint_ghline,
.gint_dvline = gint_gvline,
.dtext_opt = gtext_opt,
.dsubimage = gsubimage,
};
static struct rendering_mode const gray_exit_mode = {
.dupdate = gupdate,
.dclear = NULL,
.drect = NULL,
.dpixel = NULL,
.dgetpixel = NULL,
.gint_dhline = NULL,
.gint_dvline = NULL,
.dtext_opt = NULL,
.dsubimage = NULL,
};
//---
// Engine control (init/quit and start/stop)
//---
static int gray_int(void);
static void gray_quit(void);
/* gray_isinit(): Check whether the engine is initialized and ready to run */
static int gray_isinit(void)
{
return (vrams[0] && vrams[1] && vrams[2] && vrams[3] && timer >= 0);
}
bool dvram_init_gray( void )
{
int const MARGIN = 32;
/* Leave MARGIN bytes on each side of the region; this enables some
important optimizations in the image renderer. We also add another
32 bytes so we can manually 32-align the region */
uint32_t region = (uint32_t)kmalloc(DWIDTH*DHEIGHT*2 + MARGIN*2 + 32,
#if !defined(GINT_NO_OS_STACK)
"_ostk"
#else
NULL
#endif
);
if(region == 0)
return false;
/* 32-align the region */
region = (region + 31) & -32;
/* Skip a MARGIN */
region += MARGIN;
/* Use an uncached address */
region = (region & 0x1fffffff) | 0xa0000000;
/* Don't enable triple buffering by default */
cg_vram_gray = (void *)region;
return true;
}
/* gray_init(): Initialize the engine
This is done at startup so that memory can be reserved very early from the
heap (because not having enough memory is unrecoverable for the engine). */
GCONSTRUCTOR static void gray_init(void)
{
/* We need four VRAMs. First use the standard monochrome one */
vrams[0] = gint_vram;
#ifdef GINT_STATIC_GRAY
vrams[1] = gvrams[0];
vrams[2] = gvrams[1];
vrams[3] = gvrams[2];
#else
vrams[1] = malloc(1024);
vrams[2] = malloc(1024);
vrams[3] = malloc(1024);
#endif /* GINT_STATIC_GRAY */
/* Default delays from Graph 35+E II are different from other models */
if(gint[HWCALC] == HWCALC_G35PE2)
{
delays[0] = 762;
delays[1] = 1311;
}
else
{
delays[0] = 923;
delays[1] = 1742;
}
dvram_init_gray();
/* Try to obtain the timer right away */
timer = timer_configure(GRAY_TIMER | GRAY_CLOCK, 1000,
GINT_CALL(gray_int));
/* On failure, release the resources that we obtained */
if(!gray_isinit()) gray_quit();
}
/* gray_quit(): Free engine resources */
GDESTRUCTOR static void gray_quit(void)
{
#ifndef GINT_STATIC_GRAY
if(vrams[1]) free(vrams[1]);
if(vrams[2]) free(vrams[2]);
if(vrams[3]) free(vrams[3]);
vrams[1] = NULL;
vrams[2] = NULL;
vrams[3] = NULL;
#endif /* GINT_STATIC_GRAY */
if(timer >= 0) timer_stop(timer);
timer = -1;
}
/* gray_start(): Start the gray engine */
static void gray_start(void)
{
st = 2;
timer_reload(GRAY_TIMER, delays[0]);
timer_start(GRAY_TIMER);
runs = 1;
}
/* gray_stop(): Stop the gray engine */
static void gray_stop(void)
{
timer_pause(GRAY_TIMER);
runs = 0;
st = 0;
}
//---
// Dynamic udpate and rendering mode
//---
/* dgray(): Start or stop the gray engine at the next dupdate() */
int dgray(int mode)
{
/* Stack of states for the push modes */
static uint8_t states[32] = { 0 };
static uint8_t current = 0;
if(mode == DGRAY_ON)
{
if(!gray_isinit()) return 1;
/* Set the display module's alternate rendering mode to
override rendering functions to use their g*() variant */
if(!dgray_enabled()) dmode = &gray_mode;
}
else if(mode == DGRAY_OFF)
{
/* Set the mode to a temporary one that only overrides
dupdate() so that we can stop the engine next frame */
if(dgray_enabled()) dmode = &gray_exit_mode;
}
else if(mode == DGRAY_PUSH_ON)
{
if(current >= 32) return 1;
states[current++] = dgray_enabled() ? DGRAY_ON : DGRAY_OFF;
return dgray(DGRAY_ON);
}
else if(mode == DGRAY_PUSH_OFF)
{
if(current >= 32) return 1;
states[current++] = dgray_enabled() ? DGRAY_ON : DGRAY_OFF;
return dgray(DGRAY_OFF);
}
else if(mode == DGRAY_POP)
{
/* Stay at 0 if the user's push/pop logic is broken */
if(current > 0) current--;
/* Switch to previous state */
return dgray(states[current]);
}
else return 1;
return 0;
}
#define C_RGB(r,g,b) (((r) << 11) | ((g) << 6) | (b))
inline gdrawupscale( int x, int y, int color )
{
int u=y*396*3;
int v=x*3;
uint16_t colorcg;
if (color==C_WHITE) colorcg=0xFFFF;
else if (color==C_LIGHT) colorcg=C_RGB(20,20,20);
else if (color==C_DARK) colorcg=C_RGB(10,10,10);
else colorcg=0x0000;
int baseindex = (396*16+6+v+u); // 16 lines on top/bottom remain black and 6 columns on left/right remain black
cg_vram_gray[baseindex] = colorcg;
cg_vram_gray[baseindex+1] = colorcg;
cg_vram_gray[baseindex+2] = colorcg;
baseindex+=396;
cg_vram_gray[baseindex] = colorcg;
cg_vram_gray[baseindex+1] = colorcg;
cg_vram_gray[baseindex+2] = colorcg;
baseindex+=396;
cg_vram_gray[baseindex] = colorcg;
cg_vram_gray[baseindex+1] = colorcg;
cg_vram_gray[baseindex+2] = colorcg;
}
/* gray_int(): Interrupt handler */
int gray_int(void)
{
//t6k11_display(vrams[st ^ 2], 0, 64, 16);
timer_reload(GRAY_TIMER, delays[(st ^ 3) & 1]);
st ^= 1;
return TIMER_CONTINUE;
}
/* gupdate(): Push the current VRAMs to the screen */
int gupdate(void)
{
/* At the first gupdate(), start the engine */
if(dmode == &gray_mode && !runs)
{
gray_start();
return 0;
}
/* At the last gupdate(), stop the engine */
if(dmode == &gray_exit_mode)
{
gray_stop();
dmode = NULL;
return 1;
}
for( int j=0; j<DHEIGHT; j++ ) // 64 lines
{
for( int i=0; i<DWIDTH; i++ ) // 128 column
{
gdrawupscale( i, j, ggetpixel(i,j) ); // really not optimised; just to check if OK
}
}
r61524_display(cg_vram_gray, 0, 224, R61524_DMA_WAIT );
/* When the engine is running, swap frames */
st ^= 2;
return 0;
}
//---
// Query and configuration functions
//---
/* dgray_enabled(): Check whether gray mode is enabled */
int dgray_enabled(void)
{
return (dmode == &gray_mode);
}
/* dgray_setdelays(): Set the gray engine delays */
void dgray_setdelays(uint32_t light, uint32_t dark)
{
delays[0] = light;
delays[1] = dark;
}
/* dgray_getdelays(): Get the gray engine delays */
void dgray_getdelays(uint32_t *light, uint32_t *dark)
{
if(light) *light = delays[0];
if(dark) *dark = delays[1];
}
/* dgray_getvram(): Get the current VRAM pointers */
void dgray_getvram(uint32_t **light, uint32_t **dark)
{
int base = st;
if(light) *light = vrams[base & 2];
if(dark) *dark = vrams[base | 1];
}
/* dgray_getscreen(): Get the current screen pointers */
void dgray_getscreen(uint32_t **light, uint32_t **dark)
{
int base = st ^ 2;
if(light) *light = vrams[base & 2];
if(dark) *dark = vrams[base | 1];
}