Jump to content



Photo
* * * * * 3 votes

FX-82/-83GT/-115/-991ES PLUS Hacking


  • Please log in to reply
329 replies to this topic

#321 .kklicker

.kklicker

    Newbie

  • Members
  • Pip
  • 1 posts

  • Calculators:
    Casio fx-92 Ver A

Posted 03 February 2018 - 08:41 AM

Hello,
I'm the (un)happy owner of a (casio,obvs) fx-92 Ver A calculator which is the french/belgian version of the fx-82 series.
As I told @SopaXorzTaker in the chat, I know quite a few things in the binary exploitation field(On PCs but also some embedded devices).

I'm following the topic since a while (like the first page) so I was wondering if I could join/eventually try to help and maybe try to adapt the exploits already found to my calculator model  -I don't know if it uses the same chipset atm, I hope so- because the firmware is different and a bit limited compared to fx-82's functions.
(I yet found what I think could be an exploitable buffer overflow, gonna try to read and search about the arch when I get time)


Edited by .kklicker, 03 February 2018 - 08:46 AM.


#322 nm111

nm111

    Newbie

  • Members
  • Pip
  • 1 posts

Posted 14 February 2018 - 10:29 AM

Hi,

I think what you're doing here is quite cool, so I've made an account to join in. Do you know what I could do to try and help?

I heard you need a wiki, and I found a good site called wiki-site.com. I have made a wiki there: http://casiohacking.wiki-site.com/. You can make an account on that site and you should be able to create pages.



#323 user202729

user202729

    Casio Freak

  • Members
  • PipPipPipPip
  • 173 posts

Posted 23 February 2018 - 02:54 PM

Use a Markdown viewer to view this.

 

# Tutorial
 
## Stack
 
The stack is used for static memory allocation. Read Wikipedia: https://en.wikipedia.org/wiki/Stack-based_memory_allocation
 
Short explanation:
 
* When a function need an amount of memory, it decreases the stack pointer (SP) by that many bytes, and own the memory pointed to by SP.
* When a function no longer need that memory, it increases the stack pointer.
 
## Function call
 
For the nX/U8 core, when a function calls another functions, the address of the caller is stored in the `LCSR:LR` register, and the arguments are (often) stored into the registers `R0-R15` (and occasionally pushed on the stack, although I can't recall any example right now).
 
For example, if the function `f` taking 1 1-byte argument in `r2`, has the structure
 
    0:1234    st    r2, 08124h
    0:1236    rt
 
and a snippet of code
 
    0:2466    mov    r2, #3
    0:2468    bl     0:1234h
    0:246c    mov    r0, #0
 
is executed, the following will happen:
 
* At `0:2466`, `r2` is set to decimal value `3`.
* At `0:2468`, when the command `bl 0:1234h` is called,
    * The `LCSR:LR` register value is set to `0:246ch` (the address of the command right after the `bl` command) (that is, `LCSR = 0` and `LR = 246ch`)
    * The `CSR:PC` register value is set to `0:1234h`.
* Next, `0:1234` is executed.
* After 1 command, at `0:1236`, when the `rt` command is called, the value of `CSR:PC` is set to the value of `LCSR:LR` (which is `0:246ch`).
 
* Then, the command `0:246ch` is executed.
 
-------
 
## Recursive function
 
Next. When a function `a` that is called by another function `parent` needs to call yet another function `child`, it needs to remember the value of `LCSR:LR` when it was called (by `parent`). That is done by the command
 
    push lr
 
which allocates 4 bytes of memory on the stack, and store the value of `lcsr` and `lr` there.
 
When the function returns, instead of
 
    pop lr
    ret
(which is supposed to return the value of `lr` and `lcsr` and then do the normal return), it executes
 
    pop pc
.
 
For more detailed instruction, read the nX/U8 core instruction manual. But basically, the LR (2 bytes) is on the top, then the LCSR (1 byte), then an unused byte.
 
Note that, although the CPU allows up to 16 code/data segments, the calculators only uses 2 segments, so only the least significant bit of `lcsr` is important, all other bits are always 0. Moreover because of word alignment of `PC`, the least significant bit of the PC is always zero.
 
--------
 
So, how does that help with arbitrary code execution?
 
As we observed, there are a lot of `pop pc` commands in the code. And those commands set the program counter to whatever on the top of the stack. Therefore, if we executes a `pop pc` command and can control what is in the stack, we can make the PC to jump to arbitrary location.
 
The remaining problem is to write a program in ROP.
 
---------
 
### Example
 
For an example, let's try understanding the hackstring that was used to understand how **F030** worked, taken from [#286](http://community.casiocalc.org/topic/7583-fx-82-83gt-115-991es-plus-hacking/?p=61257).
 
Note that you should lookup the command in the disassembly listing of the 570es+/991es+ ROM to understand what I'm saying.
 
    <from #52 character> cv24 M 1 - 0 cv26 X - Int cs23 0 - cv24 M 1 - 0 cv26 cs4 - A 4 0 - ! cs32 0 -
 
First, convert it to hexadecimal for ease of understanding. You know where to look for a character table, for example you can use the Javascript code in [#301](http://community.casiocalc.org/topic/7583-fx-82-83gt-115-991es-plus-hacking/page-8#entry61330).
 
    ?? ?? ?? ... (there are 52 bytes) ... ?? ?? ??
    ee 54 31 ?? 30 f0 58 ?? 6a 27 30 ??
    ee 54 31 ?? 30 f0 04 ?? 41 34 30 ?? 57 b6 30 ??
 
The values of `??` are not important, the behavior of the hackstring is the same for all (non-null) values of `??`.
 
And what does this hackstring do?
 
First, the 100-byte hackstring is repeated in the memory, from the input area (`8154h`) to the end of the writable memory (`8e00h`).
 
(for more information why does that happen, basically a `strcpy(0x81b8, 0x8154)` get called, and all the 100 bytes inside the `0x8154..0x81b8` ranges (includes `0x8154`, excludes `0x81b8`) are not null; and the `strcpy` in the calculator is implemented like this: (pseudo-code)
 
    void strcpy(char* dest, char* src) {
        while (*src != NULL) {
            *dest = *src;
            ++dest;
            ++src;
        }
    }
 
Fortunately there are some non-writable (and so they're always null) memory in the range `0x8e00..0xefff`, so that doesn't loop forever.
 
)
 
That is, the byte at `8154h` has the value of the first byte in the hackstring, the byte at `8155h` has the value of the second byte in the string, ..., the byte at address `x` (`8154h <= x < 8e00h`) has the value of the `(x - 8154h) mod 100` (0-indexing) byte in the hackstring.
 
Then, (eventually) when the `PC` is at address `0:2768h`, `LR = 0:2768h` and `SP = 8da4h`. As you can calculate, the 4 bytes at address `8da4h .. 8da7h` has the values of the `52 .. 55`th bytes of the hackstring. (0-indexing) Now the 4 bytes `ee 54 31 ??` are on the top of the stack.
 
When the `pop pc` command is executed, `pc = 54eeh` and `csr = 1`. (remember the endianness)
 
When the command at `1:54eeh` is executed, `er0 = 0f030h` and `r2 = 58h`.
 
... hopefully you can deduce what will happen next, at least until the command `0:154f0h` is executed the second time. You should be able to figure out that the top of the stack at that time is
 
    41 34 30 ?? 57 b6 30 ??
.
 
--------
 
To understand the remaining 8 bytes of the hackstring, you need to know about some function addresses.
 
First, remember that a function which calls another function must start with `push lr` (there may be some commands that does not change `lr` before that) and ends with `pop pc`. So, if we make the `pc` be right after the `push lr` command, eventually a `pop pc` would be executed with the same `sp`, and the 4 bytes on the top of the stack is not changed (assume the function really want to returns to its caller). That way we can continue to keep control of the `pc`.
 
So, some useful functions in the calculator:
 
* `0:343eh`: A function, given an address pointed to with `er0`, and a number `r2`, print `r2` lines on the screen using the string pointed to by `er0`.
* `0:b654h`: A function taking no parameter, returning no parameter (i.e., `void f(void)`, blinks the cursor and waits for the user to press the key `shift` before returning.
 
--------
 
So 8 bytes
 
    41 34 30 ?? 57 b6 30 ??
 
(in the above hackstring) calls those two functions in order.
 
Note that I just mentioned the multiline print function is at `0:343eh`. Why using the bytes `41 34 30`? (so that `pop pc` set the `pc` to `0:3431`?
 
First, the actual command executed is at `0:3440`, because of word alignment, the value of `pc` is always even. (not so for `sp`, be careful!)
 
Now assume we set the `pc` to `0:343e`. It will push the value of `lr` on the top of the stack, and then execute some commands until `0:3478`, and then set the value of `pc` to the value of `lr` we pushed earlier. Which is not what we want. (as we can't set the `lr` to a desired value) That's also the reason why we don't like gadgets ending with `ret`. 
 
Instead, we jump to the command **right after** the `push lr`. That way the `pop pc` will pop the top of the stack at that time, and we can control the value of `pc`. 
 
(some notes regarding this:
 
(Summary: jumps to the command right after `push lr` is always correct, but other options may also be correct)
 
1. If we jump to a command before the `push lr`, the `pc` will often jump to some unexpected places, as the command right before `push lr` is often `pop pc` or `ret`.
2. If we jump to the `push lr` command, the value of `pc` after the corresponding `pop pc` will depends on the value of `lr` at the start of the function. Only useful if we can control the value of `lr`.
  A similar situation happen if we jump to the beginning of (or inside) a function returning with `ret` - we need to control the value of `lr`.
3. If we jump to the command right after the `push lr` the function is executed and the corresponding `pop pc` will pop the top of the stack. Good.
4. If we jump to some position after the `push lr` the function body is executed except some commands at the first.
 
Typically, option (3) is used because it's the simplest, but occasionally option (2) or (4) should be used instead if typing them into the calculator takes significantly less keystrokes. I will (try to) explain this part later if some hackstring uses that.
 
)
 
---------
 
## Loops
 
Next, about loops.
 
The only way to loop in return-oriented programming is to modify the value of the stack pointer `sp`. If you search for `sp` in the disassembly, you can see that the only commands modifying `sp` and is sufficiently near a (later) `rt` or `pop pc` (such that we can easily reason about what will happen if those commands (between the command modifying `sp` and the return command) is executed) are:
 
* `mov sp, er14` (often followed by `pop er14` and `pop pc`)
* `add sp, #...` (positive amount means pop that many bytes from the stack)
 
Only the first one is (currently) used for looping.
 
So, to loop we should:
 
* When `sp = A`, and a `pop pc` command is executed, execute something that doesn't modify the stack.
* Execute a gadget with `pop er14; pop pc` and put `A-2` on the top of the stack.
* Execute a gadget with `mov sp, er14; pop er14; pop pc`.
 
(it's possible to loop with something that does modify the stack, more information later)
 
When the last gadget `mov sp, er14; pop er14; pop pc` is executed, the following happens:
 
* `mov sp, er14`: `sp` is set to the value `A - 2`.
* `pop er14`: `sp` is increased by `2` bytes. `er14` contains whatever in that 2 bytes.
* `pop pc`: `pc` has the value at `A`.
 
This is an infinite loop. I have never written a conditional statement/loop, but it should be possible with some table lookup/etc.
 
--------
 
### Example:
 
Using the hackstring in [#290](http://community.casiocalc.org/topic/7583-fx-82-83gt-115-991es-plus-hacking/page-8#entry61301):
 
    <52 characters> cv24 M 1 - Fvar cv26 cv40 - Int cs23 0 - tan-1 D 0 - cs26 cv26 cs16 D 1 - cv12 = 0 - sin 2 0 - 0 cv34 Int cs23 0 - (-) cs32 0 - frac Ans ^ cs32 0 - <2 remaining characters>
 
Hexadecimal:
 
    ?? ... (52 bytes) ... ??
    ee 54 31 ?? 46 f0 fe ?? 6a 27 30 ?? b2 44 30 ?? 40 f0
    1d 44 31 ?? e2 3d 30 ?? a0 32 30 ?? 30 f8
    6a 27 30 ?? 60 b6 30 ?? ae 8b 5e b6 30 ??
    ?? ??
 
Only the 10 last bytes are related to looping.
 
`60 b6 30 ??` corresponds to the address `0:b660h`. The commands from `0:b660h` to `0:b662h` are executed.  
Then, `ae 8b` is popped into `er14`. (that is, `8baeh`)  
`5e b6 30 ??` corresponds to the address `0:b65eh`. The commands from `0:b65eh` to `0:b662h` are executed, effectively jumps to the start of the loop.
 
> There are a lot of `mov sp, er14; pop er14; pop pc` command sequences. Choose one that you find typing most easily.
 
--------
 
## Loops which modifies the stack
 
What is "modify the stack" and what is "not modify the stack"? This is pretty self-explanatory.
 
Note:
 
* A `pop` command only increases the stack pointer, does not change the value on the stack.
* A `push` command often modifies the stack, unless it's possible to prove that the stack value is always equal to the pushed value.
  That includes `push lr`.
 
So, to loop we should:
 
* When `sp = A`, and a `pop pc` command is executed, execute something that may modifies the stack.
* Return the stack to the original value.
* Execute a gadget with `pop er14; pop pc` and put `A-2` on the top of the stack.
* Execute a gadget with `mov sp, er14; pop er14; pop pc`.
 
 
Typically the stack is returned to the original value by calling the null-terminated string copy function on a 100-byte region that is not modified before the used stack content. As it's quite hard to determine which region is "not modified", this is often done by trial and error.
 
-------
 
### Example
 
### TODO
 
--------
 
### TODO: Is there any unclear part (that you can't understand)?
 

Edited by user202729, 28 February 2018 - 01:27 PM.


#324 SopaXorzTaker

SopaXorzTaker

    Casio Freak

  • Moderator
  • PipPipPipPip
  • 155 posts
  • Gender:Male
  • Interests:Electronics and programming.

  • Calculators:
    fx-991ES PLUS

Posted 23 February 2018 - 06:05 PM

@user202729: Thank you, it's pretty clear, I suggest adding some examples (directly in your post) and explaining how they work (which addresses do they jump to, etc).



#325 SopaXorzTaker

SopaXorzTaker

    Casio Freak

  • Moderator
  • PipPipPipPip
  • 155 posts
  • Gender:Male
  • Interests:Electronics and programming.

  • Calculators:
    fx-991ES PLUS

Posted 24 February 2018 - 02:25 PM

 

### TODO: Should I do Hello World first? Is this one overkill?

### TODO: Is there any unclear part (that you can't understand)?

 

I'm afraid this is a bit overkill for me (for example, "About why we uses `0:3441` and not `0:343e`, read the section about `lr` above." is quite unclear and I think that actually mentioning the code that gets executed, at least the important parts, would significantly help).

 

Yes, I think a simple, but well-explained Hello World would be better.



#326 SopaXorzTaker

SopaXorzTaker

    Casio Freak

  • Moderator
  • PipPipPipPip
  • 155 posts
  • Gender:Male
  • Interests:Electronics and programming.

  • Calculators:
    fx-991ES PLUS

Posted 24 February 2018 - 06:06 PM

Instead, we jump to the command **right after** the `push lr`. That way the `pop pc` will pop the top of the stack at that time, and we can control the value of `pc`.

 

So we have to jump to the second instruction of a function to make sure we can force it to return the PC to the address we need when it exits, correct?



#327 user202729

user202729

    Casio Freak

  • Members
  • PipPipPipPip
  • 173 posts

Posted 27 February 2018 - 05:12 PM

Updated Javascript code: (replace the one inside #301)

/*

____This_should_be_viewed_at_tabsize_at_least_8____

nul	mp	mn	me	mmu	a0	hconst	muN	muB	redH	alfa	re	lamc	gammap	lamcp	lamcn
Sx2	Sx	n	Sy2	Sy	Sxy	Sx3	Sx2y	Sx4	minX	maxX	minY	maxY	Rinf	u	mup
space	box	mue	mun	mumu	%	Fconst	econst	(	)	Na	+	,	-	decpt	@2f
0	1	2	3	4	5	6	7	8	9	:	k	<	=	>	@3f
Vm	A	B	C	D	E	Fvar	>A	>B	>C	>D	>M	>X	>Y	*	/
hhex	d	o	b	M	>a+bi	>rL8	!	X	Y	@5a	[	sqrdeg	]	^	/R
(-)	Not	Neg	Abs	x^1	x^	y^	x^2	log	Sum	Int	d/dx	Pol	Rec	and	or
sinh	cosh	tanh	e^	x10	^2	^3	^-1	R	c0	c1	{	@7c	}	xor	xnor
i	eulerE	pi	>E	>F	deg	rad	gra	Conjg	avgx	avgy	Ans	Ran#	@8d	@8e	@8f
sinh-1	cosh-1	tanh-1	10^	<=	!=	>=	@97	sqrt	M+	stata	statb	statc	r	cendot	xrt
sin	cos	tan	ln	@a4	>Conv	@a6	@a7	cbrt	M-	ox	sx	oy	sy	frac	L
sin-1	cos-1	tan-1	Rnd	c2	o'	eps0	mu0	hexA	hexB	hexC	hexD	hexE	hexF	Permu	Combi
det	Trn	Ranint#	arg	phi0	g	G0	Z0	MatA	MatB	MatC	MatAns	VctA	VctB	VctC	VctAns
P(	Q(	R(	>t	t	G	atm	in>cm	cm>in	ft>m	m>ft	yd>m	m>yd	mile>km	km>mile	nmile>m
m>nmile	acre>m2	m2>acre	galus>l	l>galus	galuk>l	l>galuk	pc>km	km>pc	kmh>ms	ms>kmh	oz>g	g>oz	lb>kg	kg>lb	atm>Pa
pa>atm	mmhg>pa	pa>mmhg	hp>kw	kw>hp	kgfcm2>	pa>kgf	kgfm>j	j>kgfm	lbfin2>	kpa>lbf	of>oc	oc>of	j>cal	cal>j	@ff

# Readable version

nul     mp      mn      me      mmu     a0      hconst  muN     muB     redH    alfa    re      lamc    gammap  lamcp   lamcn
Sx2     Sx      n       Sy2     Sy      Sxy     Sx3     Sx2y    Sx4     minX    maxX    minY    maxY    Rinf    u       mup
space   box     mue     mun     mumu    %       Fconst  econst  (       )       Na      +       ,       -       decpt   @2f
0       1       2       3       4       5       6       7       8       9       :       k       <       =       >       @3f
Vm      A       B       C       D       E       Fvar    >A      >B      >C      >D      >M      >X      >Y      *       /
hhex    d       o       b       M       >a+bi   >rL8    !       X       Y       @5a     [       sqrdeg  ]       ^       /R
(-)     Not     Neg     Abs     x^1     x^      y^      x^2     log     Sum     Int     d/dx    Pol     Rec     and     or
sinh    cosh    tanh    e^      x10     ^2      ^3      ^-1     R       c0      c1      {       @7c     }       xor     xnor
i       eulerE  pi      >E      >F      deg     rad     gra     Conjg   avgx    avgy    Ans     Ran#    @8d     @8e     @8f
sinh-1  cosh-1  tanh-1  10^     <=      !=      >=      @97     sqrt    M+      stata   statb   statc   r       cendot  xrt
sin     cos     tan     ln      @a4     >Conv   @a6     @a7     cbrt    M-      ox      sx      oy      sy      frac    L
sin-1   cos-1   tan-1   Rnd     c2      o'      eps0    mu0     hexA    hexB    hexC    hexD    hexE    hexF    Permu   Combi
det     Trn     Ranint# arg     phi0    g       G0      Z0      MatA    MatB    MatC    MatAns  VctA    VctB    VctC    VctAns
P(      Q(      R(      >t      t       G       atm     in>cm   cm>in   ft>m    m>ft    yd>m    m>yd    mile>km km>mile nmile>m
m>nmile acre>m2 m2>acre galus>l l>galus galuk>l l>galuk pc>km   km>pc   kmh>ms  ms>kmh  oz>g    g>oz    lb>kg   kg>lb   atm>Pa
pa>atm  mmhg>pa pa>mmhg hp>kw   kw>hp   kgfcm2> pa>kgf  kgfm>j  j>kgfm  lbfin2> kpa>lbf of>oc   oc>of   j>cal   cal>j   @ff

# NPRESSES

999	4	4	4	4	4	4	4	4	4	4	4	4	4	4	4	
100	100	100	100	100	100	100	100	100	100	100	100	100	4	4	4	
100	100	4	4	4	2	4	4	1	1	4	1	1	1	1	100	
1	1	1	1	1	1	1	1	1	1	2	4	100	2	100	100	
4	2	2	2	2	2	2	100	100	100	100	100	100	100	1	1	
100	100	100	100	2	100	100	2	2	2	100	100	1	100	1	100	
1	100	100	2	100	100	100	100	1	2	1	2	2	2	100	100	
2	2	2	2	1	1	2	1	4	4	4	100	100	100	100	100	
100	2	2	100	100	3	3	3	100	100	100	1	2	100	100	100	
2	2	2	2	100	100	100	100	1	100	100	100	100	100	100	2	
1	1	1	1	100	100	100	100	2	100	100	100	100	100	1	100	
2	2	2	2	4	4	4	4	100	100	100	100	100	100	2	2	
100	100	2	100	4	4	4	4	100	100	100	100	100	100	100	100	
100	100	100	100	4	4	4	4	4	4	4	4	4	4	4	4	
4	4	4	4	4	4	4	4	4	4	4	4	4	4	4	4	
4	4	4	4	4	4	4	4	4	4	4	4	4	4	4	100	


# CONST
mp	mn	me	mmu	a0	hconst	muN	muB	redH	alfa	re	lamc	gammap	lamcp	lamcn
Rinf	u	mup
mue	mun	mumu	Fconst	econst	Na
k
Vm
R	c0	c1	
c2	o'	eps0	mu0
phi0	g	G0	Z0
t	G	atm

# CONV
in>cm	cm>in	ft>m	m>ft	yd>m	m>yd	mile>km	km>mile	nmile>m
m>nmile	acre>m2	m2>acre	galus>l	l>galus	galuk>l	l>galuk	pc>km	km>pc	kmh>ms	ms>kmh	oz>g	g>oz	lb>kg	kg>lb	atm>Pa
pa>atm	mmhg>pa	pa>mmhg	hp>kw	kw>hp	kgfcm2>	pa>kgf	kgfm>j	j>kgfm	lbfin2>	kpa>lbf	of>oc	oc>of	j>cal	cal>j


0 tanh-1 @ tanh nul ? ? ? ? ? ? ? Sx2 mn Sx tanh-1 F pa>atm nul ? econst mn cos sin Vm pa>atm mun MatA @ n of>oc MatA mmu nul ? ? ? sinh-1
pa>mmhg i mp m>nmile mp pa>atm ms>kmh >A nul ? ? ? ? pa>mmhg lamcn cal>j mp VctC @ VctC mp alfa lamc pa>atm Sx3 o' L sinh-1 o sinh-1 @
sinh mn MatA @ cosh space MatB L sinh-1 o tanh-1 L sinh-1 o <= L sinh-1 h >= L sinh-1 h @ i l>galus pa>atm MatB mp tan re MatA mp @ redH
MatA or sinh-1 mn sqrt pi m>nmile xnor sinh-1 mun sqrt pi m2>acre cal>j l>galus j>kgfm MatA galus>l VctC or sinh-1 nul ? eulerE m>nmile 
xnor sinh-1 box sqrt eulerE m2>acre @ l>galus j>kgfm MatA m>ft VctC mp pa>atm h nul ? ? ? ? ? ? ? ? ? @ VctC j>kgfm and kw>hp xor j>kgfm 
B Vm muB pa>atm redH mp mn Sx

# MAP (may not be uptodate)

re--	im--	diff

276a	28fc	192

27fa	298c	192
3485	3617	192

3518	3624	10C
479c	48a8	10c
47ea	48f6	10c

4922	4A30	10E
4c34	4d42	10E

4e54	5596	742
7777	7eb9	742

7fc2	88e6	924
AFB2	B8D6	924
B148	BA6C	924

B292	Bb40	8ae
b3b2	bc60	8AE

b642	bf68	926
b660	bf86	926

C702	D4C4	DC2

154ee	154ee	0
16052	16052	0
168b0	168b0	0



javascript code:

*/














consts=`
mp	mn	me	mmu	a0	hconst	muN	muB	redH	alfa	re	lamc	gammap	lamcp	lamcn
Rinf	u	mup
mue	mun	mumu	Fconst	econst	Na
k
Vm
R	c0	c1	
c2	o'	eps0	mu0
phi0	g	G0	Z0
t	G	atm
`.split(/\s/).filter(x=>x!=="");

convs=`
in>cm	cm>in	ft>m	m>ft	yd>m	m>yd	mile>km	km>mile	nmile>m
m>nmile	acre>m2	m2>acre	galus>l	l>galus	galuk>l	l>galuk	pc>km	km>pc	kmh>ms	ms>kmh	oz>g	g>oz	lb>kg	kg>lb	atm>Pa
pa>atm	mmhg>pa	pa>mmhg	hp>kw	kw>hp	kgfcm2>	pa>kgf	kgfm>j	j>kgfm	lbfin2>	kpa>lbf	of>oc	oc>of	j>cal	cal>j
`.split(/\s/).filter(x=>x!=="");

names=`
nul	mp	mn	me	mmu	a0	hconst	muN	muB	redH	alfa	re	lamc	gammap	lamcp	lamcn
Sx2	Sx	n	Sy2	Sy	Sxy	Sx3	Sx2y	Sx4	minX	maxX	minY	maxY	Rinf	u	mup
space	box	mue	mun	mumu	%	Fconst	econst	(	)	Na	+	,	-	decpt	@2f
0	1	2	3	4	5	6	7	8	9	:	k	<	=	>	@3f
Vm	A	B	C	D	E	Fvar	>A	>B	>C	>D	>M	>X	>Y	*	/
hhex	d	o	b	M	>a+bi	>rL8	!	X	Y	@5a	[	sqrdeg	]	^	/R
(-)	Not	Neg	Abs	x^1	x^	y^	x^2	log	Sum	Int	d/dx	Pol	Rec	and	or
sinh	cosh	tanh	e^	x10	^2	^3	^-1	R	c0	c1	{	@7c	}	xor	xnor
i	eulerE	pi	>E	>F	deg	rad	gra	Conjg	avgx	avgy	Ans	Ran#	@8d	@8e	@8f
sinh-1	cosh-1	tanh-1	10^	<=	!=	>=	@97	sqrt	M+	stata	statb	statc	r	cendot	xrt
sin	cos	tan	ln	@a4	>Conv	@a6	@a7	cbrt	M-	ox	sx	oy	sy	frac	L
sin-1	cos-1	tan-1	Rnd	c2	o'	eps0	mu0	hexA	hexB	hexC	hexD	hexE	hexF	Permu	Combi
det	Trn	Ranint#	arg	phi0	g	G0	Z0	MatA	MatB	MatC	MatAns	VctA	VctB	VctC	VctAns
P(	Q(	R(	>t	t	G	atm	in>cm	cm>in	ft>m	m>ft	yd>m	m>yd	mile>km	km>mile	nmile>m
m>nmile	acre>m2	m2>acre	galus>l	l>galus	galuk>l	l>galuk	pc>km	km>pc	kmh>ms	ms>kmh	oz>g	g>oz	lb>kg	kg>lb	atm>Pa
pa>atm	mmhg>pa	pa>mmhg	hp>kw	kw>hp	kgfcm2>	pa>kgf	kgfm>j	j>kgfm	lbfin2>	kpa>lbf	of>oc	oc>of	j>cal	cal>j	@ff
`.split(/\s/).filter(x=>x!=="").map(x=>{
    let i = consts.indexOf(x);
    if (~i) x = "cs" + (i+1);
    i = convs.indexOf(x);
    if (~i) x = "cv" + (i+1);
    return x;
});

npress=`
999	4	4	4	4	4	4	4	4	4	4	4	4	4	4	4	
100	100	100	100	100	100	100	100	100	100	100	100	100	4	4	4	
100	100	4	4	4	2	4	4	1	1	4	1	1	1	1	100	
1	1	1	1	1	1	1	1	1	1	2	4	100	2	100	100	
4	2	2	2	2	2	2	100	100	100	100	100	100	100	1	1	
100	100	100	100	2	100	100	2	2	2	100	100	1	100	1	100	
1	100	100	2	100	100	100	100	1	2	1	2	2	2	100	100	
2	2	2	2	1	1	2	1	4	4	4	100	100	100	100	100	
100	2	2	100	100	3	3	3	100	100	100	1	2	100	100	100	
2	2	2	2	100	100	100	100	1	100	100	100	100	100	100	2	
1	1	1	1	100	100	100	100	2	100	100	100	100	100	1	100	
2	2	2	2	4	4	4	4	100	100	100	100	100	100	2	2	
100	100	2	100	4	4	4	4	100	100	100	100	100	100	100	100	
100	100	100	100	4	4	4	4	4	4	4	4	4	4	4	4	
4	4	4	4	4	4	4	4	4	4	4	4	4	4	4	4	
4	4	4	4	4	4	4	4	4	4	4	4	4	4	4	100	
`.split(/\s/).filter(x=>x!=="").map(x=>Number.parseInt(x,10));

keypresses = y => (x => names[x & 0xFF] + " " + names[(x >> 8) & 0xFF] + " " + (x >> 16))(Number.parseInt(y, 16));

nkey = y => (x => npress[x & 0xFF] + npress[(x >> 8) & 0xFF])(Number.parseInt(y, 16));

minkfpc = x => {
    x = Number.parseInt(x, 16) & 0x1FFFE;
    return nkey(x.toString(16)) <= nkey((x+1).toString(16)) ? keypresses(x.toString(16)) : keypresses((x+1).toString(16));
}

mapri=`
276a	28fc	192

27fa	298c	192
3485	3617	192

3518	3624	10C
479c	48a8	10c
47ea	48f6	10c

4922	4A30	10E
4c34	4d42	10E

4e54	5596	742
7777	7eb9	742

7fc2	88e6	924
AFB2	B8D6	924
B148	BA6C	924

B292	Bb40	8ae
b3b2	bc60	8AE

b642	bf68	926
b660	bf86	926

C702	D4C4	DC2

154ee	154ee	0
16052	16052	0
168b0	168b0	0
`.split(/\s/).filter(x=>x!=="")
.map(x=>Number.parseInt(x,16))

convri = x=>{
    x = Number.parseInt(x, 16);
    for (let i = 3; i < mapri.length; i += 3) {
        if (mapri[i-3+2] === mapri[i+2] && mapri[i-3] <= x && x <= mapri[i]) return (x + mapri[i+2]).toString(16);
    }
    return "";
}

convir = x=>{
    x = Number.parseInt(x, 16);
    for (let i = 3; i < mapri.length; i += 3) {
        if (mapri[i-3+2] === mapri[i+2] && mapri[i-2] <= x && x <= mapri[i+1]) return (x - mapri[i+2]).toString(16);
    }
    return "";
}

values_ = y => y.split(/\s/).map(x=>(0+names.indexOf(x).toString(16)).slice(-2));

roundkf = (x,cond)=>{
	if ("undefined" === typeof cond) cond = yi=>nkey(yi.toString(16))<100;
	if ("number" === typeof x) x = [x];
	for(i=327; i<363; ++i) (y=>{
		if (y.every(cond))
			console.log(i + ":" + y.map(x=>x.toString(16)) + "->" + y.map(x=>keypresses(x.toString(16))));
	})(
		x.map(xi=>(i*100+xi+8))
	)
}

minby=(xs,f)=>{
    var Ox=xs[0];var Of=f(Ox);
    for(var x of xs){
        var f1=f(x);if(f1<Of){Of=f1;Ox=x;}
    }return Ox;
}

rel = x => (x === ' ' ? [0x20, 0x0e] : [x.toLowerCase().charCodeAt(0), x.toUpperCase().charCodeAt(0)])
bestrel = x=>npress[x.charCodeAt(0)]<20?x.charCodeAt(0):minby(rel(x),i=>npress[i])

best = st=>st.split('').map(bestrel)

console.clear();


/*
s=`[rt] pop er0
abcd
1234
34 12 78 56
ab cd ef`

s.split('\n')
["[rt] pop er0", "abcd", "1234", "34 12 78 56", "ab cd ef"]

// do some replacement and .trim() now

a = ["abcd", "1234", "34 12 78 56", "ab cd ef"]

[].concat.apply([],a.map(x=>x.split(/\s/)))

(9) ["abcd", "1234", "34", "12", "78", "56", "ab", "cd", "ef"]

"abcdef".match(/../g).reverse() // little endian
(3) ["ef", "cd", "ab"]
*/
Quick description:

consts - list of 40 constants.
convs - list of 40 conversion operators.
names - list of 256 names.
npress - number of key presses.

keypresess - "keypresses`8ba1`" returns "cos Ans 0".
nkey - "nkey`8ba1`" returns 2.
minkfpc - given a PC, find the one that has the same (except last bit) value as it and take the least number of keypresses to achieve.
values_ - given a string of keys ("cos Ans") return hexadecimal values.
roundkf - given a list of offsets return possible positions.
best - given a string output the list of char codes to minimize number of keypresses.

#328 user202729

user202729

    Casio Freak

  • Members
  • PipPipPipPip
  • 173 posts

Posted 27 February 2018 - 05:23 PM

Code for scrolling text:
 

Memory structure:
| z = 94
| d = 162
| d1 = 163
| e = 194
[B1 ------ code ----------- | ----- data -----] (333)       [--- B2 ---] (356)     [--- B3 --- | --- data ---] (359)
(z)                        (d) (d1)           (e)           (z)                               (d)

============

explanation | keypresses
------------+------------
wait        | A F 0 -
------------+------------
pop xr0     | cv24 M 1 -
b1.e<-b3.d  | cv08 pi cv16 Ran#
copy        | (-) cs23 0 -
------------+------------
pop xr0     | cv24 M 1 -
b1.d<-b1.d1 | Permu pi Combi pi
copy        | (-) cs23 0 -
------------+------------
pop xr0     | cv24 M 1 -
b1.d,1 line | Permu pi mp -
disp        | A 4 0 -
------------+------------
pop xr0     | cv24 M 1 -
b1.e<-b1.z  | cv08 pi cs29 pi
restore stk | (-) cs23 0 -
------------+------------
actual EP   |
(#52 char)  |
------------+------------
pop er14    | Int / 0 -
b2.z-2      | x10 Ans
jump        | log / 0 -
------------+------------
data part   | <32 bytes>
------------+------------
logical EP  |
------------+------------
pop er0     | sin 2 0 -
wait time   | 0 0

(note: The `0 0` at the end corresponds to `3030` in hexadecimal (the former `0` corresponds to the latter `30` because of little-endianness) = 12336 in decimal, so each "tick" takes 1.2336 seconds)


Edited by user202729, 28 February 2018 - 05:02 PM.


#329 SopaXorzTaker

SopaXorzTaker

    Casio Freak

  • Moderator
  • PipPipPipPip
  • 155 posts
  • Gender:Male
  • Interests:Electronics and programming.

  • Calculators:
    fx-991ES PLUS

Posted 27 February 2018 - 09:02 PM

Demo video: https://www.youtube....h?v=wTOBvgXfnB4.



#330 SopaXorzTaker

SopaXorzTaker

    Casio Freak

  • Moderator
  • PipPipPipPip
  • 155 posts
  • Gender:Male
  • Interests:Electronics and programming.

  • Calculators:
    fx-991ES PLUS

Posted 28 February 2018 - 01:36 PM

KEAr5vv.png

 

Font (for reference)






1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users