From 7d63a1b5364fdf7bd2156d6af4e5295005ad0fa2 Mon Sep 17 00:00:00 2001 From: Lephe Date: Thu, 2 Jul 2020 15:48:19 +0200 Subject: [PATCH] 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. --- include/gint/drivers/r61524.h | 46 +++++++++++++++++++++++++++++++++++ include/gint/hardware.h | 12 +++++---- src/core/hardware.c | 13 +++++++++- src/r61524/r61524.c | 13 ++++++++-- src/render-cg/dupdate.c | 6 ++--- src/render-cg/dvram.c | 12 +++++++++ src/std/memory.c | 10 +++++++- 7 files changed, 100 insertions(+), 12 deletions(-) create mode 100644 include/gint/drivers/r61524.h diff --git a/include/gint/drivers/r61524.h b/include/gint/drivers/r61524.h new file mode 100644 index 0000000..3a93b4e --- /dev/null +++ b/include/gint/drivers/r61524.h @@ -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 + +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 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 */ diff --git a/include/gint/hardware.h b/include/gint/hardware.h index 56af033..32af63d 100644 --- a/include/gint/hardware.h +++ b/include/gint/hardware.h @@ -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 diff --git a/src/core/hardware.c b/src/core/hardware.c index a7a079e..f957ff6 100644 --- a/src/core/hardware.c +++ b/src/core/hardware.c @@ -3,10 +3,12 @@ //--- #include +#include #include #include #include #include +#include /* 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 */ diff --git a/src/r61524/r61524.c b/src/r61524/r61524.c index 89019ad..13c6f1a 100644 --- a/src/r61524/r61524.c +++ b/src/r61524/r61524.c @@ -7,6 +7,7 @@ #include #include #include +#include #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); diff --git a/src/render-cg/dupdate.c b/src/render-cg/dupdate.c index 439366e..282fd94 100644 --- a/src/render-cg/dupdate.c +++ b/src/render-cg/dupdate.c @@ -1,11 +1,11 @@ #include #include -//#include +#include /* 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); } diff --git a/src/render-cg/dvram.c b/src/render-cg/dvram.c index d7f4584..4cd3331 100644 --- a/src/render-cg/dvram.c +++ b/src/render-cg/dvram.c @@ -1,4 +1,5 @@ #include +#include #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) diff --git a/src/std/memory.c b/src/std/memory.c index c8afcbb..be2c2de 100644 --- a/src/std/memory.c +++ b/src/std/memory.c @@ -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; }