What's new

Chip 8

aprentice

Moderator
http://msdn.microsoft.com/library/d...s/vclang/html/_pluslang_fundamental_types.asp

1111 (4bit) = 15 decimal or 0xF hex
11111111 (8bit) = 255 decimal or 0xFF hex
111111111111 (12bit) = 4095 or 0xFFF hex

Every chip 8 opcode is 16 bits (unsigned short).

X and Y are used to illustrate the register index. it is 4 bit because the chip 8 only has 15 general purpose registers.

KK is the data stored in the op

NNN is the jump address stored in the opcode

Example: Opcode 4XKK

bits 12-16 is the opcode, you could mask the bits out then shift them right 12 bits: opcode = (data&0xF000)>>12

bits 8-12 is the register index, register_index = (data&0x0F00)>>8

bits 0-8 is the data we do a compare on: misc_data=(data&0x00FF)

edit: if someone can explain this better than me, feel free to do so, i dont have the time or patience to explain this more in dept :p
 
Last edited:

refraction

PCSX2 Coder
following on from what aprentice said ;p the op code 4XKK is for "skip next instruction if vX is not equal to KK" for example

45D3

broken down that is

4 = opcode
5 = the register we want
D3 = the constant number

that would be, if register 5 doesnt contain the value D3 then skip the next instruction.

in c++ thats something like this

if (register[((opcode&0x0F00)>>8)] != (opcode&0x00FF) PC+=2

the reason we do opcode&0x0F00, what we are saying to the computer is:
from the variable "opcode" we was the value that sits in 0x0F00, but we dont want it that big so move it over so its a smaller number.

see :) now some explination on how we get the opcode variable.

When you load a rom into the memory, because the memory is 8 bit it can only store 2 hex values in each, to get the opcode you want 16bits which is 4 hex digits, so the opcode variable MUST be 16bit. when you load it from memory you want something like this

opcode = memory(pc)<<8 + memory(pc+1)

memory(pc) will contain 45, memory(pc+1) will contain D3, the reason i bit shift the first part over is because else you will just add the second value on to the first one. say if you had the number 23 and the other part was 10 (this is decimal btw) you put them together and you get 33, so the shift takes the first values over 2 places (4 bits for each) so you start with 4500, then when you add the 10 on, you will have 4510 :)

as you can see that uses 2 memory spaces, which is why we have to incrament the variable PC by 2 every cycle.

theres my screwed up explination, i hope that helps ;p
 
Last edited:

RipNLa

New member
refraction said:
following on from what aprentice said ;p the op code 4XKK is for "skip next instruction if vX is not equal to KK" for example
...
that would be, if register 5 doesnt contain the value D3 then skip the next instruction.

in c++ thats something like this

if (register[((opcode&0x0F00)>>8)] != (opcode&0x00FF) PC+=2


Minor clarification just because I got thrown off for a split second =p It's only PC+=2, if you plan on doing it again (like at the end of a switch). As written, it should be PC+=4 to skip the next instruction since its !=
 

refraction

PCSX2 Coder
RipNLa said:
Minor clarification just because I got thrown off for a split second =p It's only PC+=2, if you plan on doing it again (like at the end of a switch). As written, it should be PC+=4 to skip the next instruction since its !=


ah yes forgot to mention that :p cos we i fetch my opcode i incrament it by 2 anyway so i dont have to put PC+=2 after each opcode is executed.

so if you dont do what i do then yes you want PC+=4 :)
 

RipNLa

New member
ARGH! This timing thing is bugging me. It's pretty much the only thing holding me back from a complete Chip8 Emulator (haven't implemented the SCHIP stuff yet). I tried doing one op every 16ms and then decrementing the DelayTimer by one each loop as well.. But this doesn't work for Space Invaders, the monsters move way too fast..so I changed it to decrement the DelayTimer once every 3 operations, so once every 48ms, and thats better, but I don't know exactly what it SHOULD be..

Any help would be great. I tried just running the DelayTimer in a separate thread as well, but that was about the same. For now I've just got a variable speed limiter...which is good enough I guess..
 

refraction

PCSX2 Coder
to slow it down i used this cos that bjz kindly told me on here, on your loop where you tell it to fetch the next opcode then execute it, stick it inside this

DWORD lt = GetTickCount();
for(;;)
{
if(GetTickCount() - lt >= 1000/60)
{
lt=GetTickCount();
//execute command goes here
}
}

that should slow down how many cycles it does per second, controlling the speed for you :)
 

Doomulation

?????????????????????????
Just for the sake...
value = 0x1234;
value & 0xF000 = 0x1000
value & 0x0F00 = 0x0200
value & 0x00F0 = 0x0030
value & 0x000F = 0x0004
value & 0x0FF0 = 0x0230

Hope you got that.
Work goes on. With my powerful debugger I discover more and more what's wrong.
There's one thing that you should be alert of.
The FX55 and FX65 instructions. Some docs say increment I after saving or loading each register. That is WRONG. You should NOT do that.

And... I'll attach my newest version as well ;)
Just so you have something to look forward to. It's mostly untested, though, so don't blame me if anything goes wrong (goes mostly to speed).

I hope there's no missing DLLs or stuff now. Tell me if anything's missing, 'kay? You need DX9 to run this.
 
Last edited:

RipNLa

New member
Refraction:
Yeah, I figured out how to get the timing down..I used a similar approach. I don't think that the DelayTimer is configured correctly. Right now, I decrement it 60 times per second. But at this rate..Space Invaders is realllly hard by the 4th wave, maybe its SUPPOSED to be that hard? If I decrement my DelayTimer like say..45 times per second, it makes the game a lot easier since it relies on the DelayTimer..so yeah, I'm just not sure how hard the game is supposed to be.

Doomulation:
Missing Registry.dll
 

RipNLa

New member
Alright! Here it is finally! For your consumption! Just don't try and load files that aren't roms, because I don't know what will happen... except for something bad!

======================================================
RIPxCHIP8 v1.0.0
======================================================

- S key Enables/Disables sound.
- PGUP/PGDN keys speed up or slow down the emulator
- NUMPAD Keys to play, Games.txt to tell you what keys to use!
(Blinky, the PACMAN clone, uses 1,2,6,9 not 2,4,6,8)

Go to TOOLS->Options to tweak speed, change graphics color, and change the tone of the BEEP! WooO talk about customization!

Oh, and I added the Chip8 Roms into this zip (their all freeware to my knowledge) just incase you didnt have it already, total zip file size is less than 100k, no DLL necessary, enjoy.
 
Last edited:

refraction

PCSX2 Coder
RipNLa thats a very good chip8 emu!! every game works which is a big achievement!! now all you need to do is add SChip8 support (which i can tell you how to do) and itll be brilliant, itd be worth submitting to emulation sites :)
 

Doomulation

?????????????????????????
Damn, how the hell did it get so fast?
I new a new damn API to render, because this system doesn't seem fit for d3d rendering.
Source code for directdraw please? :whistling
I don't have ddraw since I have dx9 :saint:

EDIT:
I reuploaded a new version of the emulator. I've gotten rid of the d3d and registry libraries and it's about 100 kb smaller. The rest of the libraries I'll keep, I will. I also tweaked speed a little more since last time.
Btw, all chip8 games are freeware, actually.
 
Last edited:

refraction

PCSX2 Coder
Right heres the emu ive been working on, pretty much fully functional, please read the Readme.txt :) if you need the msvcr71.dll or anything simular, its in the dll.zip ive also attached:) any other missing files just let me know.

Edit: i just remembered this version is compiled to work only on P4 or AMD 4 machines :S its now been replaced so it should work ok on any machine.

Edit Number 2: updated it again! (i know i only just updated it) Heres the changes log as of 2 minutes before i posted it :p

[ Legend: ]
[ + Added feature ]
[ * Improved/changed feature ]
[ - Bug fixed (we hope) ]
[ ! Attention (Notes) ]

[*] Added code in ChipVideo.cpp so it draws the black pixels as well..
seems to want it else you just get a mountain of White :p
[+] Added SChip8 Extended Op codes. (what a pain they were too!)
[-] Fixed a couple of opcodes.
[*] Changed the key register so its an array, so more than one key can be checked at once.

28/06/04

[*] Added Code to speedup/slow down the emu
[-] Blitz works now (maybe any other broken games), bit of code was ruining it!
 
Last edited:

RipNLa

New member
Doomulation said:
Damn, how the hell did it get so fast?
I new a new damn API to render, because this system doesn't seem fit for d3d rendering.
Source code for directdraw please? :whistling
I don't have ddraw since I have dx9 :saint:


Actually, my rendering was all in D3D. I don't use DDRAW either, since I use DX8 (I still have a GF4 Ti4200) =\
 

Doomulation

?????????????????????????
RipNLa said:
Actually, my rendering was all in D3D. I don't use DDRAW either, since I use DX8 (I still have a GF4 Ti4200) =\
Then how the hell did you do!? Lol, I'm trying every possible thing to get it faster.
I will concentrate on speed until I'm satisfied until I start fixing compability again.
 

aprentice

Moderator
Doomulation said:
Then how the hell did you do!? Lol, I'm trying every possible thing to get it faster.
I will concentrate on speed until I'm satisfied until I start fixing compability again.

are you doing any pixel enlargements? if you are, you lose your speed down to playable because of it :p

My chip8 emu would be lightening fast if i wasnt doing any pixel enlargements in the video core due to my cpu core being highly optimized (to make up for the speed loss in the pixel enlarger).

A solution would be to use quads, which would bring it back up on speed.
 

RipNLa

New member
aprentice said:
are you doing any pixel enlargements? if you are, you lose your speed down to playable because of it :p

My chip8 emu would be lightening fast if i wasnt doing any pixel enlargements in the video core due to my cpu core being highly optimized (to make up for the speed loss in the pixel enlarger).

A solution would be to use quads, which would bring it back up on speed.


What do you mean by pixel enlargements? Mine makes every 1x1 pixel a 10x10 pixel...is that considered pixel enlargement?...I'm even wondering if I even needed to do that since you can stretch the window to any size you want anyways...
 
Last edited:

zenogais

New member
hehe, cool Refraction, well I'm back from my Bahamas vacation, I was working on the tutorial every chance I got on vacation, I've also decided on a few things I wanted to demonstrate in this emulation tutorial (if I can), My list is as follows:

* Dynamic Recompilation
* Static Recompilation
* High-level of cross-platform compatability

Sadly I didn't get a chance to download the emulator sources before I left, so I haven't worked on it, but I did find a few bugs right before I left, which I'm now working on fixing. Also refraction, you can release the sources since I did license it under the GPL. Also I meant to make it more usable than in its current state, as having to type the ROM name in the DOS prompt is relatively annoying. Also, I'd rather not have any more releases until I can finish the tutorials, but great work, you've become a Chip8 expert! :p
 
Last edited:

zenogais

New member
Hehe, well I've just fixed the BCD encoding for NeoChip8, and I figured I'd share the solution as this is a common problem:

Code:
        //==================================================
	// Write BCD Encoded Value Of Register To Memory
	//==================================================
	case 0x33:
		{
			unsigned char ucRegister = (m_cpuContext.opcode&0x0F00)>>8;
			// Calculate BCD Encoding
			char ucBCD1 = m_pMemory->getRegister(ucRegister)/100;
			char ucBCD2 = (m_pMemory->getRegister(ucRegister) - (100*ucBCD1))/10;
			char ucBCD3 = (m_pMemory->getRegister(ucRegister) - (10 *ucBCD2));
			// Write BCD Encoded Values
			m_pMemory->writeByte(m_cpuContext.I    , ucBCD1);
			m_pMemory->writeByte(m_cpuContext.I + 1, ucBCD2);
			m_pMemory->writeByte(m_cpuContext.I + 2, ucBCD3);
		}
		break;
 

Top