r61524 render-cg: support Prizm and fx-CG Manager

This change adds a new HWCALC model, HWCALC_FXCG_MANAGER, which
identifies Casio's official fx-CG Manager software. Both the Prizm and,
to my surprise, the fx-CG Manager use the old RAM address of 88000000
(P1) and a8000000 (P2) instead of the new fx-CG 50 address of 8c000000
(P1) and ac000000 (P2).

The VRAM is hence adjusted at startup to move hardcoded pointers into
the proper space. Added to the kernel moving the VBR space dynamically
on the Prizm, this allows gint to be fully compatible with these
platforms.

The fx-CG Manager is detected by its product ID made of 0xff.

Also adds a proper interface to the R61524 driver, even though it's not
any more complete than previously, and fixes an oversight where the
HWURAM entry of the kernel data array was no longer computed since the
TLB management change.

As of now, the fx-CG Manager still has a bug regarding return-to-menu
since returning from the main menu doesn't work very well and often
loops. This has been seen occasionally on some Graph 90+E so it's
unlikely to be a platform-specific problem.
This commit is contained in:
Lephe 2020-07-02 15:48:19 +02:00
parent ed30b2cb21
commit 7d63a1b536
Signed by untrusted user: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
7 changed files with 100 additions and 12 deletions

View File

@ -0,0 +1,46 @@
//---
// gint:drivers:r61524 - Reneses R61524 driver
//
// This driver is used to control the 16-bit color LCD of the Prizm and
// fx-CG 50 series.
//---
#ifndef GINT_DRIVERS_R61524
#define GINT_DRIVERS_R61524
#include <gint/defs/types.h>
enum {
/* Send data through the DMA, return early (triple-buffering) */
R61524_DMA,
/* Send data through DMA, wait to return (no interrupts) */
R61524_DMA_WAIT,
/* Send data through CPU (slow!) */
R61524_CPU,
};
/* r61524_display(): Send an image to the display
This function sends [height] lines of the provided [vram] starting from line
[start] and going down 396 pixels each line. Three methods are avaiable, the
default is to use R61524_DMA which is what you almost always want.
@vram Source VRAM with a stride of 396*2 bytes
@start First line to send
@height Number of lines to send
@method Transfer method, see above */
void r61524_display(uint16_t *vram, int start, int height, int method);
/* r162524_win_get() and r61524_win_set(): Manipulate the display window
These functions change the screen rectangle where data is shown. Normally
gint uses the full screen of 396x224. The system uses a subrectangle of
384x216.
These functions don't integrate nicely with gint's drawing API, so if you
want to use them make sure you know how <gint/display.h> is going to be
impacted. */
void r61524_win_get(uint16_t *HSA, uint16_t *HEA, uint16_t *VSA,uint16_t *VEA);
void r61524_win_set(uint16_t HSA, uint16_t HEA, uint16_t VSA, uint16_t VEA);
#endif /* GINT_DRIVERS_R61524 */

View File

@ -85,15 +85,17 @@ void hw_detect(void);
*/
/* SH-3-based fx-9860G-family */
#define HWCALC_FX9860G_SH3 1
#define HWCALC_FX9860G_SH3 1
/* Other SH-4A-based fx-9860G-family */
#define HWCALC_FX9860G_SH4 2
#define HWCALC_FX9860G_SH4 2
/* Graph 35+E II, an SH-4A French extension of the fx-9860G family */
#define HWCALC_G35PE2 3
#define HWCALC_G35PE2 3
/* fx-CG 10/20, also known as the "Prizm" family */
#define HWCALC_PRIZM 4
#define HWCALC_PRIZM 4
/* fx-CG 50, a late extension to the Prizm family */
#define HWCALC_FXCG50 5
#define HWCALC_FXCG50 5
/* fx-CG 50 emulator */
#define HWCALC_FXCG_MANAGER 6
/*
** Extra Timer Units

View File

@ -3,10 +3,12 @@
//---
#include <gint/hardware.h>
#include <gint/mmu.h>
#include <gint/defs/attributes.h>
#include <gint/defs/types.h>
#include <gint/defs/util.h>
#include <gint/mpu/pfc.h>
#include <gint/std/string.h>
/* Holds information about the current platform */
GBSS uint32_t gint[HW_KEYS];
@ -116,11 +118,20 @@ void hw_detect(void)
/* Tell Prizms apart from fx-CG 50 by checking the stack address*/
uint32_t stack;
__asm__("mov r15, %0" : "=r"(stack));
gint[HWCALC] = (stack < 0x8c160000) ? HWCALC_PRIZM : HWCALC_FXCG50;
gint[HWCALC] = (stack < 0x8c000000) ? HWCALC_PRIZM : HWCALC_FXCG50;
/* Tell the fx-CG emulator apart using the product ID */
uint8_t *productID = (void *)0x8001ffd0;
if(!memcmp(productID, "\xff\xff\xff\xff\xff\xff\xff\xff", 8))
gint[HWCALC] = HWCALC_FXCG_MANAGER;
/* Basic memory information */
gint[HWRAM] = (2 << 20);
gint[HWROM] = (32 << 20);
/* Mapped memory */
if(isSH3()) tlb_mapped_memory(NULL, NULL);
else utlb_mapped_memory(NULL, NULL);
}
#endif /* FXCG50 */

View File

@ -7,6 +7,7 @@
#include <gint/hardware.h>
#include <gint/drivers.h>
#include <gint/dma.h>
#include <gint/drivers/r61524.h>
#define DMA SH7305_DMA
#define POWER SH7305_POWER
@ -199,7 +200,7 @@ void r61524_win_set(uint16_t HSA, uint16_t HEA, uint16_t VSA, uint16_t VEA)
/* TODO: r61524: update, backlight, brightness, gamma */
void r61524_display(uint16_t *vram, int start, int height, int interrupts)
void r61524_display(uint16_t *vram, int start, int height, int method)
{
/* Move the window to the desired region, then select address 0 */
r61524_win_set(0, 395, start, start + height - 1);
@ -211,6 +212,14 @@ void r61524_display(uint16_t *vram, int start, int height, int interrupts)
/* Bind address 0xb4000000 to the data write command */
select(write_data);
if(method == R61524_CPU)
{
extern uint16_t *gint_vram;
for(int i = 396*start; i < 396*(start+height); i++)
write(gint_vram[i]);
return;
}
void *src = vram + 396 * start;
void *dst = (void *)0xb4000000;
@ -220,7 +229,7 @@ void r61524_display(uint16_t *vram, int start, int height, int interrupts)
int blocks = 99 * (height >> 2);
/* Now roll! */
if(interrupts)
if(method == R61524_DMA)
{
/* If the previous transfer is still running, wait for it */
dma_transfer_wait(0);

View File

@ -1,11 +1,11 @@
#include <gint/display.h>
#include <display/cg.h>
//#include <gint/drivers/r61524.h>
#include <gint/drivers/r61524.h>
/* dupdate() - Push the video RAM to the display driver */
void dupdate(void)
{
r61524_display(gint_vram, 0, 224, 1);
r61524_display(gint_vram, 0, 224, R61524_DMA);
/* The DMA is still running, so we need to switch VRAMs to avoid
overwriting the data which is about to be sent. */
@ -15,5 +15,5 @@ void dupdate(void)
/* dupdate_noint() - Push VRAM to the display without interrupts */
void dupdate_noint(void)
{
r61524_display(gint_vram, 0, 224, 0);
r61524_display(gint_vram, 0, 224, R61524_DMA_WAIT);
}

View File

@ -1,4 +1,5 @@
#include <gint/display.h>
#include <gint/hardware.h>
#ifdef GINT_USER_VRAM
/* We want to put the VRAM in the user section, however we can't use the
@ -26,6 +27,17 @@ uint16_t *gint_vram = (void *)0xac0f0000;
/* On Prizm: should be: 0xa80f0000 and 0xa811b500 */
__attribute__((constructor))
static void init_vram(void)
{
/* On Prizm and fx-CG Manager, move address to 0xa8000000 */
if(gint[HWCALC] == HWCALC_PRIZM || gint[HWCALC] == HWCALC_FXCG_MANAGER)
{
main = (void *)main - 0x04000000;
scnd = (void *)scnd - 0x04000000;
gint_vram = (void *)gint_vram - 0x04000000;
}
}
/* dsetvram() - Control video RAM address and triple buffering */
void dsetvram(uint16_t *new_main, uint16_t *new_secondary)

View File

@ -95,8 +95,16 @@ void *_memmove(GUNUSED void *dst, GUNUSED const void *src, GUNUSED size_t n)
return dst;
}
int _memcmp(GUNUSED const void *s1, GUNUSED const void *s2, GUNUSED size_t n)
int memcmp(GUNUSED const void *s1, GUNUSED const void *s2, GUNUSED size_t n)
{
uint8_t const *p1 = s1;
uint8_t const *p2 = s2;
for(size_t i = 0; i < n; i++)
{
if(p1[i] != p2[i]) return (p1[i] - p2[i]);
}
return 0;
}