build system and random update

This commit is contained in:
Lephe 2020-02-17 18:06:38 +01:00
parent 67a44abedb
commit 9a3fb12c73
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
21 changed files with 850 additions and 158 deletions

154
Makefile
View File

@ -10,41 +10,70 @@
include project.cfg
# Compiler flags
cf := -mb -ffreestanding -nostdlib -Wall -Wextra \
-fstrict-volatile-bitfields $(CFLAGS)
cf-fx := $(cf) -m3 -DFX9860G
cf-cg := $(cf) -m4-nofpu -DFXCG50
CFLAGSFX := $(CFLAGS) $(CFLAGS_FX) $(INCLUDE)
CFLAGSCG := $(CFLAGS) $(CFLAGS_CG) $(INCLUDE)
# Linker flags
lf-fx := $(LDFLAGS) -Tfx9860g.ld -lgint-fx -lgcc -Wl,-Map=build-fx/map
lf-cg := $(LDFLAGS) -Tfxcg50.ld -lgint-cg -lgcc -Wl,-Map=build-cg/map
LDFLAGSFX := $(LDFLAGS) $(LDFLAGS_FX)
LDFLAGSCG := $(LDFLAGS) $(LDFLAGS_CG)
dflags = -MMD -MT $@ -MF $(@:.o=.d) -MP
cpflags := -R .bss -R .gint_bss
# Dependency list generation flags
depflags = -MMD -MT $@ -MF $(@:.o=.d) -MP
# ELF to binary flags
BINFLAGS := -R .bss -R .gint_bss
g1af := -i "$(ICON_FX)" -n "$(NAME)" --internal="$(INTERNAL)"
g3af := -n basic:"" -i uns:"$(ICON_CG_UNS)" -i sel:"$(ICON_CG_SEL)"
# G1A and G3A generation flags
NAME_G1A ?= $(NAME)
NAME_G3A ?= $(NAME)
G1AF := -i "$(ICON_FX)" -n "$(NAME_G1A)" --internal="$(INTERNAL)"
G3AF := -n basic:"$(NAME_G3A)" -i uns:"$(ICON_CG_UNS)" -i sel:"$(ICON_CG_SEL)"
ifeq "$(TOOLCHAIN_FX)" ""
TOOLCHAIN_FX := sh3eb-elf
endif
ifeq "$(TOOLCHAIN_CG)" ""
TOOLCHAIN_CG := sh4eb-elf
endif
# fxconv flags
FXCONVFX := --fx --toolchain=$(TOOLCHAIN_FX)
FXCONVCG := --cg --toolchain=$(TOOLCHAIN_CG)
#
# File listings
#
null :=
filename := $(subst $(null) $(null),-,$(NAME))
NULL :=
TARGET := $(subst $(NULL) $(NULL),-,$(NAME))
elf = $(dir $<)$(filename).elf
bin = $(dir $<)$(filename).bin
target-fx := $(filename).g1a
target-cg := $(filename).g3a
ifeq "$(TARGET_FX)" ""
TARGET_FX := $(TARGET).g1a
endif
ifeq "$(TARGET_CG)" ""
TARGET_CG := $(TARGET).g3a
endif
ELF_FX := build-fx/$(shell basename -s .g1a $(TARGET_FX)).elf
BIN_FX := $(ELF_FX:.elf=.bin)
ELF_CG := build-cg/$(shell basename -s .g3a $(TARGET_CG)).elf
BIN_CG := $(ELF_CG:.elf=.bin)
# Source files
src := $(wildcard src/*.c src/*/*.c src/*/*/*.c src/*/*/*/*.c)
src := $(wildcard src/*.[csS] \
src/*/*.[csS] \
src/*/*/*.[csS] \
src/*/*/*/*.[csS])
assets-fx := $(wildcard assets-fx/*/*)
assets-cg := $(wildcard assets-cg/*/*)
# Object files
obj-fx := $(src:%.c=build-fx/%.o) $(assets-fx:assets-fx/%=build-fx/assets/%.o)
obj-cg := $(src:%.c=build-cg/%.o) $(assets-cg:assets-cg/%=build-cg/assets/%.o)
obj-fx := $(src:%=build-fx/%.o) \
$(assets-fx:assets-fx/%=build-fx/assets/%.o)
obj-cg := $(src:%=build-cg/%.o) \
$(assets-cg:assets-cg/%=build-cg/assets/%.o)
# Additional dependencies
deps-fx := $(ICON_FX)
@ -65,46 +94,68 @@ endif
all: $(all)
all-fx: $(target-fx)
all-cg: $(target-cg)
all-fx: $(TARGET_FX)
all-cg: $(TARGET_CG)
$(target-fx): $(obj-fx) $(deps-fx)
$(TARGET_FX): $(obj-fx) $(deps-fx)
@ mkdir -p $(dir $@)
$(TOOLCHAIN_FX)-gcc -o $(ELF_FX) $(obj-fx) $(CFLAGSFX) $(LDFLAGSFX)
$(TOOLCHAIN_FX)-objcopy -O binary $(BINFLAGS) $(ELF_FX) $(BIN_FX)
fxg1a $(BIN_FX) -o $@ $(G1AF)
sh3eb-elf-gcc -o $(elf) $(obj-fx) $(cf-fx) $(lf-fx)
sh3eb-elf-objcopy -O binary $(cpflags) $(elf) $(bin)
fxg1a $(bin) -o $@ $(g1af)
$(target-cg): $(obj-cg) $(deps-cg)
sh4eb-elf-gcc -o $(elf) $(obj-cg) $(cf-cg) $(lf-cg)
sh4eb-elf-objcopy -O binary $(cpflags) $(elf) $(bin)
mkg3a $(g3af) $(bin) $@
$(TARGET_CG): $(obj-cg) $(deps-cg)
@ mkdir -p $(dir $@)
$(TOOLCHAIN_CG)-gcc -o $(ELF_CG) $(obj-cg) $(CFLAGSCG) $(LDFLAGSCG)
$(TOOLCHAIN_CG)-objcopy -O binary $(BINFLAGS) $(ELF_CG) $(BIN_CG)
mkg3a $(G3AF) $(BIN_CG) $@
# C sources
build-fx/%.o: %.c
build-fx/%.c.o: %.c
@ mkdir -p $(dir $@)
sh3eb-elf-gcc -c $< -o $@ $(cf-fx) $(dflags)
build-cg/%.o: %.c
$(TOOLCHAIN_FX)-gcc -c $< -o $@ $(CFLAGSFX) $(depflags)
build-cg/%.c.o: %.c
@ mkdir -p $(dir $@)
sh4eb-elf-gcc -c $< -o $@ $(cf-cg) $(dflags)
$(TOOLCHAIN_CG)-gcc -c $< -o $@ $(CFLAGSCG) $(depflags)
# Assembler sources
build-fx/%.s.o: %.s
@ mkdir -p $(dir $@)
$(TOOLCHAIN_FX)-gcc -c $< -o $@
build-cg/%.s.o: %.s
@ mkdir -p $(dir $@)
$(TOOLCHAIN_CG)-gcc -c $< -o $@
# Preprocessed assembler sources
build-fx/%.S.o: %.S
@ mkdir -p $(dir $@)
$(TOOLCHAIN_FX)-gcc -c $< -o $@ $(INCLUDE)
build-cg/%.S.o: %.S
@ mkdir -p $(dir $@)
$(TOOLCHAIN_CG)-gcc -c $< -o $@ $(INCLUDE)
# Images
build-fx/assets/img/%.o: assets-fx/img/%
@ mkdir -p $(dir $@)
fxconv -i $< -o $@ --fx name:img_$(basename $*)
fxconv -i $< -o $@ $(FXCONVFX) name:img_$(basename $*) $(IMG.$*)
build-cg/assets/img/%.o: assets-cg/img/%
@ mkdir -p $(dir $@)
fxconv -i $< -o $@ --cg name:img_$(basename $*)
fxconv -i $< -o $@ $(FXCONVCG) name:img_$(basename $*) $(IMG.$*)
# Fonts
build-fx/assets/fonts/%.o: assets-fx/fonts/%
@ mkdir -p $(dir $@)
fxconv -f $< -o $@ name:font_$(basename $*) $(FONT.$*)
fxconv -f $< -o $@ $(FXCONVFX) name:font_$(basename $*) $(FONT.$*)
build-cg/assets/fonts/%.o: assets-cg/fonts/%
@ mkdir -p $(dir $@)
fxconv -f $< -o $@ name:font_$(basename $*) $(FONT.$*)
fxconv -f $< -o $@ $(FXCONVCG) name:font_$(basename $*) $(FONT.$*)
# Binaries
build-fx/assets/bin/%.o: assets-fx/bin/%
@ mkdir -p $(dir $@)
fxconv -b $< -o $@ $(FXCONVFX) name:bin_$(basename $*) $(BIN.$*)
build-cg/assets/bin/%.o: assets-cg/bin/%
@ mkdir -p $(dir $@)
fxconv -b $< -o $@ $(FXCONVCG) name:bin_$(basename $*) $(BIN.$*)
#
# Cleaning and utilities
@ -116,14 +167,23 @@ build-fx/%.d: ;
build-cg/%.d: ;
.PRECIOUS: build-fx build-cg build-fx/%.d build-cg/%.d %/
clean:
@ rm -rf build*
distclean: clean
@ rm -f $(target-fx) $(target-cg)
clean-fx:
@ rm -rf build-fx/
clean-cg:
@ rm -rf build-cg/
install-fx: $(target-fx)
distclean-fx: clean-fx
@ rm -f $(TARGET_FX)
distclean-cg: clean-cg
@ rm -f $(TARGET_CG)
clean: clean-fx clean-cg
distclean: distclean-fx distclean-cg
install-fx: $(TARGET_FX)
p7 send -f $<
install-cg: $(target-cg)
install-cg: $(TARGET_CG)
@ while [[ ! -h /dev/Prizm1 ]]; do sleep 0.25; done
@ while ! mount /dev/Prizm1; do sleep 0.25; done
@ rm -f /mnt/prizm/$<

BIN
assets-cg/swift-half.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

BIN
assets-cg/swift.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 KiB

BIN
assets-cg/swords2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

BIN
assets-fx/img/opt_dump.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -8,12 +8,25 @@
/* gintctl_gint_hardware(): Detected hardware configuration */
void gintctl_gint_hardware(void);
/* gintctl_gint_ram(): Determine the size of some memory areas */
void gintctl_gint_ram(void);
/* gintctl_gint_dump(): Dump memory to filesystem */
void gintctl_gint_dump(void);
/* gintctl_gint_timer(): Show the timer status in real-time */
void gintctl_gint_timer(void);
/* gintctl_gint_bopti(): Test image rendering */
void gintctl_gint_bopti(void);
#ifdef FXCG50
/* gintctl_gint_dma(): Test the Direct Access Memory Controller */
void gintctl_gint_dma(void);
#endif
#ifdef FX9860G
/* gintctl_gint_gray(): Gray engine tuning */
@ -24,4 +37,7 @@ void gintctl_gint_grayrender(void);
#endif /* FX9860G */
/* gintctl_gint_printf(): printf() function */
void gintctl_gint_printf(void);
#endif /* GINTCTL_GINT */

View File

@ -11,12 +11,7 @@
enum {
PROFCTX_BASICS = 0,
PROFCTX_EMPTY,
PROFCTX_DCLEAR,
PROFCTX_DUPDATE,
PROFCTX_DRECT1,
PROFCTX_DRECT2,
PROFCTX_DRECT3,
PROFCTX_RENDER,
/* Last element and bound checker */
PROFCTX_COUNT,

View File

@ -3,9 +3,19 @@
#---
# Project name, should be at most 8 bytes long.
NAME = gintctl
# (You can also specify NAME_G1A or NAME_G3A to override individually.)
NAME := gintctl
NAME_G3A :=
# Internal name, should be '@' followed by at most 7 uppercase letters.
INTERNAL = @GINTCTL
# WARNING: If this convention is not followed, the add-in might not appear in
# the main menu of the calculator!
INTERNAL := @GINTCTL
# Output file name. The default is to take <NAME>, replace spaces with dashes,
# and add .g1a (or .g3a). You can specify a different folder if you want.
TARGET_FX :=
TARGET_CG :=
# fx-9860G icon location
ICON_FX = assets-fx/icon.png
@ -13,10 +23,63 @@ ICON_FX = assets-fx/icon.png
ICON_CG_UNS = assets-cg/icon-uns.png
ICON_CG_SEL = assets-cg/icon-sel.png
# Additional compiler flags
CFLAGS = -std=c11 -Os -I include
# Additional linker flags
LDFLAGS = -lprof
#---
# Toolchain selection
#---
# Toolchain for fx9860g. Please see also CFLAGS_FX below.
TOOLCHAIN_FX := sh-elf
# Toolchain for fxcg50. Please see also CFLAGS_CG below.
TOOLCHAIN_CG := sh-elf
#---
# Compiler flags
#---
# Base compiler flags for the fxSDK, you usually want to keep these.
CFLAGS := -mb -ffreestanding -nostdlib -fstrict-volatile-bitfields
# Platform-specific compiler flags.
# <> If you are using sh3eb-elf, use -m3. (You can do this on both FX and CG.)
# <> If you are using sh4eb-elf, use -m4-nofpu. (Not ideal on FX but works.)
# <> If you are using sh4eb-nofpu-elf, then your compiler will likely use the
# FPU and cause problems on the calculator. Consider another configuration.
# <> If you are using an sh-elf with several targets, specify whichever you
# support. I recommend -m3 on FX and -m4-nofpu on CG.
# Please see also TOOLCHAIN_FX and TOOLCHAIN_CG above.
CFLAGS_FX := -D FX9860G -m3
CFLAGS_CG := -D FXCG50 -m4-nofpu
# Additional compiler flags, change to your own taste!
CFLAGS += -Wall -Wextra -Os
# Include paths. Add one -I option for each folder from which you want to
# be able to include files with #include<>.
INCLUDE := -I include
# Libraries. Add one -l option for each library you are using, and also
# suitable -L options if you have library files in custom folders. To use
# fxlib, add libfx.a to the project directory and use "-L . -lfx".
LIBS := -lprof
# Base linker flags for the fxSDK, you usually want to keep these.
LDFLAGS_FX := -T fx9860g.ld -lgint-fx $(LIBS) -lgint-fx -lgcc
LDFLAGS_CG := -T fxcg50.ld -lgint-cg $(LIBS) -lgint-cg -lgcc
# Additional linker flags, if you need any.
LDFLAGS :=
# Additional platform-specific linker flags.
LDFLAGS_FX += -Wl,-Map=build-fx/map
LDFLAGS_CG += -Wl,-Map=build-cg/map
#---
# File conversion parameters
#---
# Parameters for the hexadecimal font on fx9860g
FONT.hexa.png = charset:print grid.size:3x5 grid.padding:1
IMG.swift.png = profile:p4
IMG.swords.png = profile:p8

View File

@ -1,3 +1,4 @@
#define GINT_NEED_VRAM
#include <gint/display.h>
#include <gint/keyboard.h>
#include <gintctl/gint.h>
@ -17,9 +18,8 @@ void gintctl_gint_bopti(void)
while(key != KEY_EXIT)
{
dclear(C_WHITE);
bopti_render_noclip(0, 0, &img_swift, 0, 0, 396, 224);
bopti_render_clip(x, y, &img_swords, 0, 0, img_swords.width,
img_swords.height);
dimage(0, 0, &img_swift);
dimage(x, y, &img_swords);
dupdate();
key = getkey().key;

140
src/gint/dma.c Normal file
View File

@ -0,0 +1,140 @@
#include <gint/std/stdio.h>
#include <gint/dma.h>
#include <gint/mpu/dma.h>
#include <gint/display.h>
#include <gint/keyboard.h>
#include <gintctl/util.h>
#include <gintctl/gint.h>
#ifdef FXCG50
#define DMA SH7305_DMA
#define dprint(x, y, ...) dprint(x, y, C_BLACK, C_NONE, __VA_ARGS__)
void show_dma(int x, int y, int channel)
{
sh7305_dma_channel_t *addr[6] = {
&DMA.DMA0, &DMA.DMA1, &DMA.DMA2,
&DMA.DMA3, &DMA.DMA4, &DMA.DMA5,
};
sh7305_dma_channel_t *dma = addr[channel];
#ifdef FX9860G
dma->SAR = 0x12345678;
dma->DAR = 0x9abcdef0;
dma->TCR = 0x12481248;
int dx=60, dy=8;
dprint(x, y, "DMA%d:", channel);
dprint(x, y+1*dy, "%08X", (uint32_t)dma);
dprint(x+dx, y+1*dy, "%08X", dma->DAR);
dprint(x, y+2*dy, "%08X", dma->TCR);
dprint(x+dx, y+2*dy, "%08X", dma->CHCR);
#endif
#ifdef FXCG50
int dx=45, dy=14;
dprint(x, y, "DMA%d:", channel);
dprint(x, y+1*dy, "SAR");
dprint(x+dx, y+1*dy, "%08X", dma->SAR);
dprint(x, y+2*dy, "DAR");
dprint(x+dx, y+2*dy, "%08X", dma->DAR);
dprint(x, y+3*dy, "TCR");
dprint(x+dx, y+3*dy, "%08X", dma->TCR);
dprint(x, y+4*dy, "CHCR");
dprint(x+dx, y+4*dy, "%08X", dma->CHCR);
#endif
}
/* gintctl_gint_dma(): Test the Direct Access Memory Controller */
void gintctl_gint_dma(void)
{
/* Here we'll display the DMA status at "full speed", only limited by
the dupdate() time. */
int key = 0, timeout = 1;
/* Test channel, interrupts, and source */
int channel = 0, interrupts = 0, source = 0;
/* Number of successful attempts */
int successes = 0;
#ifdef FX9860G
/* Currently visible channel */
int view = 0;
#endif
while(key != KEY_EXIT)
{
dclear(C_WHITE);
#ifdef FX9860G
show_dma(1, 1, view);
dprint(1, 32, "Channel %d", channel);
dprint(1, 40, "Interrupts %s", interrupts ? "Yes" : "No");
dprint(1, 48, "Source %s", source ? "IL" : "RAM");
dprint(103, 40, "%d", successes);
extern image_t img_opt_gint_dma;
dimage(0, 56, &img_opt_gint_dma);
#endif
#ifdef FXCG50
row_title("Direct Memory Access status");
show_dma(6, 24, 0);
show_dma(138, 24, 1);
show_dma(270, 24, 2);
dprint(6, 102, "DMAOR: %08X", DMA.OR);
dprint(6, 130, "Channel");
dprint(96, 130, "%d", channel);
dprint(6, 144, "Interrupt");
dprint(96, 144, "%s", interrupts ? "Yes" : "No");
dprint(6, 158, "Source");
dprint(96, 158, "%s", source ? "IL" : "RAM");
fkey_button(1, "RUN");
fkey_action(4, "CHANNEL");
fkey_action(5, "INT");
fkey_action(6, "SOURCE");
#endif
dupdate();
key = getkey_opt(GETKEY_DEFAULT, &timeout).key;
/* On F1, start a DMA transfer and see what happens */
if(key == KEY_F1)
{
void *src = (void *)(source ? 0xe5200000 : 0x88000000);
void *dst = gint_vram;
int blocks = 256;
if(interrupts)
{
dma_transfer(channel, DMA_4B, blocks,
src, DMA_INC, dst, DMA_INC);
dma_transfer_wait(channel);
}
else dma_transfer_noint(channel, DMA_4B, blocks,
src, DMA_INC, dst, DMA_INC);
successes++;
}
#ifdef FX9860G
/* On F2, switch the visible channel */
if(key == KEY_F2) view = (view + 1) % 6;
#endif
/* On F4, F5 and F6, change parameters */
if(key == KEY_F4) channel = (channel + 1) % 6;
if(key == KEY_F5) interrupts = !interrupts;
if(key == KEY_F6) source = !source;
}
}
#endif /* FXCG50 */

112
src/gint/dump.c Normal file
View File

@ -0,0 +1,112 @@
#include <gint/display.h>
#include <gint/keyboard.h>
#include <gint/bfile.h>
#include <gint/std/stdio.h>
#include <gintctl/util.h>
#include <gintctl/gint.h>
struct region {
char const *name;
uint32_t start;
uint32_t end;
};
static struct region const regs[] = {
{ "ROM", 0x80000000, 0x807fffff },
{ "RAM", 0x88000000, 0x88040000 },
{ "RS", 0xfd800000, 0xfd8007ff },
};
static void filename(char *out, int region_id, int rom_segment)
{
if(region_id == 0)
{
sprintf(out, "ROM-%d.bin", rom_segment);
}
else
{
sprintf(out, "%s.bin", regs[region_id].name);
}
}
#ifdef FX9860G
static void dump(int region_id, int rom_segment)
{
uint32_t start = regs[region_id].start;
int size = regs[region_id].end + 1 - start;
if(region_id == 0)
{
start += rom_segment << 20;
size = 1 << 20;
}
/* Make sure the size is *even* */
size &= ~1;
uint16_t file[30];
char file_u8[30] = "\\\\fls0\\";
filename(file_u8 + 7, region_id, rom_segment);
for(int i = 0; i < 30; i++) file[i] = file_u8[i];
BFile_Remove(file);
BFile_Create(file, BFile_File, &size);
int fd = BFile_Open(file, BFile_WriteOnly);
BFile_Write(fd, (void *)start, size);
BFile_Close(fd);
}
#endif
/* gintctl_gint_dump(): Dump memory to filesystem */
void gintctl_gint_dump(void)
{
int region_id=0, rom_segment=0;
char output_file[20];
int key = 0;
while(key != KEY_EXIT)
{
filename(output_file, region_id, rom_segment);
dclear(C_WHITE);
#ifdef FX9860G
row_print(1, 1, "Memory dump");
row_print(3, 1, "Region: %s", regs[region_id].name);
if(region_id == 0)
row_print(4, 1, "Segment: %d", rom_segment);
row_print(5, 1, "File: %s", output_file);
extern image_t img_opt_dump;
dimage(0, 56, &img_opt_dump);
#endif
#ifdef FXCG50
row_title("Memory dump to filesystem");
fkey_button(1, "ROM");
fkey_button(2, "RAM");
fkey_button(3, "RS");
// fkey_action(6, "DUMP");
#endif
dupdate();
key = getkey().key;
if(key == KEY_F1)
{
if(region_id == 0) rom_segment = (rom_segment + 1) % 8;
region_id = 0;
}
if(key == KEY_F2) region_id = 1;
if(key == KEY_F3) region_id = 2;
#ifdef FX9860G
if(key == KEY_F6) dump(region_id, rom_segment);
#endif
}
}

View File

@ -84,12 +84,14 @@ static void hw_cpg(int *row)
/* Direct Memory Access Controller */
static void hw_dma(int *row)
{
#ifdef FXCG50
int dma = gint[HWDMA];
put("Direct Memory Access" _(," Controller:"));
load_barrier(dma);
put(" (loaded)");
#endif
}
/* Timer Unit */
@ -197,8 +199,10 @@ static int display_data(int offset)
hw_cpg(row);
put("");
#ifdef FXCG50
hw_dma(row);
put("");
#endif
hw_tmu(row);
hw_etmu(row);

120
src/gint/printf.c Normal file
View File

@ -0,0 +1,120 @@
#include <gint/std/stdio.h>
#include <gint/std/string.h>
#include <gint/display.h>
#include <gint/keyboard.h>
#include <stdarg.h>
#include <gintctl/gint.h>
#include <gintctl/util.h>
static int passed = 0;
static int total = 0;
static struct {
char const *format;
char const *expected;
} fails[10];
static void check(char const *expected, char const *format, ...)
{
va_list args;
va_start(args, format);
char buffer[128];
vsnprintf(buffer, 128, format, args);
va_end(args);
total++;
if(!strcmp(buffer, expected))
{
passed++;
}
else if(total - passed <= 10)
{
fails[total - passed - 1].format = format;
fails[total - passed - 1].expected = expected;
}
}
static void check_all(void)
{
passed = 0;
total = 0;
/* Base cases with length and precision */
check("-849", "%d", -849);
check(" 78372", "%7i", 78372);
check("65536", "%3d", 65536);
check(" 0017", "%6.4d", 17);
check(" -1876", "%6.3d", -1876);
/* Sign */
check("+15", "%+i", 15);
check(" 78372", "% 7i", 78372);
check(" 65536", "% d", 65536);
/* Alignment */
check("0017 ", "%-6.4d", 17);
check("+0017 ", "%-+6.4i", 17);
/* Bases */
check("3255", "%d", 0xcb7);
check("cb7", "%x", 0xcb7);
check("CB7", "%X", 0xcb7);
check("6267", "%o", 0xcb7);
/* Argument size */
check("10000000000", "%lld", 10000000000ll);
check("123456789ab", "%llx", 0x123456789abull);
/* Alternative prefixes */
check("0x7b", "%#x", 0x7b);
check("0X7B", "%#X", 0x7b);
check("0377", "%#o", 255);
/* Pointers */
check("0xa44b0000", "%p", (void *)0xa44b0000);
/* Characters and strings */
check("HellWrld!", "%s", "HellWrld!");
check("Hello ", "%-8.5s", "Hello, World!");
check("d", "%c", 100);
check(" #", "%6c", '#');
}
/* gintctl_gint_printf(): printf() function */
void gintctl_gint_printf(void)
{
int key = 0;
while(key != KEY_EXIT)
{
dclear(C_WHITE);
#ifdef FX9860G
row_print(1, 1, "printf() tests");
row_print(3, 1, "passed: %d/%d", passed, total);
#endif
#ifdef FXCG50
row_title("Unit tests for the printf() family");
row_print(1, 1, "Passed: %d/%d", passed, total);
for(int i = 0; i < 10 && i <= total - passed - 1; i++)
{
int y = 22 + 14 * (i + 2);
dtext(6, y, fails[i].format, C_BLACK, C_NONE);
dtext(86, y, fails[i].expected, C_BLACK, C_NONE);
}
fkey_button(1, "RUN");
#endif
dupdate();
key = getkey().key;
if(key == KEY_F1) check_all();
}
}

128
src/gint/ram.c Normal file
View File

@ -0,0 +1,128 @@
#include <gint/std/stdio.h>
#include <gint/display.h>
#include <gint/keyboard.h>
#include <gintctl/util.h>
#include <gintctl/gint.h>
static int writable(uint8_t volatile *mem)
{
int save = *mem;
*mem = save ^ 0xff;
/* Read the written value and restore the pointed byte */
int measured = *mem;
*mem = save;
/* The address is writable iff we succeeded in storing ~save */
return (measured == (save ^ 0xff));
}
static int same_location(uint8_t volatile *m1, uint8_t volatile *m2)
{
uint8_t s1=*m1, s2=*m2;
*m1 = s1 ^ 0xf0;
int equal1 = (*m2 == *m1);
*m1 = s1 ^ 0x0f;
int equal2 = (*m2 == *m1);
*m1 = s1 ^ 0xff;
int equal3 = (*m2 == *m1);
*m1 = s1;
*m2 = s2;
return equal1 && equal2 && equal3;
}
static uint32_t region_size(uint8_t volatile *mem, int *reason)
{
uint32_t size = 0;
while(size <= 16384)
{
if(!writable(mem+size))
{
*reason = 1;
break;
}
if(size > 0 && same_location(mem, mem+size))
{
*reason = 2;
break;
}
size++;
}
return size;
}
/* gintctl_gint_ram(): Determine the size of some memory areas */
void gintctl_gint_ram(void)
{
uint8_t *ILRAM = (void *)0xe5200000;
uint8_t *XRAM = (void *)0xe5007000;
uint8_t *YRAM = (void *)0xe5017000;
uint8_t *MERAM = (void *)0xe8080000;
/* Size of these sections */
uint32_t IL=0, X=0, Y=0, ME=0;
/* Reason why the region stops (1=not writable, 2=wraps around) */
int ILr=0, Xr=0, Yr=0, MEr=0;
GUNUSED char const *reasons[] = {
"Not tested yet",
"Not writable past %d bytes",
"Wraps around after %d bytes",
};
int key = 0;
while(key != KEY_EXIT)
{
dclear(C_WHITE);
#ifdef FX9860G
row_print(1, 1, "On-chip memory");
row_print(3, 2, "ILRAM: %d bytes", IL);
row_print(4, 2, "XRAM: %d bytes", X);
row_print(5, 2, "YRAM: %d bytes", Y);
row_print(6, 2, "MERAM: %d bytes", ME);
extern image_t img_opt_gint_ram;
dimage(0, 56, &img_opt_gint_ram);
#endif
#ifdef FXCG50
row_title("On-chip memory discovery");
row_print(1, 1, "This program measures the size of on-chip");
row_print(2, 1, "memory sections by checking how far it can "
"write.");
dprint(6, 78, C_BLACK, C_NONE, "ILRAM:");
dprint(6, 92, C_BLACK, C_NONE, "XRAM:");
dprint(6, 106, C_BLACK, C_NONE, "YRAM:");
dprint(6, 120, C_BLACK, C_NONE, "MERAM:");
dprint(61, 78, C_BLACK, C_NONE, reasons[ILr], IL);
dprint(61, 92, C_BLACK, C_NONE, reasons[Xr], X);
dprint(61, 106, C_BLACK, C_NONE, reasons[Yr], Y);
dprint(61, 120, C_BLACK, C_NONE, reasons[MEr], ME);
fkey_button(1, "ILRAM");
fkey_button(2, "XRAM");
fkey_button(3, "YRAM");
fkey_button(4, "MERAM");
#endif
dupdate();
key = getkey().key;
if(key == KEY_F1) IL = region_size(ILRAM, &ILr);
if(key == KEY_F2) X = region_size(XRAM, &Xr);
if(key == KEY_F3) Y = region_size(YRAM, &Yr);
if(key == KEY_F4) ME = region_size(MERAM, &MEr);
}
}

View File

@ -35,9 +35,13 @@ struct menu menu_gint = {
_("gint tests", "gint features and driver tests"), .entries = {
{ "Hardware", gintctl_gint_hardware },
{ "Boot log", NULL },
{ "RAM discovery", gintctl_gint_ram },
{ "Memory dump", gintctl_gint_dump },
{ "Keyboard", NULL },
{ "Timers", gintctl_gint_timer },
#ifdef FXCG50
{ "DMA Control", gintctl_gint_dma },
#endif
{ "Real-time clock", NULL },
{ "Image rendering", gintctl_gint_bopti },
{ "Text rendering", NULL },
@ -45,6 +49,7 @@ struct menu menu_gint = {
{ "Gray engine", gintctl_gint_gray },
{ "Gray rendering", gintctl_gint_grayrender },
#endif
{ "printf family", gintctl_gint_printf },
{ NULL, NULL },
}};
@ -57,57 +62,6 @@ struct menu menu_perf = {
{ NULL, NULL },
}};
void exch_debug_thing(__attribute__((unused)) int code)
{
#ifdef FXCG50
uint32_t TEA = *((volatile uint32_t *)0xff00000c);
uint32_t TRA = *((volatile uint32_t *)0xff000020);
uint32_t PC;
__asm__("stc spc, %0" : "=r"(PC));
TRA = TRA >> 2;
dclear(C_WHITE);
print(6, 3, "An exception occured! (System ERROR)");
uint32_t *long_vram = (void *)vram;
for(int i = 0; i < 198 * 16; i++) long_vram[i] = ~long_vram[i];
char const *name = "";
if(code == 0x040) name = "TLB miss (nonexisting address) on read";
if(code == 0x060) name = "TLB miss (nonexisting address) on write";
if(code == 0x0e0) name = "Read address error (probably alignment)";
if(code == 0x100) name = "Write address error (probably alignment)";
if(code == 0x160) name = "Unconditional trap";
if(code == 0x180) name = "Illegal instruction";
if(code == 0x1a0) name = "Illegal delay slot instruction";
print(6, 25, "%03x %s", code, name);
print(6, 45, "PC");
print(38, 45, "= %08x", PC);
print(261, 45, "(Error location)");
print(6, 60, "TEA");
print(38, 60, "= %08x", TEA);
print(234, 60, "(Offending address)");
print(6, 75, "TRA");
print(38, 75, "= %#x", TRA);
print(281, 75, "(Trap number)");
print(6, 95, "An unrecoverable error ocurred in the add-in.");
print(6, 108, "Please press the RESET button to restart the");
print(6, 121, "calculator.");
dupdate_noint();
#endif
while(1);
}
//---
// Main application
//---

View File

@ -1,27 +1,87 @@
#include <gint/display.h>
#include <gint/keyboard.h>
#include <gint/std/stdio.h>
#include <gint/exc.h>
#include <gintctl/mem.h>
#include <gintctl/util.h>
int c(int c)
/* Code of exception that occurs during a memory access */
static uint32_t exception = 0;
/* Exception-catching function */
static int catch_exc(uint32_t code)
{
return (c >= 0x20 && c < 0x7f) ? c : '.';
if(code == 0x040 || code == 0x0e0)
{
exception = code;
gint_exc_skip(1);
return 0;
}
return 1;
}
int line(uint8_t *mem, char *header, char *bytes, char *ascii, int n)
{
/* First do a naive access to the first byte, and record possible
exceptions - TLB miss read and CPU read error.
I use a volatile asm statement so that the read can't be optimized
away by the compiler. */
exception = 0;
gint_exc_catch(catch_exc);
uint8_t z;
__asm__ volatile(
"mov.l %1, %0"
: "=r"(z)
: "m"(*mem));
gint_exc_catch(NULL);
sprintf(header, "%08X:", (uint32_t)mem);
if(exception == 0x040)
{
sprintf(bytes, "TLB error");
*ascii = 0;
return 1;
}
if(exception == 0x0e0)
{
sprintf(bytes, "Read error");
*ascii = 0;
return 1;
}
for(int k = 0; k < n; k++)
{
int c = mem[k];
ascii[k] = (c >= 0x20 && c < 0x7f) ? c : '.';
}
ascii[n] = 0;
for(int k = 0; 2 * k < n; k++)
{
sprintf(bytes + 5 * k, "%02X%02X ", mem[2*k], mem[2*k+1]);
}
return 0;
}
/* gintctl_mem(): Memory browser */
void gintctl_mem(void)
{
uint32_t base = 0x88010758;
int key = 0, ascii = 0;
uint32_t base = 0x88000000;
int key = 0;
#ifdef FX9860G
extern font_t font_hexa;
font_t const *old_font = dfont(&font_hexa);
int view_ascii = 0;
#endif
char header[12];
char bytes[24];
char bytes[48];
char ascii[24];
int size = 8;
int lines = _(9,14);
while(key != KEY_EXIT)
{
@ -30,48 +90,67 @@ void gintctl_mem(void)
uint32_t addr = base;
uint8_t *mem = (void *)addr;
for(int i = 0; i <= 8; i++)
for(int i = 0; i < lines; i++)
{
if(!ascii)
int status = line(mem, header, bytes, ascii, size);
#ifdef FX9860G
dtext( 5, 6*i + 1, view_ascii ? ascii : header,
C_BLACK, C_NONE);
dtext(45, 6*i + 1, bytes, C_BLACK, C_NONE);
#endif
#ifdef FXCG50
dtext(25, 26 + 12*i, header, C_BLACK, C_NONE);
dtext(110, 26 + 12*i, bytes, status ? C_RED : C_BLACK,
C_NONE);
for(int k = size - 1; k >= 0; k--)
{
sprintf(header, "%08X:", addr);
}
else
{
for(int k = 0; k < 8; k++)
header[k] = c(mem[k]);
header[8] = 0;
ascii[k+1] = 0;
dtext(275 + 9*k, 26 + 12*i, ascii + k, C_BLACK,
C_NONE);
}
#endif
sprintf(bytes, "%02X%02X %02X%02X %02X%02X %02X%02X",
mem[0], mem[1], mem[2], mem[3],
mem[4], mem[5], mem[6], mem[7]
);
dtext( 5, 6 * i + 1, header, C_BLACK, C_NONE);
dtext(45, 6 * i + 1, bytes, C_BLACK, C_NONE);
mem += 8;
addr += 8;
mem += size;
addr += size;
}
#ifdef FX9860G
extern image_t img_opt_mem;
dsubimage(0, 56, &img_opt_mem, 0, 0, 128, 8, DIMAGE_NONE);
if(ascii)
{
dsubimage(107, 56, &img_opt_mem, 107, 9, 21, 8, DIMAGE_NONE);
}
if(view_ascii) dsubimage(23, 56, &img_opt_mem, 23, 9, 21, 8,
DIMAGE_NONE);
#endif
#ifdef FXCG50
row_title("Memory browser");
fkey_button(1, "JUMP");
fkey_action(3, "ROM");
fkey_action(4, "RAM");
fkey_action(5, "ILRAM");
fkey_action(6, "ADDIN");
#endif
dupdate();
key = getkey().key;
if(key == KEY_UP) base -= 72;
if(key == KEY_DOWN) base += 72;
if(key == KEY_UP) base -= size * lines;
if(key == KEY_DOWN) base += size * lines;
if(key == KEY_F6) ascii = !ascii;
#ifdef FX9860G
if(key == KEY_F2) view_ascii = !view_ascii;
#endif
if(key == KEY_F3) base = 0x80000000;
if(key == KEY_F4) base = 0x88000000;
if(key == KEY_F5) base = 0xe5200000;
if(key == KEY_F6) base = 0x00300000;
}
#ifdef FX9860G
dfont(old_font);
#endif
}

View File

@ -12,34 +12,43 @@ struct elapsed {
uint32_t clear;
uint32_t update;
uint32_t rect1, rect2, rect3;
uint32_t fs_r5g6b5;
};
static void run_test(struct elapsed *time)
{
#define test(ctx, out, command) { \
prof_clear(ctx); \
prof_enter(ctx); \
#define test(out, command) { \
prof_clear(PROFCTX_RENDER); \
prof_enter(PROFCTX_RENDER); \
command; \
prof_leave(ctx); \
out = prof_time(ctx); \
prof_leave(PROFCTX_RENDER); \
out = prof_time(PROFCTX_RENDER); \
}
test(PROFCTX_DUPDATE, time->update,
extern image_t img_swift;
test(time->update,
dupdate()
);
test(PROFCTX_DCLEAR, time->clear,
test(time->clear,
dclear(C_WHITE)
);
test(PROFCTX_DRECT1, time->rect1,
test(time->rect1,
drect(0, 0, 31, 31, C_WHITE)
);
test(PROFCTX_DRECT2, time->rect2,
test(time->rect2,
drect(1, 1, 32, 32, C_WHITE)
);
test(PROFCTX_DRECT3, time->rect3,
test(time->rect3,
drect(0, 0, _(127,395), _(63,223), C_WHITE)
);
#ifdef FXCG50
test(time->fs_r5g6b5,
dimage(0, 0, &img_swift)
);
#endif
#undef test
}
@ -102,6 +111,9 @@ void gintctl_perf_render(void)
print(314, 90, "rect3:");
print(314, 105, "%s", printtime(time.rect3));
print(6, 130, "fullscreen img:");
print(6, 145, "%s", printtime(time.fs_r5g6b5));
}
fkey_button(1, "START");

View File

@ -40,4 +40,14 @@ void gintctl_regs(void)
dupdate();
getkey();
dclear(C_WHITE);
row_title("Register browser");
row_print(2, 1, "RAMCR: %08x", *(uint32_t *)0xff000074);
row_print(3, 1, "SAR0: %08x", *(uint32_t *)0xfe008020);
row_print(4, 1, "CHCR0: %08x", *(uint32_t *)0xfe00802c);
dupdate();
getkey();
}

View File

@ -1,4 +1,3 @@
#define GINT_NEED_VRAM
#include <gint/display.h>
#include <gint/std/stdio.h>
@ -46,7 +45,7 @@ void row_title(char const *format, ...)
#ifdef FXCG50
dtext(ROW_X, 3, str, C_BLACK, C_NONE);
uint32_t *long_vram = (void *)vram;
uint32_t *long_vram = (void *)gint_vram;
for(int i = 0; i < 198 * 16; i++) long_vram[i] = ~long_vram[i];
#endif
}
@ -74,7 +73,7 @@ void row_highlight(int row)
#endif
#ifdef FXCG50
uint32_t *long_vram = (void *)vram;
uint32_t *long_vram = (void *)gint_vram;
for(int i = 198 * y1; i < 198 * y2; i++) long_vram[i] = ~long_vram[i];
#endif
}