Compare commits

..

No commits in common. "dev" and "master" have entirely different histories.
dev ... master

34 changed files with 179 additions and 672 deletions

1
TODO
View File

@ -1,5 +1,4 @@
Extensions on existing code:
* project: add license file
* kernel: group linker script symbols in a single header file
* kernel: be consistent about *tlb_mapped_memory() in hw_detect()
* bopti: try to display fullscreen images with TLB access + DMA on fxcg50

View File

@ -1,16 +0,0 @@
# fxsdk: version=1
configure:
mkdir -p build-fx && cd build-fx && ../configure --target=fx9860g
mkdir -p build-cg && cd build-cg && ../configure --target=fxcg50
build:
make all
install:
make install
uninstall:
make uninstall
.PHONY: configure build install uninstall

View File

@ -67,11 +67,6 @@ const clock_frequency_t *clock_freq(void);
function selects a timer with timer_setup() called with TIMER_ANY. */
void sleep_us(uint64_t delay_us);
/* sleep_us_spin(): Actively sleep for a fixed duration in microseconds
Like sleep_us(), but uses timer_spinwait() and does not rely on interrupts
being enabled. Useful in timer code running without interrupts. */
void sleep_us_spin(uint64_t delay_us);
/* sleep_ms(): Sleep for a fixed duration in milliseconds */
#define sleep_ms(delay_ms) sleep_us((delay_ms) * 1000ull)

View File

@ -1,19 +0,0 @@
//---
// config - Compile-time generate configuration
//---
#ifndef GINT_CONFIG
#define GINT_CONFIG
#include <gint/defs/types.h>
/* GINT_VERSION: Latest tag and number of additional commits
"2.1.0" = Release 2.1.0
"2.1.1-5" = 5 commits after release 2.1.1 */
#define GINT_VERSION @GINT_VERSION@
/* GINT_HASH: Commit hash with 7 digits
0x03f7c0a0 = Commit 3f7c0a0 */
#define GINT_HASH @GINT_HASH@
#endif /* GINT_CONFIG */

View File

@ -189,11 +189,6 @@ typedef struct
/* Number of total glyphs */
uint32_t glyph_count;
/* Character spacing (usually 1) */
uint8_t char_spacing;
uint :24;
struct {
/* Unicode point of first character in block */
uint start :20;

View File

@ -6,7 +6,15 @@
#define GINT_GINT
#include <gint/defs/types.h>
#include <gint/config.h>
/* GINT_VERSION - the library version number
gint is versioned from its repository commits on the master branch. The
GINT_VERSION integer contains the short commit hash with 7 digits.
For instance, 0x03f7c0a0 means commit 3f7c0a0. */
extern char GINT_VERSION;
#define GINT_VERSION ((uint32_t)&GINT_VERSION)
/* gint_switch(): Switch out of gint to execute a function

View File

@ -38,9 +38,6 @@ enum {
INTC_RTC_ATI,
INTC_RTC_PRI,
INTC_RTC_CUI,
/* SPU; interrupts from the DSPs and the SPU-bound DMA */
INTC_SPU_DSP0,
INTC_SPU_DSP1,
};
//---

View File

@ -248,10 +248,10 @@ void getkey_repeat(int first, int next);
/* getkey_repeat_filter(): Set the repeat filter function
The repeat filter is called by getkey() and getkey_opt() every time a repeat
event occurs when GETKEY_REP_FILTER is set. The filter can decide whether to
keep, delay or drop the event. It can also change the repeat delays with
getkey_repeat() for fully custom repeat delay curves.
This function is called by getkey() and getkey_opt() every time a repeat
event occurs when GETKEY_REPEAT_FILTER. The function can decide whether to
keep, delay it or drop it entirely. It can also change the repeat delays
with getkey_repeat() for fully custom repeat delay curves.
The time elapsed since the last accepted repeat is passed to the filter
function; this time must be larger than the repeat time set with

View File

@ -54,17 +54,7 @@ typedef volatile struct
uint32_t :4;
uint32_t P1FC :4; /* Pphi divider 1 [*] */
);
pad(0x4);
lword_union(FSICLKCR,
uint32_t :16;
uint32_t DIVB :6; /* Division ratio for port B */
uint32_t :1;
uint32_t CLKSTP :1; /* Clock Stop */
uint32_t SRC :2; /* Clock source select */
uint32_t DIVA :6; /* Division ratio for port A */
);
pad(0x18);
pad(0x20);
lword_union(PLLCR,
uint32_t :17;
@ -75,17 +65,8 @@ typedef volatile struct
uint32_t CKOFF :1; /* CKO Output Stop */
uint32_t :1;
);
pad(0x14);
lword_union(SPUCLKCR,
uint32_t :23;
uint32_t CLKSTP :1; /* Clock Stop */
uint32_t _ :1; /* Unknown */
uint32_t :1;
uint32_t DIV :6; /* Division ratio */
);
pad(0x4);
pad(0x1c);
lword_union(SSCGCR,
uint32_t SSEN :1; /* Spread Spectrum Enable */
uint32_t :31;

View File

@ -119,7 +119,6 @@ typedef struct
// SH7305 Interrupt Controller. Refer to:
// "Renesas SH7724 User's Manual: Hardware"
// Section 13: "Interrupt Controller (INTC)"
// Also CPU73050.dll was disassembled to find out the bits.
//---
/* sh7305_intc_ipc_t - Interrupt Priority Controller
@ -132,29 +131,29 @@ typedef volatile struct
uint16_t TMU0_0 :4; /* TMU0 Channel 0 */
uint16_t TMU0_1 :4; /* TMU0 Channel 1 */
uint16_t TMU0_2 :4; /* TMU0 Channel 2 */
uint16_t :4;
uint16_t IrDA :4; /* Infrared Communication */
);
pad(2);
word_union(IPRB,
uint16_t _ :4; /* Unknown (TODO) */
uint16_t _LCDC :4; /* SH7724: LCD Controller */
uint16_t _DMAC1A:4; /* SH7724: DMAC1 channels 0..3 */
uint16_t :4;
uint16_t LCDC :4; /* LCD Controller */
uint16_t DMAC1A :4; /* Direct Memory Access Controller 1 */
uint16_t :4;
);
pad(2);
word_union(IPRC,
uint16_t TMU1_0 :4; /* TMU1 Channel 0 */
uint16_t TMU1_1 :4; /* TMU1 Channel 1 */
uint16_t TMU1_2 :4; /* TMU1 Channel 2 */
uint16_t :4;
uint16_t :4;
uint16_t :4;
uint16_t SPU :4; /* SPU's DSP0 and DSP1 */
);
pad(2);
word_union(IPRD,
uint16_t :4;
uint16_t _MMCIF :4; /* SH7724: MultiMedia Card Interface */
uint16_t MMCIF :4; /* MultiMedia Card Interface */
uint16_t :4;
uint16_t :4;
);
@ -172,12 +171,12 @@ typedef volatile struct
uint16_t KEYSC :4; /* Key Scan Interface */
uint16_t DMACOB :4; /* DMAC0 transfer/error info */
uint16_t USB0_1 :4; /* USB controller */
uint16_t _CMT :4; /* SH7724: Compare Match Timer */
uint16_t CMT :4; /* Compare Match Timer */
);
pad(2);
word_union(IPRG,
uint16_t _SCIF0 :4; /* SH7724: SCIF0 transfer/error info */
uint16_t SCIF0 :4; /* SCIF0 transfer/error info */
uint16_t ETMU1 :4; /* Extra TMU 1 */
uint16_t ETMU2 :4; /* Extra TMU 2 */
uint16_t :4;
@ -185,26 +184,26 @@ typedef volatile struct
pad(2);
word_union(IPRH,
uint16_t _MSIOF0:4; /* SH7724: Sync SCIF channel 0 */
uint16_t _MSIOF1:4; /* SH7724: Sync SCIF channel 1 */
uint16_t _1 :4; /* Unknown (TODO) */
uint16_t _2 :4; /* Unknown (TODO) */
uint16_t MSIOF0 :4; /* Clock-synchronized SCIF channel 0 */
uint16_t MSIOF1 :4; /* Clock-synchronized SCIF channel 1 */
uint16_t :4;
uint16_t :4;
);
pad(2);
word_union(IPRI,
uint16_t ETMU4 :4; /* Extra TMU 4 */
uint16_t :4;
uint16_t _ :4; /* Unknown (TODO) */
uint16_t :4;
uint16_t :4;
);
pad(2);
word_union(IPRJ,
uint16_t ETMU0 :4; /* Extra TMU 0 */
uint16_t _ :4; /* Unknown (TODO) */
uint16_t :4;
uint16_t FSI :4; /* FIFO-Buffered Serial Interface */
uint16_t _SDHI1 :4; /* SH7724: SD Card Host Interface 1 */
uint16_t SDHI1 :4; /* SD Card Host Interface channel 1 */
);
pad(2);
@ -212,14 +211,14 @@ typedef volatile struct
uint16_t RTC :4; /* Real-Time Clock */
uint16_t DMAC1B :4; /* DMAC1 transfer/error info */
uint16_t :4;
uint16_t :4;
uint16_t SDHI0 :4; /* SD Card Host Interface channel 0 */
);
pad(2);
word_union(IPRL,
uint16_t ETMU5 :4; /* Extra TMU 5 */
uint16_t _ :4; /* Unknown (TODO) */
uint16_t :4;
uint16_t TPU :4; /* Timer-Pulse Unit */
uint16_t :4;
);
pad(2);
@ -293,7 +292,7 @@ typedef struct
// Forward definitions
//---
/* Provided by intc/intc.c */
/* Provided by core/gint.c */
extern sh7705_intc_t SH7705_INTC;
extern sh7305_intc_t SH7305_INTC;

View File

@ -77,79 +77,4 @@ typedef struct
} GPACKED(4) utlb_data_t;
typedef volatile struct
{
lword_union(PTEH,
uint32_t VPN :22; /* Virtual Page Number */
uint32_t :2;
uint32_t ASID :8; /* Address Space Identifier */
);
lword_union(PTEL,
uint32_t :3;
uint32_t PPN :19; /* Phusical Page Number */
uint32_t :1;
uint32_t V :1; /* Valid */
uint32_t SZ1 :1; /* Size (bit 1) */
uint32_t PR :2; /* Protection */
uint32_t SZ0 :1; /* Size (bit 0) */
uint32_t C :1; /* Cacheable */
uint32_t D :1; /* Dirty */
uint32_t SH :1; /* Shared */
uint32_t WT :1; /* Write-through */
);
uint32_t TTB;
uint32_t TEA;
lword_union(MMUCR,
uint32_t LRUI :6; /* Least-Recently Used ITLB */
uint32_t :2;
uint32_t URB :6; /* UTLB Replace Boundary */
uint32_t :2;
uint32_t URC :6; /* UTLB Replace Counter */
uint32_t SQMD :1; /* Store Queue Mode */
uint32_t SV :1; /* Single Virtual Memory Mode */
uint32_t ME :1; /* TLB Extended Mode */
uint32_t :4;
uint32_t TI :1; /* TLB Invalidate */
uint32_t :1;
uint32_t AT :1; /* Address Translation */
);
pad(0x20);
lword_union(PTEA,
uint32_t :18;
uint32_t EPR :6;
uint32_t ESZ :4;
uint32_t :4;
);
pad(0x38);
lword_union(PASCR,
uint32_t :24;
uint32_t UBC :1; /* Control register area */
uint32_t UB6 :1; /* Area 6 */
uint32_t UB5 :1; /* Area 5 */
uint32_t UB4 :1; /* Area 4 */
uint32_t UB3 :1; /* Area 3 */
uint32_t UB2 :1; /* Area 2 */
uint32_t UB1 :1; /* Area 1 */
uint32_t UB0 :1; /* Area 0 */
);
pad(4);
lword_union(IRMCR,
uint32_t :27;
uint32_t R2 :1; /* Re-fetch after Register 2 change */
uint32_t R1 :1; /* Re-fetch after Register 1 change */
uint32_t LT :1; /* Re-fetch after LDTLB */
uint32_t MT :1; /* Re-fetch after writing TLB */
uint32_t MC :1; /* Re-fetch after writing insn cache */
);
} GPACKED(4) sh7305_mmu_t;
#define SH7305_MMU (*(sh7305_mmu_t *)0xff000000)
#endif /* GINT_MPU_MMU */

View File

@ -37,8 +37,8 @@ typedef volatile struct
uint32_t RS :1;
uint32_t IL :1;
uint32_t SndCache :1;
uint32_t _unknown1 :1;
uint32_t :1;
uint32_t FPU :1;
uint32_t :1;
uint32_t INTC :1;
@ -53,44 +53,41 @@ typedef volatile struct
uint32_t CMT :1;
uint32_t RWDT :1;
uint32_t DMAC1 :1;
uint32_t :4;
uint32_t :1;
uint32_t TMU1 :1;
uint32_t SCIF0 :1;
uint32_t SCIF1 :1;
uint32_t SCIF :1;
uint32_t KEYSC :1;
uint32_t RTC :1;
uint32_t :2;
uint32_t SCIF2 :1;
uint32_t SCIF3 :1;
uint32_t SCIF4 :1;
uint32_t SCIF5 :1;
uint32_t :1;
uint32_t MSIOF0 :1;
uint32_t MSIOF1 :1;
uint32_t :1;
);
/* Module Stop Control Register 1 */
lword_union(MSTPCR1,
uint32_t :19;
uint32_t KEYSC :1;
uint32_t RTC :1;
uint32_t :1;
uint32_t I2C0 :1;
uint32_t I2C1 :1;
uint32_t :8;
);
/* Module Stop Control Register 2
The list was established by Yatis. See <https://bible.planet-casio.
com/yatis/hardware/sh7305/power.html>. */
I stripped down this one to remove any fancy modules from the SH7724
that are unlikely to even be present in the SH7305. */
lword_union(MSTPCR2,
uint32_t :2;
uint32_t MMC :1;
uint32_t :1;
uint32_t ADC :1;
uint32_t :6;
uint32_t TPU :1;
uint32_t :4;
uint32_t USB0 :1;
uint32_t :2;
uint32_t SDC :1;
uint32_t :2;
uint32_t FLCTL :1;
uint32_t ECC :1;
uint32_t :1;
uint32_t I2C :1;
uint32_t :1;
uint32_t FSI_SPU :1;
uint32_t _unknown2 :1;
uint32_t :1;
uint32_t LCDC :1;
uint32_t _unknown3 :1;
uint32_t Cmod :1;
uint32_t :1;
uint32_t Cmod2A :1;
uint32_t :2;
uint32_t :20;
);
pad(4);

View File

@ -1,97 +0,0 @@
//---
// gint:mpu:spu - Sound Processing Unit and its DSPs
//---
#ifndef GINT_MPU_SPU
#define GINT_MPU_SPU
#include <gint/defs/types.h>
typedef volatile struct
{
uint32_t PBANKC0; /* Program Bank Control 0 */
uint32_t PBANKC1; /* Program Bank Control 1 */
pad(0x8);
uint32_t XBANKC0; /* X Bank Control 0 */
uint32_t XBANKC1; /* X Bank Control 1 */
pad(0x10);
lword_union(SPUSRST, /* SPU Software Reset */
uint32_t :24;
uint32_t DB3 :1; /* DMABUF 3 */
uint32_t DB2 :1; /* DMABUF 2 */
uint32_t DB1 :1; /* DMABUF 1 */
uint32_t DB0 :1; /* DMABUF 0 */
uint32_t :3;
uint32_t RST :1; /* Reset */
);
uint32_t const SPUADR; /* SPU address */
uint32_t const ENDIAN; /* SuperHyway endian */
pad(0x10);
uint32_t GCOM[8]; /* Global Common */
pad(0x20);
uint32_t const DMABUF[4]; /* Inter-DSP Communication Buffer */
} GPACKED(4) spu_t;
typedef volatile struct
{
uint32_t SBAR; /* Source base address */
uint32_t SAR; /* Source address */
uint32_t DBAR; /* Destination base address */
uint32_t DAR; /* Destination address */
uint32_t TCR; /* Transfer count */
uint32_t SHPRI; /* SHway priority */
uint32_t CHCR; /* Channel control */
pad(0x4);
} GPACKED(4) spu_dsp_dma_t;
typedef volatile struct {
uint32_t LSA; /* Loop start address */
uint32_t LEA; /* Loop end address */
pad(0x8);
} GPACKED(4) spu_dsp_loop_t;
typedef volatile struct
{
uint32_t DSPRST; /* DSP full reset */
uint32_t DSPCORERST; /* DSP core reset */
uint32_t const DSPHOLD; /* DSP hold */
uint32_t DSPRESTART; /* DSP restart */
pad(0x8);
uint32_t IEMASKC; /* CPU interrupt source mask */
uint32_t IMASKC; /* CPU interrupt signal mask */
uint32_t IEVENTC; /* CPU interrupt source */
uint32_t IEMASKD; /* DSP interrupt source mask */
uint32_t IMASKD; /* DSP interrupt signal mask */
uint32_t IESETD; /* DSP interrupt set */
uint32_t IECLRD; /* DSP interrupt clear */
uint32_t OR; /* DMAC operation */
uint32_t COM[8]; /* CPU-DSP communication */
uint32_t BTADRU; /* Bus-through address high */
uint32_t BTADRL; /* Bus-through address low */
uint32_t WDATU; /* Bus-through write data high */
uint32_t WDATL; /* Bus-through write data low */
uint32_t RDATU; /* Bus-through read data high */
uint32_t RDATL; /* Bus-through read data low */
uint32_t BTCTRL; /* Bus-through mode control */
uint32_t SPUSTS; /* SPU status */
pad(0x88);
spu_dsp_dma_t DMA[3];
pad(0x20);
spu_dsp_loop_t LP[3];
} GPACKED(4) spu_dsp_t;
#define SH7305_SPU (*(spu_t *)0xfe2ffc00)
#define SH7305_DSP0 (*(spu_dsp_t *)0xfe2ffd00)
#define SH7305_DSP1 (*(spu_dsp_t *)0xfe3ffd00)
#endif /* GINT_MPU_SPU */

View File

@ -19,12 +19,10 @@ void *calloc(size_t nmemb, size_t size);
/* realloc(): Reallocate dynamic memory */
void *realloc(void *ptr, size_t size);
#define RAND_MAX 0x7fffffff
/* srand(): Seed the PRNG */
void srand(unsigned int seed);
/* rand(): Generate a pseudo-random number between 0 and RAND_MAX */
/* rand(): Generate a pseudo-random number */
int rand(void);
#endif /* GINT_STD_STDLIB */

View File

@ -41,7 +41,7 @@
* Set a specific ID in timer_setup(), in which case the delay is no longer
interpreter as count of µs, but as a TCOR value.
* If this ID is a TMU, you can further add (with + or |) a prescaler
specification, one of TIMER_Pphi_{4,16,64,256}.
specification, one of TIMER_Po_{4,16,64,256}.
* Regardless of how the timer was obtained, you can use timer_reload() to
replace the value of TCOR.
* Also note that TMU0, TMU1, TMU2 and the ETMU have respective interrupt
@ -59,7 +59,7 @@
Standard TMU can count at different speeds. A fast speed offers more
precision but a slower speed offers longer delays. gint automatically
selects suitable speeds by default.
selects suitable speed by default.
If you want something very particular, you can add (with + or |) a prescaler
value to a chosen ID in timer_setup() to request that specific value. The
@ -186,12 +186,6 @@ void timer_stop(int timer);
it may have only paused. If the timer never stops, you're in trouble. */
void timer_wait(int timer);
/* timer_spinwait(): Actively wait for a timer to raise UNF
Waits until the timer raises UNF, without sleeping. This is useful for
delays in driver code that is run when interrupts are disabled. This relies
neither on the interrupt signal nor on the UNIE flag. */
void timer_spinwait(int timer);
//---
// Low-level functions
//---

View File

@ -26,7 +26,7 @@ machine ?= -m4-nofpu -mb
endif
# Compiler flags, assembler flags, dependency generation, archiving
inc := -I ../include -I include
inc := -I ../include
cflags := $(machine) -ffreestanding -nostdlib -Wall -Wextra -std=c11 -Os \
-fstrict-volatile-bitfields $(inc) $(CONFIG.MACROS) \
$(CONFIG.CFLAGS)
@ -64,7 +64,7 @@ src_obj := $(foreach s,$(src),$(call src2obj,$s))
# Files with special handling
spe-fx := ../src/font5x7.png
spe-cg := ../src/font8x9.png
spe_obj := $(foreach s,$(spe-$(CONFIG.TARGET)),$(call src2obj,$s))
spe_obj := version.o $(foreach s,$(spe-$(CONFIG.TARGET)),$(call src2obj,$s))
# All object files
obj := $(src_obj) $(spe_obj)
@ -87,8 +87,6 @@ objcopy = $(CONFIG.TOOLCHAIN)-objcopy
# Version symbol is obtained by using the last commit hash on 7 nibbles
version_hash = 0x0$(shell git rev-parse --short HEAD)
# Version number: closest tag, with additional commits
version_number = $(shell git describe --tag --always | cut -d- -f1-2)
#
@ -97,7 +95,7 @@ version_number = $(shell git describe --tag --always | cut -d- -f1-2)
all: $(target)
$(target): include/gint/config.h $(obj)
$(target): $(obj)
@ rm -f $@
$(call cmd_l,ar,$@) $(ar) rcs $(arflags) $@ $^
@ -115,11 +113,6 @@ src/%.c.o: ../src/%.c src/%.c.d
$(call cmd_b,gcc,$*.c) $(gcc) -c $< -o $@ $(dflags) $(cflags)
# Special files
include/gint/config.h: ../include/gint/config.h.in $(gitfile)
@ mkdir -p $(dir $@)
$(call cmd_m,sed,$@) cp $< $@
@ sed -i'' 's/@GINT_VERSION@/"$(version_number)"/' $@
@ sed -i'' 's/@GINT_HASH@/$(version_hash)/' $@
$(call src2obj,../src/font5x7.png): ../src/font5x7.png
@ mkdir -p $(dir $@)
$(call cmd_m,fxconv,font5x7.png) fxconv -f $< -o $@ \
@ -130,14 +123,21 @@ $(call src2obj,../src/font8x9.png): ../src/font8x9.png
$(call cmd_m,fxconv,font8x9.png) fxconv -f $< -o $@ \
--cg --toolchain=$(CONFIG.TOOLCHAIN) name:gint_font8x9 \
charset:print grid.size:8x11 grid.padding:1 grid.border:0 \
proportional:true height:9
proportional:true
# Version symbol. ld generates a .stack section for unknown reasons; I remove
# it in the linker script.
version.o: $(gitfile)
@ mkdir -p $(dir $@)
@ echo "_GINT_VERSION = $(version_hash);" > $@.txt
$(call cmd_b,ld,$@) $(ld) -r -R $@.txt -o $@
#
# Cleaning
#
clean:
@ rm -rf src include
@ rm -rf src version.o{,txt}
distclean: clean
@ rm -rf Makefile $(CONFIG) $(target)
@ -156,9 +156,7 @@ install: $(target)
install -d $(PREFIX)
install $(target) $(m644) $(PREFIX)
install ../$(CONFIG.TARGET.LONG).ld $(m644) $(PREFIX)
install -d $(PREFIX)/include/gint
cp ../include/gint/*.h $(PREFIX)/include/gint/
cp include/gint/*.h $(PREFIX)/include/gint/
cp -r ../include/gint $(PREFIX)/include
uninstall:
rm -f $(PREFIX)/$(target)

View File

@ -56,9 +56,7 @@ static void sh7705_probe(void)
/* Deduce the frequency of the main clocks. This value is ckio/3 */
int ckio_3 = 9830400;
/* Exchange the setting values 2 and 3 (corresponding to /3 and /4)
This means that /1, /2, /4 are now 0, 1, 2, which is perfect for a
quick bit shift */
/* Exchange the setting values 2 and 3 */
idiv = idiv ^ (idiv >> 1);
pdiv = pdiv ^ (pdiv >> 1);
@ -89,8 +87,8 @@ static void sh7305_probe(void)
if(CPG.FLLFRQ.SELXM == 1) fll >>= 1;
freq.FLL = fll;
/* On SH7724, the divider ratio is given by 1 / (setting + 1), but on
the SH7305 it is 1 / (2^setting + 1). */
/* On SH7724, the divider ratio is given by 1 / (setting + 1), but
SH7305 behaves as 1 / (2^setting + 1). */
int divb = CPG.FRQCRA.BFC;
int divi = CPG.FRQCRA.IFC;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -56,9 +56,6 @@ static struct info {
{ IPRK, 0xf000, IMR10, 0x04, IPRA, 0x000f },
{ IPRK, 0xf000, IMR10, 0x02, IPRA, 0x000f },
{ IPRK, 0xf000, IMR10, 0x01, IPRA, 0x000f },
/* SPU */
{ IPRC, 0x000f, IMR3, 0x04, _ /* Not supported on SH3! */ },
{ IPRC, 0x000f, IMR4, 0x08, _ },
};

View File

@ -36,31 +36,4 @@ void cpu_setCPUOPM(uint32_t CPUOPM);
/* cpu_getCPUOPM(): Get the CPU OperatioN Mode register */
uint32_t cpu_getCPUOPM(void);
//---
// Status Register
//---
/* Status Register bits */
typedef lword_union(sr_t,
uint32_t :1;
uint32_t MD :1;
uint32_t RB :1;
uint32_t BL :1;
uint32_t RC :12;
uint32_t :3;
uint32_t DSP :1;
uint32_t DMY :1;
uint32_t DMX :1;
uint32_t M :1;
uint32_t Q :1;
uint32_t IMASK :4;
uint32_t RF :2;
uint32_t S :1;
uint32_t T :1;
);
/* Get and set sr through the sr_t type */
sr_t cpu_getSR(void);
void cpu_setSR(sr_t sr);
#endif /* GINT_CORE_CPU */

View File

@ -5,23 +5,21 @@
.global _cpu_setVBR
.global _cpu_setCPUOPM
.global _cpu_getCPUOPM
.global _cpu_getSR
.global _cpu_setSR
/* cpu_setVBR(): Change VBR address */
.section .gint.mapped, "ax"
_cpu_setVBR_reloc:
mov.l r8, @-r15
mov.l r9, @-r15
sts.l pr, @-r15
stc.l sr, @-r15
/* Block all interrupts by setting IMASK=15 */
mov #0xf, r9
shll2 r9
shll2 r9
mov #0xf, r1
shll2 r1
shll2 r1
stc sr, r0
or r9, r0
or r1, r0
ldc r0, sr
/* Set the new VBR address */
@ -32,17 +30,10 @@ _cpu_setVBR_reloc:
jsr @r5
mov r6, r4
/* Enable interrupts again */
stc sr, r0
not r9, r9
and r9, r0
ldc r0, sr
/* Return the previous VBR address */
mov r8, r0
/* Enable interrupts again by restoring the status register */
ldc.l @r15+, sr
lds.l @r15+, pr
mov.l @r15+, r9
mov r8, r0
rts
mov.l @r15+, r8
@ -77,16 +68,5 @@ _cpu_getCPUOPM:
mov.l @r0, r0
.align 4
1: .long 0xff2f0000
/* cpu_getSR(): Get status register */
_cpu_getSR:
stc sr, r0
rts
nop
/* cpu_setSR(): Set status register */
_cpu_setSR:
ldc r4, sr
rts
nop

View File

@ -16,17 +16,12 @@
static void kinit_cpu(void);
/* Forcefully pull in the INTC driver which gint cannot run without */
extern gint_driver_t drv_intc;
GUNUSED gint_driver_t *gint_required_intc = &drv_intc;
//---
// Context for the CPU and registers not directly managed by a driver
//---
typedef struct
{
sr_t SR;
uint32_t VBR;
uint32_t CPUOPM;
} ctx_t;
@ -36,19 +31,11 @@ GBSS static ctx_t sys_ctx, gint_ctx;
static void ctx_save(ctx_t *ctx)
{
if(isSH4())
{
ctx->CPUOPM = cpu_getCPUOPM();
ctx->SR = cpu_getSR();
}
if(isSH4()) ctx->CPUOPM = cpu_getCPUOPM();
}
static void ctx_restore(ctx_t *ctx)
{
if(isSH4())
{
cpu_setCPUOPM(ctx->CPUOPM);
cpu_setSR(ctx->SR);
}
if(isSH4()) cpu_setCPUOPM(ctx->CPUOPM);
}
//---
@ -71,8 +58,9 @@ static void drivers_save_and_init(GUNUSED int zero)
for driver_asc(d)
{
if(isSH3() && d->driver_sh3) d->driver_sh3();
if(d->ctx_save) d->ctx_save(d->sys_ctx);
if(isSH3() && d->driver_sh3) d->driver_sh3();
if(d->init) d->init();
}
}
@ -112,15 +100,7 @@ static void drivers_switch(int who)
static void kinit_cpu(void)
{
if(isSH4())
{
cpu_setCPUOPM(cpu_getCPUOPM() | 0x00000008);
/* Enable DSP mode on the CPU */
sr_t SR = cpu_getSR();
SR.DSP = 1;
cpu_setSR(SR);
}
if(isSH4()) cpu_setCPUOPM(cpu_getCPUOPM() | 0x00000008);
}
/* kinit(): Install and start gint */

View File

@ -1,9 +1,8 @@
//---
// gint:mmu:mmu - MMU driver definition and context management
// gint:core:mmu - MMU-related definitions
//---
#include <gint/mmu.h>
#include <gint/drivers.h>
#include <gint/hardware.h>
//---
@ -149,54 +148,3 @@ uint32_t utlb_translate(uint32_t page)
}
return -1;
}
//---
// Initialization
//---
static void init(void)
{
/* Make writes to the control register area synchronous; this is needed
for the SPU to operate properly */
if(isSH4()) SH7305_MMU.PASCR.UBC = 1;
}
//---
// Context management
//---
typedef struct {
uint32_t PASCR;
uint32_t IRMCR;
} ctx_t;
GBSS static ctx_t sys_ctx, gint_ctx;
static void ctx_save(void *buf)
{
if(isSH3()) return;
ctx_t *ctx = buf;
ctx->PASCR = SH7305_MMU.PASCR.lword;
ctx->IRMCR = SH7305_MMU.IRMCR.lword;
}
static void ctx_restore(void *buf)
{
if(isSH3()) return;
ctx_t *ctx = buf;
SH7305_MMU.PASCR.lword = ctx->PASCR;
SH7305_MMU.IRMCR.lword = ctx->IRMCR;
}
gint_driver_t drv_mmu = {
.name = "MMU",
.init = init,
.sys_ctx = &sys_ctx,
.gint_ctx = &gint_ctx,
.ctx_save = ctx_save,
.ctx_restore = ctx_restore,
};
GINT_DECLARE_DRIVER(1, drv_mmu);

View File

@ -113,42 +113,16 @@ int start(int isappli, int optnum)
/* Detect hardware; this will mainly tell SH3 from SH4 on fx-9860G */
hw_detect();
/* The dynamic TLB mechanism for old SH3-based fx-9860G (basically OS
1.00 and the fx-9860G emulator) is not clear yet, so gint can't load
pages dynamically. Load everything preventively (works only if the
add-in is small enough) */
#ifdef FX9860G
if(isSH3())
{
/* Try to map every ROM address up to _srom */
volatile uint8_t *x = (void *)0x00300000;
uint32_t loaded = 0;
while(loaded < (uint32_t)&srom)
{
GUNUSED volatile uint8_t y = *x;
loaded += 1024;
x += 1024;
}
}
#endif
/* Load data sections and wipe the bss section. This has to be done
first for static and global variables to be initialized */
regcpy(&ldata, &sdata, &rdata);
regcpy(&lilram, &silram, &rilram);
regcpy(&lxram, &sxram, &rxram);
regcpy(&lyram, &syram, &ryram);
regclr(&rbss, &sbss);
/* Do not load data to ILRAM, XRAM or YRAM on SH3 - the areas don't
exist. If you use them, you're responsible! */
if(!isSH3())
{
regcpy(&lilram, &silram, &rilram);
regcpy(&lxram, &sxram, &rxram);
regcpy(&lyram, &syram, &ryram);
}
#ifdef FX9860G
/* Copy permanently-mapped code to start of user RAM (on fx-CG 50 it
/* Copy permanentely-mapped code to start of user RAM (on fx-CG 50 it
is loaded along ILRAM contents) */
void *rgmapped = mmu_uram();
regcpy(&lgmapped, &sgmapped, rgmapped);
@ -184,7 +158,6 @@ int start(int isappli, int optnum)
}
callarray(&bdtors, &edtors);
/* Before leaving the application, we need to clean everything we
changed to hardware settings and peripheral modules. The OS is bound
to be confused (and hang, or crash, or any other kind of giving up)

View File

@ -61,8 +61,9 @@ static void topti_render(int x, int y, char const *str_char, font_t const *f,
/* Move to top row */
uint16_t *target = gint_vram + 396 * y;
/* Character spacing waiting to be drawn, in pixels */
int space = 0;
/* Character spacing and space waiting to be drawn */
int space = 1;
int active_space = 0;
/* Read each character from the input string */
while(1)
@ -73,23 +74,29 @@ static void topti_render(int x, int y, char const *str_char, font_t const *f,
int glyph = topti_glyph_index(f, code_point);
if(glyph < 0) continue;
int dataw = f->prop ? f->glyph_width[glyph] : f->width;
/* Draw character spacing if background is opaque */
if(space && bg >= 0) drect(x, y, x+space-1, y+height-1, bg);
x += space;
/* Draw the space if background is opaque */
int prop_space = (code_point == ' ' && f->prop) ? 5 : 0;
if(active_space || prop_space)
{
active_space += prop_space;
if(bg >= 0) drect(x, y, x + active_space - 1,
y + height - 1, bg);
}
x += active_space;
if(prop_space) { active_space = space; continue; }
if(x >= 396) break;
int index = topti_offset(f, glyph);
/* Compute horizontal intersection between glyph and screen */
int dataw = f->prop ? f->glyph_width[glyph] : f->width;
int width = dataw, left = 0;
if(x + dataw <= 0)
{
x += dataw;
space = f->char_spacing;
active_space = space;
continue;
}
if(x < 0) left = -x, width += x;
@ -101,7 +108,7 @@ static void topti_render(int x, int y, char const *str_char, font_t const *f,
dataw, fg, bg);
x += dataw;
space = f->char_spacing;
active_space = space;
}
}
@ -114,10 +121,10 @@ void dtext_opt(int x, int y, int fg, int bg, int halign, int valign,
int w, h;
dsize(str, topti_font, &w, &h);
if(halign == DTEXT_RIGHT) x -= w - 1;
if(halign == DTEXT_CENTER) x -= (w >> 1);
if(valign == DTEXT_BOTTOM) y -= h - 1;
if(valign == DTEXT_MIDDLE) y -= (h >> 1);
if(halign == DTEXT_RIGHT) x -= w;
if(halign == DTEXT_CENTER) x -= ((w+1) >> 1);
if(valign == DTEXT_BOTTOM) y -= h;
if(valign == DTEXT_MIDDLE) y -= ((h+1) >> 1);
}
topti_render(x, y, str, topti_font, fg, bg);

View File

@ -291,3 +291,24 @@ int bopti_clip(bopti_image_t const *img, struct rbox *r)
/* Return non-zero if the result is empty */
return (width <= 0 || height <= 0);
}
void bopti_render_noclip(bopti_image_t const *img, struct rbox *r,
uint32_t *v1, uint32_t *v2)
{
int left = r->left;
/* Start column and end column (both included) */
r->left >>= 5;
if(r->columns == 1 && (r->visual_x & 31) + r->width <= 32)
{
r->x = (left & 31) - (r->visual_x & 31);
bopti_render_scsp(img, r, v1, v2);
}
else
{
/* x-coordinate of the first pixel of the first column */
r->x = r->visual_x - (left & 31);
bopti_render(img, r, v1, v2);
}
}

View File

@ -44,8 +44,6 @@ void gint_dvline(int y1, int y2, int x, int color)
if((uint)x >= 128) return;
if(y1 > y2) swap(y1, y2);
if(y1 >= 64 || y2 < 0) return;
if(y1 < 0) y1 = 0;
if(y2 >= 64) y2 = 63;
uint32_t *base = gint_vram + (y1 << 2) + (x >> 5);
uint32_t *lword = base + ((y2 - y1 + 1) << 2);

View File

@ -30,24 +30,18 @@ void masks(int x1, int x2, uint32_t *masks);
@rbox Rendering box */
int bopti_clip(bopti_image_t const *img, struct rbox *rbox);
/* bopti_render(): Render a bopti image
Copies an image into the VRAM. This function does not perform clipping;
use bopti_clip() on the rbox before calling it if needed.
/* bopti_render_noclip(): Render a bopti image without clipping
This function is only ever slightly faster than bopti_render_clip(),
eliminating two types of coordinate checks:
1. The bounding box does not overflow from the image
2. The final rendering does not overflow from the screen
@img Image encoded by [fxconv]
@rbox Rendering box (may or may not be clipped)
@v1 @v2 VRAMs (gray rendering is used if v2 != NULL) */
void bopti_render(bopti_image_t const *img, struct rbox *rbox, uint32_t *v1,
uint32_t *v2);
/* bopti_render_scsp(): Single-column single-position image renderer
This function is a specialized version of bopti_render() that can be used
when only a single column of the source image is used (all pixels to be
rendered are in a single 32-aligned 32-wide pixel column of the source) and
a single position of the VRAM is used (all pixels to be rendered end up in a
single 32-aligned 32-wide pixel column of the VRAM). */
void bopti_render_scsp(bopti_image_t const *img, struct rbox *rbox,
uint32_t *v1, uint32_t *v2);
@x @y Location of the top-left corner
@img Image encoded by [fxconv]
@left @top @w @h Bounding box to render
@v1 @v2 VRAMs (gray rendering is used if v2 != NULL) */
void bopti_render_noclip(bopti_image_t const *img, struct rbox *rbox,
uint32_t *v1, uint32_t *v2);
//---
// Alternate rendering modes

View File

@ -133,7 +133,7 @@ void topti_render(int x, int y, char const *str_char, font_t const *f,
free = topti_split(data+index, width, height, free, operators);
/* Potential space after the glyph */
int space = (*str != 0) ? f->char_spacing : 0;
int space = (*str != 0);
free -= space;
if(free > 0) continue;
@ -186,10 +186,10 @@ void dtext_opt(int x, int y, int fg, int bg, int halign, int valign,
int w, h;
dsize(str, topti_font, &w, &h);
if(halign == DTEXT_RIGHT) x -= w - 1;
if(halign == DTEXT_CENTER) x -= (w >> 1);
if(valign == DTEXT_BOTTOM) y -= h - 1;
if(valign == DTEXT_MIDDLE) y -= (h >> 1);
if(halign == DTEXT_RIGHT) x -= w;
if(halign == DTEXT_CENTER) x -= ((w+1) >> 1);
if(valign == DTEXT_BOTTOM) y -= h;
if(valign == DTEXT_MIDDLE) y -= ((h+1) >> 1);
}
topti_render(x, y, str, topti_font, topti_asm_text[fg],

View File

@ -3,6 +3,10 @@
#include "../render/render.h"
/* TODO: These parameters will eventually be specified by the font */
#define CHAR_SPACING 1
#define PROP_SPACING 5
/* dfont(): Set the default font for text rendering */
font_t const *dfont(font_t const * font)
{
@ -101,34 +105,39 @@ uint32_t topti_utf8_next(uint8_t const **str_pointer)
void dsize(char const *str_char, font_t const * f, int *w, int *h)
{
uint8_t const *str = (void *)str_char;
uint32_t code_point;
if(!f) f = topti_font;
if(h) *h = f->line_height;
if(!w) return;
/* Width for monospaced fonts is easy, unfortunately we still need to
compute the length and group bytes into Unicode code points. */
compute the length of [str]. Critical applications might do the
product themselves to avoid this cost. */
if(!f->prop)
{
int length = 0;
while((code_point = topti_utf8_next(&str))) length++;
*w = (f->width + f->char_spacing) * length - f->char_spacing;
while(*str++) length++;
*w = (f->width + CHAR_SPACING) * length - CHAR_SPACING;
return;
}
/* For proportional fonts, fetch the width of each individual glyphs */
int width = 0;
uint32_t code_point;
while(1)
{
code_point = topti_utf8_next(&str);
if(!code_point) break;
if(code_point == ' ')
{
width += PROP_SPACING + CHAR_SPACING;
continue;
}
int glyph = topti_glyph_index(f, code_point);
if(glyph < 0) continue;
width += f->glyph_width[glyph] + f->char_spacing;
if(glyph >= 0) width += f->glyph_width[glyph] + CHAR_SPACING;
}
*w = width - f->char_spacing;
*w = width - CHAR_SPACING;
}

View File

@ -1,98 +0,0 @@
#include <gint/mpu/spu.h>
#include <gint/mpu/cpg.h>
#include <gint/mpu/power.h>
#include <gint/drivers.h>
#include <gint/clock.h>
#include <gint/intc.h>
#define SPU SH7305_SPU
#define DSP0 SH7305_DSP0
#define DSP1 SH7305_DSP1
#define CPG SH7305_CPG
#define POWER SH7305_POWER
static void init(void)
{
/* Block SPU interrupts from DSP0, DSP1, and their DMA */
intc_priority(INTC_SPU_DSP0, 0);
intc_priority(INTC_SPU_DSP1, 0);
/* Stop both the SPU and FSI clocks */
CPG.FSICLKCR.lword = 0x00000103;
CPG.SPUCLKCR.lword = 0x00000100;
/* Enable the FSI clock, then the SPU/SPURAM clock */
CPG.FSICLKCR.CLKSTP = 0;
CPG.SPUCLKCR.CLKSTP = 0;
/* Power the clocks through MSTPCR2 */
POWER.MSTPCR2.FSI_SPU = 0;
/* Reset the SPU */
SPU.SPUSRST.RST = 0;
sleep_us_spin(1000);
SPU.SPUSRST.RST = 1;
sleep_us_spin(1000);
/* Initially give all P memory and X memory to DSP0 */
SPU.PBANKC0 = 0x1f;
SPU.PBANKC1 = 0x00;
SPU.XBANKC0 = 0x7f;
SPU.XBANKC1 = 0x00;
/* Perform full DSP resets */
DSP0.DSPCORERST = 1;
DSP1.DSPCORERST = 1;
DSP0.DSPRST = 0;
DSP1.DSPRST = 0;
sleep_us_spin(1000);
}
int spu_zero(void)
{
return 0;
}
//---
// Hardware context
//---
typedef struct
{
uint32_t PBANKC0, PBANKC1;
uint32_t XBANKC0, XBANKC1;
} ctx_t;
GBSS static ctx_t sys_ctx, gint_ctx;
static void ctx_save(void *buf)
{
ctx_t *ctx = buf;
ctx->PBANKC0 = SPU.PBANKC0;
ctx->PBANKC1 = SPU.PBANKC1;
ctx->XBANKC0 = SPU.XBANKC0;
ctx->XBANKC1 = SPU.XBANKC1;
}
static void ctx_restore(void *buf)
{
ctx_t *ctx = buf;
SPU.PBANKC0 = ctx->PBANKC0;
SPU.PBANKC1 = ctx->PBANKC1;
SPU.XBANKC0 = ctx->XBANKC0;
SPU.XBANKC1 = ctx->XBANKC1;
}
//---
// Driver structure definition
//---
gint_driver_t drv_spu = {
.name = "SPU",
.init = init,
.sys_ctx = &sys_ctx,
.gint_ctx = &gint_ctx,
.ctx_save = ctx_save,
.ctx_restore = ctx_restore,
};
GINT_DECLARE_DRIVER(3, drv_spu);

View File

@ -10,5 +10,5 @@ void srand(unsigned int seed)
int rand(void)
{
return tinymt32_generate_uint32(&random) & 0x7fffffff;
return tinymt32_generate_uint32(&random);
}

View File

@ -5,7 +5,8 @@
#include <gint/clock.h>
#include <gint/timer.h>
static void do_sleep(uint64_t delay_us, int spin)
/* sleep_us(): Sleep for a fixed duration in microseconds */
void sleep_us(uint64_t delay_us)
{
volatile int flag = 0;
@ -13,18 +14,5 @@ static void do_sleep(uint64_t delay_us, int spin)
if(timer < 0) return;
timer_start(timer);
if(spin) timer_spinwait(timer);
else timer_wait(timer);
}
/* sleep_us(): Sleep for a fixed duration in microseconds */
void sleep_us(uint64_t delay_us)
{
do_sleep(delay_us, 0);
}
/* sleep_us_spin(): Actively sleep for a fixed duration in microseconds */
void sleep_us_spin(uint64_t delay_us)
{
do_sleep(delay_us, 1);
timer_wait(timer);
}

View File

@ -261,13 +261,13 @@ void timer_stop(int id)
}
}
/* timer_wait(): Wait for a timer to stop */
/* timer_wait() - wait until a timer is stopped */
void timer_wait(int id)
{
if(id < 3)
{
tmu_t *T = &TMU[id];
/* Sleep only if an interrupt will be there to wake us up */
/* Sleep if an interruption will wake us up */
while(*TSTR & (1 << id)) if(T->TCR.UNIE) sleep();
}
else
@ -277,21 +277,6 @@ void timer_wait(int id)
}
}
/* timer_spinwait(): Actively wait for a timer to raise UNF */
void timer_spinwait(int id)
{
if(id < 3)
{
tmu_t *T = &TMU[id];
while(!T->TCR.UNF) {}
}
else
{
etmu_t *T = &ETMU[id-3];
while(!T->TCR.UNF) {}
}
}
//---
// Predefined timer callbacks
//---