ROM dump from Casio fx-2500 / Elektronika MK-51 calculator
November 18, 2025 ยท View on GitHub
This is a repository with ROM contents of the Casio fx-2500 calculator and its clone, Elektronika MK-51. Included is also experimental Python code to read the die photos semi-automatically and some analysis of the code.
Extracting the ROM contents from die photos
To get the ROM contents from photos, you'll need to get the images
from Travis Goodspeed's
repository and put
them into a directory named img:
mkdir -p img
cd img
ln -s ../../mk51fx2500/fx2500.bmp .
ln -s ../../mk51fx2500/mk51.tif .
Then you can run ./read_rom.py. It will read the images and write
mk51fx2500rom.txt.
Given coordinates of corners of rows and columns, the script computes locations of the bits, takes neighborhoods of them and clusters them into 2 clusters with k-means. Using given examples of a zero and a one, it assigns values to these clusters.
Currently the code requires very well stitched images. Tearing,
irregular sharpness, lighting or spacing of rows and columns
introduces significant errors. The best results come from the image
of the MK-51 ROM from an X
post. Likely
only 6 bits are read incorrectly. The fx-2500 ROM images in the X
threads all have some tearing. In the areas around the tearings the
code tends to classify bits into those on the left and on the right of
the tear, instead of zeros and ones. The MK-51 image in Travis'
GitHub repository has a small tearing at the bottom that only affects bits
around it. The fx-2500 image in that repository has some sharpness and
other irregularities that make quite a few blocks wrong. Possibly
at least some errors could be fixed by not using examples of a one and a
zero from one place in the photo for decoding all
areas. combine_*_images functions combine bits from two images using
manually selected mostly correct ranges.
The script includes a list of positions that are read incorrectly on at least some images. This is used to apply fixes. The dump included in this repository should be mostly or maybe even completely correct. I managed to emulate this code and it seems to work fine. I'll publish the emulator in another repository soon.
There are also a few functions that compute PCA. They are currently unused.
Code analysis
test_code.py contains tests that verify assumptions about
subroutines in the ROM or about how the calculator stores its state in
the registers. To run it you need to initialize the submodule:
git submodule init
git submodule update
You can then run the tests with ./test_code.py.
explore_code.py contains other code for analyzing the ROM. The
describe_key_entries function traces the code after pressing each
key (potentially preceded with the modifier keys) to detect the
function of this key combination.
Calculator state
The calculator has 8 registers. Each register can store 15 4-bit digits.
Floating point numbers on which the calculator operates are stored in the following format:
- digits 12-2 store the significand, with digit 12 storing the most significant digit,
- digits 1 and 0 store the exponent, with digit 1 storing the tens digit,
- digit 13 stores the number sign in bit 3 (minus if set) and the exponent sign in bit 1 (minus if set). Other bits are 0.
If the exponent is 0, the decimal point is right after the most significant digit.
Digit 14 is unused by floating point numbers. It is commonly used to store other parts of the state, unrelated to the number stored in the remaining digits of the register.
State map
Here are known parts of the calculator state:
-
R3[14]
- bit 3: state of the INV key on fx-2500
- bit 1: state of the F2 key on fx-48 and MK-38 or the F key on MK-51
- bit 0: state of the F1 key on fx-48 and MK-38
-
R4[13:0]: memory in the regular mode
-
R4[14]
- bits 1-0 store the trigonometric function mode:
- 00: degrees
- 01: radians
- 10: gradians
- bit 3: statistical mode if 1
- bits 1-0 store the trigonometric function mode:
-
R7[14]: selected binary operation:
- 2: root
- 3: power
- 4: division
- 5: multiplication
- 6: subtraction
- 7: addition