Ada on the Casio fx-CG50

What is the Casio fx-CG50?

It’s a graphical calculator using the SuperH architecture with its own OS and syscalls. I had to buy one for school but currently it’s collecting dust in a closet and I can’t sell it due to a stupid mistake on my part[1]

There exist multiple libraries and tools to write custom programs for. Notably fxsdk, which supports multiple calculators and has many developer tools. libfxcg where all the reverse engineered syscalls for the fx-CG50 have been defined. And mkg3a which adds the headers to the binary to make it a valid add-on that can be run.

Using these tools there have been a lot of games written for those calculators that can be installed and played during class at home.[2]

My Goals with this Project

I aim to write thick bindings to the libfxcg library (If not even invoke the syscalls manually), port/write a minimal runtime to it, develop some helpful devtools to simplify the build process (have to look into gprbuild) and in the end make a small game to play during class at home!

Currently I have a “prof-of-concept” build systems[3] that compiles a usable binary but the setup is tiresome, tedious, probably halve broken, definitely wrong and the documentation I used is partially out of date. I also need to cross compile gnat with the superh target.

Motivation

There are probably students out there using the calculator and playing games on it. And some of the students might be interested in writing programs for their calculator. Having Ada as a possible language to create calculator programs might help increase interest to learn Ada.

Also: potentially getting monetary compensation would keep me motivated enough to stay invested to actually finish a project.

What was needed and my current work env setup

Here are some infos on the current setup:

  • I download gcc and binutils sources and build them with c,c++,ada and superh support.
  • Using the custom gcc I build the libfxcg library (and test it using example.c)
  • Translated the libfxcg headers to ads using -fdump-ada-spec (could also use syscalls directly)
  • ”translated” the c “build system” to ada. (copied the relevant lines from makefile)
  • wrote a minimal barely working ada runtime just to compile main.adb. (definitely need to learn more about runtimes, get rid of stub.c and look into the OS for build in malloc calls)

My workenvironment is messy as hell but it works now!

.
├── bindings
│   ├── fxcg_app_h.ads
│   ├── fxcg_display_h.ads
│   ├── fxcg_file_h.ads
│   ├── fxcg_heap_h.ads
│   ├── fxcg_keyboard_h.ads
│   ├── fxcg_misc_h.ads
│   ├── fxcg_registers_h.ads
│   ├── fxcg_rtc_h.ads
│   ├── fxcg_serial_h.ads
│   ├── fxcg_system_h.ads
│   ├── fxcg_tmu_h.ads
│   ├── fxcg_usb_h.ads
... // there are more files but i left them out
├── build-ada.sh // ada build system
├── build.sh // c build system
├── b\~main.adb
├── b\~main.ads
├── b\~main.ali
├── b\~main.o
├── compile_commands.json //to make lsp happy
├── gnat.adc
├── gnat_stubs.c
├── gnat_stubs.o
├── main.adb
├── main.ads
├── main.ali
├── main.c // c example I translated to ada and adapted from
├── main.o
├── prizm.x
├── rts2 // rts1 didn’t work...
│   ├── adainclude
│   │   ├── a-unccon.ads
│   │   ├── a-uncdea.ads
│   │   ├── ada.ads
│   │   ├── interfac.ads
│   │   ├── s-elaall.adb
│   │   ├── s-elaall.ads
│   │   ├── s-stalib.adb
│   │   ├── s-stalib.ads
│   │   └── system.ads
│   └── adalib
│       ├── a-unccon.ali
│       ├── a-unccon.o
│       ├── a-uncdea.ali
│       ├── a-uncdea.o
│       ├── ada.ali
│       ├── ada.o
│       ├── interfac.ali
│       ├── interfac.o
│       ├── s-elaall.ali
│       ├── s-elaall.o
│       ├── s-stalib.ali
│       ├── s-stalib.o
│       ├── system.ali
│       └── system.o
├── selected.bmp // following needed for mkg3a 
├── skeleton.bin
├── skeleton.g3a
└── unselected.bmp

I just got it to work yesterday night and there is still a lot to figure out and learn. But for now I will lay this project on ice till my exam phase is over (after March). Till then I hope to get an answer from the committee. Even if it doesn’t pass I’ll still work on it but I can guarantee that I’ll be motivated enough to actually finish it.

Main.adb
pragma Restrictions (No_Exception_Handlers);


procedure Main is
   
   procedure Bdisp_AllClr_VRAM  -- ../../libfxcg/include/fxcg/display.h:30
   with Import => True, 
        Convention => C, 
        External_Name => "Bdisp_AllClr_VRAM";
 
   procedure DirectDrawRectangle
     (x1 : Integer;
      y1 : Integer;
      x2 : Integer;
      y2 : Integer;
      color : Integer)  -- ../../libfxcg/include/fxcg/display.h:45
   with Import => True, 
        Convention => C, 
        External_Name => "DirectDrawRectangle";


   function GetKey (key : access Integer) return Integer  -- ../../libfxcg/include/fxcg/keyboard.h:211
   with Import => True, 
        Convention => C, 
        External_Name => "GetKey";

   procedure PrintMiniMini
     (x : access Integer;
      y : access Integer;
      MB_string : access String;
      mode1 : Integer;
      color : Integer;
      mode2 : Integer)  -- ../../libfxcg/include/fxcg/display.h:155
   with Import => True, 
        Convention => C, 
        External_Name => "PrintMiniMini";

   KEY_CTRL_EXE : constant := 30004;  --  ../../libfxcg/include/fxcg/keyboard.h:118
   KEY_CHAR_0 : constant := 16#30#;  --  ../../libfxcg/include/fxcg/keyboard.h:5

   Key : aliased Integer;
   Ret : Integer;

   State : Boolean := True;
   MSG : aliased String := "Hello from Ada!";

   Pos_X, Pos_Y : aliased Integer := 0;
   Color_Value : Integer := 0;

   Mistery : Integer := 0;

begin
   Bdisp_AllClr_VRAM;

   while True loop

      for I in 0..7 loop
         Ret := GetKey (Key'Access);
         PrintMiniMini (Pos_X'Access, Pos_Y'Access, MSG'Access, Mistery, Color_Value, 0);
         Pos_X := 0;
         Pos_Y := Pos_Y + 10;
         Color_Value := I;
         Mistery := Mistery + 1;
      end loop;

   end loop;

end Main;

  1. I was stupid enough to show the teacher, who is responsible for managing the calculators, that they are programmable. And he said: “You do know that this delegitimizes all exams written with this calculator?“ A year later it wasn’t mandatory anymore and the exams use “stupid“ calculators now. And since no one “needs” them anymore I can’t sell mine. I should have just shut up… ↩︎

  2. There even exists a gameboy emulator. A class mate managed to play through Pokemon during class. ↩︎

  3. Since I use a custom “bare bone minimal“ runtime a lot of binder and linker values like __gnat_runtime_initialize or ___gl_default_stack_size are not defined and I just added empty definitions to a stub just to compile it ↩︎

14 Likes

Weird, but kinda neat.