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
Floor is lava
May 14, 2007

Fallen Rib
Here's my quick implementation in C/C++ using SDL2 for graphics:
https://github.com/floorislava/SDL2_Chip8_Emulator

Heavily influenced by this article and code:
http://www.multigesture.net/articles/how-to-write-an-emulator-chip-8-interpreter/

I'm going to add in a couple of toggles for the quirk mode stuff and make it more configurable. That and clean up the input code. It currently just uses fillrects for the pixels. Could easily be ported over to opengl with the same code.

Adbot
ADBOT LOVES YOU

Pollyanna
Mar 5, 2005

Milk's on them.


I'm trying to build up a "schematic" for a Chip8 machine (memory + logic) as one of my projects. I'm compiling a list of what a typical Chip8 machine "has" and what it "does". What the machine does is simple, that's the interpreter and the opcodes, but I'm a little bit hazy on the memory structure. Does this look fair?

Markdown code:
- ChipJS has:
  - 4096 bytes of **RAM**
    - in classic machines, addresses 0x000 through 0x1FF are taken up by the language interpreter, but that will not be the case in ChipJS
    - regardless, ChipJS will assume all programs begin at 0x200 in memory
  - 16 **8-bit registers**, V0 through VF
    - hold numbers between 0 and 255, or 0x00 and 0xFF
    - VF is commonly used as a "status" flag
  - a 12-bit **address register**, I
    - used for keeping track of an address in memory
    - e.g. 0x200, 0x3FF
  - a 16-level **return stack**
    - essentially a stack of 12-bit addresses like I
    - allows for subroutines
  - a **program counter**
    - keeps track of where in memory the program is currently executing
  - a **stack pointer**
    - keeps track of the position in the subroutine stack
  - a **pixel display**, implemented as a 2D array
    - 64x32 pixels, potentially other sizes as well
  - an 8-bit **sound timer** register
  - an 8-bit **delay timer** register
Another question: where do most programs "assume" font data is located? I don't see any regularly defined addresses for the font sprites.

Pollyanna fucked around with this message at 19:34 on Dec 7, 2014

shodanjr_gr
Nov 20, 2007

Pollyanna posted:

Markdown code:
- ChipJS has:
  - a 16-level **return stack**
    - essentially a stack of 12-bit addresses like I
    - allows for subroutines

If you're nitpicking the basic Chip8 has a 12-level stack.

quote:

Another question: where do most programs "assume" font data is located? I don't see any regularly defined addresses for the font sprites.

Asked this a few posts ago. The resident CHIP8 expert said:

Internet Janitor posted:

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.


Also, progress! Chip8 for iOS now has a UI:



And can run CaveExplorer:



Purple area is a placeholder view for the keypad.

SystemLogoff
Feb 19, 2011

End Session?

I'm being vain, but can I see a screenshot of one of my games from octojam running on your app? :3:

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
Pollyanna: in general that's a correct description of how modern Chip8 interpreters work. There are a few caveats if you want to get picky:
  • In addition to addresses 0x000-0x1FF being consumed by the interpreter's code, high memory from 0xEA0-0xFFF was also reserved on the COSMAC VIP to store the interpreter's stack, variables and framebuffer. Modern interpreters (including Octo) generally treat this space as fair game, but if you want a program to run on a real VIP you can't store your own code or data there.
  • The vF register is used as a carry flag, but the v0 register is also a bit special- it's the only register that can contain an offset for 0xBNNN, the instruction Octo calls jump0. This instruction is interesting because it appears in almost none of the historical games I've picked apart but Octo programmers use it all the time.
  • The address register i can only be explicitly set to 12-bit values, but on the original Chip8 interpreter it was a 16-bit register; this comes into play when using the built-in hex font. 12- or 16-bits shouldn't make a difference for well written programs.
  • As shodanjr_gr and I pointed out, the classic Chip8 stack was 12 levels deep. Starting with SuperChip (I believe) this was raised to 16. Some modern interpreters (including Octo) don't enforce a limit.
  • You might want to mention that the PC is implied to be at least 12 bits wide (although like i it was probably 16 bits wide on the original interpreter.) The width of stack entries is logically related to the size of the PC, rather than the size of i.
  • The Chip8 display is 64x32 pixels. SuperChip allows for a graphics mode with twice this resolution; 128x64.

That's coming together really nicely, shodanjr_gr! Have you tried using a nearest-neighbor upscaling routine for the display? Slightly blurry pixels is probably historically accurate for CRT displays, but I think it might look nicer with crisp rectangular pixels.

shodanjr_gr
Nov 20, 2007

SystemLogoff posted:

I'm being vain, but can I see a screenshot of one of my games from octojam running on your app? :3:

Sure, throw an Octo-style compiled program listing on paste-bin and I'll give it a shot. There's still a few programs that won't run though so don't get your hopes too high :haw:.

Internet Janitor posted:

That's coming together really nicely, shodanjr_gr! Have you tried using a nearest-neighbor upscaling routine for the display? Slightly blurry pixels is probably historically accurate for CRT displays, but I think it might look nicer with crisp rectangular pixels.

Thanks :)! My wish-list feature is to have an OpenGL-based frame buffer view with support for filters, scan-lines and different CHIP-8 computer modes. As it stands now I'm just generating a UIImage from the frame buffer array, hence the linear upscaling.

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
FYI, you can view the source code to any of the submissions in the OctoJam gallery by clicking the "source" link and then halting the program with escape or clicking the "X":

http://octojam.com/games

Among other things, SystemLogoff wrote the first ever Chip8 visual novel:

http://johnearnest.github.io/Octo/index.html?gist=967a38d5573b2e1d5499

shodanjr_gr
Nov 20, 2007

SystemLogoff posted:

I'm being vain, but can I see a screenshot of one of my games from octojam running on your app? :3:



Using a $900 smartphone for 8-bit Rock Paper Scissors. What has this world come to?

Pollyanna
Mar 5, 2005

Milk's on them.


I'm wondering how to unit/integration test a CHIP-8 interpreter. The thing about the language is that it can run for forever if you let it, so it's a little complicated to tell your tests exactly when your tests are done. If I call chipJS.run(program), then either the program needs to finish running - which can lengthen tests and how do you determine if it's "finished'? - or you can simply have it run via setInterval(), in which case you'll need a callback in order to tell your tests that you're done - and you still have to determine a finished state. Do you run for only a set amount of time? How do you know you've gone on long enough? Does the interpreter only run until it detects an infinite loop state? If so, should it handle the exiting itself or should you do it?

This is definitely something I'm not very good at wrapping my head around. :psyduck:

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
My suggestion would be:

  • Make your emulator treat illegal instructions as a halt. Octo treats 0x0000 (which is technically call machine code at address 0x000 but that is useless) this way, which works out especially conveniently because that's also what uninitialized memory immediately following your program looks like.
  • Write your test programs so that when behaving properly they will eventually execute such a halt instruction.
  • Implement your test framework to execute programs a cycle at a time and if your programs keep running after an unreasonable maximum number of ticks (say 50,000 instructions) they time out and are treated as failing.

If you don't like using 0x0000 as a halt instruction you could also look for a jump to the address of itself (in octo loop again) which is trivially detectable as an infinite loop because nothing could possibly alter its behavior. You can really tie yourself in knots dreaming up more complicated heuristics or rules of this sort but they'll never generalize. Keep it simple. Testing input is inherently fiddly and probably needs a different strategy if it's worth automated testing at all.

shodanjr_gr
Nov 20, 2007

Internet Janitor posted:

My suggestion would be:

  • Make your emulator treat illegal instructions as a halt. Octo treats 0x0000 (which is technically call machine code at address 0x000 but that is useless) this way, which works out especially conveniently because that's also what uninitialized memory immediately following your program looks like.
  • Write your test programs so that when behaving properly they will eventually execute such a halt instruction.
  • Implement your test framework to execute programs a cycle at a time and if your programs keep running after an unreasonable maximum number of ticks (say 50,000 instructions) they time out and are treated as failing.

If you don't like using 0x0000 as a halt instruction you could also look for a jump to the address of itself (in octo loop again) which is trivially detectable as an infinite loop because nothing could possibly alter its behavior. You can really tie yourself in knots dreaming up more complicated heuristics or rules of this sort but they'll never generalize. Keep it simple. Testing input is inherently fiddly and probably needs a different strategy if it's worth automated testing at all.

That's how I'm handling things in my interpreter as well and seems to be working fine so far.

Buffis
Apr 29, 2006

I paid for this
Fallen Rib
Hey, quick question.

I'm new to this. How do I incrementally load through stuff from a memory block

Let's say I have

code:
: butt 1 2 3 4 5 6
And I first want to load the first 3 numbers into v0-2 and then do something, then load the other 3 numbers into v0-2

I thought this would be something like:

code:
i := butt
load v2

# do stuff

v1 := 3
i += v1
load v2
But this doesn't seem to work. What am I doing wrong, and which docs should I look more at.

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
The load and store opcodes modify the contents of the i register, incrementing it by the number of bytes you load or store. If you aren't doing anything which modifies i in "do stuff" you could simply do:

code:
: code
	i := butt
	load v2

	# do stuff

	load v2
If you're modifying i between your reads you need to reset it to the base and add the offset:
code:
: code
	i := butt
	load v2

	# do stuff

	i := butt
	v1 := 3
	i += v1
	load v2
And of course in this particular example you could just give your buffer two labels:
code:
: butt1	1 2 3
: butt2	4 5 6

: code
	i := butt1
	load v2

	# do stuff

	i := butt2
	load v2
The documentation does briefly describe this, but it's an easy detail to miss. Chip8 memory opcodes tend to trip people up and can be a bit clumsy. I'll see about fleshing out a section in one of the guides which explains this behavior better. The best guide to Chip8 instructions is Mastering Chip8, and having a good understanding of the instruction set should make using Octo more effective. Making use of Octo's debugger may also help if you weren't already.

Buffis
Apr 29, 2006

I paid for this
Fallen Rib
Thanks, yeah I somehow missed that i got auto incremented on save/load.

Works now.

Working on a project for fun that should hopefully not take too long :)
CHIP-8 seems fun.

Buffis
Apr 29, 2006

I paid for this
Fallen Rib
So yeah, the octo debugger is pretty sweet.
Got bitten by this (but found it out while debugging):

Opcode Description
8XY4 Add the value of register VY to register VX
Set VF to 01 if a carry occurs
Set VF to 00 if a carry does not occur

8XY5 Subtract the value of register VY from register VX
Set VF to 00 if a borrow occurs
Set VF to 01 if a borrow does not occur


I assumed that VF would be 01 if a borrow occured, cause yeah, that would make more sense right?

Buffis fucked around with this message at 16:13 on Dec 30, 2014

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
Oh yeah. I made the same mistake the first time I implemented those opcodes. It's one of several reasons I created the < > <= >= pseudo-ops.

Buffis
Apr 29, 2006

I paid for this
Fallen Rib

Internet Janitor posted:

Oh yeah. I made the same mistake the first time I implemented those opcodes. It's one of several reasons I created the < > <= >= pseudo-ops.

To be fair, I also got bitten by compare-temp overriding ve for me when I didn't expect it to ;)
That said, now that I realized that compare-temp is a thing, the pseudo-ops are pretty great.

Buffis
Apr 29, 2006

I paid for this
Fallen Rib
Been playing around with Octo a bit more.

Have a pretty stable bullet engine going now, that I might turn into something cool.

Here's a quick demo of a pretty simple pattern:
http://johnearnest.github.io/Octo/index.html?gist=74f43dac16b313b60a25

Pattern above is only something like 12 bullets onscreen at the time max. Currently the engine can do 25 bullets on screen without any real issues. I'm in the process of cutting down the bullet structures to 8 bytes (from 10) though, which will allow me to address 32 bullets wit 8-bit addressing. If that's not enough, it shouldn't be super hard to extend it to 16 bit addresses for the bullets.

The implementation for acceleration is kindof lovely right now, but it's functional.

The pattern generation is pretty easy right now.

Essentially, bullets are spawn by doing
code:
		
dostuff x := 53 y := 16 vx := 244 vy := 168 ay := 0 ax := 1 pew_pew	
# x,y are coordinates. vx,vy are velocity. ax,ay are acceleration (ay not implemented yet cause I've been lazy)

The example above is:

code:
: pattern4
	vc := random 0b00001111
	vc += 8
	
	v0 := 0b00011111
	v0 &= vd
	if v0 == 0b00011111 begin
		dostuff x := 60 y := vc vx := 240 vy := 0 ay := 0 ax := 0 pew_pew	
	end

	if vd == 30 begin
		dostuff x := 53 y := 0 vx := 244 vy := 5 ay := 0 ax := 1 pew_pew	
	end
	if vd == 35 begin
		dostuff x := 53 y := 2 vx := 244 vy := 12 ay := 0 ax := 1 pew_pew	
	end
	if vd == 40 begin
		dostuff x := 53 y := 4 vx := 244 vy := 19 ay := 0 ax := 1 pew_pew	
	end
	if vd == 45 begin
		dostuff x := 53 y := 6 vx := 244 vy := 26 ay := 0 ax := 1 pew_pew	
	end
	if vd == 50 begin
		dostuff x := 53 y := 8 vx := 244 vy := 33 ay := 0 ax := 1 pew_pew	
	end
	if vd == 55 begin
		dostuff x := 53 y := 10 vx := 244 vy := 40 ay := 0 ax := 1 pew_pew	
	end

	if vd == 160 begin
		dostuff x := 53 y := 26 vx := 244 vy := 133 ay := 0 ax := 1 pew_pew	
	end
	if vd == 165 begin
		dostuff x := 53 y := 24 vx := 244 vy := 140 ay := 0 ax := 1 pew_pew	
	end
	if vd == 170 begin
		dostuff x := 53 y := 22 vx := 244 vy := 147 ay := 0 ax := 1 pew_pew	
	end
	if vd == 175 begin
		dostuff x := 53 y := 20 vx := 244 vy := 154 ay := 0 ax := 1 pew_pew	
	end
	if vd == 180 begin
		dostuff x := 53 y := 18 vx := 244 vy := 161 ay := 0 ax := 1 pew_pew	
	end
	if vd == 185 begin
		dostuff x := 53 y := 16 vx := 244 vy := 168 ay := 0 ax := 1 pew_pew	
	end

;
Here is an example of the engine doing two patterns at once, making more than 25 bullets spawn at once, which makes things a bit unpredictable, but still "stable". Handling for this could be a lot better:

http://johnearnest.github.io/Octo/index.html?gist=005dc11e44cd16fee1b0

Buffis fucked around with this message at 14:35 on Jan 1, 2015

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
That's a pretty cool start! Reminds me of Noiz.

If you want to try to improve performance and shave some bytes off your code you might want to play around with some inlining. The body subroutine never returns, so you could just replace your current main. The pew_pew subroutine is too short for you to come out ahead on cycles or ram. I assume you have it broken out so you can alter the size of the struct you write out in just one place- an alternative is to use an alias:

code:
:alias PEW_PEW v9
…
save PEW_PEW
You might also want to consider making use of the jump0/BNNN instruction to replace some of those long sequences of if statements with jump tables. For it to work out best you may have to figure out how to rearrange your intervals into powers of two.

Buffis
Apr 29, 2006

I paid for this
Fallen Rib
Yeah, I haven't bothered too much with optimization yet, since I just wrote the engine for 25 bullets to start with, and everything works mostly ok with that as long as I draw everything before the computation (at 1000 cycles per frame that is).

There's a lot of optimization to do for sure, but I'll try to mash this into something playable first.

The jump table idea sounds pretty nice. Might try that out!

Buffis
Apr 29, 2006

I paid for this
Fallen Rib
Posting a work in progress, since Internet Janitor asked me to.

danm8ku.8o:
http://johnearnest.github.io/Octo/index.html?gist=425acca04b1f79e47eb4
Controls are : WASD



The engine for this is actually a lot more capable than for this simple pattern though. It supports 32 on screen bullets with individual x/y speed and acceleration.
The ROM is <500 bytes currently, but it allocates 256 bits of additional memory for the actual bullet engine on startup.

Basically, I wanted to see how small I could get the ROM cause I was bored. Might implement something a bit more advanced like a boss with multiple stages + a title screen at some point, making this a bit more than just the very simple bullet dodger that it is right now.

Still, I'm kindof pleased with this. Code is pretty easy to read, and the "API" for spawning bullets are easy as gently caress. Current pattern is just:

code:
: pattern2
    v0 := 0b00001111
    v0 &= vd
    if v0 == 0b00001111 then pattern2_shot1
;

: pattern2_shot1
    vc := random 31
    
    gogo_bullet x := 60 y := vc vx := 150 vy := 0 ax := 130 save v7 
    gogo_bullet x := 60 y := vc vx := 150 vy := 0 ax := 134 save v7 
    gogo_bullet x := 45 y := vc vx := 75 vy := 135 ax := 130 save v7    
    gogo_bullet x := 45 y := vc vx := 75 vy := 10 ax := 130 save v7 
;
Basically, pattern2 checks if the game timer (vd) matches a bitmask, and if it does, spawns the shots with the noted bullet positions, velocities and accelerations. The game engine main loop takes care of the rest.
Adding new more advanced patterns is very easy.

Buffis fucked around with this message at 08:16 on Jan 16, 2015

Pollyanna
Mar 5, 2005

Milk's on them.


Goddamn, that's cool. I really need to get into games development, like, for real instead of just posting about it on the internet.

In related news though, we showed our projects at a meet & greet recently and everyone was blown away by my explanation of my Javascript virtual machine :v: It's really funny to me, cause it feels like something very basic and that needs infinitely more iteration to even get close to Octo, yet people are like "woah bitshifting goddamn". I suppose it's a boost to my ego, but...

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
This is a neat project- a guy gamed Doug Crawford used Octo to write a proof-of-concept spreadsheet in Chip8 and ran it on a real COSMAC VIP:

https://abitoutofplace.wordpress.com/2015/05/02/cosmaccalc-the-cosmac-vip-s-place-in-spreadsheet-history/

Don't miss the video either:

https://www.youtube.com/watch?v=6KCUhjaCdjo

I've been exchanging some emails with the author to try to extend Octo with the ability to emulate a cassette drive so that the couple dozen people who own a VIP can develop more efficiently. I have something sort of working but it's surprisingly difficult to get the waveforms just right to make the VIP happy.

At any rate it's really fun to see Octo being useful for developing against real hardware.

Tann
Apr 1, 2009

I thought October was next month and was all hyped up for Octojam :(
I think I might make a couple test things in it to reacquaint myself.

TomR
Apr 1, 2003
I both own and operate a pirate ship.
I made this and I'm happy with it even though it's awful: http://johnearnest.github.io/Octo/index.html?gist=196954a72f816e8302f7

Edit: Updated program to reflect changes to XO-Chip.

TomR fucked around with this message at 23:04 on Sep 19, 2015

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
Rumblings are beginning again on the Octo project.

I just started writing a guide to SuperChip for the docs, since there aren't many good references beyond the original SCHIP manual.

Additionally, I have created a Google Group to allow non-SA users to share programs and ask questions.

Look forward to more improvements and cleanups to Octo in the coming weeks. If there are any topics you'd like to see discussed more or better in the documentation or you encounter any bugs, please let me know!

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
I have made some small changes to XO-Chip to address things I was unhappy with.

Firstly, the syntax of the audio := i instruction was changed to simply audio. The former seemed to imply that the value of i itself was being copied rather than the indirect buffer and I thought this was confusing.

Secondly, and more significantly, the bank instructions have been entirely replaced. Banked memory causes all kinds of hell for disassembly and introduces all sorts of nasty memory layout decisionmaking during programming which Chip8 is otherwise pleasantly not required to deal with. Instead, I have created a double-wide instruction which can load a 16-bit address in i. Just use a long modifier before an address:

code:
: main
    i := long far
    ...
   
:org 0x1000
: far
    0xAB
Easy-peasy, and now you all have an essentially limitless 64 kilobyte address space to play with.

Hopefully these changes won't hurt any programs in the wild. The compiler, emulator, disassembler and documentation have all been updated to reflect these changes and excepting bugfixes I think XO-Chip is now final.

edit: I'm also checking in a few older example programs. I was able to make a crude but flexible music player in surprisingly little code using the XO-Chip audio subsystem.

Internet Janitor fucked around with this message at 00:56 on Sep 20, 2015

Buffis
Apr 29, 2006

I paid for this
Fallen Rib
I realized that I haven't actually posted Trucksimul8or in this thread so...

Here was my entry for SAGDC, written in Octo.
http://www.awfuljams.com/games/truck-simul8or
http://johnearnest.github.io/Octo/index.html?gist=a8a227e707cd138ba258

It's a truck simulator game without a truck, featuring customization and insane trucking action.

The gong show video showing it off was pretty cool:
https://www.youtube.com/watch?v=rXC5iCdDm8Q&t=3s

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
I hope you folks are ready, because it's nearly that time again:


http://octojam.com

Please spread the word!

Dr. Stab
Sep 12, 2010
👨🏻‍⚕️🩺🔪🙀😱🙀
4 colors is pretty cool

http://johnearnest.github.io/Octo/index.html?gist=306e51072134d6793f99

blastron
Dec 11, 2007

Don't doodle on it!


To help people get into putting their terribly-sampled audio into Octo via XO-Chip, I wrote Chipify, a Python script that takes mono WAV files, smashes them into 1-bit 4000 Hz format, and spits out hex strings you can paste into Octo.

This is extremely simple. I apply a low-pass filter to knock off all frequencies that are higher than 4000 Hz so that they don't get turned to noise when the sample rate is reduced. Then, I take the average of all of the high-resolution samples for a given low-resolution sample to crush it down into 4000 Hz, and then round the waveform to the nearest whole number.

Here's a couple of examples:
Heh, I chipped your mom's eight last night
A faithful reproduction of my singing voice
Chipifying even simple music produces interesting results

e: Then of course IRC wanted me to chipify a bunch more bullshit, so:
I'LL BE BACK
GHOST! BUSTERS!! (taken from the really lovely NES sound)
A modem dialing
Mabe Village from Link's Awakening
You're Correct Horse.wav

blastron fucked around with this message at 23:38 on Sep 30, 2015

Buffis
Apr 29, 2006

I paid for this
Fallen Rib
UNDERTALE SPOILERS BELOW

http://johnearnest.github.io/Octo/index.html?gist=21d9b38ddb913e2e2ac8

(code is pretty hacky, quick and dirty prototype)

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."

Buffis posted:

UNDERTALE SPOILERS BELOW

http://johnearnest.github.io/Octo/index.html?gist=21d9b38ddb913e2e2ac8

(code is pretty hacky, quick and dirty prototype)

http://johnearnest.github.io/Octo/index.html?gist=08674a582a6e77fc6859

Tann
Apr 1, 2009

I'm trying to sleep and all I can think about is bytes. Don't octo too hard kids (but do octo!)

Germstore
Oct 17, 2012

A Serious Candidate For a Serious Time

Tann posted:

I'm trying to sleep and all I can think about is bytes. Don't octo too hard kids (but do octo!)

im permabanned poster octohacker58. i first started hacking octo...

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

V and C change tempo, X erases the track. 1 2 3 4 Q add bits to the note to be played. Hold X while playing to make a new note.

Edit: I made a video of how to play.

https://www.youtube.com/watch?v=evM38ScUMAE

TomR fucked around with this message at 14:45 on Oct 4, 2015

Buffis
Apr 29, 2006

I paid for this
Fallen Rib

Buffis fucked around with this message at 08:23 on Oct 5, 2015

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
Just discovered this on the Ludlum Dare site:


http://ludumdare.com/compo/ludum-dare-33/?action=preview&uid=41319

Was it one of you folks?

TomR
Apr 1, 2003
I both own and operate a pirate ship.
I made some major changes to my music player. It has lots of controls now. It will play 8 pages of music now.

http://johnearnest.github.io/Octo/index.html?gist=98f62541b3c8177360ba

Edit: I've included 3 songs. Hold E (f on your keyboard) to skip to the next song.

TomR fucked around with this message at 00:30 on Oct 5, 2015

Adbot
ADBOT LOVES YOU

ExiledTinkerer
Nov 4, 2009
The Gameduino Project guy did a (porting and such) thing apparently:

http://excamera.com/sphinx/article-chip8.html#chip8

  • Locked thread