Still hoping for a Chip-8 port… wondering if the FX chip makes this more attractive?
Last effort was here.
The big problem is that officially CHIP-8 is supposed to have ~4KB of RAM for both machine code and working memory, and I’m not actually sure how most CHIP-8 games behave in terms of memory usage.
If they followed the practice that most assembly programs do: having separate .text, .data, and .rodata sections, then it would theoretically be easy - the .text and .rodata would be stuffed into progmem (or put on the FX), and the .data section would live in RAM. Unfortunately, I don’t think many CHIP-8 assemblers do that because they’re expecting all the memory to be modifiable, and having designated sections makes certain ‘tricks’ more difficult.
At one point I was actually considering trying to analyse the binary to work out what potential memory ranges the code might modify, but I think I eventually decided that was theoretically equivalent to solving the halting problem.
I also once considered writing my own assembler/compiler that would properly split things into distinct sections, but then I’d have to either write or find some game source code and that’s more difficult to come by than precompiled games. (Also I struggled to decide what syntax to use.)
Just to point it out:
128 KB flash, 4 KB EEPROM, 16 KB SRAM
4KB < 16KB.
If anyone were wanting to make their own device that were both Arduboy and CHIP-8 compatible, the ATmega1284p or similar would be a good chip to pick.
I sure did
Why would he pester you … he could just build it himself. The Arduboy FX+RAM.
I believe he has. I talk to him a lot about future versions of the hardware.
I had a 128 Kbyte 23LC1024 SPI SRAM breadboarded quite a while ago but didn’t persue it further then initial testing. For Chip-8 it isn’t really neccesssary as most games do not write much to ram but it will be interesting for something like a Z-machine and with the recent large FX enabled games decompressing data becomes interesting as well. I guess we need the right game for it to develop further
A ‘devkit’ version sure but a slick ‘Arduboy MX’ only @bateske can make
Just out of curiosity, is there any serious interest in playing CHIP-8 games on a Arduboy FX?
- CHIP-8 games are fun and I’d like to play them on my Arduboy FX.
- CHIP-8 games are boring and I don’t care if I can play then on my Arduboy FX or not.
Ah, now there’s something you don’t hear every day.
I would have thought that would be too memory hungry for the Arduboy, though I’ve only briefly looked into it a little while ago.
I wonder how many people here have actually played Zork?
Theoretically yes, but the problem is where they write RAM…
If you could guarantee that the games only wrote to a small range of no more than N bytes where N will fit into the Arduboy’s memory (e.g. N < 1024), that would be fine and everything would work like clockwork.
But unfortunately, there’s nothing to stop games from writing to addresses at dramatically wide intervals.
For example, a programmer might allocate a few bytes before or after a (non-reentrant) subroutine for the subroutine’s work variables, and then have several such subroutines stored end-to-end, or even just squashed them in wherever they saw fit.
You can’t mimic virtual memory because you’d need to keep a table of addresses in RAM and there’s not enough RAM for that.
That’s why I was considering a static analysis approach, but the problem there is that determining which addresses might be written to from the instructions alone is very difficult and might require analysing a large sequence of instructions to determine all the possibilities.
To give a simple example:
LD V1, K
ADD I, V1
LD [I], V0
Registers V0
and V1
are 8-bit, register I
is 16-bit.
LD V1, K
awaits a keypress and then stores the value of that key (0-15) in theV1
register.ADD I, V1
is effectively equivalent toI += V1
.LD [I], V0
is effectively equivalent to*I = V0
Thus this sequence of 3 instructions is enough for 16 addresses to be marked as ‘might be written to’, because which of those 16 is going to be written to can’t be known until runtime.
Once you start factoring other instructions (e.g. LD Vx, DT
- another source of runtime input, RND Vx, byte
- a random value generator) and possibilities (e.g. branching, loops) it can potentially become quite complicated to trace the possibilities.
Granted, in practice you probably won’t get many programs that actually do the ‘awkward’ things, but this does at least begin to illustrate why trying to statically determine which addresses are being written to could become quite complicated.
It could still theoretically work, but you’d need to determine which sequences you’ll deal with and where to draw the line at which you say the program is too complicated to deal with, and how to detect that the situation has become too complicated, rather than potentially giving out an incorrect result.
Well we sorta can. We only need to keep track of the written locations in a table with address ranges and the written data. The format could be something like:
00 - end of table
0xxx nn - one byte nn at address xxx
1xxx nn nn - two bytes nn nn at address xxx
ssseee nn … nn - nn bytes at address sss up to eee
xxx,sss,eee are addresses in the range 200 to FFF as it is not allowed to write to the interpreter addresses 000-1FFF
with random non neighbouring bytes we can keep track of 341 bytes with a 1K table.
with all sequential bytes we can track 1020 bytes with a 1K table.
I had a go at modifying a python implementation of chip-8 to track the ram writes and testet a bunch of games. Some games don’t write to ram at all, most seen don’t even use up to 100 bytes. Funny thing is that a game called BLINKY uses the most at 515 bytes of which just a few are random.
I have played return to Zork on the PC
It could work, but I would expect that seek speed might become a problem once the table starts getting larger.
Theoretically you could detect consecutive single-byte entries and merge them into multibyte entries to save space and potentially time, but again there’s the question of how much CPU time that might chew up.
Some kind of tree might get better performance (e.g. a binary heap stored in an array), but the overhead would eat into the number of bytes you could store.
The problem with manually testing the games is that you have to be sure that there isn’t some obscure branch of code that does write to RAM, otherwise the number you get as a result will be inaccurate.
At least some of those could be determined statically by detecting the absence of certain instructions that would write to memory, though that would potentially give some false negatives too because there’s no easy way to tell what’s machine code and what’s just data. E.g. if someone has a sprite containing the bytes 0xF0
, 0x55
, that might be mistaken for the instruction LD [I], V0
.
What I’d really have liked to do is have a system that compiles the games from source into a version where all the writable RAM is kept in consecutive addresses, since that would mean no fancy analysis or write tracking required at all, just a nice consecutive run of modifiable addresses alongside a nice consecutive run of read-only data and machine code, but that would require both having the games’ source code and modifying that source code to be compatible with that system in a way that wouldn’t break anything.
(You could try to create source for compiled games by trying to disassemble the code, but then you’d run into the issue of determining what’s machine code and what’s data.)