Compare commits

...

19 Commits
master ... dev

Author SHA1 Message Date
Sylvain PILLOT 883ca77167
corrected typo for send option 2024-03-21 08:30:00 +01:00
Sylvain PILLOT 8574824b31
removed build-fxascg-push target due to possible RAM allocation issues 2024-03-21 08:30:00 +01:00
Sylvain PILLOT 45b207b150
'fxsdk build-fx-as-cg' working and added send command line option 2024-03-21 08:30:00 +01:00
Sylvain PILLOT a3aa537e84
Start working on a build target FX9860G_AS_CG for fxSDK & gint 2024-03-21 08:30:00 +01:00
Lephenixnoir 4c307af02b
fxconv: preliminary support for fonts in PythonExtra 2024-03-21 08:29:06 +01:00
Lephenixnoir 2acc439ed4
fxsdk: add TARGET_FXCG50_FASTLOAD macro for add-in push builds 2024-02-03 19:45:15 +01:00
Lephenixnoir 8030d6bdc6
fxconv: PythonExtra support for bopti-cg 2024-02-03 16:00:05 +01:00
Lephenixnoir 4a84bfdcd4
fxconv: fix stupid compact mode bug 2024-02-03 16:00:05 +01:00
Lephenixnoir 6e62fb7d6d
fxconv: PythonExtra support for bopti-fx 2024-02-01 17:48:45 +01:00
Lephenixnoir 975f29a471
fxconv: (fix indent) 2024-01-31 23:28:49 +01:00
Lephenixnoir da79a6a0e8
fxlink: add --folder option to fxlink -s to select output folder 2024-01-30 22:19:19 +01:00
Lephenixnoir ecf04cb634
fxconv: make bopti-fx image data a pointer 2024-01-21 21:06:01 +01:00
Lephenixnoir 45fd52444f
fxlink: add (unused) scale parameter to SDL2 video capture 2024-01-21 21:05:36 +01:00
Lephenixnoir 9f4d17ca4f
fxlink: don't free glib pointer apparently not malloc'ed 2023-12-03 16:08:58 +01:00
Lephenixnoir 8f50f7694a
fxconv: fix c-c/c-v in range error messages 2023-10-17 21:56:38 +02:00
Lephenixnoir 88235041a3
fxconv: add i8/i16/i32, with range checks 2023-10-17 20:18:09 +02:00
Lephenixnoir be8c1f0d94
fxconv: alignment parameter in fxconv.ptr() (default 4) 2023-08-20 10:41:53 +02:00
Lephenixnoir 11e3b614c2
fxconv: add an elf_multi() function to produce multiple variables 2023-08-15 21:59:17 +02:00
Lephenixnoir cf3ab5d5e0
fxconv: copy elements in += ObjectData instead of referencing subobject
This way, after o1 += o2, when o1 is linked all the outer data of o2 is
linked alongside the outer data of o1, and the inner data remains
contiguous. This is important for arrays, where we don't want the outer
data of o2 to appear before the next inner field of o1.

With this commit, an update to o2 after o1 += o2 no longer updates o1.
This wasn't a feature in the first place.
2023-08-08 20:26:37 +02:00
12 changed files with 326 additions and 75 deletions

4
bld Executable file
View File

@ -0,0 +1,4 @@
PREFIX=$HOME/.local make -f giteapc.make configure
sudo make -C build install

View File

@ -23,6 +23,7 @@ When TYPE is specified (one-shot conversion), it should be one of:
--libimg-image Convert to the libimg image format
--custom Use a custom converter; you might want to specify an explicit
type by adding "custom-type:your_custom_type" (see below)
Custom converters can be specified by:
--converters Semicolon-separated list of custom converters (converters.py
in the current directory is detected as one per legacy)
@ -31,8 +32,13 @@ syntax (names can contain dots). For example:
fxconv -f myfont.png -o myfont.o charset:ascii grid.padding:1 height:7
Some formats differ between platforms so you should specify it when possible:
--fx Casio fx-9860G family (black-and-white calculators)
--cg Casio fx-CG 50 family (16-bit color calculators)
--fx CASIO fx-9860G family (black-and-white calculators)
--cg CASIO fx-CG 50 family (16-bit color calculators)
Finally, there is some support (non-final) for PythonExtra, in which case the
output file is as Python file instead of an object file.
--py Convert for PythonExtra (some types supported)
--py-compact Use compact bytes notation (shorter, but non-printable)
""".strip()
# Simple error-warnings system
@ -60,6 +66,7 @@ def main():
target = { 'toolchain': None, 'arch': None, 'section': None }
use_custom = False
converter_paths = []
py = { 'enabled': False, 'compact': False }
# Parse command-line arguments
@ -69,7 +76,7 @@ def main():
try:
longs = ["help", "output=", "toolchain=", "arch=", "section=", "fx",
"cg", "converters="] + types.split()
"cg", "converters=", "py", "py-compact"] + types.split()
opts, args = getopt.gnu_getopt(sys.argv[1:], "hsbifo:", longs)
except getopt.GetoptError as error:
return err(error)
@ -94,6 +101,10 @@ def main():
mode = "custom"
elif name == "--converters":
converter_paths = [path for path in value.split(";") if path]
elif name == "--py":
py['enabled'] = True
elif name == "--py-compact":
py['compact'] = True
# Other names are modes
else:
mode = name[1] if len(name)==2 else name[2:]
@ -144,6 +155,7 @@ def main():
spec.loader.exec_module(module)
converters.append(module.convert)
params["py"] = py
fxconv.convert(input, params, target, output, model, converters)
if __name__ == "__main__":

View File

@ -15,7 +15,7 @@ __all__ = [
# Color names
"FX_BLACK", "FX_DARK", "FX_LIGHT", "FX_WHITE", "FX_ALPHA",
# Conversion mechanisms
"ObjectData", "u8", "u16", "u32", "ref", "sym",
"ObjectData", "u8", "u16", "u32", "i8", "i16", "i32", "ref", "sym",
# Functions
"quantize", "convert", "elf",
# Reusable classes
@ -69,7 +69,7 @@ FX_PROFILES = [
FxProfile(0x0, "mono", { FX_BLACK, FX_WHITE }, [
lambda c: (c == FX_BLACK),
]),
# Black-and-white with transparency, equivalent of two bitmaps in ML
# Black-and-white with transparency, equivalent of two bitmaps in ML
FxProfile(0x1, "mono_alpha", { FX_BLACK, FX_WHITE, FX_ALPHA }, [
lambda c: (c != FX_ALPHA),
lambda c: (c == FX_BLACK),
@ -159,7 +159,7 @@ FX_CHARSETS = {
"ascii": [ (0x00, 128) ],
# Custom Unicode block intervals
"unicode": [],
# Single block 0x00-0xff (does not imply single-byte encoding)
# Single block 0x00-0xff (does not imply single-byte encoding)
"256chars": [ (0x00, 256) ],
}
@ -167,21 +167,40 @@ FX_CHARSETS = {
# Conversion mechanisms
#
def u8(x):
return bytes([ x & 255 ])
def u16(x):
return bytes([ (x >> 8) & 255, x & 255 ])
def u32(x):
return bytes([ (x >> 24) & 255, (x >> 16) & 255, (x >> 8) & 255, x & 255 ])
def u8(x, check=False):
if check and not (0 <= x < 2**8):
raise FxconvError(f"integer {x} out of range for u8")
return bytes([ x & 255 ])
def u16(x, check=False):
if check and not (0 <= x < 2**16):
raise FxconvError(f"integer {x} out of range for u16")
return bytes([ (x >> 8) & 255, x & 255 ])
def u32(x, check=False):
if check and not (0 <= x < 2**32):
raise FxconvError(f"integer {x} out of range for u32")
return bytes([ (x >> 24) & 255, (x >> 16) & 255, (x >> 8) & 255, x & 255 ])
def ref(base, offset=None, padding=None, prefix_underscore=True):
def i8(x, check=True):
if check and not (-2**7 <= x < 2**7):
raise FxconvError(f"integer {x} out of range for i8")
return bytes([ x & 255 ])
def i16(x, check=True):
if check and not (-2**15 <= x < 2**15):
raise FxconvError(f"integer {x} out of range for i16")
return bytes([ (x >> 8) & 255, x & 255 ])
def i32(x, check=True):
if check and not (-2**31 <= x < 2**31):
raise FxconvError(f"integer {x} out of range for i32")
return bytes([ (x >> 24) & 255, (x >> 16) & 255, (x >> 8) & 255, x & 255 ])
def ref(base, offset=None, padding=None, prefix_underscore=True, align=None):
if isinstance(base, bytes) or isinstance(base, bytearray):
base = bytes(base)
if offset is not None:
raise FxconvError(f"reference to bytes does not allow offset")
if padding and len(base) % padding != 0:
base += bytes(padding - len(base) % padding)
return Ref("bytes", base)
return Ref("bytes", base, align or 4)
elif isinstance(base, str):
if padding is not None:
@ -191,19 +210,24 @@ def ref(base, offset=None, padding=None, prefix_underscore=True):
if offset is not None:
offset = int(offset)
base = f"{base} + {offset}"
return Ref("name", base)
return Ref("name", base, align or 4)
elif isinstance(base, ObjectData):
if offset is not None or padding is not None:
raise FxconvError("reference to structure does not allow offset " +
"or padding")
return Ref("struct", base)
if offset is not None:
raise FxconvError("reference to structure does not allow offset")
if padding is not None:
raise FxconvError("reference to structure does not allow padding")
# Allow over-aligning the structure (but not more than 4)
align = max(base.alignment, align or 4)
if align > 4:
raise FxconvError(f"align {align} > 4 will not be honored (yet)")
return Ref("struct", base, align)
else:
raise FxconvError(f"invalid type {type(base)} for ref()")
def ptr(base):
return ref(base)
def ptr(*args, **kwargs):
return ref(*args, **kwargs)
def chars(text, length, require_final_nul=True):
btext = bytes(text, 'utf-8')
@ -221,7 +245,7 @@ def sym(name):
# "bytes" -> target is a bytes(), we point to that data
# "name" -> target is an str like "_sym+2", we point to that
# "struct" -> target is an ObjectData
Ref = collections.namedtuple("Ref", ["kind", "target"])
Ref = collections.namedtuple("Ref", ["kind", "target", "align"])
Sym = collections.namedtuple("Sym", ["name"])
@ -250,7 +274,7 @@ class ObjectData:
elif isinstance(other, Sym):
self.inner.append(other)
elif isinstance(other, ObjectData):
self.inner.append(other)
self.inner += other.inner
return self
@staticmethod
@ -273,34 +297,23 @@ class ObjectData:
return padding
def link(self, symbol):
inner = []
inner = self.inner
outer = []
elements = []
size = 0
# First unfold all structures within [inner] as we accumulate the total
# size of the inner data
for el in self.inner:
if isinstance(el, ObjectData):
size += self.align(size, el.alignment, inner)
code, code_size = el.link(f"{symbol} + {size}")
inner.append((code, code_size))
size += code_size
else:
inner.append(el)
size += self.element_size(el)
size = sum(self.element_size(el) for el in inner)
# Then replace complex references with unfolded data appended at the
# end of the structure
for el in inner:
if isinstance(el, Ref) and el.kind == "bytes":
elements.append(Ref("name", f"{symbol} + {size}"))
size += self.align(size, el.align, outer)
elements.append(Ref("name", f"{symbol} + {size}", None))
outer.append(el.target)
size += self.element_size(el.target)
elif isinstance(el, Ref) and el.kind == "struct":
size += self.align(size, el.target.alignment, outer)
elements.append(Ref("name", f"{symbol} + {size}"))
elements.append(Ref("name", f"{symbol} + {size}", None))
code, code_size = el.target.link(f"{symbol} + {size}")
outer.append((code, code_size))
size += code_size
@ -500,8 +513,16 @@ def convert_bopti_fx(input, params):
data[n] = layer[4 * longword + i]
n += 1
if params["py"]["enabled"]:
w, h = img.size
return ["import gint\n",
f"{params['name']} = gint.image({p.id}, {w}, {h}, ", data, ")\n"]
# Generate the object file
return header + data
o = ObjectData()
o += header
o += ptr(data)
return o
def _image_project(img, f):
# New width and height
@ -581,6 +602,17 @@ def convert_image_cg(input, params):
data, stride, palette, color_count = image_encode(img, format)
if params["py"]["enabled"]:
w, h = img.size
return [
"import gint\n",
f"{params['name']} = gint.image({format.id}, {color_count}, ",
f"{img.width}, {img.height}, {stride}, ",
data,
", ",
"None" if palette is None else palette,
")\n"]
o = ObjectData()
o += u8(format.id)
o += u8(3) # DATA_RO, PALETTE_RO
@ -775,6 +807,19 @@ def convert_topti(input, params):
# Object file generation
#---
if params["py"]["enabled"]:
l = [ "import gint\n",
f"{params['name']} = gint.font({title or None}, {flags}, ",
f"{line_height}, {grid.h}, {len(blocks)}, {glyph_count}, ",
f"{char_spacing}, ",
data_blocks,
data_glyphs ]
if proportional:
l += [data_index, data_width]
else:
l += [f"{grid.w}, {(grid.w * grid.h + 31) >> 5}"]
return l + [")\n"]
# Base data: always put the raw data and blocks first since they are
# 4-aligned, to preserve alignment on the rest of the references.
o = ObjectData()
@ -1139,8 +1184,14 @@ def convert(input, params, target, output=None, model=None, custom=None):
else:
raise FxconvError(f'unknown resource type \'{t}\'')
# PythonExtra conversion: output a file
if params["py"]["enabled"]:
if isinstance(o, ObjectData):
raise FxconvError(f'conversion doe not support Python output')
pyout(o, output, params)
# Standard conversions: save to ELF in the natural way
elf(o, output, "_" + params["name"], **target)
else:
elf(o, output, "_" + params["name"], **target)
def elf(data, output, symbol, toolchain=None, arch=None, section=None,
assembly=None):
@ -1154,9 +1205,9 @@ def elf(data, output, symbol, toolchain=None, arch=None, section=None,
The symbol name must have a leading underscore if it is to be declared and
used from a C program.
The toolchain can be any target triplet for which the compiler is
available. The architecture is deduced from some typical triplets;
otherwise it can be set, usually as "sh3" or "sh4-nofpu". This affects the
The toolchain can be any target triplet for which the compiler is
available. The architecture is deduced from some typical triplets;
otherwise it can be set, usually as "sh3" or "sh4-nofpu". This affects the
--binary-architecture flag of objcopy. If arch is set to "fx" or "cg", this
function tries to be smart and:
@ -1186,6 +1237,14 @@ def elf(data, output, symbol, toolchain=None, arch=None, section=None,
Produces an output file and returns nothing.
"""
# Unfold ObjectData into data and assembly
if isinstance(data, ObjectData):
assembly = f".global {symbol}\n" + \
f"{symbol}:\n" + \
data.link(symbol)[0] + \
(assembly or "")
data = None
# Toolchain parameters
if toolchain is None:
@ -1206,16 +1265,9 @@ def elf(data, output, symbol, toolchain=None, arch=None, section=None,
raise FxconvError(f"non-trivial architecture for {toolchain} must be "+
"specified")
# Unfold ObjectData into data and assembly
if isinstance(data, ObjectData):
asm = ".section " + section.split(",",1)[0] + "\n"
asm += f".global {symbol}\n"
asm += f"{symbol}:\n"
asm += data.link(symbol)[0]
asm += (assembly or "")
data = None
assembly = asm
if assembly:
sec = ".section " + section.split(",",1)[0]
assembly = sec + "\n" + assembly
if data is None and assembly is None:
raise FxconvError("elf() but no data and no assembly")
@ -1275,6 +1327,52 @@ def elf(data, output, symbol, toolchain=None, arch=None, section=None,
if assembly:
fp_asm.close()
def elf_multi(vars, output, assembly=None, **kwargs):
"""
Like elf(), but instead of one symbol/data pair, allows defining multiple
variables. vars should be a list [(symbol, ObjectData), ...]. Keyword
arguments are passed to elf().
"""
asm = ""
for symbol, objdata in vars:
asm += f".global {symbol}\n"
asm += f"{symbol}:\n"
asm += objdata.link(symbol)[0]
asm += assembly or ""
return elf(None, output, None, assembly=asm, **kwargs)
def pyout(bits, output, params):
# Compact into byte strings to avoid building tuples in the heap;
# MicroPython allows basically anything in literal strings (including
# NUL!), we just have to escape \, \n, \r, and ".
def byteify(c):
if c == ord('"'):
return b'\\"'
if c == ord('\n'):
return b'\\n'
if c == ord('\r'):
return b'\\r'
if c == ord('\\'):
return b'\\\\'
return bytes([c])
with open(output, "wb") as fp:
for section in bits:
if isinstance(section, bytearray):
section = bytes(section)
if isinstance(section, bytes):
if params["py"]["compact"]:
fp.write(b'b"')
for byte in section:
fp.write(byteify(byte))
fp.write(b'"')
else:
fp.write(repr(section).encode("utf-8"))
else:
fp.write(section.encode("utf-8"))
#
# Meta API
#

View File

@ -28,7 +28,8 @@ int main_list(struct fxlink_filter *filter, delay_t *delay,
int main_blocks(struct fxlink_filter *filter, delay_t *delay);
/* Main function for -s */
int main_send(struct fxlink_filter *filter, delay_t *delay, char **files);
int main_send(struct fxlink_filter *filter, delay_t *delay, char **files,
char *outfolder);
/* Main function for -i */
int main_interactive(struct fxlink_filter *filter, delay_t *delay,

View File

@ -20,7 +20,7 @@ static const char *help_string =
"usage: %1$s (-l|-b|-t) [General options]\n"
" %1$s -i [-r] [--fxlink-log[=<FILE>]] [General options]\n"
" %1$s -p <FILE> [General options]\n"
" %1$s -s <FILES>... [General options]\n"
" %1$s -s <FILES>... [--folder=OUTFOLDER] [General options]\n"
"\n"
"fxlink interacts with CASIO calculators of the fx and fx-CG families over\n"
"the USB port, using libusb. It can also transfer files for Mass Storage\n"
@ -47,6 +47,7 @@ static const char *help_string =
" --fxlink-log[=FILE] -i: Append fxlink text messages to FILE. Without\n"
" argument, a unique name is generated.\n"
" -r, --repeat -i: Reconnect if the calc disconnects (implies -w)\n"
" --folder=FOLDER -s: Select destination folder for files\n"
"\n"
"Device filters:\n"
" A device filter narrows down what devices we list or connect to by\n"
@ -67,6 +68,7 @@ int main(int argc, char **argv)
delay_t delay = delay_seconds(0);
struct fxlink_filter *filter = NULL;
bool repeat = false;
char *outfolder = NULL;
options.log_file = NULL;
options.verbose = false;
@ -77,7 +79,7 @@ int main(int argc, char **argv)
// Command-line argument parsing
//---
enum { LIBUSB_LOG=1, LOG_TO_FILE=2 };
enum { LIBUSB_LOG=1, LOG_TO_FILE=2, OUT_FOLDER=3 };
const struct option longs[] = {
{ "help", no_argument, NULL, 'h' },
{ "list", no_argument, NULL, 'l' },
@ -90,6 +92,7 @@ int main(int argc, char **argv)
{ "fxlink-log", optional_argument, NULL, LOG_TO_FILE },
{ "repeat", no_argument, NULL, 'r' },
{ "verbose", no_argument, NULL, 'v' },
{ "folder", required_argument, NULL, OUT_FOLDER },
/* Deprecated options ignored for compatibility: */
{ "quiet", no_argument, NULL, 'q' },
{ "unmount", no_argument, NULL, 'u' },
@ -165,6 +168,9 @@ int main(int argc, char **argv)
case 'f':
filter = fxlink_filter_parse(optarg);
break;
case OUT_FOLDER:
outfolder = strdup(optarg);
break;
case '?':
error = 1;
}
@ -219,7 +225,7 @@ int main(int argc, char **argv)
}
else if(mode == 's') {
#ifndef FXLINK_DISABLE_UDISKS2
rc = main_send(filter, &delay, argv + optind);
rc = main_send(filter, &delay, argv + optind, outfolder);
#else
rc = elog("this fxlink was built without UDisks2; -s is disabled");
#endif

View File

@ -44,11 +44,13 @@ static void handle_new_message(struct fxlink_device *fdev,
if(options.verbose)
printf("------------------\n");
fwrite(str, 1, msg->size, stdout);
#if 0
if(str[msg->size - 1] != '\n') {
if(!options.verbose)
printf("\e[30;47m%%\e[0m");
printf("\n");
}
#endif
if(options.verbose) {
printf("------------------\n");
}

View File

@ -16,7 +16,8 @@
#include <sys/types.h>
#include <sys/wait.h>
int main_send(struct fxlink_filter *filter, delay_t *delay, char **files)
int main_send(struct fxlink_filter *filter, delay_t *delay, char **files,
char *outfolder)
{
fxlink_filter_clean_udisks2(filter);
GError *error = NULL;
@ -53,10 +54,14 @@ int main_send(struct fxlink_filter *filter, delay_t *delay, char **files)
printf("Mounted %s to %s.\n", dev, folder);
}
else {
folder = strdup(mount_points[0]);
folder = mount_points[0];
printf("Already mounted at %s.\n", folder);
}
gchar *outpath = folder;
if(outfolder)
asprintf(&outpath, "%s/%s/", folder, outfolder);
/* Copy files with external cp(1) */
int file_count = 0;
while(files[file_count]) file_count++;
@ -69,7 +74,7 @@ int main_send(struct fxlink_filter *filter, delay_t *delay, char **files)
argv[0] = "cp";
for(int i = 0; files[i]; i++)
argv[i+1] = files[i];
argv[file_count+1] = folder;
argv[file_count+1] = outpath;
argv[file_count+2] = NULL;
/* Print command */
@ -97,6 +102,9 @@ int main_send(struct fxlink_filter *filter, delay_t *delay, char **files)
}
}
if(outfolder)
free(outpath);
/* Unmount the filesystem and eject the device */
GVariant *args = g_variant_new("a{sv}", NULL);
udisks_filesystem_call_unmount_sync(fs, args, NULL, &error);
@ -113,7 +121,6 @@ int main_send(struct fxlink_filter *filter, delay_t *delay, char **files)
printf("Ejected %s.\n", dev);
end:
free(folder);
if(argv) free(argv);
if(fs) g_object_unref(fs);
if(drive) g_object_unref(drive);

View File

@ -46,18 +46,31 @@ static void quit(void)
/* Generate an RGB888 surface from image data. */
static SDL_Surface *surface_for_image(uint8_t **RGB888_rows, int width,
int height)
int height, int scale)
{
/* Little endian setup for RGB */
SDL_Surface *s = SDL_CreateRGBSurface(0, width, height, 24,
SDL_Surface *s = SDL_CreateRGBSurface(0, width*scale, height*scale, 24,
0x000000ff, 0x0000ff00, 0x0000ff00, 0);
if(!s) {
elog("cannot create surface for image\n");
return NULL;
}
for(int i = 0; i < height; i++)
memcpy(s->pixels + i * s->pitch, RGB888_rows[i], width * 3);
for(int y = 0; y < height; y++) {
for(int dy = 0; dy < scale; dy++) {
uint8_t *src = RGB888_rows[y];
uint8_t *dst = s->pixels + (y*scale+dy) * s->pitch;
for(int x = 0; x < width; x++) {
for(int dx = 0; dx < scale; dx++) {
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst += 3;
}
src += 3;
}
}
}
return s;
}
@ -68,11 +81,14 @@ void fxlink_sdl2_display_raw(struct fxlink_message_image_raw const *raw)
return;
int current_w, current_h;
SDL_GetWindowSize(window, &current_w, &current_h);
if(current_w != raw->width || current_h != raw->height)
SDL_SetWindowSize(window, raw->width, raw->height);
int scale = 1;
SDL_Surface *src = surface_for_image(raw->data, raw->width, raw->height);
SDL_GetWindowSize(window, &current_w, &current_h);
if(current_w != raw->width * scale || current_h != raw->height * scale)
SDL_SetWindowSize(window, raw->width * scale, raw->height * scale);
SDL_Surface *src =
surface_for_image(raw->data, raw->width, raw->height, scale);
if(!src)
return;

View File

@ -30,6 +30,7 @@ fxconv_declare_assets(${ASSETS} ${ASSETS_fx} ${ASSETS_cg} WITH_METADATA)
add_executable(myaddin ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}})
target_compile_options(myaddin PRIVATE -Wall -Wextra -Os)
target_link_options(myaddin PRIVATE -Wl,-Map=Build_Addin.map -Wl,--print-memory-usage)
target_link_libraries(myaddin Gint::Gint)
if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G)
@ -38,4 +39,7 @@ if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G)
elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50)
generate_g3a(TARGET myaddin OUTPUT "MyAddin.g3a"
NAME "MyAddin" ICONS assets-cg/icon-uns.png assets-cg/icon-sel.png)
elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G_AS_CG)
generate_g3a(TARGET myaddin OUTPUT "MyAddin.g3a"
NAME "MyAddin" ICONS assets-cg/icon-uns.png assets-cg/icon-sel.png)
endif()

View File

@ -0,0 +1,58 @@
# fxSDK toolchain file for Casio graphing calculators
# Models: Prizm fx-CG 10, fx-CG 20, fx-CG 50, fx-CG 50 emulator
# Target triplet: sh-elf (custom sh3eb-elf supporting sh3 and sh4-nofpu)
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_SYSTEM_PROCESSOR sh)
# Base plateform is fx to pick the assets for the fx9860G
set(FXSDK_PLATFORM fx)
# the long name is change to be able to separate in CMakeLists.txt the different targets
set(FXSDK_PLATFORM_LONG fx9860G_AS_CG)
set(FXSDK_TOOLCHAIN sh-elf-)
set(CMAKE_C_COMPILER sh-elf-gcc)
set(CMAKE_CXX_COMPILER sh-elf-g++)
set(CMAKE_C_FLAGS_INIT "")
set(CMAKE_CXX_FLAGS_INIT "")
add_compile_options(-m4-nofpu -mb -ffreestanding -nostdlib -Wa,--dsp -DFXCG50)
add_link_options(-nostdlib -Wl,--no-warn-rwx-segments)
link_libraries(-lgcc)
add_compile_definitions(TARGET_FXCG50)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(FXSDK_CMAKE_MODULE_PATH "${FXSDK_CMAKE_MODULE_PATH}")
# Add the fxSDK prefix path to the search
set(FXSDK_PREFIX "$ENV{FXSDK_PREFIX}")
foreach(DIR IN LISTS FXSDK_PREFIX)
include_directories("${DIR}/include")
link_directories("${DIR}/lib")
endforeach()
# Determine compiler install path
execute_process(
COMMAND ${CMAKE_C_COMPILER} --print-file-name=.
OUTPUT_VARIABLE FXSDK_COMPILER_INSTALL
OUTPUT_STRIP_TRAILING_WHITESPACE)
# Provide fxSDK sysroot and standard install folders
execute_process(
COMMAND fxsdk path sysroot
OUTPUT_VARIABLE FXSDK_SYSROOT
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(
COMMAND fxsdk path include
OUTPUT_VARIABLE FXSDK_INCLUDE
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(
COMMAND fxsdk path lib
OUTPUT_VARIABLE FXSDK_LIB
OUTPUT_STRIP_TRAILING_WHITESPACE)

View File

@ -21,6 +21,10 @@ add_link_options(-nostdlib -Wl,--no-warn-rwx-segments)
link_libraries(-lgcc)
add_compile_definitions(TARGET_FXCG50)
if(CMAKE_BUILD_TYPE STREQUAL FastLoad)
add_compile_definitions(TARGET_FXCG50_FASTLOAD)
endif()
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

View File

@ -41,6 +41,14 @@ ${R}fxsdk${n} ${R}build-cg-push${n} [${R}-c${n}] [${R}-s${n}] [${R}--${n}] \
are identical to other build commands. Typical workflows will always set -s
(which requires libusb support in fxlink).
${R}fxsdk${n} ${R}build-fxascg${n} [${R}-c${n}] [${R}-s${n}] [${R}--${n}] \
[${g}<ARGS>${n}...]
Builds the current project for fx-CG 50 from a code source initially
targetting the fx-9860G(II). It will generate a .g3a add-in in lieu of a .g1a
add-in. Upscaling of the screen will be performed to accomodate the higher
resolution of the screen of the fx-CG 50 (396x224px) instead of one of the
fx-9860G (128x64px).
${R}fxsdk${n} (${R}send${n}|${R}send-fx${n}|${R}send-cg${n})
Sends the target file to the calculator. Uses p7 (which must be installed
externally) for the fx-9860G, and fxlink for the fx-CG. For the G-III series,
@ -127,7 +135,10 @@ fxsdk_new_project() {
cp "$assets"/icon-cg-sel.png "$1"/assets-cg/icon-sel.png
echo "Created a new project $NAME (build system: $generator)."
echo "Type 'fxsdk build-fx' or 'fxsdk build-cg' to compile the program."
echo "Type 'fxsdk build-fx' or 'fxsdk build-cg' or 'fxsdk build-fxascg'"
echo "to compile the program."
echo "Type 'fxsdk build-cg-push' to compile a bin to be send to"
echo "Add-In Push by circuit10"
}
fxsdk_load_config() {
@ -138,7 +149,7 @@ fxsdk_load_config() {
fxsdk_build() {
[[ ! -e build-fx && ! -e build-cg ]]
[[ ! -e build-fx && ! -e build-cg && ! -e build-fxascg ]]
none_exists=$?
if [[ -e build-fx || $none_exists == 0 ]]; then
@ -150,6 +161,11 @@ fxsdk_build() {
echo "$TAG Making into build-cg"
fxsdk_build_cg "$@"
fi
if [[ -e build-fxascg || $none_exists == 0 ]]; then
echo "$TAG Making into build-fxascg"
fxsdk_build_fxascg "$@"
fi
}
fxsdk_build_fx() {
@ -161,6 +177,9 @@ fxsdk_build_cg() {
fxsdk_build_cg_push() {
fxsdk_build_in "cg-push" "FXCG50" "$@"
}
fxsdk_build_fxascg() {
fxsdk_build_in "fxascg" "FX9860G_AS_CG" "$@"
}
fxsdk_build_in() {
platform="$1"
@ -222,16 +241,20 @@ fxsdk_build_in() {
}
fxsdk_send() {
if [[ -e "build-fx" && ! -e "build-cg" ]]; then
if [[ -e "build-fx" && ! -e "build-cg" && ! -e "build-fxascg" ]]; then
fxsdk_send_fx
fi
if [[ -e "build-cg" && ! -e "build-fx" ]]; then
if [[ -e "build-cg" && ! -e "build-fx" && ! -e "build-fxascg" ]]; then
fxsdk_send_cg
fi
if [[ -e "build-fxascg" && ! -e "build-fx" && ! -e "build-cg" ]]; then
fxsdk_send_fxascg
fi
echo "either no or several platforms are targeted, use 'fxsdk send-fx' or"
echo "fxsdk 'send-cg' to specify which calculator to send to."
echo "'fxsdk send-cg' or 'fxsdk send-fxascg' to specify which calculator to send to."
}
fxsdk_send_fx() {
@ -267,6 +290,18 @@ fxsdk_send_cg-push() {
fxlink -pw ${bin_files}
}
fxsdk_send_fxascg() {
echo "$TAG Installing for fx-CG using fxlink"
if ! command -v fxlink >/dev/null 2>&1; then
echo "error: fxlink is not installed or not available"
return 1
fi
g3a_files=$(find -maxdepth 1 -name '*.g3a')
echo "$TAG Running: fxlink -sw ${g3a_files}"
fxlink -sw ${g3a_files}
}
fxsdk_path() {
case "$1" in
"sysroot")
@ -300,6 +335,8 @@ case "$1" in
fxsdk_build_cg "${@:2}";;
"build-cg-push"|"bcgp")
fxsdk_build_cg_push "${@:2}";;
"build-fxascg"|"bfxcg"|"bfcg")
fxsdk_build_fxascg "${@:2}";;
# Install
"send"|"s")
@ -308,6 +345,8 @@ case "$1" in
fxsdk_send_fx;;
"send-cg"|"sc"|"scg")
fxsdk_send_cg;;
"send-fxascg"|"sfxcg"|"sfcg")
fxsdk_send_fxascg;;
# Utilities
"path")