Over the past week or two, I've been writing a tool to port games from the ti84ce to Windows/Linux. With the use of a few macros, one can compile a C/C++ program to run on the ti84ce or Windows/Linux.

PortCE simulates the lcd, keyboard, timers, along with some of the registers and library functions of the ti84ce. It is designed to minimize the amount of refactoring needed to port a ti84ce game to the PC. Most of the refactoring can be done by including PortCE.h in every file, and using find and replace to change int to ti_int.

To maintain compatibility between the ti84ce and Windows/Linux, the RAM_ADDRESS() and RAM_OFFSET() macros are used to access a specific address, such as a register.

Code:
// Source (Sets pixel 0,0 of the LCD to 0xFF)
*(uint8_t*)RAM_ADDRESS(0xD40000) = 0xFF;

// Compiled for Ti84-CE
*(uint8_t*)((void*)(0xD40000)) = 0xFF;

// Compiled for Windows/Linux
*(uint8_t*)((void*)&simulated_ram[0xD40000]) = 0xFF;

PortCE also includes mouse and audio support, which can add extra functionality to your game.

The idea for PortCE came from one of my own ti84ce games that I ported to Windows. Using that as a starting point, and leveraging the fact that most of graphy (Column-Major graphx) is written in C, I was able to port and test a few graphx games.


Oiram is pretty nice to play with the addition of music and sound effects. Apart from a few heap-use-after-free issues, it runs pretty well.

There are a few things I need to work out still, fileioc is fairly limited currently, and some libraries aren't implemented yet. Hopefully by porting more games I can spot more bugs and implement missing features. One of the major annoyances I have encountered is how sizeof(_BitInt(24)) == 4, which means u24_array[1] is at an offset of 4 bytes instead of 3 bytes, breaking code that reads/writes packed data.

You can checkout PortCE on GitHub: https://github.com/ZERICO2005/PortCE
Wow, very cool project! I've got a couple games I've been thinking of making simultaneously for PC and Calc, and I might could use this as a base!
Nice work!!
If you wanted to get tricky with things, you could probably wrangle addresses such that you don't need to make any changes to code that does memory-mapped IO, and instead handle it at runtime.

It looks like you're only handling RAM accesses too, so that should be very easy: you can use mmap (or VirtualAllocEx on Windows) to allocate 256k of memory at the base address of RAM:
Code:
void *const simulated_ram = mmap(0xD00000, 0x40000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);


Actually doing this safely might be better done by creating an object file containing your RAM array and linking it at a fixed address, since mmap will replace any existing mapping that happens to exist there. With typical unixy tooling that could be done with a custom linker script for the object file containing your RAM array, and I assume something similar is possible with MSVC.

If you wanted to get really crazy, you could handle real memory-mapped I/O using libsigsegv to synchronously trap on accesses to MMIO addresses, handle the accesses then resume normal execution.
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement