View Full Version : My PotatoChipAte
glVertex3f
June 30th, 2004, 18:59
Ive been trying to make one of these things... and after reading throught the "Chip8" thread, I still have a few questions. Mainly I want to know if im on the right track, and if im doing any "no no's" in my code.
Please keep in mind that this is my first emu project and I just started this yesterday. Also that I am completely selftaught and the only time I learn new things about coding is when I happen to need it for my program. <- Thats why my code might seem n00bish.
EDIT: also, I am a bit slow... I cant seem to figure out how to put the "Memory" at position "I" without messing up the other drawing code (such as finding the x and y).
Doomulation
June 30th, 2004, 19:04
Ah, nice work for a first project. Pretty good, yes, but also some errors...
Opcodes are missing (I guess you'll add them later? ;))
After the jump opcode, PC is NOT incremented (0x1000).
A subroutine is like a function. You jump to the address for the function, and then execute code until you get the op 0x00EE (return from subroutine). The emulator jumps back to where it jumped to the subroutine and continues to execute ops after it.
Btw, lots of your math ops with carry are wrong.
Here, I'll attach my experimental doc for n00bs. Some info may be inaccurate, but still... hope this helps :)
glVertex3f
June 30th, 2004, 19:54
THANK YOU!
Being the self proclaimed n00b that I am, those docs are exactly what i need.
At the risk of making my n00by-ness supreme.... I cant really understand the whol font thing...
0xF0, 0x90, 0x90, 0x90, 0xF0 <<-- Like how is this zero?
refraction
June 30th, 2004, 20:01
THANK YOU!
Being the self proclaimed n00b that I am, those docs are exactly what i need.
At the risk of making my n00by-ness supreme.... I cant really understand the whol font thing...
0xF0, 0x90, 0x90, 0x90, 0xF0 <<-- Like how is this zero?
convert it into binary ;) cos thats how chip8 draws it, you get something like this
0xF0 = 11110000
0x90 = 10010000
0x90 = 10010000
0x90 = 10010000
0xF0 = 11110000
look at what shape the 1's make ;) if you cant see ill replace the 0's with .'s
0xF0 = 1111....
0x90 = 1. .1....
0x90 = 1. .1....
0x90 = 1. .1....
0xF0 = 1111....
also the bcd command in his document
FX33 Store BCD representation of VX in I...I+2 (*****)
do NOT increment I when doing it do like it says there, I, I+1, I+2
and if his bcd code doesnt work try this
memory[I] = i/100;
memory[I] + 1 = (i%100)/10;
memory[I] + 2 = i%10;
glVertex3f
June 30th, 2004, 20:07
oh i see...
refraction
June 30th, 2004, 20:18
also the subroutine code this is a good way to do it
assign a new unsigned char array in your header 16 spaces big called stack, and an integer called Subcall or something (this will be used to point to the right place in the array.
then when it calls the subroutine do something like this
if (Subcall < 16){
stack[Subcall] = PC;
PC = opcode&0x0FFF;
Subcall++;
}
then when you return from it
(if Subcall>0){
Subcall--;
PC = stack[Subcall];
stack[Subcall] = NULL;
}
glVertex3f
June 30th, 2004, 21:39
I updated the file at the top...
Now what im wanting to know is
A) Shouldnt this at least draw SOMETHING to the screen...
and
B) Are there any crucial opcodes I am missing. I am only wanting to get something on the screen, like the PONG Paddles or what not.
The reason is, I am trying to grasp the basic concepts of what each opcode does and for what reason. Then I am going to recode all of it, and put in timers and sound and user input and make the code overall neater.
refraction
July 1st, 2004, 00:42
well at the moment the emu doesnt run for me now, it just crashes :P
but one problem ive seen, in a few opcodes (like 0x7000) youve put in PC+=2; and youve put it at the end as well so it basically does PC+=4; every cycle, which you dont want if you dont want to skip an instruction.
the display buffer should be [64][32] as its 64 across and 32 down.. so youll need to swap it round in your drawsprite opcode call as well, plus remember its drawn in a XOR form as it uses the opcode to remove sprites as well as plot them. so itd be better having it as an 8bit array rather than boolean.
plus you need to check for collision too. so youd need something like
if (DisplayBuffer[Display.x + loopX][Display.y + loopY] = 1) V[F] = 0x1;
DisplayBuffer[Display.x + loopX][Display.y + loopY] ^= 1;
and for missing opcodes, id add the rest of the 0xF000 opcodes as well, theyre pretty crucial :)
the second line being the drawing line end the first line checking for collision.
but remember to set V[F] to 0x0 at the beginning of the opcode (and nowhere else) otherwise you will get a few problems with collision detection.
glVertex3f
July 1st, 2004, 01:19
would this draw?
void DrawSprite()
{
int height;
int x, y;
int loopX, loopY;
unsigned char Data;
height = OpCode&0x000F;
x = vRegister[OpCode&0x0F00 >> 8];
y = vRegister[OpCode&0x00F0 >> 4];
for(loopY = 0; loopY < height; loopY++)
{
Data = Memory[loopY + iRegister];
for(loopX = 0; loopX < 8; loopX++)
{
if((Data&(0x80 >> loopX)) != 0)
{
if(DisplayBuffer[y + loopY][x + loopX] == 1) vRegister[0xF] = 1;
DisplayBuffer[y + loopY][x + loopX] ^= 1;
}
}
}
}
I am currently in the middle of rewriting the EMU so I cant exactly test it....
and as for the whole Display[x][y] as to Diaply[y][x]... in the past.. (on tilemaps and mapeditors) ive had to do the y/x instead of x/y... maybe its just the way i do my aray?... i'll see when i get this code fixed
zenogais
July 1st, 2004, 01:36
would this draw?
void DrawSprite()
{
int height;
int x, y;
int loopX, loopY;
unsigned char Data;
height = OpCode&0x000F;
x = vRegister[OpCode&0x0F00 >> 8];
y = vRegister[OpCode&0x00F0 >> 4];
for(loopY = 0; loopY < height; loopY++)
{
Data = Memory[loopY + iRegister];
for(loopX = 0; loopX < 8; loopX++)
{
if((Data&(0x80 >> loopX)) != 0)
{
if(DisplayBuffer[y + loopY][x + loopX] == 1) vRegister[0xF] = 1;
DisplayBuffer[y + loopY][x + loopX] ^= 1;
}
}
}
}
I am currently in the middle of rewriting the EMU so I cant exactly test it....
and as for the whole Display[x][y] as to Diaply[y][x]... in the past.. (on tilemaps and mapeditors) ive had to do the y/x instead of x/y... maybe its just the way i do my aray?... i'll see when i get this code fixed
That looks exactly correct.
glVertex3f
July 1st, 2004, 02:28
Ok I just completely rewrote the main cpu code.... The zip is updated at the top up there...
Now, why wont it run anything...
btw.. I will crash on your PC unless you have a direcoty called C:\Chip8 with the BRIX game in it lol
EDIT:
Unless im doing it wrong... my log file shows it not even sending commands to the Cpu emulation...
zenogais
July 1st, 2004, 05:06
void ReturnFromSub()
{
if(SubCall > 0)
{
SubCall--;
MemoryIndex = Stack[SubCall];
Stack[SubCall] = 0;
}
}
Well a first look shows that this function isn't quite right. I would change it to smth like this:
void ReturnFromSub()
{
if(SubCall > 0)
{
MemoryIndex = Stack[SubCall];
Stack[SubCall] = 0;
SubCall--;
}
}
Also alot of your opcodes aren't even completed.
glVertex3f
July 1st, 2004, 05:18
I was hoping to see a little progress before I finished all the OpCodes...
And i'll try that function!
EDIT:
I fixed that function.
And shouldnt this show SOMETHING.... anything!?
refraction
July 1st, 2004, 13:22
hmm well looking at the debug file your emu generated, it doesnt look like its looping properly, seems to do the first loop then thats it (as it came up as 200:0)
im not too sure on that tho im not very good with interfacing with windows :P
it would be an idea to finish off all the commands if you can, then try the emu, its amazing how many of the op codes are used, or maybe rig it up to a different game like space invaders or tetris n see if they work.
glVertex3f
July 1st, 2004, 18:46
I had it set up to write to a log file every time an instruction was passed throught the Emu... And it does nothing.. if I writ the OpCode to the log every loop... the first code is always 0x9090 with every rom I try.. then it does a 0x6xxx... and thats it.
refraction
July 1st, 2004, 19:44
I had it set up to write to a log file every time an instruction was passed throught the Emu... And it does nothing.. if I writ the OpCode to the log every loop... the first code is always 0x9090 with every rom I try.. then it does a 0x6xxx... and thats it.
hmm i dunno why its doing that. only 2 things i can suggest..
1. try removing the else statement from around CpuEmulation(); and RenderScreen(); in the main.c file.
2. finish off the F000 opcodes, especially the memory access ones.
Doomulation
July 1st, 2004, 20:30
Note #1: In clear, a simple ZeroMemory(DisplayBuffer,128*64); should do the trick.
Other than that, I see no big errors in your code.
It should loop on forever it seems, unless something breaks the loop. Try step debugging, it should do the trick.
glVertex3f
July 1st, 2004, 20:45
FX0A: This literally means halt the program until a key is pressed THEN store it...
or just store a key if it is pressed...
refraction
July 1st, 2004, 20:54
halt the program til the key is pressed. in englishC (my screwed up language i just made up off the top of my head)
check keyarray to is if any keys pressed keypressed
if key was pressed
store in vx and proceed with program.
else
pc-=2
both same effect but gets rid of having to do a for loop.
Edit: if you saw my second optionit was wrong :p and i had to redescribe the first one
glVertex3f
July 1st, 2004, 21:14
void StoreKey()
{
if(KeyPress() < 16)
{
GetRegValue = KeyPress();
MemoryIndex += 2;
}
else MemoryIndex -= 2;
}
Like that...?
glVertex3f
July 1st, 2004, 21:21
In file included from c:\chipate\chip8cpu.c:2:
c:/chipate/Chip8.h:203: `DelayTimer' redeclared as different kind of symbol
c:/chipate/Chip8.h:7: previous declaration of `DelayTimer'
c:/chipate/Chip8.h: In function `DelayTimer':
c:/chipate/Chip8.h:204: warning: assignment makes integer from pointer without a cast
c:/chipate/Chip8.h: In function `SetDelayT':
c:/chipate/Chip8.h:221: invalid lvalue in assignment
Now.. I understood that when I made the DelayTimer an integer... but I changed it to an unsigned char and still get this... What am i doing wrong?
refraction
July 1st, 2004, 21:25
no
like this
case 0x0a:
{
int pos;
m_pKeyboard->update();
for(int i = 0; i <= 15; i++)
if (m_pKeyboard->m_cKey[i] == true) pos = i; //Find out if a key has been pressed
else
pos = NULL;
if(pos!=NULL)
m_pMemory->setRegister((m_cpuContext.opcode&0x0F00)>>8, m_pKeyboard->m_cKey[pos]);
else
m_cpuContext.PC-=2;
}
break;
the else pos = NULL; makes it look like it might kill it, but it doesnt, it works fine :)
glVertex3f
July 1st, 2004, 21:32
hmm.. I couold be wrong... but I think wht I have is actually like that...
int KeyPress()
{
if(bKeys[VK_NUMPAD0]) return 0;
if(bKeys[VK_NUMPAD7]) return 1;
if(bKeys[VK_NUMPAD8]) return 2;
if(bKeys[VK_NUMPAD9]) return 3;
if(bKeys[VK_NUMPAD4]) return 4;
if(bKeys[VK_NUMPAD5]) return 5;
if(bKeys[VK_NUMPAD6]) return 6;
if(bKeys[VK_NUMPAD1]) return 7;
if(bKeys[VK_NUMPAD2]) return 8;
if(bKeys[VK_NUMPAD3]) return 9;
if(bKeys[VK_DECIMAL]) return 10;
if(bKeys[VK_RETURN]) return 11;
if(bKeys[VK_ADD]) return 12;
if(bKeys[VK_SUBTRACT]) return 13;
if(bKeys[VK_MULTIPLY]) return 14;
if(bKeys[VK_DIVIDE]) return 15;
return 16;
}
void StoreKey()
{
if(KeyPress() < 16)
{
GetRegValue = KeyPress();
MemoryIndex += 2;
}
else MemoryIndex -= 2;
}
Is this still not right?
refraction
July 1st, 2004, 21:33
In file included from c:\chipate\chip8cpu.c:2:
c:/chipate/Chip8.h:203: `DelayTimer' redeclared as different kind of symbol
c:/chipate/Chip8.h:7: previous declaration of `DelayTimer'
c:/chipate/Chip8.h: In function `DelayTimer':
c:/chipate/Chip8.h:204: warning: assignment makes integer from pointer without a cast
c:/chipate/Chip8.h: In function `SetDelayT':
c:/chipate/Chip8.h:221: invalid lvalue in assignment
Now.. I understood that when I made the DelayTimer an integer... but I changed it to an unsigned char and still get this... What am i doing wrong?
well Delaytimer is an unsigned char, cos its data straight from the register. try not to name the void and the variable with the same name, it could be getting confused :P.
can you show me the code for them parts of the file?
glVertex3f
July 1st, 2004, 21:34
OMG.. I cant believe I did that... lol :blush:
EDIT:
Ive Finished the OpCodes (I think) and um... still nothing...
I updated the ZIP on the first page.
Doomulation
July 1st, 2004, 21:42
/me calls glVertex3f n00b :evil:
We all make mistakes ;)
glVertex3f
July 1st, 2004, 21:55
ok, Ive come to a conclusion...
this is not incrementing throught the Memory..
It loops the program.... but only passes the first instruction through the emulator.
Doomulation
July 1st, 2004, 22:10
Perhaps because you missed some ops.
Try to do a PC += 2 at the end of the cpu instead. Add PC += 2 to all skip ops when you skip the next op and PC -= 2 on the jump op so the PC isn't inremented.
glVertex3f
July 1st, 2004, 22:12
the first instruction is a '0x6xxx' and that calls the RegAssign_A() function...
at the end of the function is MemoryIndex+=2... shouldnt this work?
DOOM: Ill try that and see what happens. (And what opcodes am I missing?)
Doomulation
July 1st, 2004, 22:34
Well, duh, I can't help but to this time time.
n000000000000000000000000000b!!!!!!!!!!! :P :evil: :evil: :evil: :evil: :evil: :evil: :evil: :evil: :evil: :evil:
Okay I'm, done :D
You've got 3 problems:
1) You should be able to select rom to open (not just C:\Chip8\pong).
2) Don't try to execute the rom before you've opened it! Use a variable, say bLoaded AFTER loading the rom so that it runs the cpu.
3) In the cpu, you got this:
switch(opcode & 0xF000)
Remember that Binary AND only zeroes out the bits! The value would still be 0x6000. You're switching on 0x6.
To solve this, add three 0s after each op (ie case 0x6000) or change your switch to
switch( (opcode & 0xF000) >> 12 )
Be happy that I debugged it for you, n00b =) :evil: :evil: :evil: :evil:
glVertex3f
July 1st, 2004, 22:39
lol, dont you hate it when you do stuff like this...
1) I plan on doing this later :)
2)Just did that like 2 mins ago lol
3) OOOOOOPS
Just one of those days lol
refraction
July 1st, 2004, 22:44
alternative to doing the >>12 on the switch, just put 3 0's after the existing digits :P altho it takes longer, so you end up with
case 0x1000:
and so on.
but his way is good ;p
Doomulation
July 1st, 2004, 22:45
3) Yeah BIIIIIIIIIIG OOOOOOOOOOPS. But couldn't you find it through debugging? I mean, it's not really hard to find that, is it?
Refraction: I just told him he could add three 0s after! Lol, don't you read?! :icecream:
refraction
July 1st, 2004, 22:48
Refraction: I just told him he could add three 0s after! Lol, don't you read?! :icecream:
no i dont :bouncy:
glVertex3f
July 1st, 2004, 22:54
I dont know how to debug... (If you mean by using the :debugger:)
In case you forgot im a n00b remember lol
I only started WInAPI/OpenGL like a month ago...
And I made you changes and A few dots randomly show up on the screen now
Doomulation
July 1st, 2004, 23:01
Then go learn ffs lol. If you can't debug, then you can't get anywhere. :huh:
glVertex3f
July 1st, 2004, 23:03
"Then go learn ffs lol." <--- ffs?
refraction
July 1st, 2004, 23:15
"Then go learn ffs lol." <--- ffs?
for f u c k sake
i thought you were a programming n00b, not a net n00b :P
glVertex3f
July 1st, 2004, 23:26
oh lol, I thought he was referring to programming lol
refraction
July 1st, 2004, 23:36
oh lol, I thought he was referring to programming lol
what he was saying is learn how to debug, learn how to look at whats happening and realise why its not working :) it helps to know how C code works as well, try running a program in your head, look at what youve given it and follow what it should do, then realise why its not doing it, like with your switch case problem ;)
glVertex3f
July 1st, 2004, 23:57
Yeah, I do that alot (not enough), but today has been one of those days where your mind doesnt go as fast as you would hope ;)
Thats what my WriteLog function is for (wich I have working again).
right now its showing me all the instructions the rom is sending.. I compare that with the output from my "disassembler" program and see whats going on.
Im gonna add some more debug crap now so I can make it work better.
PS: Thank you DOOM and refraction for putting up with my noobness...Im sure i'll be back with another problem in a day or two (minutes)
refraction
July 2nd, 2004, 00:18
PS: Thank you DOOM and refraction for putting up with my noobness...Im sure i'll be back with another problem in a day or two (minutes)
haha its ok, your humor and willingness to admit your a n00b that compensates for it :) any more probs give either of us a shout
glVertex3f
July 2nd, 2004, 03:16
Ok, I was looking over my code, and thought "DOH, Im not shifting my RegValues...."
When I was not shifting them... A few dots, some blinking, would appear on the screen... Now after I shifted the "vRegister"s it shows nothing...
Am I not suppose to shift them?
EDIT: I updated the zip incase anyone wanted to take a look. If you notice anything majorly wrong let me know.
refraction
July 2nd, 2004, 12:24
you havent shifted them ;p
look a little advice when working with hex. if you want a single number say you got this for example
0x8264 <--- thats the add arithmetic opcode
say you do 0x0F00 to grab the 2, what you actually have there is 0x200, so you would be trying to access V[200] which is no good, so you need to shift it over. every number you go left from the end you add 4 to the shift like this
.0 x 0 0 0 0 <-- the hex
....12 8 4 0 <-- the shift to get it into a single number
so when you do vRegister[opcode&0x0F00] you are going for a number its its hundreds. so you wanna shift it like this
vRegister[((opcode&0x0F00)>>8)]
that will give you the single value you want.
may i suggest you read through the tutorial on the link below to get the basics of operators and working with hex etc.
cplusplus.com online tutorial (http://www.cplusplus.com/doc/tutorial/)
glVertex3f
July 2nd, 2004, 17:56
No, I know what shifting is. Thats what I am saying. It would show a few dots on the screen and a few would blink. But later I saw that I didnt shift the Register values and I was like DOH! So I shifted them.... and then it displayed nothing.. no dots...
I guess my point was why did it show something when I didnt shift the register values.
Why did vRegister[200] (which is what it was ending up with) actually showsomething!?
:)
refraction: I said I was a n00b, not a uber noob :bouncy:
Doomulation
July 2nd, 2004, 19:39
Very simple. Unlike VB, VC++ does not look if you're writing/reading outside an array. The compiler merly uses a formula to see the offset you're trying to read/write to.
If each variable in the array is 4 bytes and you try to access element 200, it uses the following forumula: addr_of_array + (4 * 200) = addr_of_array + 800. That's the location it will read from.
Do you expect this memory to be empty? No. It almost never is. You're reading junk data. You should actually concider yourself lucky that you don't get an access violation.
Make SURE you're filling the right registers everywhere. When it asks to draw from a certain register, do a sanity check to see if these contain any valid values. Also make sure the I register is properly set to point at the correct data.
You can use your watch window to see for example memory and see if there's any data there or if it's pretty much empty. This should be a fairly easy problem to solve with the debugger.
Remember: if your variables are corrupted somewhere in your program, use data breakpoints.
EDIT:
Compiling code...
Compilation errors found! Listing compilation errors in bold!
void SkipIF_A()
{
if(vRegister[OpCode&0x0F00] == (OpCode&0x00FF)) MemoryIndex += 4;
else MemoryIndex += 2;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
void SkipIF_B()
{
if(vRegister[OpCode&0x0F00] != (OpCode&0x00FF)) MemoryIndex += 4;
else MemoryIndex += 2;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
void SkipIF_C()
{
if(vRegister[OpCode&0x0F00] == vRegister[OpCode&0x00F0]) MemoryIndex += 4;
else MemoryIndex += 2;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
void SkipIF_D()
{
if(vRegister[OpCode&0x0F00] != vRegister[OpCode&0x00F0]) MemoryIndex += 4;
else MemoryIndex += 2;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
void RegAssign_A()
{
vRegister[OpCode&0x0F00] = (OpCode&0x00FF);
MemoryIndex += 2;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
void RegAssign_B()
{
vRegister[OpCode&0x0F00] += (OpCode&0x00FF);
MemoryIndex += 2;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
void RegAssign_C()
{
vRegister[OpCode&0x0F00] = vRegister[OpCode&0x00F0];
MemoryIndex += 2;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
void RegAssign_D()
{
vRegister[OpCode&0x0F00] |= vRegister[OpCode&0x00F0];
MemoryIndex += 2;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
void RegAssign_E()
{
vRegister[OpCode&0x0F00] &= vRegister[OpCode&0x00F0];
MemoryIndex += 2;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
void RegAssign_F()
{
vRegister[OpCode&0x0F00] ^= vRegister[OpCode&0x00F0];
MemoryIndex += 2;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
void RegAssign_G()
{
if(vRegister[OpCode&0x00F0] > (0xFF - vRegister[OpCode&0x0F00])) vRegister[0xF] = 1;
vRegister[OpCode&0x0F00] += vRegister[OpCode&0x00F0];
MemoryIndex += 2;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
Compilation error! If carry is not detected, register VF is set to 0!
void RegAssign_H()
{
if(vRegister[OpCode&0x0F00] >= vRegister[OpCode&0x00F0]) vRegister[0xF] = 1;
else vRegister[0xF] = 0;
[b] vRegister[OpCode&0x0F00] -= vRegister[OpCode&0x00F0];
MemoryIndex += 2;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
void RegAssign_I()
{
vRegister[0xF] = (vRegister[OpCode&0x0F00]&0x01);
vRegister[OpCode&0x0F00] >>= 1;
MemoryIndex += 2;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
Compilation warning: Bad name for shifting?
void RegAssign_J()
{
if(vRegister[OpCode&0x00F0] >= vRegister[OpCode&0x0F00]) vRegister[0xF] = 1;
else vRegister[0xF] = 0;
vRegister[OpCode&0x0F00] = vRegister[OpCode&0x00F0] - vRegister[OpCode&0x0F00];
MemoryIndex += 2;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
void RegAssign_K()
{
vRegister[0xF] = ((vRegister[OpCode&0x0F00]&0x80) >> 7);
vRegister[OpCode&0x0F00] <<= 1;
MemoryIndex += 2;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
void RegRandom()
{
vRegister[OpCode&0x0F00] = ((rand() % 16) & (OpCode&0x00FF));
MemoryIndex += 2;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
void DrawSprite()
{
int height;
int x, y;
int loopX, loopY;
unsigned char Data;
height = (OpCode&0x000F);
x = vRegister[OpCode&0x0F00];
y = vRegister[OpCode&0x00F0];
for(loopY = 0; loopY < height; loopY++)
{
Data = Memory[loopY + iRegister];
for(loopX = 0; loopX < 8; loopX++)
{
if((Data&(0x80 >> loopX)) != 0)
{
if(DisplayBuffer[x + loopX][y + loopY] == 1) vRegister[0xF] = 1;
DisplayBuffer[x + loopX][y + loopY] ^= 1;
}
}
}
MemoryIndex += 2;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
void SkipIFKey()
{
if(KeyPress() < 16) MemoryIndex += 4;
else MemoryIndex += 2;
WriteLog(Log);
}
void SkipIFnKey()
{
if(KeyPress() == 16) MemoryIndex += 4;
else MemoryIndex += 2;
WriteLog(Log);
}
Compilation error! These opcodes checks if the register found in register defined by OpCode & 0x0F00 is pressed or not!
void DelayTimer()
{
vRegister[OpCode&0x0F00] = DTimer;
MemoryIndex += 2;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
void StoreKey()
{
if(KeyPress() < 16)
{
vRegister[OpCode&0x0F00] = KeyPress();
MemoryIndex += 2;
}
else MemoryIndex -= 2;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
void SetDelayT()
{
DTimer = vRegister[OpCode&0x0F00];
MemoryIndex += 2;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
void SetSoundT()
{
STimer = vRegister[OpCode&0x0F00];
MemoryIndex += 2;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
void IAssignment()
{
iRegister += vRegister[OpCode&0x0F00];
MemoryIndex += 2;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
void IToFont()
{
iRegister = vRegister[OpCode&0x0F00] * 5;
MemoryIndex += 2;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
void SaveMem()
{
int loop;
for(loop = 0; loop < vRegister[OpCode&0x0F00]; loop++)
Memory[iRegister + loop] = vRegister[loop];
MemoryIndex += 2;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
void LoadMem()
{
int loop;
for(loop = 0; loop < vRegister[OpCode&0x0F00]; loop++)
vRegister[loop] = Memory[iRegister + loop];
MemoryIndex += 2;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
void StoreBCD()
{
iRegister = vRegister[OpCode&0x0F00];
Memory[iRegister] = (iRegister ) / 100;
Memory[iRegister + 1] = (iRegister / 10) % 10;
Memory[iRegister + 2] = (iRegister % 100) / 10;
WriteLog(Log);
}
Compilation error! Register value not shifted properly!
Counting compilation errors: ...error... lost count. Cannot continue.
Congratulations, you've just been awarded for the sloppiest coding of all time! Congraulations, n00b! :flowers:
zenogais
July 2nd, 2004, 20:04
Very simple. Unlike VB, VC++ does not look if you're writing/reading outside an array. The compiler merly uses a formula to see the offset you're trying to read/write to.
If each variable in the array is 4 bytes and you try to access element 200, it uses the following forumula: addr_of_array + (4 * 200) = addr_of_array + 800. That's the location it will read from.
Do you expect this memory to be empty? No. It almost never is. You're reading junk data. You should actually concider yourself lucky that you don't get an access violation.
Make SURE you're filling the right registers everywhere. When it asks to draw from a certain register, do a sanity check to see if these contain any valid values. Also make sure the I register is properly set to point at the correct data.
You can use your watch window to see for example memory[I] and see if there's any data there or if it's pretty much empty. This should be a fairly easy problem to solve with the debugger.
Remember: if your variables are corrupted somewhere in your program, use data breakpoints.
The formula can be simplified in C++ format to:
int nMyArray[10];
int nOffset = 1;
*(((char*)nMyArray) + (nOffset*sizeof(int))) = 4;
In order for Doomulations technique to work in C++, everything must be recast into a char*, but this is how memory is handled under-the-hood. Also, I would recommend crashing if the "sanity check" fails, this would mean using assert() or C++ exceptions (if you're using assert's then C: <assert.h> C++: <cassert>). Using an assert will show you exactly on what line the crash happens in your program, but with exceptions you can throw a string telling the exact error. Which one you choose is up to you.
glVertex3f
July 2nd, 2004, 22:08
"Congratulations, you've just been awarded for the sloppiest coding of all time! Congraulations, n00b!"
What do you mean? I've said several times "Doh, I forgot to shift"...
:bye3:
btw, is the Dev-C++ debugger even worth using?
refraction
July 3rd, 2004, 00:45
"Congratulations, you've just been awarded for the sloppiest coding of all time! Congraulations, n00b!"
What do you mean? I've said several times "Doh, I forgot to shift"...
:bye3:
btw, is the Dev-C++ debugger even worth using?
no he doesnt mean the program debugger, cos your c code could be perfectly fine, but its if its emulating the machine properly or not. so you need a debugger for the actual system your emulating :)
glVertex3f
July 3rd, 2004, 02:55
Ok I made a debugger to output what the EMU is being told to do (and im quite proud of it)...
Any way...
VX = KK: V[E] 05
VX = KK: V[5] 00
VX = KK: V[B] 06
VX = KK: V[A] 00
I = 30C
DrawSprite: X = 0 Y = 6 Height = 1
VX = VX + KK: V[A] 04
Skip IF VX == KK: V[A] 40
MemoryIndex = 208
I = 30C
DrawSprite: X = 4 Y = 6 Height = 1
VX = VX + KK: V[A] 04
Skip IF VX == KK: V[A] 40
MemoryIndex = 208
I = 30C
DrawSprite: X = 8 Y = 6 Height = 1
VX = VX + KK: V[A] 04
Skip IF VX == KK: V[A] 40
MemoryIndex = 208
I = 30C
DrawSprite: X = C Y = 6 Height = 1
VX = VX + KK: V[A] 04
Skip IF VX == KK: V[A] 40
MemoryIndex = 208
I = 30C
DrawSprite: X = 10 Y = 6 Height = 1
VX = VX + KK: V[A] 04
Skip IF VX == KK: V[A] 40
MemoryIndex = 208
I = 30C
DrawSprite: X = 14 Y = 6 Height = 1
VX = VX + KK: V[A] 04
Skip IF VX == KK: V[A] 40
MemoryIndex = 208
I = 30C
DrawSprite: X = 18 Y = 6 Height = 1
This is some of the output... This way is alot easier to find problems..
Is this what you are talking about?
zenogais
July 3rd, 2004, 05:47
Thats exactly what we were talking about, nice work!
glVertex3f
July 3rd, 2004, 06:47
Im still working out some opcodes... but one interesting thing... See that debug output up there... That would basically make you think it is actually drawing something to screen... well, it doesnt... UNLESS!
If I take out the
if((Data&(0x80 >> loopX)) != 0)
It shows crap in the screen... of course not what its supposed to.. but it does.
So my question is what is wrong with my drawing code!?
void DrawSprite()
{
int height;
int x, y;
int loopX, loopY;
unsigned char Data;
height = (OpCode&0x000F);
x = vRegister[(OpCode&0x0F00) >> 8];
y = vRegister[(OpCode&0x00F0) >> 4];
for(loopY = 0; loopY < height; loopY++)
{
Data = Memory[loopY + iRegister];
for(loopX = 0; loopX < 8; loopX++)
{
if((Data&(0x80 >> loopX)) != 0)
{
if(DisplayBuffer[x + loopX][y + loopY] == 1) vRegister[0xF] = 1;
DisplayBuffer[x + loopX][y + loopY] ^= 1;
}
}
}
MemoryIndex += 2;
RenderScreen();
}
Doomulation
July 3rd, 2004, 21:36
Yes, but asm output is not enough. You'll want a nice GUI debugger, where you can step your code and see the effects.
Make SURE you have shifted ALL your registers properly, as I showed in the code above. Create a define named GetReg or something.
Even when I first made the emulator, I got output, although it was off a little. You must be doing some simple mistake.
EDIT: Here's my newest version of the doc. It should be complete. I've updated the doc with my latest opcodes, which seem to get most games working perfecly :) Note that most of the opcodes were fixed by refraction, as he's been working on it like 24 hours a day.
Anyway, this should help you once you fix your display!
glVertex3f
July 3rd, 2004, 22:23
Thanks Doom,
I'll give that a look as son as I figure out my drawing code. Cant figure out what's going on with it.
glVertex3f
July 4th, 2004, 08:55
I have found the mother of all problems... I cant belive no one else saw this in my code. It's so simple.
I think when I actually put the ROM into the memory array... the loop is broken before the ROM is through loading. I realized this as I was looking through debug output. the iRegister was pointing to a place in memory that was far ahead of any data hence nothing to draw.
I need to figure out a way to get the file size and read that amount then break instead of the way I was doing it.
refraction
July 4th, 2004, 20:59
EDIT: Here's my newest version of the doc. It should be complete. I've updated the doc with my latest opcodes, which seem to get most games working perfecly :) Note that most of the opcodes were fixed by refraction, as he's been working on it like 24 hours a day.
Anyway, this should help you once you fix your display!
one problem in that mate, the Schip8 fonts arent exactly double the chip8 ones, on chip8 they are 4x5, and schip is 4x10 i think, you may get away with 8x10, it may also be that but ive never seen a doc that actually says that!
Doomulation
July 4th, 2004, 21:26
8x10 is double width of a chip8 font. It looks better plus it won't cause trouble since it's 8 bits.
Besides that, each schip8 pixel is supposed to be two chip8 pixels. Remember that.
glVertex3f: I, as well as the others, I guess, just skimmed through your code without actually running it. Plus, I only looked at your opcodes, and not the rest of the code. Which is probably why I missed this.
But if you use code such as this, it should be no problem:
FILE* fFile = fopen(rom);
fseek(fFile,0,SEEK_END);
int size = ftell(fFile);
fseek(fFile,0,SEEK_SET);
fread(memory,size,1,fFile);
fclose(fFile);
This will read the entire rom into memory directly. If it does this, I cannot see how it can't miss parts of the rom.
aprentice
July 4th, 2004, 21:27
one problem in that mate, the Schip8 fonts arent exactly double the chip8 ones, on chip8 they are 4x5, and schip is 4x10 i think, you may get away with 8x10, it may also be that but ive never seen a doc that actually says that!
I ran the fontset in dooms docs through the fontset tester in my chip8 emu and these are the results. It looks fine to me... (D,E,F goes offscreen by 1 pixel but thats my fault since i have it in CHIP8 mode res)
refraction
July 4th, 2004, 21:36
umm, then fonts look the same width to me of 4 pixels. so that brings me to think youve got 4x5 and 4x10 fonts, which is what i said ;)
Doomulation
July 4th, 2004, 23:30
Wellll... actually, my fonts are only 4x10, I'm too lazy to re-do them. But they are supposed to be 8x10. If you don't believe me, run alien and when you see the "0 1" at the beginning, you'll notice a lot of gap.
That alone makes me think they should be 8x10.
EDIT: Look at the pic.
zenogais
July 5th, 2004, 02:19
Nice debugger Doomulation! :D I'm working on something similar to that one at the moment, the debugger will also have a memory disassembly which can be stepped through in real time. I'm also thinking about finally moving out of a console application, and creating a windows application from which I can run the programs. Anyway, there are alot of top notch Chip8 emulators on these forums, so glVertex3f, I would recommend that you look at the source code for at least one of these emulators, as there are plenty for you to learn from, just don't copy code without giving proper credits :happy:
sammyboy
July 6th, 2004, 18:51
I agree with zenogais, I know nothing about debuggers apart from the fact that they show up bugs (do they fix them as well or something).
But from my past experience most of them look messy but your looks really clean.
glVertex3f
July 7th, 2004, 04:50
Speaking of debuggers... anyone know of a nice tutorial or can someone give me an example of how to text/variables onto my little debuger window.
Note: I have a basic Dialog box for a bebug window, I just need to know how to put crap on it lol.
EDIT: also My emu is showing great progress... Some games are nearly playable (note: Nearly).
aprentice
July 7th, 2004, 05:20
http://winprog.org/tutorial/
glVertex3f
July 7th, 2004, 05:43
Ive been there but it only shows how to print text through the resource file. I want to be able to print variables onto the window. Can I assign variables in the resource file?
smcd
July 7th, 2004, 08:05
You could try looking up SetWindowText or SetDlgItemText - use it to set the text in an edit box or the like.
glVertex3f
July 7th, 2004, 18:55
Ok, i'll google it :)
Thank You!
glVertex3f
July 8th, 2004, 07:06
Have a look at this Debug output
OpCode: 0x22F6 Memory[220] Call SubRoutine at 2F6
OpCode: 0xA314 Memory[2F6] I = 314
OpCode: 0xF533 Memory[2F8] Store BCD
OpCode: 0xF265 Memory[2FA] Load Mem
OpCode: 0xF129 Memory[2FC] I to Font
OpCode: 0x6337 Memory[2FE] V[3] = 37
OpCode: 0x6400 Memory[300] V[4] = 00
OpCode: 0xD345 Memory[302] DrawSprite: X = 55 Y = 0 Height = 5
OpCode: 0x7305 Memory[304] V[3] = V[3] + 05
OpCode: 0xF229 Memory[306] I to Font
OpCode: 0xD345 Memory[308] DrawSprite: X = 60 Y = 0 Height = 5
OpCode: 0x00EE Memory[30A] Return From Sub
OpCode: 0x0000 Memory[2] Return From Sub
OpCode: 0x0000 Memory[2] Return From Sub
After that it loops the Return From Subroutine indefinately.
I am pretty sure I need to store the place where the memory was when it first called the SubRoutine but I cant figure out what or how.
Here is my call\return SubRoutine code
void CallSubRoutine()
{
if(SubCall < 16)
{
Stack[SubCall] = MemoryIndex;
MemoryIndex = (OpCode&0x0FFF);
SubCall++;
}
}
void ReturnFromSub()
{
if(SubCall > 0)
{
MemoryIndex = Stack[SubCall];
Stack[SubCall] = 0;
SubCall--;
}
MemoryIndex += 2;
}
zenogais
July 8th, 2004, 07:11
Here's a quick fix for ya:
void ReturnFromSub()
{
if(SubCall > 0)
{
MemoryIndex = Stack[--SubCall];
}
MemoryIndex += 2;
}
Hope this will help you. Its not absolutely vital that you set the previous stack address to zero, just as long as you don't reuse it, which shouldn't happen.
glVertex3f
July 8th, 2004, 07:39
It still gets "stuck" at the ReturnFromSub function...
EDIT: Here is my full source if you would like to have a gander
refraction
July 8th, 2004, 11:36
take out that memory index increment, i have a feeling thats the cause of the problem
glVertex3f
July 8th, 2004, 18:30
Well, I had thought about that, but it still got stuck.
When it calls it the first time it looks ok but then it calls it again and the MemoryIndex drops and it gets stuck there
Kevin19
July 8th, 2004, 19:22
Hello and good morning glVertex3f
The same thing happened to me yesterday and when i looked at the report my debugger issued it seemed to have stuck at the address which indicates the RTS opcode the return from subroutine instruction
It took my a while to figure out a solution to this problem
and the solution is to increase the size of the stack array I increased mine to 40 and had the cycles set to 200 and it works beautifully
This is my RTS function Incase you want to compare
if((opcode&0xFF)==0xEE)
{
PC=stack[++SP];
}
And this is my JSR
stack[SP--]=PC=PC+2;
PC=opcode&0xFFF;
zenogais
July 8th, 2004, 20:05
Hello and good morning glVertex3f
The same thing happened to me yesterday and when i looked at the report my debugger issued it seemed to have stuck at the address which indicates the RTS opcode the return from subroutine instruction
It took my a while to figure out a solution to this problem
and the solution is to increase the size of the stack array I increased mine to 40 and had the cycles set to 200 and it works beautifully
This is my RTS function Incase you want to compare
if((opcode&0xFF)==0xEE)
{
PC=stack[++SP];
}
And this is my JSR
stack[SP--]=PC=PC+2;
PC=opcode&0xFFF;
Thats not really the answer. Its just a fluke that that worked, but as you can see in your emulator you don't set a cap on the number of calls you can make.
The problem is that the address he returns to isn't the same as the address he jumps from.
Kevin19
July 8th, 2004, 20:32
I stopped at the part when he said he ran into the kind of problem I had
And no i do not think it really matters
I might not be working very carefully but i still know that nothing is accurate when you work under the supervision of a compiler
I still think he should increase the Array because his debugger indicates the same stop at RTS I do not know how extended and knowledgeable You are And i would not want to derogate You and start bashing so i am going to stop here
I also suggest him to try and decrease the cycles to 200
I am almost 100 percent sure that it would work and solve his problem if he did IT
Doomulation
July 8th, 2004, 22:48
Nice debugger Doomulation! :D
Thanks.
I agree with zenogais, I know nothing about debuggers apart from the fact that they show up bugs (do they fix them as well or something).
Basically, a debugger is a tool which helps you find bugs in your software.
Kevin19: I think the actualy problem lies writing beyond array bounds. Increasing the size of the array probably won't help, as no game ever does more than 16 sub jumps from what I have seen.
I've experienced a similar problem as the return address gets corrupt. Put a breakpoint at the sub jump op and trace your way along the code to see when the the value gets corrupted.
The best way to do this is a data breakpoint.
refraction
July 9th, 2004, 00:05
it could also be another opcode is messing it up, like with Dragon1 i found it was making loads of illegal jumps for some reason which i dont know, but it was nothign to do with the subroutine code, i suggest you check your other opcodes as well, ill have a look through n see if i can see anything that would cause the illegal jumps.
Edit: right i just had a look through and theres just a couple of problems with opcodes i can see, altho i dont know how it affects your jumps.
void RegRandom()
{
vRegister[(OpCode&0x0F00) >> 8] = ((rand() % 16) & (OpCode&0x00FF));
MemoryIndex += 2;
}
that i think should be more like this
void RegRandom()
{
vRegister[(OpCode&0x0F00) >> 8] = (rand() & (OpCode&0x00FF));
MemoryIndex += 2;
}
as i think its a number lower or equal to 0x00FF, dont quote me on it tho :P if not try
void RegRandom()
{
vRegister[(OpCode&0x0F00) >> 8] = ((rand()%0xFF) & (OpCode&0x00FF));
MemoryIndex += 2;
}
The 0x8000 opcodes with carry, you should set the carry to the value in VX like you did with RegAssign_I(), but so it does
vRegister[0xF] = vRegisterX&0x1;
oh and your font code, you have to times the number in VX by 5 to get the correct point in the memory (which may be one of your problems)
apart from that something is seriously wrong with your l33t programming skillz cos it crashes after about 1 second of running :P
Doomulation
July 9th, 2004, 20:29
I doubt the other opcodes messes up the returns. They can cause all kinds of problems, but not return errors unless writing outside the array bounds. Which was actually a problem I dealt with, which caused the error in the joust game I think that I bothered you about some time ago (remember?).
glVertex3f
July 11th, 2004, 03:32
This might seem like tying up the horse after its already drown... or something... but I have a question...
C or C++... Is one really more eficient than the other. I mean I hardly ever see an emulator written with C++ (except a few chip8 emus).
And a follow up on that question
I want an example of how to emulate the memory by allocating it indtead of an array.
like
unsigned char Memory;
Memory = new unsigned char;
If someone could give me an example of how that would work as far as pointing to a certain place in the memory. And Loading the rom into the Memory.
zenogais
July 11th, 2004, 05:39
This might seem like tying up the horse after its already drown... or something... but I have a question...
C or C++... Is one really more eficient than the other. I mean I hardly ever see an emulator written with C++ (except a few chip8 emus).
And a follow up on that question
I want an example of how to emulate the memory by allocating it indtead of an array.
like
unsigned char Memory;
Memory = new unsigned char;
If someone could give me an example of how that would work as far as pointing to a certain place in the memory. And Loading the rom into the Memory.
That is rather like beating the dead horse, but the truth is it doesn't really matter. Both languages are fairly fast, though some hardcore C programmers will claim that C++ is always faster, which is just plain wrong. I personally think C++ has some powerful features that authors of other emulators who program in C have to go out of their way to implement (virtual functions and polymorphism are good examples). also, when allocating memory the C++ way as you are showing, you would do this:
// Allocating a single pointer variable
unsigned char* pMemory = new unsigned char;
// Deallocating the single pointer variable
delete pMemory
....
// Allocating an array using new
unsigned char* pMemory = new unsigned char[0xFFF];
// Deallocating the array using delete
delete [] pMemory;
..
or
..
delete[] pMemory;
As for loading the roms into memory, well theres plenty of source code on these forums for you to look at.
glVertex3f
July 11th, 2004, 05:47
Well, see im going to rewrite my emulator. I wanted to know of another way of emulating memory besides making an array. But without an array, I dont know how to go to a certain address in the memory I allocated.
For example:
unsigned char *Memory = new unsigned char;
MemoryIndex = 0x200;
Now how would I load the rom starting at "MemoryIndex" or jump to "MemoryIndex"?
zenogais
July 11th, 2004, 05:49
Well, see im going to rewrite my emulator. I wanted to know of another way of emulating memory besides making an array. But without an array, I dont know how to go to a certain address in the memory I allocated.
For example:
unsigned char *Memory = new unsigned char;
MemoryIndex = 0x200;
Now how would I load the rom starting at "MemoryIndex" or jump to "MemoryIndex"?
The only logical way to emulate the memory is an array, other than that theres a series of much much less efficient ways of doing it.
glVertex3f
July 11th, 2004, 06:11
so..
unsigned char *Memory = new unsigned char[0xFFF];
//Would that be more eficient than
unsigned char Memory[0xFFF]
I am wanting to go back and redo this emulator because I want to be sure I understand all the concepts well. At the point I am at now theres no way I could go and emulate a GB or anything, but for future refrence... would an Atari be a logical next step. I really dont need something with ALOT of instructions.
zenogais
July 11th, 2004, 06:35
so..
unsigned char *Memory = new unsigned char[0xFFF];
//Would that be more eficient than
unsigned char Memory[0xFFF]
I am wanting to go back and redo this emulator because I want to be sure I understand all the concepts well. At the point I am at now theres no way I could go and emulate a GB or anything, but for future refrence... would an Atari be a logical next step. I really dont need something with ALOT of instructions.
One is not necessarily more efficient than the other. The first one allocates the memory dynamically at a point of your choosing during execution, the second allocates the memory statically on the heap at program start. I prefer the dynamic method because you can detect out-of-memory errors more efficiently with it (if you set the Memory pointer to 0 at before allocating and its still 0 after using operator new then you know the system is out-of-memory, as most operator new's are just wrappers around malloc and free) and also its size can be expanded at anytime during program execution.
Also, the ATARI would certainly be a logical next step after the Chip8, although the ATARI just uses a customized 6502C processor, i.e. the processor used in the NES I believe. I think that most processors besides the Chip8 have "alot" of instructions. But they can also do more things than the Chip8. I hope this stuff helps you.
smcd
July 11th, 2004, 17:27
Err... if it is "allocated" inside the program before running, that'd be STATIC, not DYNAMIC. Looks like you mixed those 2 up, zenogais?
zenogais
July 11th, 2004, 21:38
Err... if it is "allocated" inside the program before running, that'd be STATIC, not DYNAMIC. Looks like you mixed those 2 up, zenogais?
Did I? All I know is that if you use new or malloc to allocate it, thats dynamic. If you declare the size at compile time without using new or malloc, thats static.
Cyberman
July 12th, 2004, 00:02
Did I? All I know is that if you use new or malloc to allocate it, thats dynamic. If you declare the size at compile time without using new or malloc, thats static.
I think you are quite confused :)
First off...
delete [] array_of_data;
is an OLD C++ method of deleting arrays. It's not needed anymore, Bjorne Stausap got rid of that about 10 years ago because it was confusing and obfuscating. In C++ the compilor knows the type it's deleting because the object knows what it is.
Thus
delete aray_of_data;
is quite acceptable.
Static Dynamic and Stack allocated.
All righty you've got these ALL confused.
Static is technically another version of a globally allocated variable, the difference is that the static type is only accessable in the scope in which it's used.
unsigned long Lerg()
{
static unsigned long whatsit;
whatsit++;
return whatsit;
}
whatsit will always be incremented by lerge but is never accessable by anything else. DO NOT USE STATIC unless you know exactly what you are doing. Otherwise it could have some bad consequences.
You know what dynamic already is.
LOCALLY allocated arrays and variables are only in existance when that function inside a class or C function is called. These are actually alocated on the stack.
unsigned long lerg::lerg(void)
{
unsigned long whatsit;
whatsit++;
return whatsit;
}
This is BAD code because whatsit is not initialized, basically it could be any value. The variable only exists within the scope of the function outside it, it is not allocated nor accessable by the compilor. Static however since it is globably allocated can still exist and persist although is inaccessable except from within the scope it's used.
Cyb
glVertex3f
July 12th, 2004, 00:09
So.... I could allocate an aray of memory like so
unsigned char *Memory = new unsigned char [0xFFF];
// initialize memory
now are you saying its bad to access this directly? That I shut make Memory a local variable only accessible inside a function an use it through a pointer?
(Isnt it already a pointer though)
smcd
July 12th, 2004, 04:05
<Was extremely sleepy> and posting again. I must stop this dangerous habit...
zenogais
July 12th, 2004, 08:43
@Cyb:
Well actually I was talking about static vs dynamic allocation, static being nonchangable, dynamic being changeable. Not static variables vs dynamic variables.
Anyway, most of the stuff you said was correct except for the fact about delete[] being deprecated from the standard. I went and checked the standard, and it says that every compiler needs to define "operators new, new[], delete, delete[]", and if you read further into the standard you'll find that the behavior of delete on any variable allocated with new[] is undefined. In other words this is a dangerous operation and should'nt be used, use delete[]. Allocated variables (other than class) carry no type information along with them, meaning that a variable of type "unsigned char" allocated with new[] doesn't know that its an array. In order for these kinds of objects to retain type data , there would have to be "extra" hidden code generated by the compiler which would make operator new and delete in all their forms much less efficient than their C equivalent malloc and free, which would be a very poor design decision just to avoid the programmers making a simple mistake.
glVertex3f
July 12th, 2004, 17:43
so your sayin the whole allocating memory array with new is a bad idea?
zenogais
July 12th, 2004, 20:04
so your sayin the whole allocating memory array with new is a bad idea?
Sorry man, didn't mean to confuse you. As far as memory arrays are concerned "yes you need to allocate an array of memory to emulate the chip8's memory".
Doomulation
July 12th, 2004, 20:38
so your sayin the whole allocating memory array with new is a bad idea?
To clear things up a bit, read this:
Know the diffrence between the stack and the heap. Using new, you put data on the heap; not using new, you put them on the stack.
Now, in most threads (and default), the stack is only 1 mb. But on the heap, there is no such limitation. The heap is only limited by the actual amount of memory you have available in your machine (save for the fact that windows actually hands each application a max of 4 gb of memory).
Therefore, large data should be put on the heap, and lesser on the stack.
Data on stack is prefer because it's automatically destroyed by the compiler. With memory on the heap, you must manually destroy it with delete.
Also, data on the stack is "static," as explained. It's always the same size and cannot be changed. Data allocated on the heap is dynamic and size can be changed during the long run.
So no--there is nothing wrong with using the new on the memory :)
glVertex3f
July 12th, 2004, 20:47
So as far as Chi8 is concered its 6 in one hand and half a dozen in the other? :P
Doomulation
July 12th, 2004, 21:08
Ehhhh... I don't think I got your meaning there :blush:
glVertex3f
July 12th, 2004, 21:20
ok since your a programmer lets do it this way...
#define SIX 6
#define DOZEN 12
int hand1, hand2;
if(System == Chip8) {
hand1 = SIX;
hand2 = DOZEN/2;
}
EDIT:
In pure terms.... I desnt really matter wich one (on the stack/heap) with Chip8. Neither has an advantage.
Doomulation
July 12th, 2004, 21:38
I understood what you said, but not what it meant...
Use whichever you feel you wish to use... there's no forcing you. Either is as good. But usually you'd use the stack for small data and the heap for large data.
glVertex3f
July 12th, 2004, 21:59
One more thing... am I really this bad of a programmer that I cant get this Chip8 to work.
I mean I have looked through several Chip8 emulator sources and I seem to be doin everything right but it still gets stuck at the return from subroutine.
Doomulation
July 12th, 2004, 22:21
As I wrote before,
first, you check the subroutine call. Make sure it stores the correct return address.
Then, at the return, if the address to return to is wrong, then it gets garbeled somewhere. Add a data breakpoint to see where it's getting corrupted.
Easy.
glVertex3f
July 12th, 2004, 22:22
"Add a data breakpoint "
What is that exactly.. heh... :blush:
Doomulation
July 12th, 2004, 22:25
A data breakpoint is a breakpoint that breaks whenever the contents of a variable changes or meets a certain condition.
In NET, it's easy to add one of these. Simply right-click the variable to add a breakpoint for, select new breakpoint, goto the data tab, and lastly, remove the function delcaration (the part before the first comma) so that it looks in all functions.
glVertex3f
July 12th, 2004, 23:01
I noticed that if I add 0x200 to the MemoryIndex in the rts function the games kinda actually work. So................. thats really odd....
refraction
July 13th, 2004, 11:02
"Add a data breakpoint "
What is that exactly.. heh... :blush:
he means pause the program where you can look at the data that is in the registers and what the opcode is that is called, where your emu is pointing etc
I noticed that if I add 0x200 to the MemoryIndex in the rts function the games kinda actually work. So................. thats really odd....
how do you mean exactly?? the only play anything should have 0x200 is right at the start, the return sub function should be pointing at the location directly after the last subrouting was called, nothing else.
glVertex3f
July 13th, 2004, 19:17
the only play anything should have 0x200 is right at the start, the return sub function should be pointing at the location directly after the last subrouting was called, nothing else.
I know that.... You know that... My emulator... im not so sure.
I noticed that when the rts function returned it seems to be exactly 200 below where it should be.. so i thought.. hmm... and added 200, and it worked. So what can be causing the index loss?
(And as far as the break points and stuff, Im learning how to use the MSVC++ Express Beta because Dev-C++ seems like to much of a chore)
Doomulation
July 13th, 2004, 19:34
glVertex: I recommend you take a better look at your subroutine return code. Because actually, that might even be incorrect. Some games are mostly unaffected by this (pong), and some others crash later (most schip8 games, ie alien, dragon, etc).
When you use the express beta, do as I instructed, it should work in there. You need to learn this aspect of debugging. Someday, you will go nuts if you don't have this in store.
glVertex3f
July 13th, 2004, 21:21
Yup I finally realized exactly what your talkin about doom lol.
I am currently rewriting the emulator in the express beta. Im sure i'll be back soon :P
glVertex3f
July 14th, 2004, 01:35
MSVC Express beta error output
------ Build started: Project: ChipAte, Configuration: Debug Win32 ------
Compiling...
InitWin.cpp
c:\VCProj\ChipAte\ChipAte\InitWin.cpp(85 ) : error C2143: syntax error : missing ')' before ';'
c:\VCProj\ChipAte\ChipAte\InitWin.cpp(85 ) : error C2660: 'glOrtho' : function does not take 2 arguments
c:\VCProj\ChipAte\ChipAte\InitWin.cpp(85 ) : error C2143: syntax error : missing ';' before ','
c:\VCProj\ChipAte\ChipAte\InitWin.cpp(85 ) : error C2143: syntax error : missing ';' before ','
c:\VCProj\ChipAte\ChipAte\InitWin.cpp(85 ) : error C2059: syntax error : ')'
c:\VCProj\ChipAte\ChipAte\InitWin.cpp(12 2) : error C2143: syntax error : missing ')' before ';'
c:\VCProj\ChipAte\ChipAte\InitWin.cpp(12 2) : error C2660: 'CreateChip8Window' : function does not take 2 arguments
c:\VCProj\ChipAte\ChipAte\InitWin.cpp(12 2) : error C2143: syntax error : missing ';' before ','
c:\VCProj\ChipAte\ChipAte\InitWin.cpp(12 2) : error C2143: syntax error : missing ';' before ','
c:\VCProj\ChipAte\ChipAte\InitWin.cpp(12 2) : error C2059: syntax error : ')'
c:\VCProj\ChipAte\ChipAte\InitWin.cpp(12 8) : warning C4244: 'return' : conversion from 'WPARAM' to 'int', possible loss of data
main.cpp
c:\VCProj\ChipAte\ChipAte\main.cpp(88) : warning C4244: '=' : conversion from 'LRESULT' to 'LONG', possible loss of data
Generating Code...
Build log was saved at "file://c:\VCProj\ChipAte\ChipAte\Debug\BuildLog .htm"
ChipAte - 11 error(s), 2 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Heres the lines(and funsctions) in question...
void SizeOpenGLScreen(int width, int height)
{
if(height == 0)
height = 1;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, -15, 0, 1); <--HERE
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR cmdline, int ishow)
{
HWND hWnd;
hWnd = CreateChip8Window("Potato ChipAte", SCREEN_WIDTH, SCREEN_HEIGHT, hInstance); <--here
if(hWnd == NULL) return TRUE;
Init(hWnd);
return MainLoop();
}
refraction
July 14th, 2004, 01:45
could be one of your compiler settings, does it do the same on release as well as debug?
glVertex3f
July 14th, 2004, 01:49
yup same thing on release.
wait how do you switch to release mode.... lol
refraction
July 14th, 2004, 01:52
the drop down box at the top that says "Debug" in it :P
glVertex3f
July 14th, 2004, 01:53
yup same thing :)
refraction
July 14th, 2004, 01:55
make sure its compiling in C++ and not C in your project options, ive had problem with it in the past, plus make sure you havent accidently left anything open which shouldnt be just before that code.
glVertex3f
July 14th, 2004, 01:58
Compile as C++ Code (/TP)
and i checked and everything looks fine.
refraction
July 14th, 2004, 02:15
what are your definitions of screen_width and screen_height?
seems its exiting after screen_height
glVertex3f
July 14th, 2004, 03:02
640 and 320
EDIT: I replaced thee macros with the actual numbers and it worked... odd
------ Build started: Project: ChipAte, Configuration: Debug Win32 ------
Linking...
InitWin.obj : error LNK2019: unresolved external symbol __imp__SetPixelFormat@12 referenced in function "bool __cdecl bSetUpPixelFormat(struct HDC__ *)" (?bSetUpPixelFormat@@YA_NPAUHDC__@@@Z)
InitWin.obj : error LNK2019: unresolved external symbol __imp__ChoosePixelFormat@8 referenced in function "bool __cdecl bSetUpPixelFormat(struct HDC__ *)" (?bSetUpPixelFormat@@YA_NPAUHDC__@@@Z)
Debug/ChipAte.exe : fatal error LNK1120: 2 unresolved externals
Build log was saved at "file://c:\VCProj\ChipAte\ChipAte\Debug\BuildLog .htm"
ChipAte - 3 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
...
Im linking
user32.lib
advapi32.lib
opengl32.lib
glu32.lib
Oh the errors... the errors...
refraction
July 14th, 2004, 03:16
my opengl sdk has these files
opengl.lib
glu.lib
no 32's infront of them.
glVertex3f
July 14th, 2004, 03:19
hmm mine are Opengl32.lib and GLU32.lib... and GLAUX.lib
Mine must be Microsofts version and yours is Silicon's
refraction
July 14th, 2004, 03:25
probably why yes :)
glVertex3f
July 14th, 2004, 03:29
so.... what in the world do i do now... lol
EDIT: rofl...
#define SCREEN_WIDTH 640;
#define SCREEN_HEIGHT 320;
#define SCREEN_DEPTH 16;
lol semicolons...
refraction
July 14th, 2004, 05:10
tit :P
glVertex3f
July 14th, 2004, 07:48
but the bSetPixelFormat problem stil stands :(
EDIT: I had to link the gdi32.lib to my project. So alls well! FOR NOW!
Doomulation
July 14th, 2004, 20:35
You know... although it might seem nice, the vc++ 2005 express beta is bad. Really bad. Buggy and missing functionality. I'd really use something else in place of it.
glVertex3f
July 15th, 2004, 05:40
Ok, maybe its because im tired... i dunno. Im afraid its just one of those problems that so simple you overlook it.
My emulator.. wont emulate.
After having trouble with MSVC++ beta, I rewrote (again) my emulator in Dev-C++.
Its now in C++ and not C and (to me anyway) cleaned up a bit.
If you notice anything wrong please let me know.
smcd
July 15th, 2004, 06:24
Ever tried Mingw Studio? (semi-offtopic) but it kicks Dev-Cpp's ass. (uses the same compiler, mingw)
glVertex3f
July 15th, 2004, 06:35
:plain: I just downloaded it...... Wow....... Why didnt you tell me sooner :P
EDIT:
Upon using it... im not so sure... it seems a bit sloppy.. maybe its just me being tired i dunno.
EDIT2: About the code, Overlook the part in the sprite function
Display[x + lx][y + lx]
I fixed that part but still shows nothing.
refraction
July 15th, 2004, 11:16
hmm i dunno if you need to read up a bit on open gl http://nehe.gamedev.net
I think its probably the same as SDL as its based on opengl, but you need to lock the screen before drawing the pixels then unlock it when youve finished.
glVertex3f
July 15th, 2004, 19:29
wha...? lock the screen?
Yes I am new to OpenGL(WinAPI for that matter) but ive made several programs with it i'm not sure what you mean by locking the screen.
EDIT:
refraction, I just looked over several OpenGL tutorials and I dont see anything about locking the screen. And I did the drawing code the same way I did my other emulator and it "worked".
Doomulation
July 15th, 2004, 20:59
Btw, I just wanted to ask you... have you ran into any troubles using a two-dimensional array? Last I looked, which was some time ago, two-dimensional array for the screen seemed like a bad idea.
How about you?
glVertex3f
July 15th, 2004, 22:18
I havent had any trouble. Thats how ive always done tilebased games.
It seems alot easier that doing it with out an array.
refraction
July 16th, 2004, 00:24
hmm, ill have to have a look through the rest of your code then and see if i can see anything.. ive never used raw opengl so i dont know, locking the screen is a method used in SDL (opengl wrapper) i just assumed it was a feature of OpenGL
zenogais
July 16th, 2004, 02:05
hmm, ill have to have a look through the rest of your code then and see if i can see anything.. ive never used raw opengl so i dont know, locking the screen is a method used in SDL (opengl wrapper) i just assumed it was a feature of OpenGL
SDL != OpenGL Wrapper
SDL is a cross-platform library for 2D graphics. On windows it actually wraps DirectX, on Linux I would guess it wraps some form of OpenGL or other graphics API. However, SDL does have the ability to integrate with OpenGL on both Platforms, how this is accomplished I haven't checked.
refraction
July 16th, 2004, 02:08
Simple DirectMedia Layer is a cross-platform multimedia library designed to provide low level access to audio, keyboard, mouse, joystick, 3D hardware via OpenGL, and 2D video framebuffer.
i was close :)
glVertex3f
July 16th, 2004, 04:51
Interesting... Look what happens when I load BLITZ
http://img19.exs.cx/img19/4125/ss6.jpg
refraction
July 16th, 2004, 12:26
gmm, id say there is a math problem there, missing the first letter completely :P
glVertex3f
July 16th, 2004, 20:31
not to mention the last 3 letters :P
Oh and as far as the flickering...
would simply drawing every other frame work or do I need something more complex to eliminate flickering.
smcd
July 16th, 2004, 20:35
If you use Windows GDI for the graphics, you can use an offscreen DC & then BitBlt it onto the screen, this helps.
glVertex3f
July 18th, 2004, 05:12
Ok found a couple of problems
// i was assigning the registers with this
OpCode&0xFFF;
//instead of
OpCode&0x0FFF;
simple typo, but it still wont work.
EDIT:
I think ive found a problem... how can I use the C++ fstream function "read"
Rom.read(Memory, filesize);
and start at 0x200.... how do I start at 0x200...
smcd
July 18th, 2004, 05:27
0x0FFF is the same as 0xFFF, hehe.
glVertex3f
July 18th, 2004, 05:29
lol are you serious....
i thought it would be the same as 0xFFF0...
anyway, can you help me with my other problem up there.
Its boggling my mind!
To make it simpler
bool CPU::LoadRom(char *sFileName)
{
ifstream Rom(sFileName);
if(!Rom.is_open())
return FALSE;
Rom.seekg(0, ios::end);
long size = Rom.tellg();
Rom.seekg(0, ios::beg);
Rom.read(Memory, size);
Rom.close();
return TRUE;
}
how can I make it start reading it in at 0x200 in the array?
EDIT:
Got It:
Rom.read(Memory + 0x200, size);
Also heres the updated source. It runs games but the graphics are a bit messed up, some games simply close the window, some crash and somelock up.
Now its just some debugging.
refraction
July 18th, 2004, 14:49
you realise in your source youve missed out the PC+=2; after its called the op? so its infinately calling the same one, apart from with you skip instruction commands (which do the normal jump to next op code) and your jump op command which seems to move to the new position then step back one, why you did that i dont know :P
take the PC-=2 out of the jump opcode and put PC+=2; just after youve called the opcode you want and read it in.
plus you want to set I to 0x200 on reset as well.
glVertex3f
July 18th, 2004, 18:16
lol I did a PC += 2 in the Main loop. Either there after the OpCode switch in the Emulate function. I cant remember wich one as I have been trying different places to make sure its the same result.
I was incrementing PC every loop and doing a PC += 2 when I skip and a PC -= 2 when I did a jmp() or a jsr();
refraction
July 18th, 2004, 21:06
well then you forgot it on this one :p
void CPU::jmi()
{
PC = (OpCode&0x0FFF) + V[0x0];
}
but best way i found is the way zenogais showed me, get it to read in the opcode, then increment the PC before it runs the op code so you have like
Opcode = Memory[PC]<<4 + Memory[PC+1];
PC+=2;
then run your opcode, then no more incrementing until it gets round to that again, or obviously if its a skip instruction :)
only think you have to take in account it will be 2 positions above the actual position its on, so if you run a debugger make sure you output (PC - 2)
glVertex3f
July 19th, 2004, 02:23
GDB... GNU Debugger...
How, in, the, world.....
I keep trying to do the whole
file ChipAte
and it says no debug symbols found.
What does this mean. Do I have to add something to my actual source. Is theer an easier alternative for debugging, instead of this GDB?
smcd
July 19th, 2004, 02:33
What compiler are you using? If using gcc/g++ did you compile in DEBUG mode (as in no -s option to strip symbols)? GDB is cranky, I don't like it much either.
glVertex3f
July 19th, 2004, 02:53
oh I have to compile it differently huh?
Seems like they coulda put in a "Compile DEBUG" or something like that.
Im using Dev-C++ with the gcc.
Ok let me go fight with it and see who wins!
glVertex3f
July 19th, 2004, 04:11
Bah, I cant figure out how to set up break points and step through my code.
The manual is not really much help either.
I need to find out whats going on with my Subroutine functions.
smcd
July 19th, 2004, 07:44
This is one of those times when having Visual Studio is really nice... :P I've got a (legal) copy if you'd be interested.
Doomulation
July 19th, 2004, 16:32
Yeah... visual studio is easy to use and powerful.
Anyone noticed you can actually fetch the opcode like this?
word opcode = (word)memory[PC];
;)
Go for some tutorials on the web and you'll probably find how to do stuff with the ide.
refraction
July 19th, 2004, 17:21
Yeah... visual studio is easy to use and powerful.
Anyone noticed you can actually fetch the opcode like this?
word opcode = (word)memory[PC];
;)
Go for some tutorials on the web and you'll probably find how to do stuff with the ide.
that would only fetch half the op code, because it uses 2 memory positions PC & PC+1
smcd
July 20th, 2004, 03:43
A word is typically thought of as 16bit, thus 2 bytes. (assuming x86 platform).
refraction
July 20th, 2004, 12:29
exactly, and thee reason mine and many other chip8 emulators do this at the start
u16 PC = 0x0000
:P
Doomulation
July 20th, 2004, 16:57
that would only fetch half the op code, because it uses 2 memory positions PC & PC+1
Bad refraction, bad! :P
As stated, word is 2 bytes (16 bits) ;)
aprentice
July 20th, 2004, 22:33
Bad refraction, bad! :P
As stated, word is 2 bytes (16 bits) ;)
no no, bad doomulation, bad :P
How much effort did you put in thinking this out before
you made your suggestion and critisims? :P
Not to put you to shame, but like refraction has said, it will
only read half the opcode :P
glVertex3f
July 21st, 2004, 07:47
Ive been thinking... The few Chip8 threads on here have more than enough info for people new to emulation programming. Someone should turn all this info into a tutorial.
I have definately learned alot from this board and its members (I think I have learned quite a bit in a relatively short amount of time).
I havent touched my emulator in several days, Ive had other projects plus a small sense of hopelessnes (Its hard to keep going when you cant find your problems). But I am getting ready to open my code back up and get to work. I'm gonna get this thing finished ;)
Doomulation
July 21st, 2004, 10:54
no no, bad doomulation, bad :P
How much effort did you put in thinking this out before
you made your suggestion and critisims? :P
Not to put you to shame, but like refraction has said, it will
only read half the opcode :P
Bah, I don't care! :whistling
It should work in theory (besides the endianess =/), soooo.... didn't feel a need to try it. :saint:
refraction
July 21st, 2004, 12:07
example 0x1846 = jump opcode in chip8 to jump to 0x846, and oh look! the op code is 16 bits wide!! fancy that :P
and glvertex3f: Its not really a tutorial (But there is one in the making) but there is a well commented source code of the NeoChip8 emu me and zenogais worked on HERE (http://www.zenogais.net/projects/NeoChip8/)
if you take out the NeoChip8/ from the address it has a function pointers tutorial in the tutorial section to tell you how to make jump tables properly :)
i shall enquire about the actual tutorial later on.
smcd
July 21st, 2004, 18:13
Doomulation it would work in assembly (telling the assembler to fetch a value 16bits wide from memory XXXX) but in C and/or C++ it'd just cast the 8-bit value at that location to a 16-bit value. :)
glVertex3f
July 22nd, 2004, 06:19
Thought I would share something interesting from the debug output.
OpCode: 0x22F6 Memory[220] Call SubRoutine at 2F6
OpCode: 0xA314 Memory[2F6] I = 314
OpCode: 0xF533 Memory[2F8] Store BCD
OpCode: 0xF265 Memory[2FA] Load Mem
OpCode: 0xF129 Memory[2FC] I to Font
OpCode: 0x6337 Memory[2FE] V[3] = 37
OpCode: 0x6400 Memory[300] V[4] = 00
OpCode: 0xD345 Memory[302] DrawSprite: X = 55 Y = 0 Height = 5
OpCode: 0x7305 Memory[304] V[3] = V[3] + 05
OpCode: 0xF229 Memory[306] I to Font
OpCode: 0xD345 Memory[308] DrawSprite: X = 60 Y = 0 Height = 5
OpCode: 0x00EE Memory[30A] Return From Sub
OpCode: 0xF0F0 Memory[22] Return From Sub
OpCode: 0x1020 Memory[24] MemoryIndex = 020
OpCode: 0xF090 Memory[20] MemoryIndex = 020
OpCode: 0xF0F0 Memory[22] MemoryIndex = 020
OpCode: 0x1020 Memory[24] MemoryIndex = 020
OpCode: 0xF090 Memory[20] MemoryIndex = 020
OpCode: 0xF0F0 Memory[22] MemoryIndex = 020
OpCode: 0x1020 Memory[24] MemoryIndex = 020
Notice where the subroutine is called... and noticed where it returns to. Could there be just some simple mistake causing this?
Also, here is updated code where I have fixed a few OpCodes.
Doomulation
July 22nd, 2004, 11:17
Doomulation it would work in assembly (telling the assembler to fetch a value 16bits wide from memory XXXX) but in C and/or C++ it'd just cast the 8-bit value at that location to a 16-bit value. :)
Hmmm... now I think I got it.
What if I did...
word opcode = *(word*)&memory[PC];
That should do it! Just the stupid endianess would probably get it backwards.
glVertex3f: your return address is definetly getting corrupted from what I see. And I wrote before, "use data breakpoints." That is your easiest and best solution. Or simply step through all the opcodes and watch your return address to see where it gets corrupted.
I don't have an IDE at my current location, so I can't test for you.
glVertex3f
July 23rd, 2004, 07:46
I downloaded and installed the MinGW studio again. And I am really enjoying the IDE. A few problems though.
..\..\Emul8\Chip8.cpp:81: error: invalid conversion from `unsigned char*' to `
char*'
That happens here..
bool CPU::LoadRom(char *sFileName)
{
ifstream Rom(sFileName);
if(!Rom.is_open())
return FALSE;
Rom.seekg(0, ios::end);
long size = Rom.tellg();
Rom.seekg(0, ios::beg);
Rom.read(Memory + 0x200, size); <---- HERE
Rom.close();
return TRUE;
}
Why is this happening and how can I fix it?
edit: Also I had functions named and() or() and xor()
These names seemed to be keywords in this IDE.. why is that.
EDIT2: I did this
Rom.read((char*)Memory + 0x200, size);
Is this acceptable?
EDIT AGAIN:
Also I tried to use the debugger and I set some breakpoints and watch points on PC and Stack and I cant really figure out how to find out where things go wrong. Any tips or advice on how to debug on this thing would be great
smcd
July 23rd, 2004, 10:18
To keep the same type, make Memory of type "unsigned char[]" and your Rom.read( method to take "unsigned char*" as the first parameter as well, or vice versa?
refraction
July 23rd, 2004, 12:59
I downloaded and installed the MinGW studio again. And I am really enjoying the IDE. A few problems though.
..\..\Emul8\Chip8.cpp:81: error: invalid conversion from `unsigned char*' to `
char*'
That happens here..
bool CPU::LoadRom(char *sFileName)
{
ifstream Rom(sFileName);
if(!Rom.is_open())
return FALSE;
Rom.seekg(0, ios::end);
long size = Rom.tellg();
Rom.seekg(0, ios::beg);
Rom.read(Memory + 0x200, size); <---- HERE
Rom.close();
return TRUE;
}
Why is this happening and how can I fix it?
edit: Also I had functions named and() or() and xor()
These names seemed to be keywords in this IDE.. why is that.
EDIT2: I did this
Rom.read((char*)Memory + 0x200, size);
Is this acceptable?
you want unsigned char as its gonna be a hex value from 0x0 to 0xFF in each memory space, signed only does -0x7F to 0x80.
look for mine or zenogais's source in the chip8 thread and have a look at our load rom code to see how we load ours in.
glVertex3f
July 23rd, 2004, 17:29
you want unsigned char as its gonna be a hex value from 0x0 to 0xFF in each memory space, signed only does -0x7F to 0x80.
look for mine or zenogais's source in the chip8 thread and have a look at our load rom code to see how we load ours in.
Thats my problem. Memory IS an unsigned char and the compiler is freaking out because the (read()) function accepts a char* and not unsigned char*
I will look at that source and see what happens.
EDIT:
Rom.read(RomBuffer, size);
memcpy(Memory + 0x200, RomBuffer, size);
:whistling
smcd
July 23rd, 2004, 18:27
This is why I use C I/O, fread uses a void pointer, it just doesn't care what it is so long as it has a place to go. :P
glVertex3f
July 23rd, 2004, 20:25
lol, thanks again seth for showing me the MinGW Studio.
zenogais
July 23rd, 2004, 20:25
This is why I use C I/O, fread uses a void pointer, it just doesn't care what it is so long as it has a place to go. :P
C++ does the same exact thing, should be:
Rom.read(&RomBuffer, romFileSize);
Where rom file size is an integer with the total size of the rom file determined as follows:
Rom.seekg(ios::cur, ios::beg);
long size1 = Rom.tellg();
Rom.seekg(ios::cur, ios::end);
long size2 = Rom.tellg();
Rom.seekg(ios::cur, ios::beg);
long romFileSize = (size2 - size1);
glVertex3f
July 23rd, 2004, 20:57
Rom.seekg(ios::cur, ios::beg);
long size1 = Rom.tellg();
Rom.seekg(ios::cur, ios::end);
long size2 = Rom.tellg();
Rom.seekg(ios::cur, ios::beg);
long romFileSize = (size2 - size1);
Question... is this the same thing or is it better to do it the above way.
Rom.seekg(ios::cur, ios::end);
long romFileSize = Rom.tellg();
Rom.seekg(ios::cur, ios::beg);
Also if I do
Rom.read(&RomBuffer, size);
wouldnt that actually be passing an int value into the function.
EDIT: just tried it and it wont compile that way.
refraction
July 23rd, 2004, 21:01
if you look size1 grabs the beginning of the file, and size2 grabs the end of the file
Edit: i see what you mean tho.. size1 would probably return the value 0 anyway... so possibly
smcd
July 23rd, 2004, 21:30
Zenogais:
// C I/O ... it is using void *
int fread( void *buffer, size_t size, size_t num, FILE *stream );
// C++ I/O ... it is using char *
istream &read( char *buffer, streamsize num );
A side note, given that it is an array, you don't have to put the ampersand in the read(&
glVertex3f
July 24th, 2004, 01:59
You ever wanna... take a stick... and beat yourself?
unsigned char stack[16];
Can you believe this whole time.. the biggest problem was that I accidentally made it an unsigned char instead of short..... omg....
Good news, I found this out by using the debugger, I'm starting to figure this thing out lol.
refraction
July 24th, 2004, 02:09
i woulda thought ud guess that if you had a stack, seen as the opcode comprises of a 16bit hex number :P
didnt you get any "short to char conversion: data may be lost"
errors when compiling? :P
glVertex3f
July 24th, 2004, 04:37
i woulda thought ud guess that if you had a stack, seen as the opcode comprises of a 16bit hex number :P
didnt you get any "short to char conversion: data may be lost"
errors when compiling? :P
Actually the char instead of short was a simplr typo I made in the midst of declaring stuff. And would you believe I didnt get that error/warning at all!
I new it was supposed to be a short but I never thought I woulda made it a char. :paperbag:
EDIT:
Yay, Space Invaders runs without crashing!!! Woo...
lol :P
Question: If a 2d array is not a good idea, how else could I do the graphics?
zenogais
July 24th, 2004, 09:07
Zenogais:
// C I/O ... it is using void *
int fread( void *buffer, size_t size, size_t num, FILE *stream );
// C++ I/O ... it is using char *
istream &read( char *buffer, streamsize num );
A side note, given that it is an array, you don't have to put the ampersand in the read(&
You can cast just about anything into a char*, so it works almost exactly the same. Thanks for the ampersand correction though.
glVertex3f
July 25th, 2004, 10:12
Heres the updated code. It runs a few games pretty well. I think there might be a problem with the LoadRom function as some games fail to even start. Ive used the debugger and found that on pong everything loads right until It tries to draw. The x y and height values are all correct but its detecting that the information at Register I is all 0. This leads me to believe somethings wrong with the loading function.
I know I've been asking for alot of help, but at least I'm learning from all this.
If you see anything wrong or something you just dont like... let me know.
Doomulation
July 25th, 2004, 12:15
Actually the char instead of short was a simplr typo I made in the midst of declaring stuff. And would you believe I didnt get that error/warning at all!
I new it was supposed to be a short but I never thought I woulda made it a char. :paperbag:
EDIT:
Yay, Space Invaders runs without crashing!!! Woo...
lol :P
Question: If a 2d array is not a good idea, how else could I do the graphics?
Ummm bad IDE! BAD!
Actually, if you looked at the stack array when assigning a value, you'd see the value getting corrupted the second it's assigned. That's common debugging, mate.
refraction
July 25th, 2004, 18:12
why do you have it converting the x, y and height from unsigned chars to unsigned shorts? they should be the same format, or convert them to int's (which is what i did).
on your load rom function try doing memory[0x200] instead of adding it... just as a tester.
but whatever you do make sure all the values are set to 0x200 before it starts emulating.
glVertex3f
July 25th, 2004, 18:22
Doomulation, thats how I found the problem, was using the debugger.
refraction, the x y and height being shorts was just something I was trying.
And using Memory[0x200], wouldnt that try to load it into "Memory[0x200]" and not "Memory"?
refraction
July 25th, 2004, 19:15
Doomulation, thats how I found the problem, was using the debugger.
refraction, the x y and height being shorts was just something I was trying.
And using Memory[0x200], wouldnt that try to load it into "Memory[0x200]" and not "Memory"?
well in mine it just returns the address 0x200 like so..
in.read((char*)memory->get_pointer(0x200), size);
get pointer just returns that address like this
u8* ChipMemory::get_pointer(u16 location) {
return (&memory[location]);
}
glVertex3f
July 25th, 2004, 22:27
memcpy(&Memory[0x200], RomBuffer, size);
thanks refraction. It seems to work about the same but this way seems more "correct".
refraction
July 25th, 2004, 22:35
memcpy(&Memory[0x200], RomBuffer, size);
thanks refraction. It seems to work about the same but this way seems more "correct".
any improvement on running games?
glVertex3f
July 25th, 2004, 23:36
I haven't seen any. Its just like a handfull of the games will run fine, and the others wont run at all. Ive been doing some debugging and all I can come up with is somethings wrong with my drawing code. Its just wierd that it works really well on some games.
Doomulation said 2d arrays were a bad idea. Could someone simply explain the concept of using a "1-D" array to hold X and Y coords?
refraction
July 25th, 2004, 23:48
I haven't seen any. Its just like a handfull of the games will run fine, and the others wont run at all. Ive been doing some debugging and all I can come up with is somethings wrong with my drawing code. Its just wierd that it works really well on some games.
Doomulation said 2d arrays were a bad idea. Could someone simply explain the concept of using a "1-D" array to hold X and Y coords?
best using a single dimension array which is like 4096 big (or whatever 64*32 is) then store the pixels in that by adding x & y together.
glVertex3f
July 25th, 2004, 23:59
Its really that simple?
I think I will try to do it this way as I havent seen anyone else use a 2d aray so must be something wrong lol.
Also Wipeoff works better since I did the &Memory[0x200]..
EDIT: Hmm.. some odd results.. I know I'm missing something here.
void CPU::sprite()
{
int x = V[(OpCode&0x0F00) >> 8];
int y = V[(OpCode&0x00F0) >> 4];
int height = (OpCode&0x000F);
V[0xF] = 0;
for(int ly = 0; ly < height; ly++) {
unsigned char Data = Memory[I + ly];
for(int lx = 0; lx < 8; lx++) {
if((Data&(0x80 >> lx)) != 0) {
if(Display[(x + lx) + (y + ly)] == 1) V[0xF] = 1;
Display[(x + lx) + (y + ly)] ^= 1;
}
}
}
Draw();
}
EDIT:
I had to multiply the "y" values by 64. Is this the correct way or is there something better.
refraction
July 26th, 2004, 01:29
I had to multiply the "y" values by 64. Is this the correct way or is there something better.
yes thats right, you times Y by 64 as 64 of the spaces are the X line, so you have to shift it forward 64 to change line.
and yes, it is that simple :P
smcd
July 26th, 2004, 01:38
yes thats right, you times Y by 64 as 64 of the spaces are the X line, so you have to shift it forward 64 to change line.
and yes, it is that simple :P
A possible speed improvement, to multiply by 64 ... since 64 is a power of 2, you can do a bitwise shift.
refraction
July 26th, 2004, 02:14
A possible speed improvement, to multiply by 64 ... since 64 is a power of 2, you can do a bitwise shift.
not really, multiplication is pretty fast, its division that is slow (i think thats the right way round)
plus i dont think it would work, the result might be wrong.
glVertex3f
July 26th, 2004, 04:16
Actually it does work. As far as I can tell.
zenogais
July 26th, 2004, 05:53
A possible speed improvement, to multiply by 64 ... since 64 is a power of 2, you can do a bitwise shift.
Any decent compiler would do this anyways.
glVertex3f
July 28th, 2004, 01:11
I need a little help. Can someone please explain the act of scrolling the screen?
I certainly dont want to make a larger array to hold the extra data.
I know im probably just not thinking hard enough, but just the basic "concept" of the process should work :)
refraction
July 28th, 2004, 01:16
I need a little help. Can someone please explain the act of scrolling the screen?
I certainly dont want to make a larger array to hold the extra data.
I know im probably just not thinking hard enough, but just the basic "concept" of the process should work :)
i find the best way is to copy it into another array the same size as the main one (but shifted by 4) in a for loop, tho you might need some if statements in there to make sure it doesnt too far and end up on a diff line or out of the screen array. then wipe the screen array then use the memcpy command to copy it back over (cos its faster than a for loop).
if you can find a way to use memcpy both ways or cut out using 2 different sequences, good luck to you :P
glVertex3f
July 28th, 2004, 01:31
Thank you refraction. I am still also trying to get all the Chip8 roms working, but they are being quite stuborn. For example when I load Connect4... The first OpCode it tries is 0x1200... so it jumps to 0x200... were the opcode 0x1200 is waiting. Also, on the
jsr() function, the first time a sub routine is called it works fine, but if it calls another jsr... the PC becomes a rather large number causing the opcode to be zero. Some very odd and simple sounding problems here.
EDIT: Also should I create 2 arrays at startup (One Chip8 and one SuperChip8) Or create the array at runtime as needed?
refraction
July 28th, 2004, 01:58
Thank you refraction. I am still also trying to get all the Chip8 roms working, but they are being quite stuborn. For example when I load Connect4... The first OpCode it tries is 0x1200... so it jumps to 0x200... were the opcode 0x1200 is waiting. Also, on the
jsr() function, the first time a sub routine is called it works fine, but if it calls another jsr... the PC becomes a rather large number causing the opcode to be zero. Some very odd and simple sounding problems here.
EDIT: Also should I create 2 arrays at startup (One Chip8 and one SuperChip8) Or create the array at runtime as needed?
well on my text version i just had the SChip8 size array then doubled the size of the pixels. but when i did NeoChip8 with zenogais, i made the normal chip8 one on startup and if the Schip8 mode was called it destroyed that array and made one the schip8 size.
Can you post your jsr and return code?
glVertex3f
July 28th, 2004, 02:00
void CPU::rts()
{
if(SubCall > 0)
PC = Stack[--SubCall];
}
void CPU::jmp()
{
PC = (OpCode&0x0FFF);
}
void CPU::jsr()
{
if(SubCall < 16) {
Stack[SubCall++] = PC;
PC = (OpCode&0x0FFF);
}
}
refraction
July 28th, 2004, 02:02
its probably because your not decrementing right ;)
its
PC = Stack[SubCall--];
you were decrementing it before it accessed it, or not decrementing it at all lol
glVertex3f
July 28th, 2004, 02:06
er... you sure about that refraction?
refraction
July 28th, 2004, 02:07
er... you sure about that refraction?
pretty sure. theres no other reason that i can see on why it isnt working.
glVertex3f
July 28th, 2004, 03:17
I tried it anyway and it starts looping itself backwards. For example.. on brix it draws a line the turs around and "undraws" it. Odd behavior like that.
I cant find any reason why my emu wont work either... except the programmer lol.
refraction
July 28th, 2004, 03:30
I tried it anyway and it starts looping itself backwards. For example.. on brix it draws a line the turs around and "undraws" it. Odd behavior like that.
I cant find any reason why my emu wont work either... except the programmer lol.
i know itll probably do the same but try incrementing and decrementing Subcall outside of the Stack array call so you do like
Stack[SubCall] = PC;
SubCall++;
then to return
SubCall--;
PC = Stack[SubCall];
cos it could be that its not decrementing the stack on the return until after its tried to put it back into PC, which could cause problems :P
glVertex3f
July 28th, 2004, 06:18
That still didnt work.. so... I revamped it...
The games seem to work now but I have the stupidest problem...
I cant clear the screen.....
void Video::reset()
{
delete [] Display;
Display = new unsigned char [CHIP8_DISPLAY_SIZE];
ZeroMemory(Display, sizeof(Display));
}
Am i just way off base here?
Heres the updated source. I separated every thing off. Display, Memory, and CPU all have there own class + other changes.
Some of it may be sloppy but this is the first time ive attempted to do some of these things so bear with me :P
refraction
July 28th, 2004, 06:20
way way off!! just do
memset(Display, 0, sizeof CHIP8_DISPLAY_SIZE);
or something simular to that, cant remember off the top of my head :P
Edit: looked through your source, looks pretty much alright to me, bitshift is an interesting way of doing things instead of *64 :P but if it works then go for it
glVertex3f
July 28th, 2004, 06:28
EDIT:
lol never mind... you were right refraction
memset(Display, 0, CHIP8_DISPLAY_SIZE);
EDIT2:
wow.. memset seems to be fixing alot of my problems...
Thank you refraction...
And people not to harsh on my code please, lol. I know not what I do.
refraction
July 28th, 2004, 06:44
EDIT:
lol never mind... you were right refraction
memset(Display, 0, CHIP8_DISPLAY_SIZE);
EDIT2:
wow.. memset seems to be fixing alot of my problems...
Thank you refraction...
And people not to harsh on my code please, lol. I know not what I do.
yes the mem commands are very handy, as they can be handled much more efficently than erasing and making new arrays and copying arrays like i said with scrolling, after the dodgy for loop to shift the pixels 4 places left or whatever (if you find a better way of doing that let me know!) you can use memcpy to bring it back nice and fast like so
memcpy(Display, TempDisp, CHIP8_DISPLAY_SIZE);
much faster code is generated than for loops :)
glVertex3f
July 29th, 2004, 07:21
Am i doing this right?
void CPU::sprite()
{
int x = cMemory.V[(opCode&0x0F00) >> 8];
int y = cMemory.V[(opCode&0x00F0) >> 4];
int height = cVideo.superChip ? 16 : (opCode&0x000F);
int width = cVideo.superChip ? 16 : 8;
int dataCheck = cVideo.superChip ? 0x8000 : 0x80;
cMemory.V[0xF] = 0;
for(int ly = 0; ly < height; ly++) {
unsigned char data = cMemory.memory[cMemory.I + ly];
for(int lx = 0; lx < width; lx++) {
if((data&(dataCheck >> lx)) != 0) {
if(cVideo.display[(x + lx) + ((y + ly) * cVideo.screenW)] == 1) cMemory.V[0xF] = 1;
cVideo.display[(x + lx) + ((y + ly) * cVideo.screenW)] ^= 1;
}
}
}
cVideo.draw();
}
refraction
July 29th, 2004, 13:50
as far as i can tell it looks like it should work as long as cVideo.SuperChip does return a boolean value and cVideoScreenWidth is being set to the correct width of the screen.
just one thing to remember (if you havent done it already) when you output it to the screen times the values by the size of the pixels your using, else itll just be a big pile of mush and a very small screen ;p
glVertex3f
July 30th, 2004, 02:12
Im begining to think that opengl is just way to much for this project. What graphics library should I use... (I dont have MSVC++ so i dont think I could use DirectX)
smcd
July 30th, 2004, 04:47
You could try SDL (which uses OpenGL I believe), then you might can even make a portable emulator. :P Otherwise there are packages to use DirectX with gcc/g++ in Windows, or you could use the Windows API, poke around google, Windows GDI Programming. Or, try Borland's compiler, it should be able to do DirectX stuff too I think, but not sure because I don't like it/use it.
refraction
July 30th, 2004, 05:31
yeh i used SDL, its an OpenGL wrapper (you were right :P) and is very simple to use especially for this! and comes in handy for later emulators :)
glVertex3f
July 30th, 2004, 06:01
I think i'll probably see if I can get the emulation stable before I change the graphics.
Anyhow, a few problems...
http://img61.exs.cx/img61/4874/Alien.jpg
Thats not supposed to be like that im sure...
heres the updated code.
EDIT: I just realized that SDL creates its own window... can you still do menus and the like?
refraction
July 30th, 2004, 13:48
umm that picture doesnt work.
yes SDL does create its own window, a lot of emulators do the same, i wouldnt worry about there being 2 windows really, just make sure the SDL window is created when you click run instead of when the program starts, so you dont have 2 windows right at the beginning :)
glVertex3f
July 30th, 2004, 17:56
so SDL has no commands for menus? I would like to have it set up like it is now, where you have the main window with the menus on it and thats it.
zenogais
July 30th, 2004, 19:35
so SDL has no commands for menus? I would like to have it set up like it is now, where you have the main window with the menus on it and thats it.
You can still keep the window, its just that a seperate window will pop up when the game starts running.
glVertex3f
July 30th, 2004, 19:39
hmm, i guess I could figure out a way to make the main window display all the roms that are in a certain directory... Anyone know how that would work?
smcd
July 30th, 2004, 20:41
In windows you can use FindFirstFile/FindNextFile and if you want, filter the results by using a file extension (dunno what you'd use for chip8 there are several extensions I've seen).
glVertex3f
July 31st, 2004, 06:14
I finally got SDL working.. now I need to learn it... hmmm... could take a while.. :blush: oh well :party:
glVertex3f
August 1st, 2004, 08:11
hmmm debugger caught something
Program has received a signal-name="SIGSEGV",signal-meaning="Segmentation fault" at Video::update()({name="this",value="0x439000"}), file C:\MWProj\SDLChip\Display.cpp:47
Heres that piece of code.
unsigned int clrBlack = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
SDL is probably the trickiest library ive ever tried to learn. Maybe im just tired. Was it hard to learn for you all here? Did you go by any tutorials or just the included docs?
zenogais
August 1st, 2004, 10:48
For me SDL is probably the easiest graphics library I've ever come across.
glVertex3f
August 1st, 2004, 16:27
See, my problem is Ive only learned two. Allegro was first, then OpenGL.... so yeah...
Since im not as tired, I think i'll look at it again.
glVertex3f
August 3rd, 2004, 04:06
AHHH. I have been working on my emulator, and now every Chip8 rom runs almost flawlessly. A few roms have a few tiny glitches and Super chip 8 isnt done.. but still... wow... :)
Sorry im on a happy trip.
EDIT: Question, whats a HP48 flag?
also, I am afraid i am dong this wrong.
void CPU::setChip8()
{
cVideo.superChip = FALSE;
cVideo.pixelWidth = 10;
cVideo.screenW = 64;
cVideo.screenH = 32;
delete [] cVideo.display;
cVideo.display = new unsigned char [CHIP8_DISPLAY_SIZE];
}
void CPU::setSuperChip8()
{
cVideo.superChip = TRUE;
cVideo.pixelWidth = 5;
cVideo.screenW = 128;
cVideo.screenH = 64;
delete [] cVideo.display;
cVideo.display = new unsigned char [SCHIP8_DISPLAY_SIZE];
}
???
smcd
August 3rd, 2004, 05:48
HP48 has to do with a chip8 emulator that runs on an HP48 calculator, from what I understand, nothing really related to chip8?
glVertex3f
August 3rd, 2004, 05:50
thats what I thought... interesting...
I just noticed in some docs (doomulations I believe) on the str and ldr instructions for SChip8 it said to save to HP48 flags...
refraction
August 3rd, 2004, 10:45
with HP48 flags you can use it simular to the Writing V values to memory, you can either make them in a position below 0x200 (you only need 8 spaces as they at < 8) or you can create a seperate unsigned char array to store them in, its up to you.
As sethmcdoogle said its not really used on chip8 games, but if you come to implement schip8 games (which is probably a nice idea) then its a good idea to put them in.
glVertex3f
August 4th, 2004, 08:31
I am begining to think this will not work this way.
When I swithc between Chip8 and SuperChip8 modes.. I do a
delete [] display;
display = new unsigned char [SCHIP8_DISPLAY_SIZE];
Is that supposed to work that way?
zenogais
August 4th, 2004, 10:08
Yup, that is exactly right. as long as display is defined as:
unsigned char* display;
glVertex3f
August 4th, 2004, 18:49
Must be a problem somewhere else in my code then...
All of the normal chip 8 roms run great. When I run Schip games, it has some display problems. Like "scrambled" graphics and it doesnt clear the screen correctly.. I'll post the SCHIP related code in a sec...
EDIT:
Heres the code related to changing the display mode and the clear screen function
void CPU::setChip8()
{
cVideo.superChip = FALSE;
cVideo.pixelWidth = 10;
cVideo.screenW = 64;
cVideo.screenH = 38;
cVideo.resetMode();
}
void CPU::setSuperChip8()
{
cVideo.superChip = TRUE;
cVideo.pixelWidth = 5;
cVideo.screenW = 128;
cVideo.screenH = 64;
cVideo.resetMode();
}
void CPU::cls()
{
if(cVideo.superChip)
memset(cVideo.display, 0, SCHIP8_DISPLAY_SIZE);
else memset(cVideo.display, 0, CHIP8_DISPLAY_SIZE);
cVideo.draw();
}
here is the resetMode function
void Video::resetMode()
{
if(superChip) {
delete [] display;
display = new unsigned char [SCHIP8_DISPLAY_SIZE];
}
else {
delete [] display;
display = new unsigned char [CHIP8_DISPLAY_SIZE];
}
}
glVertex3f
August 4th, 2004, 20:58
What the freak, I made a SDL version of my emu, and I used std::cout to display some text... WHY THE SHIZNIT di SDL send it to a file called stdout.txt!? the text never showed up in the console..! lol, is this normal or am I going crazy.
EDIT: keep in mind the text is a "Enter rom name: " BEFORE I Initialize SDL.
smcd
August 4th, 2004, 21:38
Yes, stdout/stderr to files is normal. You could use windows functions to spawn a file picker dialog instead of having them type in the filename?
glVertex3f
August 4th, 2004, 21:44
Well, I was gonna make this a "portable" version. Surely you can use cout and cin...
smcd
August 4th, 2004, 22:00
Ever considered making it take arguments on the command line, instead?
glVertex3f
August 4th, 2004, 22:04
Yeah I guess i'll just have to go that route I guess.
I just remember seeing an emulator that used cout... might have been Zenogais's
glVertex3f
August 5th, 2004, 06:15
I think im gonna put this ChipAte to rest for a while. It is the only project ive been working on for the past month or so. Here is the latest binary and source. I believe it is a very decent Chip 8 emulator, not so much for Super CHip 8 though. Not alot of options at all (pause and reset.. thats it)
If anyone is interested in testing it here it is. I might resurect it oneday(or tommorow, who knows :P)
EDIT: I would like to go on to another project but I dont know what that would be... aprentice seems to think I should not do a GB emu, but I dont know what else to tackle. It seems like an atari would be more complicated?
If an Atari 2600 would be the way to go... I suppose that I need to emulate the 6502 processor?
glVertex3f
August 9th, 2004, 05:39
I know you thought I was gone, but dont let out that sigh of relief yet. :P
Did any of you have trouble with the rom BLINKY when you programmed your Chip8 emu's.
It only took me a good day or so to get everything running except for blinky
(And of course Super Chip roms, but I cant expect them to work if theres a problem in the basic Chip 8 code).
All the roms run fine except for Blinky. I was wondering if any of you had this problem and what caused it.
refraction
August 9th, 2004, 12:15
apart from the fact the emu runs way to fast to be playable, blinky seems to run fine
glVertex3f
August 9th, 2004, 19:09
Oh, crap, I meant on the SDL version of the emu ive been working on.
I havent posted source/executable yet, I was just wondering if any of you had a problem with blinky, while programming your emulator. Its the only chip8 rom that wont work correctly.
refraction
August 9th, 2004, 23:50
hmm i did have a problem with the ghosts like echoing on the screen, but i think it was down to the bit shifts being wrong or something silly.
i did originally have a problem where it was killing me if i hit a wall, but i cant remember how i fixed it ;p
glVertex3f
August 10th, 2004, 02:52
http://img70.exs.cx/img70/1319/blinky.jpg
I tihnk my Blinky problem is a tad more severe lol.
Its just odd, all the other games work, so theres something that happens in blinky that doesnt happen in other roms.
EDIT:
Finally got a couple SChip roms working, Chip8 BLINKY still has the same problem.
I know you all are busy now with GB emu's but just in case you take a break :)
Here is current Source/Binary
(note: the source is probably pretty sloppy, but what can I say, thats what you get for programming while your half asleep)
Also, a few function keys in the emu...
ESC - Quit
F1 - Pause
F2 - Reset
F3 - Cycle through a few colors
F4 - Toggle Sound
F5 - muahaha, try it and see :devil:
glVertex3f
September 12th, 2004, 06:36
Well, The past couple of days I have builta Chip 8 emulator from scratch.
I believe that this is the only Chip8 emulator to use Graphics plugins. Thats right... I made a graphics plugin for a chip 8 emulator. Any way... here is a screen shot.
http://img7.exs.cx/img7/2198/BMC8.jpg
[note]
The "Plugin" only has code in it to actually draw to the screen.
e.g.
void Draw(int x, int y, int width, int height, bool on)
{
if(on) {
glBegin(GL_TRIANGLE_STRIP);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex2i( (x * width) + width , (y * height) );
glColor3f(1.0f, 1.0f, 1.0f);
glVertex2i( (x * width) , (y * height) );
glColor3f(0.0f, 0.5f, 0.0f);
glVertex2i( (x * width) + width , (y * height) + height);
glColor3f(0.0f, 0.4f, 0.0f);
glVertex2i( (x * width) , (y * height) + height);
glEnd();
}
else {
glBegin(GL_TRIANGLE_STRIP);
glColor3f(0.0f, 0.0f, 0.0f);
glVertex2i( (x * width) + width , (y * height) );
glColor3f(0.0f, 0.0f, 0.0f);
glVertex2i( (x * width) , (y * height) );
glColor3f(0.0f, 0.0f, 0.0f);
glVertex2i( (x * width) + width , (y * height) + height);
glColor3f(0.0f, 0.0f, 0.0f);
glVertex2i( (x * width) , (y * height) + height);
glEnd();
}
}
I might make the plugins more flexible... we'll see...
I havent added Super Chip 8 support yet.
I might get around to doing that soon, Im about ready to take a break from ANYTHING chip 8.
I think you'll see from my source that I definately have learned alot from everyone here. You all have taken me from noob to almost intermediate :P
The code does have a few problems such as some global variables. I need to start making an opengl class for my projects.
[note] FMOD is used for sound and the fmod.dll is included.
Let me know what you think.
[edit]
Ah, forgot to upload the freakin file.
Powered by vBulletin® Version 4.1.10 Copyright © 2012 vBulletin Solutions, Inc. All rights reserved.