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; }