mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2024-12-28 04:23:36 +01:00
Major bopti update (one of the last, I hope). Added comparison with ML as fifth application (hidden).
This commit is contained in:
parent
d122624c56
commit
34dd27d7a3
34 changed files with 808 additions and 343 deletions
160
Makefile
160
Makefile
|
@ -1,11 +1,161 @@
|
|||
## Temporary things there
|
||||
#! /usr/bin/make -f
|
||||
#---
|
||||
#
|
||||
# gint project Makefile.
|
||||
#
|
||||
#---
|
||||
|
||||
|
||||
|
||||
#---
|
||||
# Project variables.
|
||||
#---
|
||||
|
||||
# Modules
|
||||
modules-gint = bopti core display gray keyboard mpu screen tales timer
|
||||
modules-libc = setjmp string
|
||||
|
||||
# Targets
|
||||
target-g1a = gintdemo.g1a
|
||||
target-lib = libgint.a
|
||||
target-std = libc.a
|
||||
|
||||
# Tools
|
||||
cc = sh3eb-elf-gcc
|
||||
as = sh3eb-elf-as
|
||||
ar = sh3eb-elf-ar
|
||||
ob = sh3eb-elf-objcopy
|
||||
wr = g1a-wrapper
|
||||
|
||||
# Flags
|
||||
cflags = -m3 -mb -nostdlib -I include -ffreestanding -std=c11
|
||||
|
||||
# Demo application (could be done better)
|
||||
demo-src = $(notdir $(wildcard demo/*.[cs]))
|
||||
demo-ld = demo/gintdemo.ld
|
||||
demo-icon = demo/icon.bmp
|
||||
demo-res = $(notdir $(wildcard demo/resources/*))
|
||||
demo-obj = $(patsubst %,build/demo_%.o,$(demo-src) $(demo-res))
|
||||
demo-elf = build/gintdemo.elf
|
||||
demo-bin = build/gintdemo.bin
|
||||
demo-libs = -lgcc -L. -lgint -lc
|
||||
|
||||
|
||||
|
||||
#---
|
||||
# Automatic variables.
|
||||
#---
|
||||
|
||||
# Modules are subfolders of src/.
|
||||
modules = $(modules-gint) $(modules-libc)
|
||||
|
||||
define n
|
||||
# This is a newline character.
|
||||
|
||||
endef
|
||||
|
||||
# Module-scope variables.
|
||||
$(foreach mod, $(modules), $(eval \
|
||||
mod-$(mod)-c = $(notdir $(wildcard src/$(mod)/*.c)) $n\
|
||||
mod-$(mod)-asm = $(notdir $(wildcard src/$(mod)/*.s)) $n\
|
||||
mod-$(mod)-dep = $(wildcard include/*.h src/$(mod)/*.h) $n\
|
||||
mod-$(mod)-src = $$(mod-$(mod)-c)$$(mod-$(mod)-asm) $n\
|
||||
mod-$(mod)-obj = $$(patsubst %,build/$(mod)_%.o,$$(mod-$(mod)-src)) \
|
||||
))
|
||||
|
||||
# Target-scope variables.
|
||||
obj-std = $(foreach mod,$(modules-libc),$(mod-$(mod)-obj))
|
||||
obj-lib = $(foreach mod,$(modules-gint),$(mod-$(mod)-obj))
|
||||
|
||||
|
||||
|
||||
#---
|
||||
# Rule templates.
|
||||
#---
|
||||
|
||||
# C source file template:
|
||||
# $1 module name
|
||||
# $2 file base name
|
||||
# $2 filename
|
||||
define rule-c-source
|
||||
build/$1_$2.c.o: src/$1/$2.c
|
||||
$(cc) $(cflags) -c $$< -o $$@
|
||||
build/$1_$2.o: src/$1/$2 $(mod-$1-dep)
|
||||
$(cc) -c $$< -o $$@ $(cflags) -I src/$1 -O2
|
||||
endef
|
||||
|
||||
$(eval $(call rule-c-source,display,area))
|
||||
# asm source file template:
|
||||
# $1 module name
|
||||
# $2 filename
|
||||
define rule-asm-source
|
||||
build/$1_$2.o: src/$1/$2
|
||||
$(as) -c $$< -o $$@
|
||||
endef
|
||||
|
||||
|
||||
|
||||
#---
|
||||
# Building.
|
||||
#---
|
||||
|
||||
# Generic rules
|
||||
|
||||
all: build $(target-std) $(target-lib) $(target-g1a)
|
||||
@ echo 'All done!'
|
||||
|
||||
build:
|
||||
mkdir -p $@
|
||||
|
||||
$(target-std): $(obj-std)
|
||||
$(ar) rcs $@ $^
|
||||
|
||||
$(target-lib): $(target-std) $(obj-lib)
|
||||
$(ar) rcs $@ $(obj-lib)
|
||||
|
||||
$(target-g1a): $(target-std) $(target-lib) $(demo-obj)
|
||||
$(cc) -o $(demo-elf) $(cflags) -T $(demo-ld) $(demo-obj) $(demo-libs)
|
||||
$(ob) -R .comment -R .bss -O binary $(demo-elf) $(demo-bin)
|
||||
$(wr) $(demo-bin) -o $@ -i $(demo-icon)
|
||||
|
||||
# Automated rules
|
||||
|
||||
$(foreach mod,$(modules), \
|
||||
$(foreach source,$(mod-$(mod)-c), $(eval \
|
||||
$(call rule-c-source,$(mod),$(source)))) \
|
||||
$(foreach source,$(mod-$(mod)-asm), $(eval \
|
||||
$(call rule-asm-source,$(mod),$(source)))) \
|
||||
)
|
||||
|
||||
# This one should not be optimized. It makes __attribute__((interrupt_handler))
|
||||
# buggy... maybe. Anyway there's a bug in this file.
|
||||
build/core_gint.c.o: src/core/gint.c $(mod-core-dep)
|
||||
$(cc) -c $< -o $@ $(cflags) -I src/core
|
||||
|
||||
# Demo application
|
||||
|
||||
build/demo_%.c.o: demo/%.c
|
||||
$(cc) -c $< -o $@ $(cflags)
|
||||
|
||||
build/demo_%.bmp.o: demo/resources/%.bmp
|
||||
fxconv $< -o $@ -n $(patsubst demo/resources/%.bmp,res_%,$<)
|
||||
|
||||
build/demo_font.bmp.o: demo/resources/font.bmp
|
||||
fxconv $< -o $@ --font -n res_font
|
||||
|
||||
|
||||
|
||||
#---
|
||||
# Cleaning and others.
|
||||
#---
|
||||
|
||||
clean:
|
||||
@ rm -rf build/*
|
||||
|
||||
mrproper: clean
|
||||
@ rm -f $(target-g1a) $(target-lib) $(target-std)
|
||||
@ rm -rf build
|
||||
|
||||
distclean: mrproper
|
||||
|
||||
install:
|
||||
usb-connector SEND $(target-g1a) $(target-g1a) fls0
|
||||
|
||||
|
||||
.PHONY: all clean mrproper distclean
|
||||
|
|
14
TODO
14
TODO
|
@ -12,6 +12,7 @@
|
|||
@ vram overflow
|
||||
@ keyboard test threading interface
|
||||
|
||||
+ gint vs. ML with 248x124 at (-60, -28)
|
||||
+ use alloca() for tales
|
||||
+ call exit handlers
|
||||
+ compute frequencies
|
||||
|
@ -26,6 +27,7 @@
|
|||
+ bitmap parts
|
||||
+ bitmap clipping
|
||||
|
||||
- install critical failure handler to prevent failing resets
|
||||
- write and test gray engine
|
||||
- full rtc driver (time)
|
||||
- callbacks and complete user API
|
||||
|
@ -34,3 +36,15 @@
|
|||
~ exhaustive save for setjmp()
|
||||
~ registers that need to be saved when configuring gint
|
||||
~ possible bug when -O2 __attribute__((interrupt_handler))
|
||||
|
||||
|
||||
|
||||
Some notes
|
||||
----------
|
||||
|
||||
Test cases for bitmap drawing:
|
||||
- aligned 32 / non-aligned 32
|
||||
- monochrome / gray
|
||||
- small / large
|
||||
- does not overflow / overflows
|
||||
# blending modes
|
||||
|
|
408
demo/gintdemo.c
408
demo/gintdemo.c
|
@ -10,15 +10,14 @@
|
|||
#include <stdint.h>
|
||||
#include <7305.h>
|
||||
|
||||
extern unsigned int bgint, egint;
|
||||
|
||||
//---
|
||||
// A few procedures for displaying text in the system's vram.
|
||||
// A few ugly procedures for displaying text. Will have to enhance this
|
||||
// soon -- which means printf().
|
||||
//---
|
||||
|
||||
void print(const char *str, int x, int y)
|
||||
{
|
||||
print_raw(str, x, y);
|
||||
dtext(str, x, y);
|
||||
}
|
||||
void print_hex(unsigned int n, int x, int y)
|
||||
{
|
||||
|
@ -60,6 +59,24 @@ void print_hexa(unsigned int n, int digits, int x, int y)
|
|||
ch[digits] = 0;
|
||||
print(ch, x, y);
|
||||
}
|
||||
void print_int(int n, int x, int y)
|
||||
{
|
||||
char str[20] = { 0 };
|
||||
int i, o = 0;
|
||||
int digits = 0, copy = n;
|
||||
|
||||
if(!n) { str[o++] = '0'; print(str, x, y); return; }
|
||||
if(n < 0) str[o++] = '-', n = -n;
|
||||
while(copy) digits++, copy /= 10;
|
||||
|
||||
for(i = 0; i < digits; i++)
|
||||
{
|
||||
str[o + digits - i - 1] = n % 10 + '0';
|
||||
n /= 10;
|
||||
}
|
||||
|
||||
gtext(str, x, y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -109,14 +126,16 @@ void keyboard_test(void)
|
|||
|
||||
timer_start(TIMER_USER, 1700, TIMER_Po_256, keyboard_test_timer, 0);
|
||||
|
||||
dclear();
|
||||
print("Keyboard state:", 0, 0);
|
||||
print("multi-getkey ^^", 50, 55);
|
||||
dupdate();
|
||||
|
||||
while(1)
|
||||
{
|
||||
multigetkey(keys, 4, 0);
|
||||
if(keys[0] == KEY_EXIT && keys[1] == KEY_NONE) break;
|
||||
|
||||
dclear();
|
||||
print("Keyboard state:", 0, 0);
|
||||
print("multi-getkey ^^", 50, 55);
|
||||
|
||||
#define hexa(h) ('0' + (h) + 39 * ((h) > 9))
|
||||
|
||||
|
@ -141,109 +160,73 @@ void keyboard_test(void)
|
|||
timer_stop(TIMER_USER);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
const unsigned char data[1024] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 7, 159, 0, 0, 1, 192, 0, 0, 0, 0, 0, 121, 240, 0, 0, 0,
|
||||
31, 191, 192, 0, 3, 224, 27, 216, 0, 0, 1, 251, 252, 0, 0, 0, 57, 247, 222,
|
||||
30, 7, 240, 36, 36, 62, 25, 131, 159, 24, 255, 129, 224, 0, 227, 142, 126, 1,
|
||||
192, 45, 172, 127, 127, 192, 14, 1, 255, 199, 224, 0, 227, 140, 240, 1, 192,
|
||||
26, 88, 115, 127, 224, 14, 57, 221, 207, 0, 0, 227, 13, 192, 1, 192, 34, 68,
|
||||
120, 30, 0, 14, 25, 156, 220, 0, 0, 227, 253, 252, 1, 192, 36, 36, 126, 28,
|
||||
0, 14, 219, 156, 223, 192, 0, 227, 253, 252, 1, 192, 36, 36, 31, 12, 0, 46,
|
||||
27, 140, 223, 192, 0, 227, 141, 193, 193, 192, 40, 20, 7, 140, 0, 206, 25, 140,
|
||||
220, 28, 0, 227, 140, 225, 129, 199, 24, 24, 99, 156, 1, 14, 25, 204, 206, 24,
|
||||
0, 227, 142, 127, 1, 195, 39, 228, 255, 156, 2, 14, 24, 237, 199, 240, 1, 247,
|
||||
222, 62, 1, 198, 44, 44, 223, 30, 2, 31, 28, 237, 131, 224, 1, 224, 0, 0, 3,
|
||||
254, 27, 216, 0, 0, 4, 30, 0, 0, 0, 0, 3, 192, 0, 0, 7, 252, 0, 0, 0, 0, 4,
|
||||
60, 1, 249, 240, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 4, 0, 97, 240, 56, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 224, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
4, 0, 47, 192, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 32, 255, 128, 63, 128,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 32, 255, 0, 48, 78, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 15, 176, 255, 0, 112, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 8, 56, 255, 0,
|
||||
96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 8, 60, 255, 0, 224, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 130, 56, 126, 255, 3, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 192,
|
||||
62, 255, 15, 224, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 14, 191, 255, 192, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 6, 129, 255, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 6, 0, 255, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 7, 128, 63, 192,
|
||||
1, 0, 96, 1, 224, 1, 0, 0, 0, 2, 0, 0, 7, 0, 31, 192, 0, 0, 95, 1, 11, 68, 88,
|
||||
0, 0, 4, 0, 0, 7, 128, 31, 192, 0, 1, 192, 129, 204, 85, 100, 0, 0, 8, 0, 0,
|
||||
15, 128, 63, 224, 0, 0, 95, 1, 8, 85, 68, 0, 1, 144, 0, 0, 31, 128, 143, 224,
|
||||
64, 0, 96, 1, 232, 41, 68, 0, 2, 96, 0, 31, 255, 129, 7, 248, 96, 0, 0, 0, 0,
|
||||
0, 0, 0, 4, 0, 0, 96, 254, 129, 7, 254, 96, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 128,
|
||||
254, 131, 135, 255, 224, 0, 0, 1, 192, 64, 16, 0, 8, 0, 7, 0, 254, 131, 255,
|
||||
63, 224, 0, 0, 1, 38, 113, 208, 0, 8, 0, 13, 0, 222, 147, 254, 31, 224, 0, 0,
|
||||
1, 41, 74, 80, 0, 8, 0, 25, 0, 222, 67, 254, 31, 160, 0, 0, 1, 41, 74, 80, 0,
|
||||
12, 0, 49, 0, 222, 19, 254, 62, 48, 0, 0, 1, 198, 113, 208, 0, 2, 0, 32, 128,
|
||||
222, 195, 255, 252, 56, 0, 0, 0, 0, 0, 0, 0, 2, 0, 124, 64, 220, 151, 135, 248,
|
||||
127, 0, 0, 0, 0, 0, 0, 0, 2, 0, 66, 32, 221, 223, 7, 240, 255, 0, 0, 0, 0, 0,
|
||||
0, 0, 2, 0, 129, 23, 93, 159, 15, 241, 131, 0, 0, 0, 0, 0, 0, 0, 4, 0, 128,
|
||||
136, 217, 95, 3, 226, 9, 0, 0, 1, 240, 0, 0, 0, 4, 0, 128, 72, 89, 95, 129,
|
||||
228, 18, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0, 72, 73, 127, 128, 224, 36, 0, 0, 0, 0,
|
||||
0, 0, 0, 28, 1, 0, 76, 129, 127, 192, 96, 8, 0, 0, 0, 0, 0, 0, 0, 16, 1, 0,
|
||||
231, 203, 124, 96, 64, 0, 0, 0, 0, 0, 0, 0, 0, 16, 1, 1, 28, 123, 240, 12, 64,
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 16, 1, 2, 28, 143, 128, 15, 192, 7, 0, 0, 0, 0, 0, 0,
|
||||
0, 16, 1, 4, 17, 143, 24, 15, 192, 14, 0, 0, 0, 0, 0, 0, 0, 28, 1, 4, 1, 135,
|
||||
24, 31, 192, 24, 0, 0, 0, 0, 0, 0, 0, 18, 1, 62, 1, 135, 248, 63, 224, 192,
|
||||
0, 0, 0, 0, 0, 0, 0, 35, 1, 195, 1, 135, 128, 254, 126, 1, 0, 0, 0, 0, 0, 0,
|
||||
0, 35, 193, 131, 195, 135, 255, 248, 112, 1, 0, 0, 0, 0, 0, 0, 0, 67, 241, 131,
|
||||
14, 207, 255, 192, 224, 3, 0, 0, 0, 0, 0, 0, 3, 67, 15, 143, 56, 255, 7, 1,
|
||||
224, 7, 0, 0, 0, 0, 0, 0, 28, 130, 7, 255, 112, 204, 7, 131, 224, 31, 0, 0,
|
||||
0, 0, 0, 0, 32, 134, 30, 29, 120, 156, 7, 255, 224, 127, 0, 0, 0, 0, 0, 63,
|
||||
197, 206, 60, 56, 192, 248, 15, 255, 248, 255, 0, 0, 0, 0, 0, 120, 5, 227, 248,
|
||||
56, 195, 248, 127, 191, 254, 63, 0, 0, 0, 0, 7, 254, 255, 193, 255, 15, 193,
|
||||
255, 15, 31, 252, 31 };
|
||||
*/
|
||||
|
||||
/*
|
||||
bitmap_test()
|
||||
Displays various bitmaps to ensure bopti is working correctly.
|
||||
*/
|
||||
void bitmap_test(void)
|
||||
{
|
||||
extern Image binary_resources_bitmap_opt_start;
|
||||
extern Image binary_resources_symbol_start;
|
||||
extern Image binary_resources_symbol2_start;
|
||||
extern Image binary_resources_sprites_start;
|
||||
extern Image res_bitmap_opt_start;
|
||||
extern Image res_symbol_start;
|
||||
extern Image res_symbol2_start;
|
||||
extern Image res_sprites_start;
|
||||
extern Image res_swords_start;
|
||||
|
||||
Image *opt = &binary_resources_bitmap_opt_start;
|
||||
Image *sprites = &binary_resources_sprites_start;
|
||||
Image *sybl = &binary_resources_symbol_start;
|
||||
Image *sybl2 = &binary_resources_symbol2_start;
|
||||
Image *opt = &res_bitmap_opt_start;
|
||||
Image *sybl = &res_symbol_start;
|
||||
Image *sybl2 = &res_symbol2_start;
|
||||
Image *sprites = &res_sprites_start;
|
||||
Image *swords = &res_swords_start;
|
||||
|
||||
// enum BlendingMode blend = Blend_Or;
|
||||
uint32_t a32 = 0xffffffff;
|
||||
int black_bg = 0;
|
||||
int black_bg = 0, gray = 0;
|
||||
int key;
|
||||
int x = 20, y = 10;
|
||||
|
||||
while(1)
|
||||
{
|
||||
dclear();
|
||||
if(gray)
|
||||
{
|
||||
gray_start();
|
||||
gclear();
|
||||
|
||||
if(black_bg) dreverse_area(0, 0, 127, 63);
|
||||
dimage(opt, 0, 57);
|
||||
if(black_bg) greverse_area(0, 0, 127, 63);
|
||||
gimage(opt, 0, 57);
|
||||
|
||||
dimage(sprites, 2 & a32, 2);
|
||||
dimage(sybl, 30 & a32, 40);
|
||||
dimage(sybl2, 62 & a32, 40);
|
||||
gimage(sprites, x, y);
|
||||
gimage(swords, x, y + 35);
|
||||
|
||||
dupdate();
|
||||
gupdate();
|
||||
}
|
||||
else
|
||||
{
|
||||
gray_stop();
|
||||
dclear();
|
||||
|
||||
if(black_bg) dreverse_area(0, 0, 127, 63);
|
||||
dimage(opt, 0, 57);
|
||||
|
||||
dimage(sybl, 30 & a32, 40);
|
||||
dimage(sybl2, 62 & a32, 40);
|
||||
|
||||
dupdate();
|
||||
|
||||
}
|
||||
|
||||
key = getkey();
|
||||
if(key == KEY_EXIT) break;
|
||||
|
||||
/*
|
||||
if(key == KEY_F1) blend = Blend_Or;
|
||||
if(key == KEY_F2) blend = Blend_And;
|
||||
if(key == KEY_F3) blend = Blend_Invert;
|
||||
*/
|
||||
if(key == KEY_F1) gray = !gray;
|
||||
if(key == KEY_F2) a32 ^= 31;
|
||||
if(key == KEY_F3) black_bg = !black_bg;
|
||||
|
||||
if(key == KEY_F4) black_bg = !black_bg;
|
||||
if(key == KEY_F5) a32 ^= 31;
|
||||
if(key == KEY_UP) y--;
|
||||
if(key == KEY_DOWN) y++;
|
||||
if(key == KEY_LEFT) x--;
|
||||
if(key == KEY_RIGHT) x++;
|
||||
}
|
||||
|
||||
gray_stop();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -256,10 +239,10 @@ void bitmap_test(void)
|
|||
|
||||
void text_test(void)
|
||||
{
|
||||
extern Font binary_resources_font_start;
|
||||
Font *font = &binary_resources_font_start;
|
||||
extern Font res_font_start;
|
||||
Font *font = &res_font_start;
|
||||
|
||||
print_configure(font);
|
||||
text_configure(font);
|
||||
|
||||
dclear();
|
||||
|
||||
|
@ -284,31 +267,89 @@ void text_test(void)
|
|||
|
||||
void gray_test(void)
|
||||
{
|
||||
extern Image binary_resources_illustration_start;
|
||||
Image *illustration = &binary_resources_illustration_start;
|
||||
extern Image res_illustration_start;
|
||||
Image *illustration = &res_illustration_start;
|
||||
|
||||
int light, dark;
|
||||
int key;
|
||||
int *v1, *v2;
|
||||
|
||||
gray_getDelays(&light, &dark);
|
||||
int delays[2]; // { light, dark }
|
||||
int key, changed = 1, i;
|
||||
int selected = 0;
|
||||
|
||||
gray_getDelays(delays, delays + 1);
|
||||
gray_start();
|
||||
|
||||
while(1)
|
||||
{
|
||||
gclear();
|
||||
dimage(illustration, 0, 0);
|
||||
gclear_area(64, 0, 127, 63);
|
||||
// gupdate();
|
||||
if(changed)
|
||||
{
|
||||
gray_setDelays(delays[0], delays[1]);
|
||||
gclear();
|
||||
|
||||
key = getkey();
|
||||
v1 = gray_lightVRAM();
|
||||
v2 = gray_darkVRAM();
|
||||
|
||||
for(i = 0; i < 63; i++)
|
||||
{
|
||||
v1[(i << 2)] = v1[(i << 2) + 1] =
|
||||
-((i & 31) < 16);
|
||||
v2[(i << 2)] = v2[(i << 2) + 1] =
|
||||
-(i < 32);
|
||||
}
|
||||
|
||||
// gimage(illustration, 0, 0);
|
||||
// gclear_area(64, 0, 127, 63);
|
||||
|
||||
gtext("light", 78, 6);
|
||||
print_int(delays[0], 103, 6);
|
||||
|
||||
gtext("dark", 78, 15);
|
||||
print_int(delays[1], 103, 15);
|
||||
|
||||
gtext(">", 70, selected ? 15 : 6);
|
||||
gupdate();
|
||||
}
|
||||
|
||||
changed = 0;
|
||||
|
||||
key = getkey_opt(Getkey_RepeatArrowKeys, 1);
|
||||
if(key == KEY_EXIT) break;
|
||||
/*
|
||||
if(key == KEY_F1) gray_setDelays(--light, dark);
|
||||
if(key == KEY_F2) gray_setDelays(++light, dark);
|
||||
|
||||
if(key == KEY_F5) gray_setDelays(light, --dark);
|
||||
if(key == KEY_F6) gray_setDelays(light, ++dark);
|
||||
*/
|
||||
changed = 1;
|
||||
|
||||
switch(key)
|
||||
{
|
||||
case KEY_F1:
|
||||
delays[0] = 860;
|
||||
delays[1] = 1298;
|
||||
break;
|
||||
case KEY_F2:
|
||||
delays[0] = 912;
|
||||
delays[1] = 1343;
|
||||
break;
|
||||
case KEY_F3:
|
||||
delays[0] = 993;
|
||||
delays[1] = 1609;
|
||||
break;
|
||||
case KEY_F6:
|
||||
selected = !selected;
|
||||
break;
|
||||
case KEY_UP:
|
||||
delays[selected] += 10;
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
if(delays[selected] >= 110) delays[selected] -= 10;
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
delays[selected]++;
|
||||
break;
|
||||
case KEY_LEFT:
|
||||
if(delays[selected] >= 101) delays[selected]--;
|
||||
break;
|
||||
default:
|
||||
changed = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gray_stop();
|
||||
|
@ -322,6 +363,7 @@ void gray_test(void)
|
|||
*/
|
||||
int main_menu(void)
|
||||
{
|
||||
extern unsigned int bgint, egint;
|
||||
const char *mpu_names[] = {
|
||||
"MPU_Unkown",
|
||||
"MPU_SH7337",
|
||||
|
@ -358,11 +400,158 @@ int main_menu(void)
|
|||
if(key == KEY_2) return 2;
|
||||
if(key == KEY_3) return 3;
|
||||
if(key == KEY_4) return 4;
|
||||
if(key == KEY_5) return 5;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const unsigned char screen[1024] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 7, 159, 0, 0, 1, 192, 0, 0, 0, 0, 0, 121, 240, 0, 0, 0,
|
||||
31, 191, 192, 0, 3, 224, 27, 216, 0, 0, 1, 251, 252, 0, 0, 0, 57, 247, 222,
|
||||
30, 7, 240, 36, 36, 62, 25, 131, 159, 24, 255, 129, 224, 0, 227, 142, 126, 1,
|
||||
192, 45, 172, 127, 127, 192, 14, 1, 255, 199, 224, 0, 227, 140, 240, 1, 192,
|
||||
26, 88, 115, 127, 224, 14, 57, 221, 207, 0, 0, 227, 13, 192, 1, 192, 34, 68,
|
||||
120, 30, 0, 14, 25, 156, 220, 0, 0, 227, 253, 252, 1, 192, 36, 36, 126, 28,
|
||||
0, 14, 219, 156, 223, 192, 0, 227, 253, 252, 1, 192, 36, 36, 31, 12, 0, 46,
|
||||
27, 140, 223, 192, 0, 227, 141, 193, 193, 192, 40, 20, 7, 140, 0, 206, 25, 140,
|
||||
220, 28, 0, 227, 140, 225, 129, 199, 24, 24, 99, 156, 1, 14, 25, 204, 206, 24,
|
||||
0, 227, 142, 127, 1, 195, 39, 228, 255, 156, 2, 14, 24, 237, 199, 240, 1, 247,
|
||||
222, 62, 1, 198, 44, 44, 223, 30, 2, 31, 28, 237, 131, 224, 1, 224, 0, 0, 3,
|
||||
254, 27, 216, 0, 0, 4, 30, 0, 0, 0, 0, 3, 192, 0, 0, 7, 252, 0, 0, 0, 0, 4,
|
||||
60, 1, 249, 240, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 4, 0, 97, 240, 56, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 224, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
4, 0, 47, 192, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 32, 255, 128, 63, 128,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 32, 255, 0, 48, 78, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 15, 176, 255, 0, 112, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 8, 56, 255, 0,
|
||||
96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 8, 60, 255, 0, 224, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 130, 56, 126, 255, 3, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 192,
|
||||
62, 255, 15, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 14, 191, 255, 192, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 6, 129, 255, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 6, 0, 255, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 7, 128, 63, 192,
|
||||
0, 0, 96, 1, 224, 1, 0, 0, 0, 2, 0, 0, 7, 0, 31, 192, 0, 0, 95, 1, 11, 68, 88,
|
||||
0, 0, 4, 0, 0, 7, 128, 31, 192, 0, 1, 192, 129, 204, 85, 100, 0, 0, 8, 0, 0,
|
||||
15, 128, 63, 224, 0, 0, 95, 1, 8, 85, 68, 0, 1, 144, 0, 0, 31, 128, 143, 224,
|
||||
64, 0, 96, 1, 232, 41, 68, 0, 2, 96, 0, 31, 255, 129, 7, 248, 96, 0, 0, 0, 0,
|
||||
0, 0, 0, 4, 0, 0, 96, 254, 129, 7, 254, 96, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 128,
|
||||
254, 131, 135, 255, 224, 0, 0, 1, 192, 64, 16, 0, 8, 0, 7, 0, 254, 131, 255,
|
||||
63, 224, 0, 0, 1, 38, 113, 208, 0, 8, 0, 13, 0, 222, 147, 254, 31, 224, 0, 0,
|
||||
1, 41, 74, 80, 0, 8, 0, 25, 0, 222, 67, 254, 31, 160, 0, 0, 1, 41, 74, 80, 0,
|
||||
12, 0, 49, 0, 222, 19, 254, 62, 48, 0, 0, 1, 198, 113, 208, 0, 2, 0, 32, 128,
|
||||
222, 195, 255, 252, 56, 0, 0, 0, 0, 0, 0, 0, 2, 0, 124, 64, 220, 151, 135, 248,
|
||||
127, 0, 0, 0, 0, 0, 0, 0, 2, 0, 66, 32, 221, 223, 7, 240, 255, 0, 0, 0, 0, 0,
|
||||
0, 0, 2, 0, 129, 23, 93, 159, 15, 241, 131, 0, 0, 0, 0, 0, 0, 0, 4, 0, 128,
|
||||
136, 217, 95, 3, 226, 9, 0, 0, 1, 240, 0, 0, 0, 4, 0, 128, 72, 89, 95, 129,
|
||||
228, 18, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0, 72, 73, 127, 128, 224, 36, 0, 0, 0, 0,
|
||||
0, 0, 0, 28, 1, 0, 76, 129, 127, 192, 96, 8, 0, 0, 0, 0, 0, 0, 0, 16, 1, 0,
|
||||
231, 203, 124, 96, 64, 0, 0, 0, 0, 0, 0, 0, 0, 16, 1, 1, 28, 123, 240, 12, 64,
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 16, 1, 2, 28, 143, 128, 15, 192, 7, 0, 0, 0, 0, 0, 0,
|
||||
0, 16, 1, 4, 17, 143, 24, 15, 192, 14, 0, 0, 0, 0, 0, 0, 0, 28, 1, 4, 1, 135,
|
||||
24, 31, 192, 24, 0, 0, 0, 0, 0, 0, 0, 18, 1, 62, 1, 135, 248, 63, 224, 192,
|
||||
0, 0, 0, 0, 0, 0, 0, 35, 1, 195, 1, 135, 128, 254, 126, 1, 0, 0, 0, 0, 0, 0,
|
||||
0, 35, 193, 131, 195, 135, 255, 248, 112, 1, 0, 0, 0, 0, 0, 0, 0, 67, 241, 131,
|
||||
14, 207, 255, 192, 224, 3, 0, 0, 0, 0, 0, 0, 3, 67, 15, 143, 56, 255, 7, 1,
|
||||
224, 7, 0, 0, 0, 0, 0, 0, 28, 130, 7, 255, 112, 204, 7, 131, 224, 31, 0, 0,
|
||||
0, 0, 0, 0, 32, 134, 30, 29, 120, 156, 7, 255, 224, 127, 0, 0, 0, 0, 0, 63,
|
||||
197, 206, 60, 56, 192, 248, 15, 255, 248, 255, 0, 0, 0, 0, 0, 120, 5, 227, 248,
|
||||
56, 195, 248, 127, 191, 254, 63, 0, 0, 0, 0, 7, 254, 255, 193, 255, 15, 193,
|
||||
255, 15, 31, 252, 31 };
|
||||
|
||||
void ML_bmp_or_cl(const unsigned char *bmp, int x, int y, int width, int height)
|
||||
{
|
||||
unsigned short line;
|
||||
char shift, *screen, *p;
|
||||
int i, j, real_width, begin_x, end_x, begin_y, end_y;
|
||||
char bool1=1, bool2=1, bool3;
|
||||
if(!bmp || x<1-width || x>127 || y<1-height || y>63 || height<1 || width<1) return;
|
||||
p = (char*)&line;
|
||||
real_width = (width-1>>3<<3)+8;
|
||||
if(y < 0) begin_y = -y;
|
||||
else begin_y = 0;
|
||||
if(y+height > 64) end_y = 64-y;
|
||||
else end_y = height;
|
||||
shift = 8-(x&7);
|
||||
if(x<0)
|
||||
{
|
||||
begin_x = -x>>3;
|
||||
if(shift != 8) bool1 = 0;
|
||||
} else begin_x = 0;
|
||||
if(x+real_width > 128) end_x = 15-(x>>3), bool2 = 0;
|
||||
else end_x = real_width-1>>3;
|
||||
bool3 = (end_x == real_width-1>>3);
|
||||
screen = display_getCurrentVRAM()+(y+begin_y<<4)+(x>>3);
|
||||
|
||||
for(i=begin_y ; i<end_y ; i++)
|
||||
{
|
||||
if(begin_x < end_x)
|
||||
{
|
||||
line = bmp[i*(real_width>>3)+begin_x] << shift;
|
||||
if(bool1) screen[begin_x] |= *p;
|
||||
if(shift!=8) screen[begin_x+1] |= *(p+1);
|
||||
for(j=begin_x+1 ; j<end_x ; j++)
|
||||
{
|
||||
line = bmp[i*(real_width>>3)+j] << shift;
|
||||
screen[j] |= *p;
|
||||
if(shift!=8) screen[j+1] |= *(p+1);
|
||||
}
|
||||
}
|
||||
line = bmp[i*(real_width>>3)+end_x];
|
||||
if(bool3) line &= -1<<real_width-width;
|
||||
line <<= shift;
|
||||
if(begin_x < end_x || bool1) screen[end_x] |= *p;
|
||||
if(bool2) screen[end_x+1] |= *(p+1);
|
||||
screen += 16;
|
||||
}
|
||||
}
|
||||
|
||||
#include <../src/timer/timer_internals.h>
|
||||
void debug(void)
|
||||
{
|
||||
extern Image res_screen_start;
|
||||
struct mod_tmu *timer;
|
||||
int time1, time2;
|
||||
int i;
|
||||
|
||||
timer_get(TIMER_USER, &timer, NULL);
|
||||
|
||||
dclear();
|
||||
ML_bmp_or_cl(screen, 1, 1, 128, 64);
|
||||
dupdate();
|
||||
getkey();
|
||||
|
||||
dclear();
|
||||
dimage(&res_screen_start, 1, 1);
|
||||
dupdate();
|
||||
getkey();
|
||||
|
||||
dclear();
|
||||
dtext("ML...", 2, 2);
|
||||
dupdate();
|
||||
|
||||
timer_start(TIMER_USER, 0x0fffffff, TIMER_Po_4, NULL, 0);
|
||||
for(i = 0; i < 1000; i++) ML_bmp_or_cl(screen, 1, 1, 128, 64);
|
||||
time1 = timer->TCNT;
|
||||
timer_stop(TIMER_USER);
|
||||
time1 = 0x0fffffff - time1;
|
||||
|
||||
dclear();
|
||||
dtext("gint...", 2, 2);
|
||||
dupdate();
|
||||
|
||||
timer_start(TIMER_USER, 0x0fffffff, TIMER_Po_4, NULL, 0);
|
||||
for(i = 0; i < 1000; i++) dimage(&res_screen_start, 1, 1);
|
||||
time2 = timer->TCNT;
|
||||
timer_stop(TIMER_USER);
|
||||
time2 = 0x0fffffff - time2;
|
||||
|
||||
dclear();
|
||||
print_hex(time1, 2, 2);
|
||||
print_hex(time2, 2, 9);
|
||||
dupdate();
|
||||
while(getkey() != KEY_EXIT);
|
||||
}
|
||||
|
||||
/*
|
||||
main()
|
||||
Handles application calls.
|
||||
|
@ -371,10 +560,10 @@ int main_menu(void)
|
|||
*/
|
||||
int main(void)
|
||||
{
|
||||
extern Font binary_resources_font_start;
|
||||
Font *font = &binary_resources_font_start;
|
||||
extern Font res_font_start;
|
||||
Font *font = &res_font_start;
|
||||
|
||||
print_configure(font);
|
||||
text_configure(font);
|
||||
|
||||
int app;
|
||||
|
||||
|
@ -387,6 +576,7 @@ int main(void)
|
|||
if(app == 2) bitmap_test();
|
||||
if(app == 3) text_test();
|
||||
if(app == 4) gray_test();
|
||||
if(app == 5) debug();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
BIN
demo/resources/screen.bmp
Normal file
BIN
demo/resources/screen.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
BIN
gintdemo.g1a
Normal file
BIN
gintdemo.g1a
Normal file
Binary file not shown.
|
@ -62,7 +62,7 @@ struct _st_rtc
|
|||
gap(1);
|
||||
|
||||
union {
|
||||
unsigned char;
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :2;
|
||||
unsigned TENS :2;
|
||||
|
@ -208,7 +208,7 @@ struct _st_rtc
|
|||
struct {
|
||||
unsigned ENB :1;
|
||||
unsigned :7;
|
||||
}
|
||||
};
|
||||
} RCR3;
|
||||
|
||||
} __attribute__((packed));
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
// Heading declarations.
|
||||
//---
|
||||
|
||||
#include <stdint.h>
|
||||
#include <tales.h>
|
||||
|
||||
enum Color
|
||||
|
@ -150,4 +151,45 @@ void dimage(struct Image *image, int x, int y);
|
|||
|
||||
|
||||
|
||||
//---
|
||||
// Rectangle masks.
|
||||
//
|
||||
// The concept of 'rectangle masks' is used several times in this module.
|
||||
// It is based on the fact that an operation that affects a rectangle acts
|
||||
// the same on all its lines. Therefore the behavior of the operation is
|
||||
// determined by its behavior on a single line, which is represented using
|
||||
// 'masks' whose bits indicate whether a pixel is affected (1) or not (0).
|
||||
//
|
||||
// For example when clearing the screen rectangle (16, 16, 112, 48), the
|
||||
// masks will represent information '16 to 112 on x-axis', and will hold
|
||||
// the following values : 0000ffff, ffffffff, ffffffff and ffff0000. These
|
||||
// masks can then be used by setting vram[offset] &= ~masks[i]. This
|
||||
// appears to be very flexible : for instance, vram[offset] ^= masks[i]
|
||||
// will reverse the pixels in the same rectangle.
|
||||
//
|
||||
// This technique can also be used in more subtle cases with more complex
|
||||
// patterns, but within this module it is unlikely to happen.
|
||||
//
|
||||
//---
|
||||
|
||||
/*
|
||||
adjustRectangle()
|
||||
Adjusts the given rectangle coordinates to ensure that :
|
||||
- the rectangle is entirely contained in the screen
|
||||
- x1 < x2
|
||||
- y1 < y2
|
||||
which is needed when working with screen rectangles.
|
||||
*/
|
||||
void adjustRectangle(int *x1, int *y1, int *x2, int *y2);
|
||||
|
||||
/*
|
||||
getMasks()
|
||||
Computes the rectangle masks needed to affect pixels located between x1
|
||||
and x2 (both included). The four masks are stored in the third argument
|
||||
(seen as an array).
|
||||
*/
|
||||
void getMasks(int x1, int x2, uint32_t *masks);
|
||||
|
||||
|
||||
|
||||
#endif // _DISPLAY_H
|
||||
|
|
|
@ -60,6 +60,16 @@ void gray_getDelays(int *light, int *dark);
|
|||
Finding values that give proper grays is quite the hard part of the
|
||||
gray engine. Usual values are about 1000, with light being between 75
|
||||
and 90% of dark.
|
||||
|
||||
Typical values:
|
||||
|
||||
values stability stripes colors
|
||||
---------------------------------------------------------
|
||||
860, 1298 excellent worst static good
|
||||
912, 1343 bad none very good
|
||||
993, 1609 medium light fast good (default)
|
||||
---------------------------------------------------------
|
||||
|
||||
*/
|
||||
void gray_setDelays(int light, int dark);
|
||||
|
||||
|
|
|
@ -14,17 +14,12 @@ typedef unsigned int jmp_buf[16];
|
|||
/*
|
||||
setjmp()
|
||||
Configures a jump by saving data to the given jump buffer.
|
||||
|
||||
@arg env Empty jump buffer.
|
||||
*/
|
||||
int setjmp(jmp_buf env);
|
||||
|
||||
/*
|
||||
longjmp()
|
||||
Performs a long jump.
|
||||
|
||||
@arg env Jump buffer configure with setjmp().
|
||||
@arg value setjmp() will return this integer after the jump.
|
||||
*/
|
||||
void longjmp(jmp_buf env, int value);
|
||||
|
||||
|
|
|
@ -34,15 +34,15 @@ void exit(int status);
|
|||
|
||||
/*
|
||||
malloc()
|
||||
Allocs 'size' bytes and returns a pointer to a free memory area.
|
||||
Allocates 'size' bytes and returns a pointer to a free memory area.
|
||||
Returns NULL on error.
|
||||
*/
|
||||
void *malloc(size_t size);
|
||||
|
||||
/*
|
||||
calloc()
|
||||
Allocs 'n' elements of size 'size' and wipes the memory area. Returns
|
||||
NULL on error.
|
||||
Allocates 'n' elements of size 'size' and wipes the memory area.
|
||||
Returns NULL on error.
|
||||
*/
|
||||
void *calloc(size_t n, size_t size);
|
||||
|
||||
|
|
|
@ -12,20 +12,12 @@
|
|||
Copies a memory area. The two areas must not overlap (if they do, use
|
||||
memmove()). A smart copy is performed when possible. To enhance
|
||||
performance, make sure than destination and source are both 4-aligned.
|
||||
|
||||
@arg destination
|
||||
@arg source
|
||||
@arg byte_number
|
||||
*/
|
||||
void *memcpy(void *destination, const void *source, size_t byte_number);
|
||||
|
||||
/*
|
||||
memset()
|
||||
Sets the contents of a memory area. A smart copy is performed.
|
||||
|
||||
@arg area
|
||||
@arg byte Byte to write in the area.
|
||||
@arg byte_number
|
||||
*/
|
||||
void *memset(void *destination, int byte, size_t byte_number);
|
||||
|
||||
|
|
16
info
16
info
|
@ -1,16 +0,0 @@
|
|||
|
||||
Experimental power reduction as function of the keyboard analysis frequency.
|
||||
|
||||
SH3
|
||||
None 0 %
|
||||
4 Hz 2.8 %
|
||||
16 Hz 2.8 %
|
||||
64 Hz 2.8 %
|
||||
256 Hz 20.0 %
|
||||
|
||||
SH4
|
||||
None 0 %
|
||||
4 Hz 1.8 %
|
||||
16 Hz 1.8 %
|
||||
64 Hz 1.8 %
|
||||
256 Hz 3.6 %
|
BIN
libc.a
BIN
libc.a
Binary file not shown.
BIN
libgint.a
BIN
libgint.a
Binary file not shown.
|
@ -1,18 +1,22 @@
|
|||
#include <bopti_internals.h>
|
||||
|
||||
// Monochrome video ram, light and dark buffers (in this order).
|
||||
int *vram, *v1, *v2;
|
||||
|
||||
/*
|
||||
bopti_op()
|
||||
Operates on a vram long. The operator will often not contain 32 bits of
|
||||
image information. Since neutral bits are not the same for all
|
||||
operations, the op_mask argument indicates which bits should be used
|
||||
for the operation. Which operation has to be done is determined by the
|
||||
channel setting.
|
||||
operations, a mask is used to indicate which bits should be used for
|
||||
the operation. This mask is taken for the image's rectangle masks (see
|
||||
module display for more information on rectangle masks).
|
||||
Which operation is performed is determined by the channel setting.
|
||||
*/
|
||||
static void bopti_op_mono(int offset, uint32_t operator, uint32_t op_mask)
|
||||
void bopti_op_mono(int offset, uint32_t operator, struct Command *c)
|
||||
{
|
||||
operator &= op_mask;
|
||||
operator &= c->masks[offset & 3];
|
||||
|
||||
switch(channel)
|
||||
switch(c->channel)
|
||||
{
|
||||
case Channel_Mono:
|
||||
vram[offset] |= operator;
|
||||
|
@ -26,11 +30,11 @@ static void bopti_op_mono(int offset, uint32_t operator, uint32_t op_mask)
|
|||
break;
|
||||
}
|
||||
}
|
||||
static void bopti_op_gray(int offset, uint32_t operator, uint32_t op_mask)
|
||||
void bopti_op_gray(int offset, uint32_t operator, struct Command *c)
|
||||
{
|
||||
operator &= op_mask;
|
||||
operator &= c->masks[offset & 3];
|
||||
|
||||
switch(channel)
|
||||
switch(c->channel)
|
||||
{
|
||||
case Channel_Mono:
|
||||
v1[offset] |= operator;
|
||||
|
@ -66,74 +70,75 @@ static void bopti_op_gray(int offset, uint32_t operator, uint32_t op_mask)
|
|||
because bopti_grid() will perform a 32-bit shift when x is a multiple
|
||||
of 32, which is undefined behavior.
|
||||
*/
|
||||
static void bopti_grid_a32(const uint32_t *layer, int x, int y,
|
||||
int column_count)
|
||||
void bopti_grid_a32(const uint32_t *layer, int column_count, int height,
|
||||
struct Command *c)
|
||||
{
|
||||
int vram_column_offset = (y << 2) + (x >> 5);
|
||||
int vram_column_offset = (c->y << 2) + (c->x >> 5);
|
||||
int vram_offset = vram_column_offset;
|
||||
int column, row;
|
||||
|
||||
for(column = 0; column < column_count; column++)
|
||||
{
|
||||
for(row = 0; row < height; row++)
|
||||
for(row = c->top; row < c->bottom; row++)
|
||||
{
|
||||
(*op)(vram_offset, *layer, 0xffffffff);
|
||||
layer++;
|
||||
(*c->op)(vram_offset, layer[row], c);
|
||||
vram_offset += 4;
|
||||
}
|
||||
|
||||
vram_column_offset++;
|
||||
vram_offset = vram_column_offset;
|
||||
layer += height;
|
||||
}
|
||||
}
|
||||
static void bopti_grid(const uint32_t *layer, int x, int y, int column_count)
|
||||
void bopti_grid(const uint32_t *layer, int column_count, int height,
|
||||
struct Command *c)
|
||||
{
|
||||
if(!column_count) return;
|
||||
if(!(x & 31))
|
||||
if(!(c->x & 31))
|
||||
{
|
||||
bopti_grid_a32(layer, x, y, column_count);
|
||||
bopti_grid_a32(layer, column_count, height, c);
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t *p1, *p2;
|
||||
uint32_t l1, l2;
|
||||
uint32_t l1, l2, operator;
|
||||
int right_column, line;
|
||||
|
||||
int vram_column_offset = (y << 2) + (x >> 5);
|
||||
int vram_column_offset = (c->y << 2) + (c->x >> 5) + (c->x < 0);
|
||||
int vram_offset = vram_column_offset;
|
||||
|
||||
int shift1 = 32 - (x & 31);
|
||||
int shift2 = (x & 31);
|
||||
int shift1 = 32 - (c->x & 31);
|
||||
int shift2 = (c->x & 31);
|
||||
|
||||
uint32_t operator, and_mask;
|
||||
uint32_t and_mask_0 = 0xffffffff >> shift2;
|
||||
uint32_t and_mask_1 = 0xffffffff << shift1;
|
||||
|
||||
// Initializing two pointers. Since the columns are written one after
|
||||
// another, they will be updated directly to parse the whole grid.
|
||||
// Initializing two pointers. They will read two adjacent columns at
|
||||
// the same time (p2 is column ahead of p1). Since the columns are
|
||||
// written one after another, incrementing them will suffice when
|
||||
// reaching the end of two columns, to move them to the next ones.
|
||||
p1 = layer - height;
|
||||
p2 = layer;
|
||||
|
||||
// Drawing vram longwords, using pairs of columns.
|
||||
for(right_column = 0; right_column <= column_count; right_column++)
|
||||
{
|
||||
and_mask = 0xffffffff;
|
||||
if(right_column == 0) and_mask &= and_mask_0;
|
||||
if(right_column == column_count) and_mask &= and_mask_1;
|
||||
// We don't want to write the first vram column when x is negative.
|
||||
if(c->x < 0) p1 += height, p2 += height;
|
||||
right_column = (c->x < 0);
|
||||
|
||||
for(line = 0; line < height; line++)
|
||||
// Drawing vram longwords, using pairs of columns.
|
||||
while(right_column <= column_count)
|
||||
{
|
||||
for(line = c->top; line < c->bottom; line++)
|
||||
{
|
||||
l1 = (right_column > 0) ? (*p1) : (0);
|
||||
l2 = (right_column < column_count) ? (*p2) : (0);
|
||||
p1++, p2++;
|
||||
l1 = (right_column > 0) ? p1[line] : (0);
|
||||
l2 = (right_column < column_count) ? p2[line] : (0);
|
||||
|
||||
operator = (l1 << shift1) | (l2 >> shift2);
|
||||
(*op)(vram_offset, operator, and_mask);
|
||||
(*c->op)(vram_offset, operator, c);
|
||||
vram_offset += 4;
|
||||
}
|
||||
|
||||
p1 += height;
|
||||
p2 += height;
|
||||
vram_column_offset++;
|
||||
vram_offset = vram_column_offset;
|
||||
right_column++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,13 +149,13 @@ static void bopti_grid(const uint32_t *layer, int x, int y, int column_count)
|
|||
is read and updated so that it points to the next line at the end of
|
||||
the operation.
|
||||
*/
|
||||
static uint32_t bopti_end_get1(const unsigned char **data)
|
||||
uint32_t bopti_end_get1(const unsigned char **data)
|
||||
{
|
||||
uint32_t operator = **data;
|
||||
*data += 1;
|
||||
return operator;
|
||||
}
|
||||
static uint32_t bopti_end_get2(const unsigned char **data)
|
||||
uint32_t bopti_end_get2(const unsigned char **data)
|
||||
{
|
||||
uint32_t operator = *((uint16_t *)*data);
|
||||
*data += 2;
|
||||
|
@ -165,63 +170,57 @@ static uint32_t bopti_end_get2(const unsigned char **data)
|
|||
whose with is lower than 32. (Actually is it lower or equal to 16;
|
||||
otherwise it would have been a column and the end would be empty).
|
||||
*/
|
||||
static void bopti_end_nover(const unsigned char *end, int x, int y, int width)
|
||||
void bopti_end_nover(const unsigned char *end, int size, struct Command *c)
|
||||
{
|
||||
uint32_t (*get)(const unsigned char **data) =
|
||||
(width > 8) ? bopti_end_get2 : bopti_end_get1;
|
||||
|
||||
int vram_offset = (y << 2) + (x >> 5);
|
||||
int row;
|
||||
(size == 2) ? bopti_end_get2 : bopti_end_get1;
|
||||
|
||||
// We *have* shift >= 0 because of this function's 'no overlap'
|
||||
// requirement.
|
||||
int shift_base = (width > 8) ? 16 : 24;
|
||||
int shift = shift_base - (x & 31);
|
||||
|
||||
uint32_t and_mask = (0xffffffff << (32 - width)) >> (x & 31);
|
||||
int shift = (32 - (size << 3)) - (c->x & 31);
|
||||
int vram_offset = (c->y << 2) + (c->x >> 5);
|
||||
uint32_t operator;
|
||||
int row;
|
||||
|
||||
for(row = 0; row < height; row++)
|
||||
// Skipping c->top lines (because get() function only allows sequential
|
||||
// access).
|
||||
end += c->top * size;
|
||||
|
||||
for(row = c->top; row < c->bottom; row++)
|
||||
{
|
||||
operator = (*get)(&end);
|
||||
operator <<= shift;
|
||||
|
||||
(*op)(vram_offset, operator, and_mask);
|
||||
(*c->op)(vram_offset, operator, c);
|
||||
vram_offset += 4;
|
||||
}
|
||||
}
|
||||
static void bopti_end(const unsigned char *end, int x, int y, int width)
|
||||
void bopti_end(const unsigned char *end, int size, struct Command *c)
|
||||
{
|
||||
if((x & 31) + width <= 32)
|
||||
{
|
||||
bopti_end_nover(end, x, y, width);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t (*get)(const unsigned char **data) =
|
||||
(width > 8) ? (bopti_end_get2) : (bopti_end_get1);
|
||||
(size == 2) ? (bopti_end_get2) : (bopti_end_get1);
|
||||
|
||||
int vram_offset = (y << 2) + (x >> 5);
|
||||
int vram_offset = (c->y << 2) + (c->x >> 5);
|
||||
uint32_t row_data, operator;
|
||||
int row;
|
||||
|
||||
int shift_base = (width > 8) ? 16 : 24;
|
||||
int shift1 = (x & 31) - shift_base;
|
||||
int shift2 = shift_base + 32 - (x & 31);
|
||||
int shift_base = (32 - (size << 3));
|
||||
int shift1 = (c->x & 31) - shift_base;
|
||||
int shift2 = shift_base + 32 - (c-> x & 31);
|
||||
|
||||
uint32_t and_mask_0 = 0xffffffff >> (x & 31);
|
||||
uint32_t and_mask_1 = 0xffffffff << (64 - width - (x & 31));
|
||||
// Skipping c->top lines (because get() function only allows sequential
|
||||
// access).
|
||||
end += c->top * size;
|
||||
|
||||
uint32_t row_data, operator;
|
||||
|
||||
for(row = 0; row < height; row++)
|
||||
for(row = c->top; row < c->bottom; row++)
|
||||
{
|
||||
row_data = (*get)(&end);
|
||||
|
||||
operator = row_data >> shift1;
|
||||
(*op)(vram_offset, operator, and_mask_0);
|
||||
(*c->op)(vram_offset, operator, c);
|
||||
|
||||
operator = row_data << shift2;
|
||||
(*op)(vram_offset + 1, operator, and_mask_1);
|
||||
(*c->op)(vram_offset + 1, operator, c);
|
||||
|
||||
vram_offset += 4;
|
||||
}
|
||||
|
@ -237,41 +236,63 @@ static void bopti_end(const unsigned char *end, int x, int y, int width)
|
|||
bopti()
|
||||
Draws a layer in the video ram.
|
||||
*/
|
||||
static void bopti(const unsigned char *layer, int x, int y, int columns,
|
||||
int end_size)
|
||||
void bopti(const unsigned char *layer, struct Structure *s, struct Command *c)
|
||||
{
|
||||
const unsigned char *end = layer + ((columns * height) << 2);
|
||||
int end_x = x + (columns << 5);
|
||||
const unsigned char *grid, *end;
|
||||
int grid_columns, has_end;
|
||||
|
||||
bopti_grid((const uint32_t *)layer, x, y, columns);
|
||||
if(end_size) bopti_end(end, end_x, y, end_size);
|
||||
// Skipping columns at the beginning.
|
||||
grid = layer + ((c->left * s->height) << 2);
|
||||
|
||||
// Updating the command arguments to eliminate some information about
|
||||
// parts that are not being drawn.
|
||||
c->x += (c->left << 5);
|
||||
c->y += c->top;
|
||||
|
||||
// Columns are identified by ids 0 to s->columns - 1, and the end has
|
||||
// id s->columns. So the end is drawn if this last column is included.
|
||||
has_end = (c->right == s->columns);
|
||||
// Computing number of grid columns to draw.
|
||||
grid_columns = c->right - c->left + 1 - has_end;
|
||||
|
||||
bopti_grid((const uint32_t *)grid, grid_columns, s->height, c);
|
||||
|
||||
if(has_end)
|
||||
{
|
||||
end = layer + ((s->columns * s->height) << 2);
|
||||
c->x += (grid_columns << 5);
|
||||
|
||||
if((c->x & 31) + s->end_size <= 32)
|
||||
bopti_end_nover(end, s->end_bytes, c);
|
||||
else
|
||||
bopti_end(end, s->end_bytes, c);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
getStructure()
|
||||
Determines the image size and data pointer.
|
||||
*/
|
||||
static void getStructure(struct Image *img, int *width, int *height,
|
||||
int *layer_size, const unsigned char **data, int *columns,
|
||||
int *end_size)
|
||||
void getStructure(struct Image *img, struct Structure *s)
|
||||
{
|
||||
int column_count, end, end_bytes, layer;
|
||||
|
||||
// Large images.
|
||||
if(!img->width && !img->height)
|
||||
{
|
||||
if(width) *width = (img->data[0] << 8) | img->data[1];
|
||||
if(height) *height = (img->data[2] << 8) | img->data[3];
|
||||
if(data) *data = img->data + 4;
|
||||
s->width = (img->data[0] << 8) | img->data[1];
|
||||
s->height = (img->data[2] << 8) | img->data[3];
|
||||
s->data = img->data + 4;
|
||||
|
||||
column_count = (*width + 31) >> 5;
|
||||
end = end_bytes = 0;
|
||||
column_count = (s->width + 31) >> 5;
|
||||
end = 0;
|
||||
end_bytes = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(width) *width = img->width;
|
||||
if(height) *height = img->height;
|
||||
if(data) *data = img->data;
|
||||
s->width = img->width;
|
||||
s->height = img->height;
|
||||
s->data = img->data;
|
||||
|
||||
column_count = img->width >> 5;
|
||||
end = img->width & 31;
|
||||
|
@ -280,13 +301,21 @@ static void getStructure(struct Image *img, int *width, int *height,
|
|||
end <= 8 ? 1 :
|
||||
end <= 16 ? 2 :
|
||||
4;
|
||||
|
||||
if(end_bytes == 4)
|
||||
{
|
||||
column_count++;
|
||||
end = 0;
|
||||
end_bytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// The layer size must be rounded to a multiple of 4.
|
||||
layer = img->height * ((column_count << 2) + end_bytes);
|
||||
if(layer & 3) layer += 4 - (layer & 3);
|
||||
|
||||
if(columns) *columns = column_count;
|
||||
if(end_size) *end_size = end;
|
||||
if(layer_size) *layer_size = layer;
|
||||
s->columns = column_count;
|
||||
s->end_bytes = end_bytes;
|
||||
s->end_size = end;
|
||||
s->layer_size = layer;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#define _BOPTI_INTERNALS_H 1
|
||||
|
||||
#include <stdint.h>
|
||||
#include <display.h>
|
||||
|
||||
/*
|
||||
enum Channel
|
||||
|
@ -49,15 +50,43 @@ enum Format
|
|||
Channel_DarkAlpha
|
||||
};
|
||||
|
||||
// The following variables refer to parameters that do not change during the
|
||||
// drawing operation (at least for the time of a layer). They could be passed
|
||||
// on by every function from the module, but this would be heavy and useless.
|
||||
// Using global variables is not really a proper solution but it does simplify
|
||||
// code much.
|
||||
/*
|
||||
struct Structure
|
||||
Describes an image's structure.
|
||||
*/
|
||||
struct Structure
|
||||
{
|
||||
int width, height;
|
||||
int layer_size;
|
||||
|
||||
const unsigned char *data;
|
||||
int columns;
|
||||
int end_size, end_bytes;
|
||||
};
|
||||
|
||||
/*
|
||||
struct Command
|
||||
Contains a drawing operation's parameters.
|
||||
*/
|
||||
struct Command
|
||||
{
|
||||
// Channel being drawn.
|
||||
enum Channel channel;
|
||||
// Operation used (whether bopti_op_mono() or bopti_op_gray()).
|
||||
void (*op)(int offset, uint32_t operator, struct Command *command);
|
||||
// Portion of the bitmap which is drawn. 'top' and 'bottom' refer to
|
||||
// lines where 'left' and 'right' refer to column ids.
|
||||
int left, right, top, bottom;
|
||||
// Position of the bitmap on the screen.
|
||||
int x, y;
|
||||
// Rectangle masks.
|
||||
uint32_t masks[4];
|
||||
};
|
||||
|
||||
// The video ram addresses are set by the public functions and used internally
|
||||
// by the module.
|
||||
// Monochrome video ram, light and dark buffers (in this order).
|
||||
extern int *vram, *v1, *v2;
|
||||
extern enum Channel channel;
|
||||
extern int height;
|
||||
extern void (*op)(int offset, uint32_t operator, uint32_t op_mask);
|
||||
|
||||
|
||||
|
||||
|
@ -69,12 +98,13 @@ extern void (*op)(int offset, uint32_t operator, uint32_t op_mask);
|
|||
bopti_op()
|
||||
Operates on a vram long. The operator will often not contain 32 bits of
|
||||
image information. Since neutral bits are not the same for all
|
||||
operations, the op_mask argument indicates which bits should be used
|
||||
for the operation. Which operation has to be done is determined by the
|
||||
channel setting.
|
||||
operations, a mask is used to indicate which bits should be used for
|
||||
the operation. This mask is taken for the image's rectangle masks (see
|
||||
module display for more information on rectangle masks).
|
||||
Which operation is performed is determined by the channel setting.
|
||||
*/
|
||||
void bopti_op_mono(int offset, uint32_t operator, uint32_t op_mask);
|
||||
void bopti_op_gray(int offset, uint32_t operator, uint32_t op_mask);
|
||||
void bopti_op_mono(int offset, uint32_t operator, struct Command *c);
|
||||
void bopti_op_gray(int offset, uint32_t operator, struct Command *c);
|
||||
|
||||
/*
|
||||
bopti_grid() -- general form
|
||||
|
@ -85,10 +115,12 @@ void bopti_op_gray(int offset, uint32_t operator, uint32_t op_mask);
|
|||
The need for bopti_grid_a32() is not only linked to optimization,
|
||||
because bopti_grid() will perform a 32-bit shift when x is a multiple
|
||||
of 32, which is undefined behavior.
|
||||
bopti_grid() calls bopti_grid_32() by default.
|
||||
*/
|
||||
void bopti_grid_a32(const uint32_t *layer, int x, int y, int column_count);
|
||||
void bopti_grid(const uint32_t *layer, int x, int y, int column_count);
|
||||
|
||||
void bopti_grid_a32(const uint32_t *layer, int columns, int height,
|
||||
struct Command *c);
|
||||
void bopti_grid(const uint32_t *layer, int columns, int height,
|
||||
struct Command *c);
|
||||
/*
|
||||
bopti_end_get()
|
||||
Returns an operator for the end of a line, whose width is lower than 32
|
||||
|
@ -105,23 +137,24 @@ uint32_t bopti_end_get2(const unsigned char **data);
|
|||
|
||||
Draws the end of a layer, which can be considered as a whole layer
|
||||
whose with is lower than 32. (Actually is it lower or equal to 16;
|
||||
otherwise it would have been a column and the end would be empty).
|
||||
otherwise it would have been a column and the end would be empty). The
|
||||
'size' arguments is in bytes.
|
||||
Unlike bopti_grid_a32(), bopti_end_nover() is not called automatically
|
||||
by bopti_end().
|
||||
*/
|
||||
void bopti_end_nover(const unsigned char *end, int x, int y, int width);
|
||||
void bopti_end(const unsigned char *end, int x, int y, int width);
|
||||
void bopti_end_nover(const unsigned char *end, int size, struct Command *c);
|
||||
void bopti_end(const unsigned char *end, int size, struct Command *c);
|
||||
|
||||
/*
|
||||
bopti()
|
||||
Draws a layer in the video ram.
|
||||
*/
|
||||
void bopti(const unsigned char *layer, int x, int y, int columns,
|
||||
int end_size);
|
||||
void bopti(const unsigned char *layer, struct Structure *s, struct Command *c);
|
||||
|
||||
/*
|
||||
getStructure()
|
||||
Determines the image size and data pointer.
|
||||
*/
|
||||
void getStructure(struct Image *img, int *width, int *height, int *layer_size,
|
||||
const unsigned char **data, int *columns, int *end_size);
|
||||
void getStructure(struct Image *img, struct Structure *structure);
|
||||
|
||||
#endif // _BOPTI_INTERNALS_H
|
||||
|
|
|
@ -7,17 +7,33 @@
|
|||
*/
|
||||
void dimage(struct Image *img, int x, int y)
|
||||
{
|
||||
int width, layer_size, columns, end;
|
||||
int format = img->format, i = 0;
|
||||
const unsigned char *data;
|
||||
|
||||
if(img->magic != 0xb7) return;
|
||||
if(img->format != Format_Mono && img->format != Format_MonoAlpha)
|
||||
return;
|
||||
op = bopti_op_mono;
|
||||
|
||||
// 'height' refers to a static variable for this file.
|
||||
getStructure(img, &width, &height, &layer_size, &data, &columns, &end);
|
||||
struct Structure s;
|
||||
struct Command command;
|
||||
int actual_width;
|
||||
int format = img->format, i = 0;
|
||||
|
||||
if(format != Format_Mono && format != Format_MonoAlpha) return;
|
||||
getStructure(img, &s);
|
||||
|
||||
//---
|
||||
// Adjusting image parameters.
|
||||
//---
|
||||
|
||||
if(x + s.width < 0 || x > 127 || y + s.height < 0 || y > 63) return;
|
||||
|
||||
command.top = (y < 0) ? (-y) : (0);
|
||||
command.bottom = (y + s.height > 64) ? (64 - y) : (s.height);
|
||||
command.left = ((x < 0) ? (-x) : (0)) >> 5;
|
||||
actual_width = (x + s.width > 128) ? (128 - x) : (s.width);
|
||||
command.right = ((actual_width + 31) >> 5) - 1;
|
||||
|
||||
command.x = x;
|
||||
command.y = y;
|
||||
command.op = bopti_op_mono;
|
||||
|
||||
getMasks(x, x + actual_width - 1, command.masks);
|
||||
|
||||
vram = display_getCurrentVRAM();
|
||||
|
||||
|
@ -26,9 +42,9 @@ void dimage(struct Image *img, int x, int y)
|
|||
// Drawing every layer, in order of formats.
|
||||
if(format & 1)
|
||||
{
|
||||
channel = (1 << i);
|
||||
bopti(data, x, y, columns, end);
|
||||
data += layer_size;
|
||||
command.channel = (1 << i);
|
||||
bopti(s.data, &s, &command);
|
||||
s.data += s.layer_size;
|
||||
}
|
||||
|
||||
format >>= 1;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <bopti_internals.h>
|
||||
#include <display.h>
|
||||
#include <gray.h>
|
||||
|
||||
/*
|
||||
|
@ -7,15 +8,31 @@
|
|||
*/
|
||||
void gimage(struct Image *img, int x, int y)
|
||||
{
|
||||
int width, layer_size, columns, end;
|
||||
int format = img->format, i = 0;
|
||||
const unsigned char *data;
|
||||
|
||||
if(img->magic != 0xb7) return;
|
||||
op = bopti_op_gray;
|
||||
|
||||
// 'height' refers to a static variable for this file.
|
||||
getStructure(img, &width, &height, &layer_size, &data, &columns, &end);
|
||||
struct Structure s;
|
||||
struct Command command;
|
||||
int actual_width;
|
||||
int format = img->format, i = 0;
|
||||
|
||||
getStructure(img, &s);
|
||||
|
||||
//---
|
||||
// Adjusting image parameters.
|
||||
//---
|
||||
//-65:-68
|
||||
if(x + s.width < 0 || x > 127 || y + s.height < 0 || y > 63) return;
|
||||
|
||||
command.top = (y < 0) ? (-y) : (0);
|
||||
command.bottom = (y + s.height > 64) ? (64 - y) : (s.height);
|
||||
command.left = ((x < 0) ? (-x) : (0)) >> 5;
|
||||
actual_width = (x + s.width > 128) ? (128 - x) : (s.width);
|
||||
command.right = ((actual_width + 31) >> 5) - 1;
|
||||
|
||||
command.op = bopti_op_gray;
|
||||
|
||||
if(x >= 0) getMasks(x, x + actual_width - 1, command.masks);
|
||||
else getMasks(0, actual_width + x - 1, command.masks);
|
||||
|
||||
v1 = gray_lightVRAM();
|
||||
v2 = gray_darkVRAM();
|
||||
|
@ -25,9 +42,13 @@ void gimage(struct Image *img, int x, int y)
|
|||
// Drawing every layer, in order of formats.
|
||||
if(format & 1)
|
||||
{
|
||||
channel = (1 << i);
|
||||
bopti(data, x, y, columns, end);
|
||||
data += layer_size;
|
||||
// These members are modified by bopti()!
|
||||
command.x = x;
|
||||
command.y = y;
|
||||
command.channel = (1 << i);
|
||||
|
||||
bopti(s.data, &s, &command);
|
||||
s.data += s.layer_size;
|
||||
}
|
||||
|
||||
format >>= 1;
|
||||
|
|
|
@ -53,8 +53,8 @@ int start(void)
|
|||
__GLibAddinAplExecutionCheck(0, 1, 1);
|
||||
|
||||
// Initializing everything.
|
||||
init();
|
||||
gint_init();
|
||||
init();
|
||||
|
||||
|
||||
|
||||
|
@ -69,8 +69,8 @@ int start(void)
|
|||
// Remember to flush and close opened streams.
|
||||
|
||||
// Un-initializing everything.
|
||||
gint_quit();
|
||||
fini();
|
||||
gint_quit();
|
||||
|
||||
return exit_code;
|
||||
}
|
||||
|
|
|
@ -91,6 +91,11 @@ void gint_init(void)
|
|||
unsigned int *ptr = &bgint;
|
||||
unsigned int *src = &gint_data;
|
||||
|
||||
// This initialization routine is usually called before any
|
||||
// constructor. We want to ensure that the MPU type is detected, but
|
||||
// mpu_init() hasn't been called yet.
|
||||
mpu_init();
|
||||
|
||||
// Loading the interrupt handler into the memory.
|
||||
while(ptr < &egint) *ptr++ = *src++;
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include <gint.h>
|
||||
#include <mpu.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
static void (*rtc_callback)(void) = NULL;
|
||||
|
||||
/*
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
void dclear_area(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
unsigned int masks[4];
|
||||
uint32_t masks[4];
|
||||
adjustRectangle(&x1, &y1, &x2, &y2);
|
||||
getMasks(x1, x2, masks);
|
||||
|
||||
|
|
|
@ -4,25 +4,6 @@
|
|||
//
|
||||
// Handles vram manipulation and drawing.
|
||||
//
|
||||
//
|
||||
// :: Rectangle masks
|
||||
//
|
||||
// The concept of 'rectangle masks' is used several times in this module.
|
||||
// It is based on the fact that an operation that affects a rectangle acts
|
||||
// the same on all its lines. Therefore the behavior of the operation is
|
||||
// determined by its behavior on a single line, which is represented using
|
||||
// 'masks' whose bits indicate whether a pixel is affected (1) or not (0).
|
||||
//
|
||||
// For example when clearing the screen rectangle (16, 16, 112, 48), the
|
||||
// masks will represent information '16 to 112 on x-axis', and will hold
|
||||
// the following values : 0000ffff, ffffffff, ffffffff and ffff0000. These
|
||||
// masks can then be used by setting vram[offset] &= ~masks[i]. This
|
||||
// appears to be very flexible : for instance, vram[offset] ^= masks[i]
|
||||
// will reverse the pixels in the same rectangle.
|
||||
//
|
||||
// This technique can also be used in more subtle cases with more complex
|
||||
// patterns, but within this module it is unlikely to happen.
|
||||
//
|
||||
//---
|
||||
|
||||
#ifndef _DISPLAY_INTERNALS_H
|
||||
|
@ -30,23 +11,4 @@
|
|||
|
||||
extern int *vram;
|
||||
|
||||
/*
|
||||
adjustRectangle()
|
||||
Adjusts the given rectangle coordinates to ensure that :
|
||||
- the rectangle is entirely contained in the screen
|
||||
- x1 < x2
|
||||
- y1 < y2
|
||||
which is needed when working with screen rectangles.
|
||||
*/
|
||||
static void adjustRectangle(int *x1, int *y1, int *x2, int *y2);
|
||||
|
||||
/*
|
||||
getMasks()
|
||||
Computes the rectangle masks needed to affect pixels located between x1
|
||||
and x2 (both included). The four masks are stored in the third argument
|
||||
(seen as an array).
|
||||
See this module's internals header file for more information.
|
||||
*/
|
||||
static void getMasks(int x1, int x2, unsigned int *masks);
|
||||
|
||||
#endif // _DISPLAY_INTERNALS_H
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
static void dhline(int x1, int x2, int y, enum Color color)
|
||||
{
|
||||
unsigned int masks[4];
|
||||
uint32_t masks[4];
|
||||
int offset = y << 2;
|
||||
int i;
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
*/
|
||||
void dreverse_area(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
unsigned int masks[4];
|
||||
uint32_t masks[4];
|
||||
adjustRectangle(&x1, &y1, &x2, &y2);
|
||||
getMasks(x1, x2, masks);
|
||||
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
#include <display_internals.h>
|
||||
#include <display.h>
|
||||
|
||||
/*
|
||||
getMasks()
|
||||
Computes the rectangle masks needed to affect pixels located between x1
|
||||
and x2 (both included). The four masks are stored in the third argument
|
||||
(seen as an array).
|
||||
See this module's internals header file for more information.
|
||||
*/
|
||||
void getMasks(int x1, int x2, unsigned int *masks)
|
||||
void getMasks(int x1, int x2, uint32_t *masks)
|
||||
{
|
||||
// Indexes of the first and last longs that are non-blank.
|
||||
int l1 = x1 >> 5;
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include <timer.h>
|
||||
|
||||
static int internal_vrams[3][256];
|
||||
const void *vrams[4];
|
||||
static const void *vrams[4];
|
||||
|
||||
static int current = 0;
|
||||
static int delays[2];
|
||||
|
@ -33,7 +33,10 @@ static int runs = 0;
|
|||
*/
|
||||
void gray_start(void)
|
||||
{
|
||||
if(runs) return;
|
||||
|
||||
timer_start(TIMER_GRAY, delays[0], GRAY_PRESCALER, gray_interrupt, 0);
|
||||
current &= 1;
|
||||
runs = 1;
|
||||
}
|
||||
|
||||
|
@ -44,6 +47,8 @@ void gray_start(void)
|
|||
*/
|
||||
void gray_stop(void)
|
||||
{
|
||||
if(!runs) return;
|
||||
|
||||
timer_stop(TIMER_GRAY);
|
||||
runs = 0;
|
||||
|
||||
|
@ -79,18 +84,18 @@ inline int gray_runs(void)
|
|||
gray_lightVRAM()
|
||||
Returns the module's gray vram address.
|
||||
*/
|
||||
inline void *gray_lightVRAM(void)
|
||||
void *gray_lightVRAM(void)
|
||||
{
|
||||
return (void *)vrams[current & 2];
|
||||
return (void *)vrams[~current & 2];
|
||||
}
|
||||
|
||||
/*
|
||||
gray_lightVRAM()
|
||||
Returns the module's dark vram address.
|
||||
*/
|
||||
inline void *gray_darkVRAM(void)
|
||||
void *gray_darkVRAM(void)
|
||||
{
|
||||
return (void *)vrams[(current & 2) | 1];
|
||||
return (void *)vrams[(~current & 2) | 1];
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -130,7 +135,7 @@ inline void gupdate(void)
|
|||
*/
|
||||
void gray_interrupt(void)
|
||||
{
|
||||
timer_reload(TIMER_GRAY, delays[current & 1]);
|
||||
timer_reload(TIMER_GRAY, delays[(~current) & 1]);
|
||||
screen_display(vrams[current]);
|
||||
current ^= 1;
|
||||
}
|
||||
|
@ -146,6 +151,6 @@ void gray_init(void)
|
|||
vrams[2] = (const void *)internal_vrams[1];
|
||||
vrams[3] = (const void *)internal_vrams[2];
|
||||
|
||||
delays[0] = 900;
|
||||
delays[1] = 1000;
|
||||
delays[0] = 993;
|
||||
delays[1] = 1609;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
// Keyboard variables.
|
||||
extern volatile unsigned char keyboard_state[10];
|
||||
extern volatile int interrupt_flag = 0;
|
||||
extern volatile int interrupt_flag;
|
||||
|
||||
// Key statistics.
|
||||
extern int repeat_first, repeat_next;
|
||||
|
|
|
@ -42,8 +42,7 @@ void keyboard_interrupt(void)
|
|||
*/
|
||||
void keyboard_init(void)
|
||||
{
|
||||
timer_start(TIMER_KEYBOARD, 1700, TIMER_Po_256, keyboard_interrupt,
|
||||
0);
|
||||
timer_start(TIMER_KEYBOARD, 1700, TIMER_Po_256, keyboard_interrupt, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
14
src/tales/gtext.c
Normal file
14
src/tales/gtext.c
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include <tales.h>
|
||||
#include <gray.h>
|
||||
|
||||
/*
|
||||
gtext()
|
||||
Prints the given raw string.
|
||||
*/
|
||||
void gtext(const char *str, int x, int y)
|
||||
{
|
||||
display_useVRAM(gray_lightVRAM());
|
||||
dtext(str, x, y);
|
||||
display_useVRAM(gray_darkVRAM());
|
||||
dtext(str, x, y);
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
text_configure()
|
||||
Sets the font and mode to use for the following print operations.
|
||||
*/
|
||||
void text_configure(struct Font *font)
|
||||
void text_configure(struct Font *next_font)
|
||||
{
|
||||
font = next_font;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include <timer.h>
|
||||
#include <timer_internals.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
struct Timer timers[3] = { { NULL, 0 }, { NULL, 0 }, { NULL, 0 } };
|
||||
|
||||
/*
|
||||
|
@ -9,7 +11,6 @@ struct Timer timers[3] = { { NULL, 0 }, { NULL, 0 }, { NULL, 0 } };
|
|||
*/
|
||||
void timer_interrupt(int timer)
|
||||
{
|
||||
// Getting the timer address.
|
||||
struct mod_tmu *tmu;
|
||||
timer_get(timer, &tmu, NULL);
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include <timer.h>
|
||||
#include <timer_internals.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/*
|
||||
timer_stop()
|
||||
Stops the given timer. This function may be called even if the timer is
|
||||
|
|
Loading…
Reference in a new issue