Merge pull request 'v.0.1' (#1) from dev into master

Reviewed-on: https://gitea.planet-casio.com/mibi88/libMicrofx/pulls/1
This commit is contained in:
mibi88 2023-01-19 09:39:30 +01:00
commit 9639301d13
20 changed files with 845 additions and 1 deletions

View File

@ -1,3 +1,15 @@
# libMicrofx
Make very small add-ins.
Make very small add-ins.
With this library you can easly make very small add-ins, but they are not as fast as add-ins made using gint, so you should use gint to write more complex add-ins. This library only provides support of the fx98xx series of CASIO monochrome calculators that support add-ins.
## Getting started
An example add-in is in template. Start your project with this folder. Requires sh-elf-* of the fxsdk.
The library is in microfx_src. If the library was updated, update you project by replacing lib with a new version compiled by typing `make` in microfx_src.
You can read the header files in lib/include/microfx to see the available functions.
Thanks to Lephenixnoir and Yatis for their help !

27
microfx_src/Makefile Normal file
View File

@ -0,0 +1,27 @@
CC = sh-elf-gcc
AR = sh-elf-ar
OUT = libMicrofx.a
OUT_DIR = lib
SRC = src/start.c src/syscall.S src/microfx.c src/img.c
OBJ = $(SRC:src/%=build/%.o)
BUILD = build
all: $(OBJ) | $(OUT_DIR)/
$(AR) rsv $(OUT_DIR)/$(OUT) $(OBJ)
cp --recursive include $(OUT_DIR)/
cp src/fx98xx.ld $(OUT_DIR)/
$(BUILD)/%.o: src/% | $(BUILD)/
$(CC) -c $< -o $@ -Os
.PRECIOUS: %/
%/:
@ mkdir -p $@
clean: $(BUILD)/ | $(OUT_DIR)/
rm $(OUT_DIR) --recursive
rm $(BUILD) --recursive

View File

@ -0,0 +1,6 @@
#ifndef MICROFX_CONFIG_H
#define MICROFX_CONFIG_H
#define EX_VERSION "@libMicrofx_VERSION@"
#endif

View File

@ -0,0 +1,20 @@
#ifndef IMG_H
#define IMG_H
enum {SNORMAL = 0, SINVERTED, STRANSP, SNOWHITE, SNOBLACK};
/* void simage(int sx, int sy, int w, int h, unsigned char *img, int mode);
Draws an image from a Sprite Coder string that is in img,
where the top left corner is at (sx, sy).
w is the width and h the height of the image.
mode can be :
SNORMAL : Draws the image normally.
SINVERTED : Draws the image with inverted colors.
STRANSP : Black is white and white is not drawn. Useful for
transparency in sprites.
*/
void simage(int sx, int sy, int w, int h, unsigned char *img, int mode);
#endif

View File

@ -0,0 +1,63 @@
#ifndef KEYCODES_H
#define KEYCODES_H
#define KCF1 79
#define KCF2 69
#define KCF3 59
#define KCF4 49
#define KCF5 39
#define KCF6 29
#define KCSHIFT 78
#define KCOPTN 68
#define KCVARS 58
#define KCMENU 48
#define KCLEFT 38
#define KCUP 28
#define KCALPHA 77
#define KCX2 67
#define KCPOW 57
#define KCEXIT 47
#define KCDOWN 37
#define KCRIGHT 27
#define KCXOT 76
#define KCLOG 66
#define KCLN 56
#define KCSIN 46
#define KCCOS 36
#define KCTAN 26
#define KCFRAC 75
#define KCSD 65
#define KCLPAR 55
#define KCRPAR 45
#define KCCOMMA 35
#define KCARROW 25
#define KC7 74
#define KC8 64
#define KC9 54
#define KCDEL 44
#define KCAC 10
#define KC4 73
#define KC5 63
#define KC6 53
#define KCMULTI 43
#define KCDIV 33
#define KC1 72
#define KC2 62
#define KC3 52
#define KCPLUS 42
#define KCMIN 32
#define KC0 71
#define KCDOT 61
#define KCEXP 51
#define KCNEGA 41
#define KCEXE 31
#endif

View File

@ -0,0 +1,132 @@
#ifndef MICROFX_H
#define MICROFX_H
#include "keycodes.h"
/******* DISPLAY *******/
enum {SWHITE = 0, SBLACK};
/* void sclear(void);
Clears the VRAM in white.
*/
void sclear(void);
/* void supdate(void);
Put the VRAM on the screen.
*/
void supdate(void);
/* void srect(int x1, int y1, int x2, int y2);
Draws a white rectangle with a black border of one pixel from (x1, y1) to (x2, y2)
in the VRAM.
*/
void srect(int x1, int y1, int x2, int y2);
/* void sline(int x1, int y1, int x2, int y2, int color);
Draws a line with a width of one pixel from (x1, y1) to (x2, y2) in the VRAM of
color color.
The available colors are SWHITE or SBLACK.
*/
void sline(int x1, int y1, int x2, int y2, int color);
/* void spixel(int x, int y, int color);
Set the pixel at (x, y) in the color color in the VRAM.
The available colors are SWHITE or SBLACK.
*/
void spixel(int x, int y, int color);
/* void stext(int x, int y, char *text);
Puts the text text at (x, y) on the screen using casio
default font.
*/
void stext(int x, int y, char *text);
/* void slocate(int x, int y, char *text);
Works like the Locate function of CASIO Basic.
*/
void slocate(int x, int y, char *text);
/******* KEYBOARD *******/
/* int kisdown(void);
Returns a positive int if a key is down.
Returns 0 if there is no key down.
*/
int kisdown(void);
/* int kcheck(int key, int type);
/!\ Not working /!\
Checks if the key key is down or not : returns a positive
int if the key is down, or 0 if he's not down.
*/
int kcheck(int key);
/* int kgetkey(void);
Works like the Getkey function of CASIO Basic.
Returns the pressed key.
*/
int kgetkey(void);
/******* TOOLS *******/
/* void itoa(int n, char *buffer);
Put a string of the int n in buffer.
*/
void itoa(int n, char *buffer);
/******* TIME *******/
/* void tsleep_ms(int ms);
Wait ms miliseconds.
*/
void tsleep_ms(int ms);
/* void tgetticks(void);
Get 1/128 seconds ticks since midnight.
*/
int tgetticks(void);
/* int tiselapsed(int start, int ms);
Check if ms where elapsed since start (ticks that you can
get with tgetticks).
Returns 1 if ms is elapsed and 0 if it is not.
*/
int tiselapsed(int start, int ms);
/******* CPU *******/
/* void csleep(void);
Uses asm sleep instruction.
Can be used to reduce battery usage of some loops.
*/
void csleep(void);
#endif

33
microfx_src/src/fx98xx.ld Normal file
View File

@ -0,0 +1,33 @@
ENTRY(_start)
MEMORY
{
rom (rx) : ORIGIN = 0x00300200, LENGTH = 512K
ram (rw) : ORIGIN = 0x08100200, LENGTH = 20K
}
SECTIONS
{
.text : {
*(.pretext)
*(.text)
} > rom
.rodata : {
*(.rodata)
*(.rodata.str1.4)
_romdata_start = . ;
} > rom
.bss : {
_start_bss = . ;
_bssdatasize = . ;
LONG(0);
*(.bss)
*(COMMON)
_end_bss = . ;
} > ram
.data : AT(_romdata_start) {
_start_data = . ;
*(.data)
_end_data = . ;
} > ram
}

29
microfx_src/src/img.c Normal file
View File

@ -0,0 +1,29 @@
#include "../include/microfx/ext/img.h"
#include <microfx/microfx.h>
void simage(int sx, int sy, int w, int h, unsigned char *img, int mode) {
/* Draws an image from a sprite coder string */
int x, y, rpos, gpos, bpos, color;
for(y=0;y<h;y++){
for(x=0;x<w;x++){
rpos = y*(w+(w%2))+x;
gpos = rpos/8;
bpos = rpos%8;
color = (img[gpos] << bpos) & 0x80;
switch(mode){
case STRANSP:
if(color) spixel(sx+x, sy+y, SWHITE);
break;
case SNOWHITE:
if(color) spixel(sx+x, sy+y, SBLACK);
break;
case SNOBLACK:
if(!color) spixel(sx+x, sy+y, SWHITE);
break;
default: /* SNORMAL or SINVERTED */
spixel(sx+x, sy+y, mode ? !color : color);
break;
}
}
}
}

119
microfx_src/src/microfx.c Normal file
View File

@ -0,0 +1,119 @@
#include "../include/microfx/microfx.h"
/******* DISPLAY *******/
/* Syscalls */
void _Bdisp_PutDisp_DD(void);
void _Bdisp_DrawRectangle(int x1, int y1, int x2, int y2);
void _Bdisp_AllClr_VRAM(void);
void _Bdisp_SetPoint_VRAM(int x, int y, int color);
void _PrintXY(int x, int y, unsigned char *text, int type);
void _locate(int x, int y);
void _Print(unsigned char *text);
void _Bdisp_DrawLineVRAM(int x1, int y1, int x2, int y2);
void _Bdisp_ClearLineVRAM(int x1, int y1, int x2, int y2);
/* Microfx */
void sclear() {
_Bdisp_AllClr_VRAM();
}
void supdate() {
_Bdisp_PutDisp_DD();
}
void spixel(int x, int y, int color) {
_Bdisp_SetPoint_VRAM(x, y, color);
}
void srect(int x1, int y1, int x2, int y2) {
_Bdisp_DrawRectangle(x1, y1, x2, y2);
}
void sline(int x1, int y1, int x2, int y2, int color) {
if(color){
_Bdisp_DrawLineVRAM(x1, y1, x2, y2);
}else{
_Bdisp_ClearLineVRAM(x1, y1, x2, y2);
}
}
void stext(int x, int y, char *text) {
_PrintXY(x, y, (unsigned char*)text, 0);
}
void slocate(int x, int y, char *text) {
_locate(x, y);
_Print((unsigned char*)text);
}
/******* KEYBOARD *******/
/* Syscalls */
short _Keyboard_GetPressedTime(void);
int _Keyboard_KeyDown(void);
int _Keyboard_PRGM_GetKey(unsigned char* buffer);
/* Microfx */
int kisdown(void) {
return _Keyboard_KeyDown();
}
int kcheck(int key) {
/* TODO : Compatibility with older calcs. */
/* Get the column and the row of the key. */
int row = key%10;
int column = key/10 - 1;
/* The bit that I will read in the KIUDATA
register. */
int column_pos = column + 8 * (row & 1);
/* row_data will contain the data of the
KIUDATA register that we need.
keyboard_register contains the address of
KIUDATA0. */
unsigned short *keyboard_register = (unsigned short*)0xA44B0000;
unsigned short row_data;
/* Get KIUDATAx where x is row / 2 because two rows
are stored in each KIUDATA register. */
row_data = keyboard_register[row/2];
/* Get the bit located at column. */
return (row_data >> column_pos) & 1;
}
int kgetkey(void){
unsigned char buffer[12];
_Keyboard_PRGM_GetKey(buffer);
return (buffer[1] & 0x0F) * 10 + ((buffer[2] & 0xF0 ) >> 4);
}
/******* Time *******/
/* Syscalls */
void _Sleep(int delay_ms);
int _RTC_GetTicks(void);
int _RTC_Elapsed_ms(int start_value, int duration_in_ms);
/* Microfx */
void tsleep_ms(int ms) {
_Sleep(ms);
}
int tgetticks(void) {
return _RTC_GetTicks();
}
int tiselapsed(int start, int ms) {
return _RTC_Elapsed_ms(start, ms);
}
/******* CPU *******/
void csleep(void) {
__asm__("sleep");
}

21
microfx_src/src/start.c Normal file
View File

@ -0,0 +1,21 @@
extern char start_bss, end_bss;
extern char start_data, end_data;
extern char romdata_start;
extern int main(void);
__attribute__((section(".pretext")))
int start(int isappli, int optnum) {
int i;
char *bss_startptr = &start_bss;
for(i=0;i<&end_bss - &start_bss;i++){
bss_startptr[i] = 0;
}
char *data_startptr = &start_data;
char *romdataptr = &romdata_start;
for(i=0;i<&end_data - &start_data;i++){
data_startptr[i] = romdataptr[i];
}
return main();
}

82
microfx_src/src/syscall.S Normal file
View File

@ -0,0 +1,82 @@
.text
.global __Bdisp_PutDisp_DD
.global __Bdisp_DrawRectangle
.global __Bdisp_AllClr_VRAM
.global __Bdisp_SetPoint_VRAM
.global __Bdisp_GetPoint_VRAM
.global __PrintXY
.global __locate
.global __Print
.global __Bdisp_DrawLineVRAM
.global __Bdisp_ClearLineVRAM
/* Keyboard */
.global __Keyboard_GetPressedTime
.global __Keyboard_IsKeyPressed
.global __Keyboard_IsKeyPressed_fast
.global __Keyboard_KeyDown
.global __Keyboard_PRGM_GetKey
/* Time */
.global __Sleep
.global __RTC_GetTicks
.global __RTC_Elapsed_ms
/* Files */
/* Tools */
.global _itoa
#define syscall(syscall_number) \
mov.l 1f, r0 ;\
mov.l do_syscall, r2 ;\
jmp @r2 ;\
nop ;\
.align 4 ;\
1: .long syscall_number
/* Display */
__Bdisp_PutDisp_DD:
syscall(0x028)
__Bdisp_DrawRectangle:
syscall(0x0763)
__Bdisp_AllClr_VRAM:
syscall(0x143)
__Bdisp_SetPoint_VRAM:
syscall(0x146)
__Bdisp_GetPoint_VRAM:
syscall(0x149)
__PrintXY:
syscall(0x150)
__locate:
syscall(0x807)
__Print:
syscall(0x808)
__Bdisp_DrawLineVRAM:
syscall(0x030)
__Bdisp_ClearLineVRAM:
syscall(0x031)
/* Keyboard */
__Keyboard_GetPressedTime:
syscall(0x249)
__Keyboard_IsKeyPressed:
syscall(0x24C)
__Keyboard_IsKeyPressed_fast:
syscall(0x24B)
__Keyboard_KeyDown:
syscall(0x24D)
__Keyboard_PRGM_GetKey:
syscall(0x6C4)
/* Time */
__Sleep:
syscall(0x0420)
__RTC_GetTicks:
syscall(0x03B)
__RTC_Elapsed_ms:
syscall(0x03C)
/* Files */
/* Nothing here ... */
/* Tools */
_itoa:
syscall(0x541)
/* Menu */
/* Nothing here ... */
do_syscall: .long 0x80010070

40
template/Makefile Normal file
View File

@ -0,0 +1,40 @@
NAME = Template
ELF = $(NAME).elf
BIN = $(NAME).bin
CC = sh-elf-gcc
SRC = src/main.c
OBJ = $(SRC:src/%=build/%.o)
ICON = icon.png
LIB = lib
BUILD = build
VERSION = v.1.0
all: $(BIN)
fxgxa --g1a -n $(NAME) -i $(ICON) --version="$(VERSION)" -o $(NAME).g1a build/$(BIN)
sh-elf-objdump -h $(BUILD)/$(ELF)
$(BIN): $(ELF)
sh-elf-objcopy -O binary build/$(ELF) build/$(BIN) -R .bss
$(ELF): $(OBJ) | $(LIB)/
$(CC) $(OBJ) $(LIB)/libMicrofx.a -o $(BUILD)/$@ -nostdlib -T lib/fx98xx.ld -ffreestanding -mb -m3 -Os -Wa,--dsp
$(BUILD)/%.o: src/% | $(BUILD)/
$(CC) -c $< -o $@ -Os -Ilib/include/
.PRECIOUS: %/
%/:
@ mkdir -p $@
clean: $(BUILD)
rm $(BUILD) --recursive
rm $(NAME).g1a

BIN
template/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

33
template/lib/fx98xx.ld Normal file
View File

@ -0,0 +1,33 @@
ENTRY(_start)
MEMORY
{
rom (rx) : ORIGIN = 0x00300200, LENGTH = 512K
ram (rw) : ORIGIN = 0x08100200, LENGTH = 20K
}
SECTIONS
{
.text : {
*(.pretext)
*(.text)
} > rom
.rodata : {
*(.rodata)
*(.rodata.str1.4)
_romdata_start = . ;
} > rom
.bss : {
_start_bss = . ;
_bssdatasize = . ;
LONG(0);
*(.bss)
*(COMMON)
_end_bss = . ;
} > ram
.data : AT(_romdata_start) {
_start_data = . ;
*(.data)
_end_data = . ;
} > ram
}

View File

@ -0,0 +1,6 @@
#ifndef MICROFX_CONFIG_H
#define MICROFX_CONFIG_H
#define EX_VERSION "@libMicrofx_VERSION@"
#endif

View File

@ -0,0 +1,20 @@
#ifndef IMG_H
#define IMG_H
enum {SNORMAL = 0, SINVERTED, STRANSP, SNOWHITE, SNOBLACK};
/* void simage(int sx, int sy, int w, int h, unsigned char *img, int mode);
Draws an image from a Sprite Coder string that is in img,
where the top left corner is at (sx, sy).
w is the width and h the height of the image.
mode can be :
SNORMAL : Draws the image normally.
SINVERTED : Draws the image with inverted colors.
STRANSP : Black is white and white is not drawn. Useful for
transparency in sprites.
*/
void simage(int sx, int sy, int w, int h, unsigned char *img, int mode);
#endif

View File

@ -0,0 +1,63 @@
#ifndef KEYCODES_H
#define KEYCODES_H
#define KCF1 79
#define KCF2 69
#define KCF3 59
#define KCF4 49
#define KCF5 39
#define KCF6 29
#define KCSHIFT 78
#define KCOPTN 68
#define KCVARS 58
#define KCMENU 48
#define KCLEFT 38
#define KCUP 28
#define KCALPHA 77
#define KCX2 67
#define KCPOW 57
#define KCEXIT 47
#define KCDOWN 37
#define KCRIGHT 27
#define KCXOT 76
#define KCLOG 66
#define KCLN 56
#define KCSIN 46
#define KCCOS 36
#define KCTAN 26
#define KCFRAC 75
#define KCSD 65
#define KCLPAR 55
#define KCRPAR 45
#define KCCOMMA 35
#define KCARROW 25
#define KC7 74
#define KC8 64
#define KC9 54
#define KCDEL 44
#define KCAC 10
#define KC4 73
#define KC5 63
#define KC6 53
#define KCMULTI 43
#define KCDIV 33
#define KC1 72
#define KC2 62
#define KC3 52
#define KCPLUS 42
#define KCMIN 32
#define KC0 71
#define KCDOT 61
#define KCEXP 51
#define KCNEGA 41
#define KCEXE 31
#endif

View File

@ -0,0 +1,132 @@
#ifndef MICROFX_H
#define MICROFX_H
#include "keycodes.h"
/******* DISPLAY *******/
enum {SWHITE = 0, SBLACK};
/* void sclear(void);
Clears the VRAM in white.
*/
void sclear(void);
/* void supdate(void);
Put the VRAM on the screen.
*/
void supdate(void);
/* void srect(int x1, int y1, int x2, int y2);
Draws a white rectangle with a black border of one pixel from (x1, y1) to (x2, y2)
in the VRAM.
*/
void srect(int x1, int y1, int x2, int y2);
/* void sline(int x1, int y1, int x2, int y2, int color);
Draws a line with a width of one pixel from (x1, y1) to (x2, y2) in the VRAM of
color color.
The available colors are SWHITE or SBLACK.
*/
void sline(int x1, int y1, int x2, int y2, int color);
/* void spixel(int x, int y, int color);
Set the pixel at (x, y) in the color color in the VRAM.
The available colors are SWHITE or SBLACK.
*/
void spixel(int x, int y, int color);
/* void stext(int x, int y, char *text);
Puts the text text at (x, y) on the screen using casio
default font.
*/
void stext(int x, int y, char *text);
/* void slocate(int x, int y, char *text);
Works like the Locate function of CASIO Basic.
*/
void slocate(int x, int y, char *text);
/******* KEYBOARD *******/
/* int kisdown(void);
Returns a positive int if a key is down.
Returns 0 if there is no key down.
*/
int kisdown(void);
/* int kcheck(int key, int type);
/!\ Not working /!\
Checks if the key key is down or not : returns a positive
int if the key is down, or 0 if he's not down.
*/
int kcheck(int key);
/* int kgetkey(void);
Works like the Getkey function of CASIO Basic.
Returns the pressed key.
*/
int kgetkey(void);
/******* TOOLS *******/
/* void itoa(int n, char *buffer);
Put a string of the int n in buffer.
*/
void itoa(int n, char *buffer);
/******* TIME *******/
/* void tsleep_ms(int ms);
Wait ms miliseconds.
*/
void tsleep_ms(int ms);
/* void tgetticks(void);
Get 1/128 seconds ticks since midnight.
*/
int tgetticks(void);
/* int tiselapsed(int start, int ms);
Check if ms where elapsed since start (ticks that you can
get with tgetticks).
Returns 1 if ms is elapsed and 0 if it is not.
*/
int tiselapsed(int start, int ms);
/******* CPU *******/
/* void csleep(void);
Uses asm sleep instruction.
Can be used to reduce battery usage of some loops.
*/
void csleep(void);
#endif

BIN
template/lib/libMicrofx.a Normal file

Binary file not shown.

6
template/src/main.c Normal file
View File

@ -0,0 +1,6 @@
#include <microfx/microfx.h>
int main(void) {
stext(1, 1, "A Microfx Add-in !");
return 1;
}