FONTCHARACTER Reference - compatibility, sets
27 posts
• Page 2 of 3 • 1, 2, 3
- SimonLothar
- Senior Member
-
- Posts: 605
- Joined: Sat Sep 15, 2012 6:59 am
- Location: Krautland ****
- Calculators: Casio fx-7400GII, Casio fx-7400GII (SH4), Casio fx-9750GII, Casio fx-9750GII (SH4), Casio fx-9860G, Casio fx-9860G SD, Casio fx-9860G Slim, Casio fx-9860GII SD, Casio fx-9860GII SD Power Graphic 2, Casio Classpad 330 plus, Casio fx-CG20, Casio fx-CG50, Casio Classpad fx-CP400
Re: FONTCHARACTER Reference - compatibility, sets
cakeisalie5 wrote:And if I understand well, the second dword is the flags of the entry. What I don't understand is that in your example, the size of the element is the high nibble of the first byte of the flags, where here, it looks like it is the lowest nibble. Also, the characters looks deformed: for 0x0E, it should be 0xE591 but it is 0xE691, 0x14 should be [0x66,0x31] but it is [0x66,0xD1]...
The string of opcode 0x0E is 0xE691. (one character)
The string of opcode 0x14 is 0x66E5D1. (two characters)
Perhaps the flags are stored in a byte only. I used Dword to minimize the output's line-count.
At present the meaning of the byte's flags is not known to me.
Your observation seems to be right, that the low nibble of the flag-byte represents the count of characters of the opcode string.
I'll be back!
- cakeisalie5
- Senior Member
-
- Posts: 101
- Joined: Sun Mar 27, 2016 10:24 am
- Location: France
- Calculators: Casio Afx 1.0, Casio fx-9860GII, Casio fx-CG50
Re: FONTCHARACTER Reference - compatibility, sets
Okay, so I was making a stupid error in my code. This is fixed, I can now read logical things.
Here's my code (works on a PC using GNU/Linux):
EDIT: Using what I've manually decoded, I guessed the flags (first byte's high nibble) were:
- 0x04: appended newline
- 0x08: appended space
Here's my code (works on a PC using GNU/Linux):
Extractor: Show
EDIT: Using what I've manually decoded, I guessed the flags (first byte's high nibble) were:
- 0x04: appended newline
- 0x08: appended space
Part of the Planète Casio community (FR) - main author of Cahute
- SimonLothar
- Senior Member
-
- Posts: 605
- Joined: Sat Sep 15, 2012 6:59 am
- Location: Krautland ****
- Calculators: Casio fx-7400GII, Casio fx-7400GII (SH4), Casio fx-9750GII, Casio fx-9750GII (SH4), Casio fx-9860G, Casio fx-9860G SD, Casio fx-9860G Slim, Casio fx-9860GII SD, Casio fx-9860GII SD Power Graphic 2, Casio Classpad 330 plus, Casio fx-CG20, Casio fx-CG50, Casio Classpad fx-CP400
Re: FONTCHARACTER Reference - compatibility, sets
Fine. So that is unravelled, too.cakeisalie5 wrote:EDIT: Using what I've manually decoded, I guessed the flags (first byte's high nibble) were:
- 0x04: appended newline
- 0x08: appended space
I'll be back!
- cakeisalie5
- Senior Member
-
- Posts: 101
- Joined: Sun Mar 27, 2016 10:24 am
- Location: France
- Calculators: Casio Afx 1.0, Casio fx-9860GII, Casio fx-CG50
Re: FONTCHARACTER Reference - compatibility, sets
Yup! I'll be using these to correct and complete the FONTCHARACTER Reference then (just as I thought I had more or less finished *-*). Thanks ![Very Happy :D](./images/smilies/icon_e_biggrin.gif)
![Very Happy :D](./images/smilies/icon_e_biggrin.gif)
Part of the Planète Casio community (FR) - main author of Cahute
- cakeisalie5
- Senior Member
-
- Posts: 101
- Joined: Sun Mar 27, 2016 10:24 am
- Location: France
- Calculators: Casio Afx 1.0, Casio fx-9860GII, Casio fx-CG50
Re: FONTCHARACTER Reference - compatibility, sets
Found something odd. In your code, you said:
The fact is, in the fx9860_au/os/1.05.bin, the first entries look valid (but are not: 0xE701 should resolve as [ns]):
if the content of the E7-table is not an address in the OS-range, the E7-opcodes do not exist (OS 1.xx).
The fact is, in the fx9860_au/os/1.05.bin, the first entries look valid (but are not: 0xE701 should resolve as [ns]):
- Code: Select all
Opcode 0xE700 - 0x801703FF02000000 (0x0) - 0xE640,0x00
Opcode 0xE701 - 0x801703FF02000000 (0x0) - 0xE640,0x00
Opcode 0xE702 - 0x801703FF02000000 (0x0) - 0xE640,0x00
Opcode 0xE703 - 0x801703FF02000000 (0x0) - 0xE640,0x00
Opcode 0xE704 - 0x801703FF02000000 (0x0) - 0xE640,0x00
Opcode 0xE705 - 0x801703FF02000000 (0x0) - 0xE640,0x00
Opcode 0xE706 - 0x0027000000280000 (0x0) - <empty>
Opcode 0xE707 - 0x00290000002A0000 (0x0) - <empty>
Opcode 0xE708 - 0x002B0000002C0000 (0x0) - <empty>
Opcode 0xE709 - 0x002D0000002E0000 (0x0) - <empty>
Part of the Planète Casio community (FR) - main author of Cahute
- SimonLothar
- Senior Member
-
- Posts: 605
- Joined: Sat Sep 15, 2012 6:59 am
- Location: Krautland ****
- Calculators: Casio fx-7400GII, Casio fx-7400GII (SH4), Casio fx-9750GII, Casio fx-9750GII (SH4), Casio fx-9860G, Casio fx-9860G SD, Casio fx-9860G Slim, Casio fx-9860GII SD, Casio fx-9860GII SD Power Graphic 2, Casio Classpad 330 plus, Casio fx-CG20, Casio fx-CG50, Casio Classpad fx-CP400
Re: FONTCHARACTER Reference - compatibility, sets
Neither OS 1.05 nor OS 1.05AU has E7-opcodes.
Try
for (int minor = 0; minor <= 255; minor++) {
instead of
for (int minor = 0; minor < 255; minor++) {
Try
for (int minor = 0; minor <= 255; minor++) {
instead of
for (int minor = 0; minor < 255; minor++) {
I'll be back!
- cakeisalie5
- Senior Member
-
- Posts: 101
- Joined: Sun Mar 27, 2016 10:24 am
- Location: France
- Calculators: Casio Afx 1.0, Casio fx-9860GII, Casio fx-CG50
Re: FONTCHARACTER Reference - compatibility, sets
Done! Just putting it there so I can link to it :p
EDIT: Updated with new information.
- Code: Select all
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
/* The FONTCHARACTER Opcode Table
* ------------------------------
* The OS has two different tables for the characters: one with the glyphs,
* for the simple characters, and one with the opcodes (also called
* multi-characters). This program will extract and print the data from
* an OS image's opcode table.
*
* This table is not referenced directly in any way, but Simon Lothar found
* a trick to find it: browse the 0x7fc syscall (which resolves opcodes as
* strings), and checks for a `mov.l` which refers to a valid OS address.
* And it works!
*
* Then resolved address refers to a <ID of the major> -> <table of the major>
* table. The majors are: 0x00, 0xF9, 0x7F, 0xF7, 0xE5, 0xE6, 0xE7.
* 0xE7 appeared more or less with OS2; used with an older OS, it will probably
* display crap or invalid stuff.
*
* The table of the major is a <character minor> -> <entry>.
* Each entry is 8-bytes long. The first 4 bytes represent the absolute adress
* (in OS's virtual mapping 0x8XXXXXXX) of the string, and the other 4 bytes
* are the other info about the character:
*
* - the high nibble of the first byte are the flags;
* - the second nibble of the first byte seem to be the size of the character
* (although this looks unused, therefore unreliable);
* - the other bytes look like alignment (always zero).
*
* The strings are null-terminated. The flags are:
*
* - 0x4: newline should be appended to the string
* (although this looks unused, even if referenced in the 0x7fc syscall;
* it's the syscall 0x6a6, "PRGM_IsEndOfLine" that determines if the
* character should be followed by a newline or not, and it validates the
* 0x0C, 0x0D and 0x3A characters only);
* - 0x8: space should be appended to the string.
*
* Keep in mind that "unattributed" characters are in fact resolved
* as '@' (0x40)! (except the 0x40 character, of course)
*
* Also, I think unknown leading characters in the fixed-width FONTCHARACTER
* encoding are resolved as the 0x00 leading character, which means that
* 0xFFFF is resolved as 0x00FF = 0xFF, which is resolved as 0x00. */
/* ************************************************************************** */
/* Utilities */
/* ************************************************************************** */
/* useless, therefore totally important! :D */
#define be8toh(x) (x)
/* let's do it this way. */
#define pbyte(x) (((uint8_t*) &os[(x) & 0x0FFFFFFF]))
#define pword(x) (((uint16_t*)&os[(x) & 0x0FFFFFFF]))
#define pdword(x) (((uint32_t*)&os[(x) & 0x0FFFFFFF]))
#define byte(x) ( be8toh( *pbyte (x) ))
#define word(x) (be16toh( *pword (x) ))
#define dword(x) (be32toh( *pdword(x) ))
/**
* print_opcode:
* Print an opcode the refc way, using its information.
*
* @arg s the pointer to the characters (not-a-string).
* @arg size the number of characters to read.
* @arg flags the flags of the multi-character.
*/
static void print_opcode(unsigned int opcode, const uint8_t *s, int flags)
{
unsigned int c;
/* get the size of the string */
unsigned int inisize = 0; int spe = 0;
const uint8_t *t = s;
while (*t || spe) {
if (spe)
spe = 0;
else if (strchr("\xF9\xF7\x7F\xE5\xE6\xE7", *t))
spe = *t;
t++;
if (!spe) inisize++;
}
unsigned int size = inisize;
/* print the info */
printf("0x%04X - ", opcode);
if (!size) printf("<empty>");
while (size--) {
if (*s && strchr("\xF9\xF7\x7F\xE5\xE6\xE7", *s)) {
c = ((unsigned int)*s << 8) | *(s + 1);
s++;
} else
c = *s;
s++;
if (inisize == 1 && c == opcode && !flags)
printf("<simple>");
else if (inisize == 1 && (c & 0xFF) == 0x40)
printf("<unattributed>");
else printf("0x%0*X", (c > 0xFF) ? 4 : 2, c);
if (size) printf(",");
}
if (flags & 0x08)
printf(",0x20");
// if (flags & 0x04) -- see syscall 0x6a6
if (opcode == 0x3A || opcode == 0x0D || opcode == 0x0C || opcode == 0x00)
printf(" [is end of line]");
printf("\n");
}
/**
* main:
* The main function of the program.
*
* The program should be called this way:
* ./a.out <path/to/os.bin>
*
* @arg ac the arguments count
* @arg av the arguments values
* @return the error code (0 if ok)
*/
/* main function */
int main(int ac, char **av)
{
int ret = 1;
FILE *f = NULL; char *os = NULL;
/* open the thing */
if (ac != 2) return (0);
f = fopen(av[1], "r");
if (!f) return (1);
/* get the OS size */
fseek(f, 0, SEEK_END);
long sz = ftell(f);
fseek(f, 0, SEEK_SET);
/* get the OS */
os = malloc(sz);
if (!os) goto fail;
fread(os, 1, sz, f);
fclose(f); f = NULL;
/* get the table base */
uint32_t base = 0;
uint32_t is = dword(dword(0x8001007C) + 4 * 0x7FC);
printf("Syscall address is 0x%08X\n", is);
for (; word(is) != 0x000B /* current instruction isn't `rts` */; is += 2) {
/* check if it's a mov.l opcode */
if ((word(is) & 0xF000) != 0xD000)
continue;
/* get the offset */
base = dword((is + 4 * (word(is) & 0x00FF) + 4) & 0xFFFFFFFC);
/* check if it points to OS range */
if ((base >= 0x80010000) && (base <= 0x80400000))
break;
/* reset the base address */
base = 0;
}
if (!base) {
fprintf(stderr, "We have not found the base!\n");
goto fail;
}
/* we have the base! */
printf("Base address is 0x%08X\n", base);
for (int tid = 0; tid < 7; tid++) {
for (int minor = 0x00; minor <= 0xFF; minor++) {
uint32_t cbase = base + tid * 0x800 + minor * 8;
int major = (int[]){0x00, 0xF9, 0x7F, 0xF7, 0xE5, 0xE6, 0xE7}[tid];
uint32_t daddr = dword(cbase), snd = dword(cbase + 4);
/* `size` used to be calculated here, but it was unreliable */
int flags = (snd >> 28);
/* check if valid character, and not '@' */
if (daddr < 0x80010000 || daddr > 0x80400000) continue;
print_opcode((major << 8) | minor, pbyte(daddr), flags);
}
}
/* we're good */
ret = 0;
fail:
if (f) fclose(f);
free(os);
return (ret);
}
EDIT: Updated with new information.
Last edited by cakeisalie5 on Mon Feb 20, 2017 3:38 pm, edited 2 times in total.
Part of the Planète Casio community (FR) - main author of Cahute
- cakeisalie5
- Senior Member
-
- Posts: 101
- Joined: Sun Mar 27, 2016 10:24 am
- Location: France
- Calculators: Casio Afx 1.0, Casio fx-9860GII, Casio fx-CG50
Re: FONTCHARACTER Reference - compatibility, sets
Huh... that's awkward. I've tried disassembling the 0x7FC (as a training) and, while understanding where your method comes from, my result was this (disasm):
First thing I saw was that the byte was read after the string was copied, so the length of the string looks unused (which means if they are stripped, this won't have any effect... unless some other syscalls use them?).
Second thing is that this syscall doesn't add any newline on the 0x40 flag, and it doesn't look like there is a newline-only character (0x0A is used by something else). Do you know if there is any syscall related to that? The SDK manual about the character set deals with control characters in the 0xF9 table, but I don't know if these are used for newlines... Oo
0x7FC: Show
First thing I saw was that the byte was read after the string was copied, so the length of the string looks unused (which means if they are stripped, this won't have any effect... unless some other syscalls use them?).
Second thing is that this syscall doesn't add any newline on the 0x40 flag, and it doesn't look like there is a newline-only character (0x0A is used by something else). Do you know if there is any syscall related to that? The SDK manual about the character set deals with control characters in the 0xF9 table, but I don't know if these are used for newlines... Oo
Last edited by cakeisalie5 on Mon Jan 30, 2017 8:34 pm, edited 1 time in total.
Part of the Planète Casio community (FR) - main author of Cahute
- SimonLothar
- Senior Member
-
- Posts: 605
- Joined: Sat Sep 15, 2012 6:59 am
- Location: Krautland ****
- Calculators: Casio fx-7400GII, Casio fx-7400GII (SH4), Casio fx-9750GII, Casio fx-9750GII (SH4), Casio fx-9860G, Casio fx-9860G SD, Casio fx-9860G Slim, Casio fx-9860GII SD, Casio fx-9860GII SD Power Graphic 2, Casio Classpad 330 plus, Casio fx-CG20, Casio fx-CG50, Casio Classpad fx-CP400
Re: FONTCHARACTER Reference - compatibility, sets
I did not find any reference to the length-nibble. The length of an OpCodeString seems to be determined by syscall sys0534_MB_ByteCount only.cakeisalie5 wrote:First thing I saw was that the byte was read after the string was copied, so the length of the string looks unused (which means if they are stripped, this won't have any effect... unless some other syscalls use them?).
It looks as if the necessity of a newline is determined by syscallcakeisalie5 wrote:Second thing is that this syscall doesn't add any newline on the 0x40 flag, and it doesn't look like there is a newline-only character (0x0A is used by something else). Do you know if there is any syscall related to that? The SDK manual about the character set deals with control characters in the 0xF9 table, but I don't know if these are used for newlines... Oo
0x06A6: int PRGM_IsEndOfLine( char*opcode );
If *opcode is 0x3A(:), 0x0D, 0x0C or 0x00, the function returns 1.
Else it returns 0.
Inside of syscall 0x07fc the 0x40 flag is used without any detectable effect. A zero byte is replaced by a zero byte, if I am not totally mistaken.
I'll be back!
- cakeisalie5
- Senior Member
-
- Posts: 101
- Joined: Sun Mar 27, 2016 10:24 am
- Location: France
- Calculators: Casio Afx 1.0, Casio fx-9860GII, Casio fx-CG50
Re: FONTCHARACTER Reference - compatibility, sets
SimonLothar wrote:The length of an OpCodeString seems to be determined by syscall sys0534_MB_ByteCount only.
Well, it looks like MB_strcpy doesn't use the result of MB_ByteCount. So anyway, yeah, that looks null-terminated.
Also:
SimonLothar wrote:Try
for (int minor = 0; minor <= 255; minor++) {
instead of
for (int minor = 0; minor < 255; minor++) {
Well actually, the syscall I have here (OS 2.05, fx-9860GII-2) uses a cmp/gt, so it is < 0xLLFF (where 0xLL is the leading character).
![Razz :P](./images/smilies/icon_razz.gif)
And thanks for the 0x6A6 syscall!
I've updated my program with the new elements
![Smile :)](./images/smilies/icon_e_smile.gif)
Part of the Planète Casio community (FR) - main author of Cahute
27 posts
• Page 2 of 3 • 1, 2, 3
Return to Calculator Hacking/Modding Discussions
Who is online
Users browsing this forum: No registered users and 4 guests