What's new

Chip 8

huntercool

New member
OldSkoolEmu chip8 emulator

This is a multiple old skool console emulator

It is emulates the NES, Gameboy, Wanderswan and many other old skool consoles, but not yet.

For now only the Chip8 (not superchip) is implemented and it doesnt emulate every single game.

To use it you drag a chip8 rom (from the same folder as the emulator) onto the emulator exe to start. If you dont supply a rom, the default rom called Kaleid will start.

Arguments(not implemented):
-s=System (specify the emulation system)
-soundon/off (turn sound on/off)
-l=file (load a saved state file)
-c=file (load a cheat definition file)

Keys:
Chip8 keypad (the right setup is the original keypad)
1234 123C
qwer 456D
asdf 789E
zxcv A0BF

Tab - Take a screenshot and save it in the current folder

F1 - Slow down
F2 - Speed up
F3 - Reset
F4 - Toggle Sound on/off

F5 - Cheat Engine (not implemented)
F6 - Save State (not implemented)
F7 - Load State (not implemented)

Notes:
The crazy color is to spice thing up a bit
To disable sound permanently just remove beep.ogg
Sound emulation isnt synchronized

Enjoy :party:

Any suggestions are appreciated.

Also this is my first emulator ever, programmed using strictly ISO C++.
 
Last edited:

smcd

Active member
huntercool said:
Also this is my first emulator ever, programmed using strictly ISO C++.

Can't be strictly ISO C++ since "ISO C++" knows nothing of graphics :p
 

hap

New member
Well done for a first try, huntercool. But why mention features that make the reader think they're implemented, and then tell them they're unimplemented ? :p
Makes me think of some ebay auctions selling an XBOX, listing a lot of features, and then telling 'this is only the box' ;)
k, done joking, some feedback:

- make those crazy colours optional
- F2 doesn't do anything here (so it's always slow)
- sound doesn't work here, and the emulator crashes if I press F4 twice
- where's the source ? ;)
 

Garstyciuks

New member
Has anyone had any problems with their emulators that it can not count the score? My always says 0 (pong), but I can't find where's the bug (although FX29 do work properly). Maybe you have some ideas what instruction could be wrong? And in which register does pong store the score of both players?

And my emulator always crashed when I tried to play brix (after all the bricks are drawn and the ball starts to move). After I have disabled the collision detection in 15th register, it can run (but can't hit anything, since the collision disabled :p). Here is my code for drawing and collision detection:

Code:
case 0xD:
	//draw
	x = memory.reg[(opcode&0x0F00)>>8];
	y = memory.reg[(opcode&0x00F0)>>4];
	height = opcode&0x000F;

	memory.Push(memory.I);
			
	for (j=0; j<height; j++)
	{
		for (i=7; i>=0; i--)
		{
			xt=x;
			yt=y;
			/*if (memory.vram[x+i][y+j]==1) memory.reg[15]=1;
			else memory.reg[15]=0;*/
			if (xt+(7-i)>=64) xt-=64;
			if (yt+j>=32) yt-=32;
			memory.vram[xt+(7-i)][yt+j] ^= (memory.ram[memory.I]&(1<<i))>>i;
		}
		memory.I++;
	}

	memory.I = memory.Pop();

	memory.pos+=2;
	break;

All the variables which are not in memory namespace are integers. memory.I is the index pointer, memory.vram is the video memory. The commented code is supposed to detect the collision, but I guess it's wrong, because it crashes with brix and some other games.

Sometimes the ball at the beginning of pong game starts to move left, instead of right and scores for player 1.
 
Last edited:

Doomulation

?????????????????????????
The BCD or what it's called, is the instruction used for calculating scores... you might check that.
Your draw opcode is wrong. First, reset carry flag at beginning of function. Set it to 1 if a collision is detected. Do NOT reset it under the function's duration.
Also draw pixels from left to right.

It would be something like...
Code:
case 0xD:
	//draw
	x = memory.reg[(opcode&0x0F00)>>8];
	y = memory.reg[(opcode&0x00F0)>>4];
	memory.reg[15]=0; // NEW!
	height = opcode&0x000F;

	memory.Push(memory.I);
			
	for (j=0; j<height; j++)
	{
		for (i=0; i>=7; i++) // CHANGED!
		{
			xt=x;
			yt=y;
			if (memory.vram[x+i][y+j]==1) memory.reg[15]=1; // CHANGED!
			if (xt+(7-i)>=64) xt-=64;
			if (yt+j>=32) yt-=32;
			memory.vram[xt+(7-i)][yt+j] ^= (memory.ram[memory.I]&(1<<i))>>i;
		}
		memory.I++;
	}

	memory.I = memory.Pop();

	memory.pos+=2;
	break;

Check for the comments "// NEW!" and "// CHANGED!"
 
Last edited:

Garstyciuks

New member
I fixed my drawing function. If anyone is interested, here is the right code:

Code:
case 0xD:
	//draw
	x = memory.reg[(opcode&0x0F00)>>8];
	y = memory.reg[(opcode&0x00F0)>>4];
	memory.reg[15] = 0;
	height = opcode&0x000F;
	memory.Push(memory.I);
	
	for (j=0; j<height; j++)
	{
		for (i=0; i<8; i++)
		{
			xt=x;
			yt=y;
			if (memory.vram[x+i][y+j] && ((memory.ram[memory.I]&(128>>i))>>(7-i))) memory.reg[15]=1;
			if (xt+i>=64) xt-=64;
			if (yt+j>=32) yt-=32;
			memory.vram[xt+i][yt+j] ^= (memory.ram[memory.I]&(128>>i))>>(7-i);
		}
		memory.I++;
	}

	memory.I = memory.Pop();

	memory.pos+=2;
	break;

And I found the bug with the score stuff. My code wasn't correctly storing registers into memory and vice versa. I can run most of the games now, but there are some issues with kaleid. The code I used for calling subroutines was

Code:
case 0x2: //call
	memory.Push(memory.pos+2);
	memory.pos = opcode & 0x0FFF;
	break;

And for returning:

Code:
if ((opcode&0x00FF)==0xEE)
	{//ret
		memory.pos=memory.Pop();
	}
	memory.pos+=2;
	break;

And I have recently noticed that I should make memory.Push(memory.pos) in the call opcode, but then kaleid won't work, it's stuck repeating 4 or 5 same cycles and not doing anything, while with memory.Push(memory.pos+2) it worked. Does anyone has any ideas?
 

Garstyciuks

New member
OK, I have finally finished my chip8/schip8 emulator. I have spent reasonable amount of time on this project and I think that it is quite finished and bugless. I have tested all the games I could find and they seemed all playable. My emulator also has a debugger, which allows you to see all the variables and change them. (To change a variable, first you have to pause, then write the new value in the field you want and press the update button (all values must begin with '0x')). I suggest using interval 3 and interrupts around 8-14 for chip8 games and interval 3, interrupts 16-30 for schip games. I also fixed the scroll test ROM, so it is not emulator specific and can run normally on any emulator, supporting 0xFX30 opcode. I have attached an executable version of my emulator and complete source code. If you have any questions or suggestions, feel free to contact me. You can use the source code for learning purposes and include it in your own programs.

Edit: Forgot to talk about the controls :) The controls are on the numeric pad, as suggested in David Winters' documentation

Edit 2: Updated the executable and the source code. Fixed the settings.dat bug and added an option to choose the position of the keypad (either on the letters (1234, qwer, asdf, zxcv) or the numpad(789/, 456*, 123-, 0.enter+))

Edit 3: Probably the last update for my emulator. Fixed some minor bugs that were almost unnoticable for the user and improved the compatibility with older versions of Windows.

P.S. I think Fish 'N' Chips emulator has a bug with scrolling pixels to the right. When running the modified scroll test it seems that you first delete the left pixels and then shift them, which leads into image data loss.

P.P.S. Don't mind the name of my emulator, I wasn't feeling very creative :unsure:
 
Last edited:

hap

New member
Very accurate and stable, nice work. Though one thing I need to complain about is that it writes 'settings.sav' to the last opened folder, instead of the same folder as the emulator.

You might also want to change the keypad, eg. Ant plays kind of awkward now. Use the 'Keypad Test' program to test it (in current roms.zip, source below).

You were right about the bug in my emulator, thanks. It shifted the leftmost pixels to the left instead of to the right, stupid ;p .. I've fixed it (update is on my homepage).

roms updated: http://www.emutalk.net/313299-post622.html

Code:
Keypad Test, by hap

press a chip8 key and the pressed char will light up
if you want to do something funny, soft-reset the chip8/emulator over and over,
and the sprite layout will become messed up ;p

chip8 keypad:
1 2 3 c
4 5 6 d
7 8 9 e
a 0 b f

200: 124e	jump to start

initial sprite coordinate data:
202: 0819, 0: 8,25
204: 0101, 1: 1,1
206: 0801, 2: 8,1
208: 0f01, 3: 15,1
20a: 0109, 4: 1,9
20c: 0809, 5: 8,9
20e: 0f09, 6: 15,9
210: 0111, 7: 1,17
212: 0811, 8: 8,17
214: 0f11, 9: 15,17
216: 0119, a: 1,25
218: 0f19, b: 15,25
21a: 1601, c: 22,1
21c: 1609, d: 22,9
21e: 1611, e: 22,17
220: 1619, f: 22,25

6*7 filled rectangle sprite data:
222: fc
223: fc
224: fc
225: fc
226: fc
227: fc
228: fc
229: 00

SUB: get sprite coordinates for char [v2] into v0,v1
22a: a202	i=202
22c: 820e	v2<<1
22e: f21e	i=i+v2
230: 8206	v2>>1
232: f165	v0,v1=mem[i]
234: 00ee	ret

SUB: save v0,v1 into mem [v2] (reverse of previous one)
236: a202	i=202
238: 820e	v2<<1
23a: f21e	i=i+v2
23c: 8206	v2>>1
23e: f155	mem[i]=v0,v1
240: 00ee	ret

SUB: wait
242: 6f10	vf=16
244: ff15	timer=vf
246: ff07	vf=timer
248: 3f00	skip next if vf==0
24a: 1246	jmp 246
24c: 00ee	ret


24e: 00e0	cls

draw font
250: 6200	v2=0
252: 222a	call 22a
254: f229	i=v2 font char
256: d015	draw 4*5 font at v0,v1
258: 70ff	v0--
25a: 71ff	v1-- (--: block sprite around the font sprite: font=4*5, block=(4+2)*(5+2) )
25c: 2236	call 236
25e: 7201	v2++
260: 3210	skip next if v2==16
262: 1252	jmp 252

main loop
264: f20a	store pressed key into v2
266: 222a	call 22a (get)
268: a222	i=222 (sprite)
26a: d017	draw at v0,v1; 7 lines
26c: 2242	call 242 (wait)
26e: d017	remove sprite by redrawing
270: 1264	jmp 264
 
Last edited:

Garstyciuks

New member
Thanks for reminding me about settings.dat :) I have noticed this behavior, but forgot to do something about it, lol. And thanks for your suggestion.
 

Garstyciuks

New member
Does anyone know how to implement 0xFX75 and 0xFX85 instructions? It seems that only Loopz.sc is using those two. And according to the documentation I found over here the flags are ment to change how the HP48 operates. So it is probably not possible for us to make loopz.sc running.
 
Last edited:

hap

New member
So there are system flags and user flags. I reckon it's the user flags that can be used as variables for SCHIP. In this case (Loopz) they're set to specific values before running the SCHIP program.

To implement them to be functional within the SCHIP program, just create an additional 16 byte array (David Winter says the maximum is 8, but that link you posted says it's 64).

(from David Winter's document)
FX75 Save V0...VX (X<8) in the HP48 flags (***)
FX85 Load V0...VX (X<8) from the HP48 flags (***)

----
I'll try hacking Loopz.sc to make it work on emulators, hold on...
 

Garstyciuks

New member
I believe that the HP48 flags are one bit sized, so it can only fit eight 1 byte sized registers. And if it is set before the game is run, how the hell should we know the values for it? Lot of h4x has to be made. :term:
 

hap

New member
Ah, yes they're probably bits indeed, the maximum of 8 makes more sense that way.

Anyway...

Code:
difficulty select for Loopz, by hap, feb 17th 2006

Andreas Daumann's Loopz was originally only for HP48
this change adds difficulty select within the SCHIP program, so it'll work
on SCHIP emulators, no changes were made in the main program

to select difficulty:
same keys as in loopz: c=up, d=down, 5=ok

v0,v1,v2 are set before running loopz
v1 and v2 should be $AA, dunno why
v0 is the difficulty (0 to 9)

original loopz program: $200-$f9d
difficulty select: $f9e-$fff (full ;p )


200: 1f9e	jump to difficulty select (will be reset to original 120f later)

init
f9e: 00ff	schip
fa0: 00e0	cls
fa2: 600d	v0=d (d of difficulty :P )
fa4: 611b	v1=27
fa6: f030	i->'d' font char
fa8: d11a	draw 'd' at 27,27
faa: 6000	v0=0
fac: 2fc4	call draw sub

loop
fae: 2fce	call wait sub
fb0: f10a	v1=pressed key
fb2: 2fc4	call draw sub (remove old number)
fb4: 4105	if key==ok
fb6: 1fe6	jmp done
fb8: 410c	else if key==up
fba: 2fda	call up sub
fbc: 410d	else if key==down
fbe: 2fe0	call down sub
fc0: 2fc4	call draw sub
fc2: 1fae	jmp loop

SUB draw difficulty
fc4: f030	i->v0 font char
fc6: 6208	v2=8
fc8: 631b	v3=17
fca: d23a	draw it at 8,27
fcc: 00ee	ret

SUB wait
fce: 6110	v1=16
fd0: f115	timer=v1
fd2: f107	v1=timer
fd4: 3100	skip next if v1==0
fd6: 1fd2	jmp fd2
fd8: 00ee	ret

SUB up
fda: 3009	if v0!=9
fdc: 7001	v0++
fde: 00ee	ret

SUB down
fe0: 3000	if v0!=0
fe2: 70ff	v0--
fe4: 00ee	ret

done
fe6: 00e0	cls
fe8: 6202	v2=2
fea: f218	sound timer=v2
fec: 8200	v2=v0
fee: 6012	v0=12
ff0: 610f	v1=0f
ff2: a200	i=200 (start address)
ff4: f155	[i]=v0,v1 (set original jump)
ff6: 8020	v0=v2
ff8: 61aa	v1=aa
ffa: 62aa	v2=aa
ffc: f275	copy v0,v1,v2 to flags
ffe: 1200	jump to start

updated roms again: http://www.emutalk.net/313299-post622.html
 

Garstyciuks

New member
OK, I have made a bit of h4x. That wasn't much at all. To run loopz, you have to have this flags stored at the beginning: 0000000010101010101010100000000000000000000000000000000000000000. Or just 0xAA at the second and third byte of the flags. At first I got a bit frustrated by the loopz game play, but it seems that you have to connect as much pipes as you can and at the end your score will be summed. I'm going to compile a newer version of my emulator executable and reattach it (along with the source code) to my release post.
 

hap

New member
Yes, and the 1st byte in the flags is 0 to 9 for the difficulty: 0 being the easiest, 9 being the hardest.
 

Garstyciuks

New member
I haven't used SDL, but I think that it is possible to use anything for it (as long as you can plot pixels, or draw some rectangles). Early versions of my emulator used GDI, but because it was too slow, I have implemented OpenGL.
 

Top