Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
Dijkstracula
Mar 18, 2003

You can't spell 'vector field' without me, Professor!

I assume this is one of y'all's doing :pcgaming:

Adbot
ADBOT LOVES YOU

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
Yeah, I wrote that.



I didn't think it would turn into a rant about CS majors versus "creative majors". Oh well. :smith:

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
I did a bunch of refactoring this evening, and now there is a simplified Octo frontend which could be suitable for embedding in an iframe on a blog or something. I thought it'd be nice for those times when a GIF just doesn't capture the full majesty of a program.
code:
<iframe
	src="http://johnearnest.github.io/Octo/embed.html?scale=2&gist=f3685a75817cde6d5c0d"
	width="256"
	height="128"
/>
scale is optional and the gist argument is the same id used when you have Octo "share" a program.

If anybody notices something is broken, please bring it to my attention- I changed a lot of little things today and I never really trust myself in these dynamic languages.

SharpenedSpoonv2
Aug 28, 2008
I hear there's something cool coming because of the iframes confirm/deny?

Only registered members can see post attachments!

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
Confirmed!

With the turn of the month just around the corner, get ready for

A month-long Chip8 game jam powered by Octo, with a spiffy website SharpenedSpoon built.

Spread the word: http://octojam.com

JossiRossi
Jul 28, 2008

A little EQ, a touch of reverb, slap on some compression and there. That'll get your dickbutt jiggling.
I am pretty psyched for this. I won't be around much at the end of the month so I hope to get something out before then. Maybe even actually game like? Who knows!

Marsol0
Jun 6, 2004
No avatar. I just saved you some load time. You're welcome.
Oh man, I am so in!

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
If anyone is having trouble coming up with ideas, the COSMAC VIP manual has some suggestions:


Some of these are oddly prophetic visions of the game industry to come.

Everdraed
Sep 7, 2003

spankety, spankety, spankety
By using Octo for your cool chip8 projects, you can have as much fun as these dudes:



Whether you're a cool kid with a neat dad or cool dad with a neat kid, Octo is something the whole family can enjoy!

Anybody interested in doing stuff for the Octo-ber jam, or have chip8 questions should totally consider joining the #SAGameDev chat on irc.synirc.net since IJ is there and super helpful with this stuff. It's like a party, and one of the favors is chip8! :toot:

Everdraed fucked around with this message at 03:54 on Oct 1, 2014

everythingWasBees
Jan 9, 2013




Internet Janitor posted:

Confirmed!

With the turn of the month just around the corner, get ready for

A month-long Chip8 game jam powered by Octo, with a spiffy website SharpenedSpoon built.

Spread the word: http://octojam.com

Ooh, this sounds like a lot a fun.

Everdraed
Sep 7, 2003

spankety, spankety, spankety

Everdraed posted:

Whether you're a cool kid with a neat dad or cool dad with a neat kid, Octo is something the whole family can enjoy!

TomR
Apr 1, 2003
I both own and operate a pirate ship.
http://johnearnest.github.io/Octo/index.html?gist=c04837da2ba15ee564f2

I'm working on my game.

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
I've done a number of effortposts about some crazy scheme that I managed to get working, but today I'd like to briefly discuss an idea that didn't pan out.

Chip8 memory limitations are one of the most serious constraints in building games for the platform. With that in mind, I had an interesting idea for pushing the envelope by trying to adapt a game which is defined by its reliance on abundant static data: Myst. Cloning the entire game in any capacity is strictly out of the question, but how far could we go?

Chip8 has 3584 bytes, or 3.5kb, of memory. A SuperChip 128x64 full-screen bitmap requires 1024 bytes of memory. Assuming we reserve 512 bytes for a game engine- moving a cursor, drawing images- this means we'd be able to have 3 screenfuls of art. That's barely even a start screen! Ok, how about 64x32? That would be 256 bytes of memory per image, or 12 screens. Still not enough for much of an adventure game. If we could manage to compress those images to 50% of their size (or less!), 24 screens starts to sound like enough for a small game.

Our options for compression are limited by the speed and resources of the Chip8. The decompressor must be fairly simple and cannot rely on extensive static data- every byte we spend on its machinery and lookup tables is a byte we have to wring out of our data twofold to come out ahead. Run-Length Encoding seemed like a practical solution, so I whipped up a few compressors to see how well they performed.

Our baseline bitmaps can represent 8 pixels in exactly 1 byte of data. Most of the schemes I considered split data bytes into a pair of nybbles. The most obvious scheme uses the first nybble to store the length of a run of black pixels and the second nybble to store the length of a run of white pixels. This means that, for example, a run of 30 black pixels might be encoded as 0xF0 0xF0. In the best case we can store 30 pixels of data in 1 byte, and in the worst case we might only store a single pixel. A more balanced approach uses the first nybble as a pattern of 4 bits to draw and the second nybble as the number of additional times that pattern is repeated. The best case is representing a whopping 64 pixels of data in one byte and the worst case is representing 4.

This second idea seemed promising enough to code up. I tried searching for repeating strips vertically and horizontally: http://pastebin.com/kZuY4m7D

For a very regular test image, the results looked good:


code:
horiz-pattern:	149 bytes	(-107)
verti-pattern:	91 bytes	(-165)
But for something a bit more evocative of the game I have in mind, not so good:


code:
horiz-pattern:	355 bytes	(+99)
verti-pattern:	264 bytes	(+8)
The performance of compression algorithms is inherently data-dependent, and it may well be possible to achieve compression by imposing restrictions on the art. Maniac Mansion's graphics were famously created through a back-and-forth process of drawing, running the images through a tile-based compression algorithm and tweaking the drawings to get the best results. I might be able to make a point-and-click first-person adventure game, but having done some tinkering I have serious doubts I'd be able to make something like Myst.

Any thoughts? If any of you are up for a challenge, see if you can come up with a compression algorithm which would yield good results for both of my test images while still being feasible to implement on a Chip8.

Internet Janitor fucked around with this message at 02:20 on Oct 4, 2014

Lime
Jul 20, 2004

Internet Janitor posted:

Minor note: I corrected an error in the subtraction opcodes of my interpreter. I've updated all the affected example programs. Jusion's "Thom8s Was Alone" was broken by this fix, so I repaired it. The version linked in the OP should work now.

I was fixing up something I did before to work with this change, and I noticed Octo is treating a zero result from a subtraction as underflow. If you do v0 := 3 v1 := 3 v0 -= v1 then vf == 0 even though there was no underflow / borrow. Is this the correct behavior?

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
Oh god damnit I screwed that up again. I am a bad programmer. Thanks for bringing that to my attention, Lime.

You're right, Octo was still behaving incorrectly. I have fixed the emulator, compiler and decompiler. Fortunately, any code which was using the < > <= >= pseudo-ops doesn't need to be changed. It doesn't look like any of the example programs or anything else posted in the thread is broken by this change.

Sorry about that, folks. :smith:

edit: Along the way I discovered a code emission bug related to while which should be resolved now.

Internet Janitor fucked around with this message at 16:01 on Oct 5, 2014

Lime
Jul 20, 2004

Cool, fast work. My Bresenhams line drawing algorithm now needs a couple less instructions.

Related, I was thinking about your compression problem and not getting anywhere, but I know drawings things programmatically was popular in old adventure games, so I tried a dead simple list of lines representation for your scenes. Here's the geometric one. 25 lines at 3 bytes each = 75 bytes, a bit better than RLE. The unpacker and the line drawing take up another 157 bytes.

I didn't work up the whole Myst-like scene but what I started suggests maybe 60 lines total, so 180 bytes. Adding a two byte form for very short, 'touch-up' lines might shave off another ~20 bytes. Other possibilities are commands to start connected line sequences or to do sprite drawing, handling for example the four trees at right. 100 bytes per scene might really be workable this way, and with some cheap 20-30 byte interstitial scenes, you could get a pretty full feeling world.

Lime fucked around with this message at 17:30 on Oct 5, 2014

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
I agree, some procedural drawing approach might work. Neat demo! I've been doing a bit of tinkering with triangle rasterization routines myself.

Another approach that has been discussed in IRC is decomposing the scene into layers or subimages which can be reused and/or compressed separately. Using a few sprites for complex regions of images and line drawing for sparser areas might strike a good balance.

Scaevolus
Apr 16, 2007

The RLE method can work with better coding.

Taking the example high-complexity image, here's what the run-lengths are:

[5, 2, 64, 10, 47, 3, 6, 2, 3, 1, 2, 2, 31, 1, 8, 1, 7, 4, 4, 2, 2, 1, 3, 1, 29, 1, 1, 1, 7, 1, 11, 4, 2, 2, 1, 1, 3, 1, 28, 1, 1, 1, 6, 2, 15, 4, 2, 1, 3, 1, 27, 1, 1, 1, 6, 1, 1, 1, 2, 1, 4, 8, 5, 1, 3, 1, 27, 1, 1, 1, 3, 1, 2, 1, 1, 1, 2, 10, 1, 15, 23, 1, 2, 1, 3, 1, 2, 1, 1, 1, 2, 5, 1, 2, 2, 1, 13, 1, 24, 1, 2, 1, 3, 1, 2, 1, 1, 1, 2, 5, 1, 1, 3, 14, 25, 1, 2, 1, 3, 2, 1, 1, 2, 1, 1, 3, 1, 1, 1, 1, 2, 11, 1, 3, 15, 1, 9, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 4, 2, 1, 1, 1, 2, 3, 7, 1, 1, 3, 15, 1, 9, 1, 3, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 7, 1, 1, 1, 1, 1, 15, 1, 8, 1, 4, 1, 1, 1, 1, 2, 3, 1, 1, 1, 2, 2, 1, 1, 2, 1, 1, 1, 2, 3, 2, 1, 1, 1, 1, 1, 13, 5, 6, 1, 4, 1, 1, 1, 1, 1, 4, 1, 1, 1, 3, 1, 1, 1, 2, 1, 1, 1, 2, 3, 2, 1, 1, 1, 1, 1, 14, 3, 7, 2, 3, 1, 1, 1, 2, 1, 2, 1, 2, 1, 3, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 15, 1, 8, 1, 5, 1, 2, 3, 1, 1, 2, 1, 3, 1, 1, 1, 2, 2, 1, 1, 1, 3, 2, 1, 1, 1, 1, 1, 15, 1, 7, 1, 6, 1, 3, 1, 2, 2, 5, 1, 1, 1, 3, 1, 1, 1, 1, 3, 2, 6, 14, 1, 7, 1, 4, 1, 1, 1, 4, 1, 1, 1, 6, 1, 1, 1, 3, 9, 6, 1, 13, 1, 7, 9, 3, 2, 7, 1, 1, 1, 3, 1, 4, 1, 3, 2, 5, 1, 12, 1, 11, 1, 2, 1, 5, 1, 7, 1, 1, 1, 3, 1, 3, 1, 1, 4, 1, 2, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 2, 1, 3, 1, 3, 1, 1, 1, 3, 4, 9, 1, 4, 1, 10, 1, 7, 5, 1, 1, 5, 1, 1, 1, 6, 1, 1, 1, 3, 1, 7, 5, 1, 1, 4, 1, 9, 1, 2, 5, 4, 9, 8, 1, 1, 1, 4, 1, 12, 11, 2, 5, 9, 1, 4, 1, 2, 1, 7, 1, 2, 1, 4, 1, 17, 1, 1, 1, 3, 10, 6, 1, 4, 1, 2, 6, 1, 1, 3, 1, 4, 1, 18, 5, 6, 2, 2, 12, 5, 1, 2, 1, 4, 1, 4, 1, 17, 1, 2, 1, 8, 1, 1, 1, 12, 3, 3, 1, 2, 1, 3, 1, 6, 1, 15, 13, 3, 1, 14, 2, 1, 1, 3, 1, 2, 8, 14, 1, 2, 1, 9, 3, 1, 1, 16, 3, 2, 1, 23, 1, 2, 1, 10, 1, 2, 1, 15, 2, 3, 1, 2, 13, 9, 12, 2, 1, 2, 1, 15, 1, 21, 2, 19, 6, 16, 1, 5]


The number for each is total: 587 (1: 317, 2: 82, 3: 50, 4: 25, 5: 17, 6: 14, 7: 13, 9: 10, 15: 10, 8: 7, 10: 5, 12: 5, 13: 5, 14: 5, 11: 4, 16: 2, 17: 2, 23: 2, 27: 2, 18: 1, 19: 1, 21: 1, 24: 1, 25: 1, 28: 1, 29: 1, 31: 1, 47: 1, 64: 1)

Elias gamma coding encodes positive integers into a stream of bits, like so:
code:
Number          Encoding    Implied probability
1 = 2^0 + 0     1           1/2
2 = 2^1 + 0     010         1/8
3 = 2^1 + 1     011         1/8
4 = 2^2 + 0     00100       1/32
5 = 2^2 + 1     00101       1/32
6 = 2^2 + 2     00110       1/32
7 = 2^2 + 3     00111       1/32
8 = 2^3 + 0     0001000     1/128
9 = 2^3 + 1     0001001     1/128
10 = 2^3 + 2    0001010     1/128
11 = 2^3 + 3    0001011     1/128
12 = 2^3 + 4    0001100     1/128
13 = 2^3 + 5    0001101     1/128
14 = 2^3 + 6    0001110     1/128
15 = 2^3 + 7    0001111     1/128
16 = 2^4 + 0    000010000   1/512
17 = 2^4 + 1    000010001   1/512
Note how the probability closely matches the input distribution. After encoding, the image takes up 198B: 00101 010 0000001000000 0001010 00000101111 011 00110 010 011 1...

Interestingly, it does worse with vertical runs, since the probability distribution doesn't match as well. A different choice of universal code might fix this. (1: 288, 2: 111, 3: 46, 4: 28, 5: 18, 7: 11, 6: 10, 8: 10, 10: 8, 11: 8, 13: 7, 21: 7, 9: 6, 24: 5, 12: 4, 15: 3, 16: 2, 19: 2, 20: 2, 22: 2, 28: 2, 14: 1, 17: 1, 18: 1, 23: 1, 26: 1)

tl;dr:
code:
raw: 256

RLE + Elias-gamma coding:
simple-horiz: 121
simple-vert: 129
complex-horiz: 198
complex-vert: 208

Scaevolus fucked around with this message at 19:33 on Oct 5, 2014

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
I've been tinkering with array languages recently and it lead me to realize that I entirely skipped over a useful class of sorting algorithms in my earlier investigation- Counting Sorts.

There are several variations on the idea, but the classic Counting Sort does a single scan of the input array, counting instances of each key in an array of "buckets" which correspond to each value the key could take on. From this histogram a second pass can read values back out in sequence and fill the source array. It's possible to achieve linear-time sorting in this manner, but it is only practical when the range of values to consider is fairly small.

For purposes of illustration I'll restrict the problem space to sorting nybbles (0-15)- as a result the cycle counts will not be directly comparable to those of the previous examples. Our first task is to declare and initialize our bucket array:

code:
: empty
	0 0 0 0 0 0 0 0

: buckets
	0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

: bucket-sort
	# zero bucket array
	i := empty
	load v7
	save v7 # unrolled loop to zero bucket array
	save v7 # and initialize loop counters for later.

	...
I'm using several tricks here- I fill the lower 8 registers from an 'empty' buffer and then take advantage of the fact that i will automatically be incremented to the head of the buckets array and then perform two writes to "stamp" zeroes over the entire array. I could save an instruction if my empty array was large enough to zero all 16 registers, but it's a code size tradeoff. For zeroing a larger bucket array I might do something like this:

code:
: empty
	0 0 0 0 0 0 0 0 0

: buckets
	0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
	...

: bucket-sort
	i := empty
	load v8 # also initialize v8 as 0
	loop
		save v7     # zero 8 bytes
		v8 += 1
		if v8 != 32 # 8x32 = 256
	again

	...
Either way, fairly fast. We're able to make those autoincrements work for us. Summing the histogram is much clumsier as we have to juggle i between arrays:

code:
	...

	# bucket the elements
	# v1 is data index (already 0)
	loop
		# load data
		i := data
		i += v1
		load v0
		vf := v0

		# increment bucket
		i := buckets
		i += vf
		load v0
		v0 += 1
		i := buckets
		i += vf
		save v0

		v1 += 1
		if v1 != SIZE then
	again

	...
And finally, unpacking runs. This is a bit clumsy, but we're able to build a very tight writing loop using a technique similar to our earlier memory fill. the longer our runs, the more this will pay off.
code:
	...

	# unpack bucket counts
	# v1 is temporary count
	# v2 is data   index (already 0)
	# v3 is bucket index (already 0)
	loop
		i := buckets
		i += v3
		load v0
		if v0 == 0 then jump no-write
			v1 := v0
			v0 := v3
			i  := data
			i  += v2
			v2 += v1
			loop
				save v0
				v1 += -1
				if v1 != 0 then
			again
		: no-write
		v3 += 1
		if v3 != MAX_VAL then
	again
;
Notice how overall I avoid initializing index registers explicitly by taking advantage of the fact that they will be zeroed as part of my initial memory fill routine.

Performance is impressive. The counting sort handles our example 16 element loose-packed nybble array in only 471 cycles, while our best previous (and slightly more general) attempt took 481, using only 122 bytes instead of 422. Increasing the range of sortable values rapidly increases memory requirements, but there are many possible tradeoffs and tweaks. Overall it looks like this type of algorithm provides a second viable option for running sorts on real hardware. See the entire program together.

I hope some of you have been having fun with Octojam this month. If you haven't started yet there's still plenty of time to make a game!

Internet Janitor fucked around with this message at 21:11 on Oct 20, 2014

Dr. Stab
Sep 12, 2010
👨🏻‍⚕️🩺🔪🙀😱🙀
To reinforce what IJ said, if you haven't started on Octojam, there's still plenty of time. Games, by necessity, are very simple in Chip8. You could have a passable game done in a couple hours.

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
I've added a feature which may make writing complicated programs in Octo a little more convenient- a multi-statement if with an optional else clause. I was a little torn on adding a feature like this because using an if…begin…else…end will sometimes be less efficient than using the simpler conditional skip if…then, but ultimately I decided to listen to user requests- the benefits of more readable, structured code are worth the complexity.

An arbitrary example from the manual:
code:
if v0 > 5 begin
    v1 := random 0xFF

    if v1 == 5 begin
        v2 := v1
        v3 := v1
    else
        delay := v1
    end
end
I have updated the manual and a few of the example programs and added some tests. In the near future I intend to go through the tutorial documentation and update examples to use these constructs where they are appropriate. Existing programs should be fine without any modifications (unless you used end or else as an identifier) and if you prefer writing in a more assembly-like style you can get by without this construct just fine. Please bring any problems you may experience to my attention.

SystemLogoff
Feb 19, 2011

End Session?

Internet Janitor posted:

Confirmed!

With the turn of the month just around the corner, get ready for

A month-long Chip8 game jam powered by Octo, with a spiffy website SharpenedSpoon built.

Spread the word: http://octojam.com

I finished my game! It's Rock-Paper-Scissors, but it's pretty! :v:

All the other games are amazing as well, and I hope to see some more before the month is over. :3:

Dr. Stab
Sep 12, 2010
👨🏻‍⚕️🩺🔪🙀😱🙀
I also finished my game. There was a game I was working on for a while but then I abandoned that to make this one over two days instead: Turnover 77

SharpenedSpoonv2
Aug 28, 2008
It's not really a game, but here's some cellular automata:
http://octojam.com/game/TvvT5yvbCARj6qaCi
It's a naive implementation, for sure, but I'm happy I finally got it done!

Dr. Stab posted:

I also finished my game. There was a game I was working on for a while but then I abandoned that to make this one over two days instead: Turnover 77

This game is really really awesome, and you should go change your name at http://octojam.com/me so it doesn't show up as "Your Name Here"

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
Octojam is complete! Thanks for participating and helping spread the word, everyone.

I'm already busy at work implementing some new features. I'm going to go back on my previous stance of avoiding the creation of novel snowflake Chip8 extensions and propose a handful of modest new instructions which I think address known deficiencies without destroying Chip8's unique flavor of creative limitation. I would very much like to hear what you folks have to say about these ideas before they become set in stone. Take at look at my draft and rationale here:

http://pastebin.com/raw.php?i=HbqLv600

There have also been several requests regarding enhanced (read: existent) audio playback, so I'm debating several options for a simple and easy-to-use mechanism which allows Octo to create an interesting range of sounds. Here is a prototype of such a system- please play with it and let me know what you think:


edit: this audio editor is now a panel in the Octo IDE itself.

The Octo IDE itself would get a similar-looking little editor panel to make testing and tweaking audio patterns convenient, sort of like the built-in sprite editor.

Internet Janitor fucked around with this message at 21:22 on Nov 4, 2014

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
An initial release of XO-Chip is now live. Have a look at the Revised XO-Chip spec and feel free to experiment. I wouldn't be surprised if there are still some bugs to shake out so please be patient and report any problems you encounter.



I have updated the built-in sprite editor with color support and incorporated a modified version of the audio prototype as a sound effect editor:


I still need to update my graphics importing utilities with color support but they should be ready soon.

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
Everdraed, JonTerp and I took an afternoon and played every entry in the OctoJam. Check out the video:

https://www.youtube.com/watch?v=B-FROP4pYe0

I tried to provide interesting technical details, Everdraed focused on talking about game design and JonTerp provided a fresh player's perspective. Whether you participated in the jam or you're just curious about the games that were submitted it's a fun overview.

shodanjr_gr
Nov 20, 2007
Is there a place where I can get some CHIP-8 programs that only use the basic instruction set (not any XO-Chip extensions or CHIP-8E)?

I'm writing a baby's first CHIP-8 interpreter in Swift and could use some source material.

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
Chip8.com has a Program Pack which has a large archive of binaries classified by type- Chip8, Superchip, etc. I've found some bugs and strange assumptions in some of the SuperChip programs in that collection by disassembling them, but the Chip8 roms all seem more or less clean. I believe that most of the Chip8 programs are transcribed directly from the Cosmac VIP Manual.

Also worth noting, Octo will only compile programs with XO-Chip instructions if you opt-in using the options panel and it indicates whether programs it compiles make use of SuperChip or XO-Chip instructions. Many of the examples that come with Octo or were developed during the OctoJam are "clean" and can be used to test a basic Chip8 interpreter. The two features I am intentionally soft on in my emulation are enforcing limits on call stack depth (Octo allows unlimited depth, the real chip8 interpreter capped depth at 12 nested subroutines) and code size (the real chip8 interpreter reserves a couple hundred bytes of high ram for storing its state, modern chip8 interpreters tend to leave that alone and usable by programs).

Internet Janitor fucked around with this message at 20:28 on Nov 21, 2014

shodanjr_gr
Nov 20, 2007

Internet Janitor posted:

Chip8.com has a Program Pack which has a large archive of binaries classified by type- Chip8, Superchip, etc. I've found some bugs and strange assumptions in some of the SuperChip programs in that collection by disassembling them, but the Chip8 roms all seem more or less clean. I believe that most of the Chip8 programs are transcribed directly from the Cosmac VIP Manual.

That's actually an awesome resource! Thanks!

quote:

Also worth noting, Octo will only compile programs with XO-Chip instructions if you opt-in using the options panel and it indicates whether programs it compiles make use of SuperChip or XO-Chip instructions. Many of the examples that come with Octo or were developed during the OctoJam are "clean" and can be used to test a basic Chip8 interpreter. The two features I am intentionally soft on in my emulation are enforcing limits on call stack depth (Octo allows unlimited depth, the real chip8 interpreter capped depth at 12 nested subroutines) and code size (the real chip8 interpreter reserves a couple hundred bytes of high ram for storing its state, modern chip8 interpreters tend to leave that alone and usable by programs).

Actually I've set up my interpret to protect the memory for both the stack and the interpreter-specific memory range ([0,0x200]) but I'd like to have a "modern-mode" toggle that allows access to those + any extended instructions. Also, one of the things I haven't been able to nail down is the location for storage of the font bitmaps. Are they supposed to be dumped in the [0,0x200] range in "proper" CHIP8 implementations or do they go somewhere else?

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
Storing the font(s) in the 0x000-0x200 range is what essentially every modern chip8 interpreter does, and I think it's a safe assumption. If you check out the VIP manual I linked you'll see that the font data was originally stored in the VIP OS rom, outside of chip8's 4k addressing space entirely. Reasonable programs that use the proper font access opcodes shouldn't know or care where that data is stored.

edit: oh, and one more thing- please do NOT use cowgod's technical reference as a source of opcode descriptions. It gets a number of things subtly wrong. Mastering Chip8 is a much more accurate resource. The testquirks.8o program illustrates some of these differences, and in all three of the behaviors Octo is doing what Scaevolus confirmed the original Chip8 interpreter did.

Internet Janitor fucked around with this message at 21:21 on Nov 21, 2014

shodanjr_gr
Nov 20, 2007
Thanks to Internet Janitor's 8-bit advice the core of my interpreter is working:



Still need to implement timers but I think ill work on the front-end a bit for now.

e:

shodanjr_gr fucked around with this message at 05:28 on Nov 25, 2014

toiletbrush
May 17, 2010
My ObjC Chip-8 interpreter had a bunch of crappy switch statements on opcodes, does Swifts pattern-matchy switches tidy that sort of thing up quite nicely?

shodanjr_gr
Nov 20, 2007

toiletbrush posted:

My ObjC Chip-8 interpreter had a bunch of crappy switch statements on opcodes, does Swifts pattern-matchy switches tidy that sort of thing up quite nicely?

Not as far as I can tell...My dispatch loop looks the same as it would look in ObjC...Also I'd say that Swift's type system makes it a bit more cumbersome to work with strongly typed op-codes and memory words since it will not implicitly cast anything to anything else...

However, being able to break into the interpreter loop during execution and REPL to probe memory locations/registers/etc is like magic.

Floor is lava
May 14, 2007

Fallen Rib
I started working on a chip8 emulator after reading some random hackernews article and then someone linked me this thread.

Wish I had found this earlier.

Edit: Current progress, Quick SDL Chip8 Emulator:

Floor is lava fucked around with this message at 10:19 on Nov 29, 2014

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
Important note- I have fixed some subtle bugs that crept into the ChipWar example game a while back when I made corrections to Octo's emulation. If you've been trying to use ChipWar as a test program for your own emulators, build yourself a fresh rom. My apologies if this misbehavior has caused problems for anyone's emulator debugging. Please report any other bugs you find in the examples.

Edit: If you folks are working on your own Chip8 implementation, drop a link to wherever your project is hosted and I can add it to the OP.

shodanjr_gr
Nov 20, 2007
I'll put mine on github when I get the core interpreter running well, hook up touch input and have at least a built-in way to mess around with some demos. Haven't had much time to work on it lately but I'm running into issues with the CaveExplorer demo with the position register (V2 iirc) for the sprite drawing overflowing which leads to hilarious things such as:

Floor is lava
May 14, 2007

Fallen Rib
Should I leave in the part of FX56 & FX66 where the wiki adds "I=I+X+1" for the original or just use the current implementation?

Pollyanna
Mar 5, 2005

Milk's on them.


Internet Janitor posted:

edit: oh, and one more thing- please do NOT use cowgod's technical reference as a source of opcode descriptions. It gets a number of things subtly wrong. Mastering Chip8 is a much more accurate resource. The testquirks.8o program illustrates some of these differences, and in all three of the behaviors Octo is doing what Scaevolus confirmed the original Chip8 interpreter did.

Oh poo poo, I should have used this when I started refactoring my JS implementation of it. This looks much nicer!

Adbot
ADBOT LOVES YOU

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."

floor is lava posted:

Should I leave in the part of FX56 & FX66 where the wiki adds "I=I+X+1" for the original or just use the current implementation?

FX56 and FX66 should add X+1 to I; this is how the original Chip8 interpreter behaved. Many modern Chip8 interpreters skip this, but it seems that ignoring the change to I originates with SuperChip8 interpreters and was made worse by cowgod's documentation repeating the mistake. Some SuperChip programs in the wild rely on the incorrect behavior. One possible compromise is to provide a "quirks mode" which can be enabled for this feature, as Octo does. When writing new programs I think you should either assume I is changed after FX56 and FX66 or write your code such that either behavior will make no difference.

While we're on the topic of the Wikipedia description of Chip8, regarding this footnote:

wikipedia: Chip8 posted:

VF is set to 1 when range overflow (I+VX>0xFFF), and 0 when there isn't.
This is undocumented feature of the Chip-8 and used by Spacefight 2019! game.

This is completely unsubstantiated. That behavior does not exist in the original Chip8 interpreter and while I haven't been able to test it, I have found no hard evidence it exists in the original SuperChip8 interpreter either. The author of that program presumably depended on a bug of whatever interpreter they were using at the time. This bizarrely alters the semantics of many other programs and I do not recommend anyone attempt to support this feature.

Internet Janitor fucked around with this message at 20:35 on Dec 5, 2014

  • Locked thread