|
|
Search
|
|||||||
| Home | Register | Downloads | FAQ | Members List | Calendar | Arcade | Mark Forums Read |
![]() |
|
|
LinkBack | Thread Tools | Display Modes |
|
|
#201 (permalink) |
|
Mobile Fanatic
![]() ![]() ![]() ![]() ![]() ![]() ![]() Join Date: Nov 2006
Location: Santa Cruz, CA
Posts: 6,213
|
Go go! 13 hours later and I have to remove the attachment because... my name was in the source code! Ahh... disaster! (or not!)Anyway, I've opened a new thread in the emu news submission forums, and posted a new version there... without my name in the source code and with something nice: a fix for Spacefight 2019! If you've tried that game on your emu, you'd know that... you will experience the infamous ship ghosting problem that seemingly has no cure! Well, I... got the cure! It seems to be the very last unimplemented and undocumented feature of the Chip-8 (note: it's a Chip-8 opcode). Here is what it is: FX1E opcode: ADI - Add value of register VX into I And here's the missing part: set VF if the result is a buffer overflow, or unset if it's not a buffer overflow. Buffer overflow occurs when the addition makes I > 0xfff. In short, that opcode should be something like this: V[0xf] = (I + V[x] > 0xfff) ? 1 : 0; I = (I + V[x]) % 0x1000; And... that's it, folks. The very last Chip-8 feature that is usually neglected because... not too many games would be that large in size, but... Spacefight 2019 was. Anyway, I hope that should conclude my quest for the perfect SuperChip emu now, unless... something else comes up. Hopefully not.
__________________
cChip interpreter WIP - current status: Release Candidate LRx Filter RC - current performance rating: 9/10 Last edited by runawayprisoner; July 31st, 2009 at 17:17.. |
|
|
|
| Advertisement | [Remove Advertisement] | ||
|
|
|
|
#202 (permalink) |
![]() ![]() ![]() ![]() Join Date: Sep 2006
Location: Sweden
Posts: 511
|
Nice work with your emulator, have been following it for a while ![]() Haha, about the name-slip up, are you afraid of the random psychopath that get's turned on by good code and would stalk you?
__________________
![]() ( #1 Core2Duo E8400 @ 3.61 Ghz, 3072 MB DDR2-RAM @ 802mhz, XFX Geforce GTX260 XT - N-Lited WinXP SP3 and Arch Linux 64-bit). <- http://www.myspace.com/preptile -> | /P. Rep. |
|
|
|
|
|
#203 (permalink) |
|
Mobile Fanatic
![]() ![]() ![]() ![]() ![]() ![]() ![]() Join Date: Nov 2006
Location: Santa Cruz, CA
Posts: 6,213
|
Mmm... nope. But my employers might be able to find it somehow (by Googling!) and then I'd kind of be in trouble as I'm under licenses and stuffs.
__________________
cChip interpreter WIP - current status: Release Candidate LRx Filter RC - current performance rating: 9/10 |
|
|
|
|
|
#204 (permalink) |
|
Emu author
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Join Date: Apr 2001
Location: Cleveland OH, USA
Posts: 1,184
|
You're not allowed to make a CHIP8 emulator? Are you sure about that? I wouldn't be very worried about such a thing. Unless you're under a contract that disallows you from making anything independently at all.
|
|
|
|
|
|
#205 (permalink) | |
|
Mobile Fanatic
![]() ![]() ![]() ![]() ![]() ![]() ![]() Join Date: Nov 2006
Location: Santa Cruz, CA
Posts: 6,213
|
Quote:
__________________
cChip interpreter WIP - current status: Release Candidate LRx Filter RC - current performance rating: 9/10 |
|
|
|
|
|
|
#206 (permalink) |
|
Emu author
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Join Date: Apr 2001
Location: Cleveland OH, USA
Posts: 1,184
|
Ouch. I don't know who would write up something like that, it's pretty outrageous. Maybe there'll come a point where you can't be a chef without having to give all your home prepared meals to the restaurant. Not that I can fault you for taking a job like that in this job climate. I'd have to be very desperate to go for something like that myself. |
|
|
|
|
|
#207 (permalink) |
|
Mobile Fanatic
![]() ![]() ![]() ![]() ![]() ![]() ![]() Join Date: Nov 2006
Location: Santa Cruz, CA
Posts: 6,213
|
Well, I gotta help clear off some debts for my parents, so... anything that helps counts. ![]() The extra I can make may be good, too. For higher studies and gadgets...
__________________
cChip interpreter WIP - current status: Release Candidate LRx Filter RC - current performance rating: 9/10 |
|
|
|
|
|
#208 (permalink) | |
|
Regular User ;)
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Join Date: Oct 2007
Location: Naples Florida
Posts: 10,001
|
Quote:
Don't worry, Rap makes extra cash selling prized swag. As for the project, its really a hellish scheme he is about to unleash on us all.
__________________
A Mac is like an escort, you pay a ton and get nothing.
A PC is like a hooker, it's a lot cheaper and gives you what you're after.. and if unlucky some diseases as well, that's why you gotta use protection. -CC |
|
|
|
|
|
|
#210 (permalink) |
|
Registered User
Join Date: Sep 2009
Location: uk
Posts: 2
|
wow I havnt been to ngemu since 2002 ![]() I was wondering if anyone could help out with some trouble I'm having that I assume is down to the drw opcode. Basically sprites arnt being erased properly; for example in Invaders, the title screen and scrolling text is drawn perfectly yet the alien ships are not erased completely when they move (some pixels are and others are not) My drw code is (not yet optimized ):Code:
private void drw_vx_vy_nibble()
{
Opcode.SetMnemonic("DRW V{0:X1}, V{1:X1}, #{2:X1}", Opcode.X, Opcode.Y, Opcode.N);
if (DisassembleEnabled)
{
return;
}
RAMStream.Seek(Registers.I);
byte[] sprite = RAMStream.ReadBytes((ushort) Opcode.N);
/*
* Be nice and return to PC
*/
RAMStream.Seek(Registers.PC);
Registers.V[0xF] = 0;
for (byte a = 0; a < sprite.Length; a++)
{
bool[] pixel = new bool[8];
pixel[0] = ((sprite[a] & Convert.ToByte("10000000", 2)) > 0);
pixel[1] = ((sprite[a] & Convert.ToByte("01000000", 2)) > 0);
pixel[2] = ((sprite[a] & Convert.ToByte("00100000", 2)) > 0);
pixel[3] = ((sprite[a] & Convert.ToByte("00010000", 2)) > 0);
pixel[4] = ((sprite[a] & Convert.ToByte("00001000", 2)) > 0);
pixel[5] = ((sprite[a] & Convert.ToByte("00000100", 2)) > 0);
pixel[6] = ((sprite[a] & Convert.ToByte("00000010", 2)) > 0);
pixel[7] = ((sprite[a] & Convert.ToByte("00000001", 2)) > 0);
for (byte b = 0; b < 8; b++)
{
byte x = (byte) ((Registers.V[Opcode.X] + b > 64) ? 0 : Registers.V[Opcode.X] + b);
byte y = (byte) ((Registers.V[Opcode.Y] + a > 32) ? 0 : Registers.V[Opcode.Y] + a);
if(VideoDriver.GetPixel(x, y))
{
Registers.V[0xF] = 1;
}
VideoDriver.SetPixel(x, y, VideoDriver.GetPixel(x, y) ^ pixel[b]);
}
}
VideoDriver.Render();
}
Code:
public override bool GetPixel(int x, int y)
{
return (surface.GetPixel(new Point(x, y)) == Color.White);
}
public override void SetPixel(int x, int y, bool on)
{
Color color = (on) ? Color.White : Color.Black;
surface.SetPixels(new Point(x, y), new Color[1, 1] { { color } });
}
(C# & SDL btw )
|
|
|
|
|
|
#211 (permalink) |
|
Emu Author
![]() ![]() ![]() Join Date: Dec 2004
Location: North Carolina
Posts: 374
|
before starting i beg you to switch from sdl for c#, its a bad memory hog if you sit and watch the memory use(it was 10 times worse when i did space invaders). also you need to be drawing both black and white pixels, did not spend much time looking over your code but try that and see if it helps. |
|
|
|
|
|
#212 (permalink) |
|
Registered User
Join Date: Sep 2006
Location: surrey
Posts: 45
|
well I finally figured out the issues with chip 8. Still not sure what the printf thing is about but yeah, chip8 works now. just have to set it so that it actually expands to fill up the entire texture in chip8 mode. |
|
|
|
|
|
#213 (permalink) | |
|
Registered User
Join Date: Sep 2009
Location: uk
Posts: 2
|
Quote:
A color returned by Surface.GetPixel doesn't match exactly the System.Drawing color; the name member is missing so Code:
surface.GetPixel(x, y) == Color.White Code:
surface.GetPixel(x, y).ToArgb() == Color.White.ToArgb() Will definately be looking into using a seperate toolkit, XNA sounds interesting... |
|
|
|
|
|
|
#214 (permalink) |
|
Emu Author
![]() ![]() ![]() Join Date: Dec 2004
Location: North Carolina
Posts: 374
|
yea that was another reason why i hated sdl, it got real bad for me at times. i say learn directx for c#, or do xna but managed directx is a bit easier to do emulators with than xna i would think, though i have a lot of experience with both.
|
|
|
|
|
|
#215 (permalink) |
|
Banned
![]() ![]() Join Date: Jan 2009
Location: spain
Posts: 221
|
someone here can explain the codes in the debugger ? only a line for example : V0 40 0x28 / 0x0200 1217 JP535 what means all this addres?? i´m a low dev and i want to learn to code in emus, please give me a litle hand |
|
|
|
|
|
#216 (permalink) |
|
Administrator
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Join Date: Dec 2001
Location: Montreal, Canada
Posts: 7,846
|
what debugger is that taken from? V0 --> Register identifier 40 --> Value in that register 0x28 --> Same value but in HEX (0x28 == 40) 0x0200 --> Most likely the PC. This is the address we're executing. 1217 --> The 2 bytes opcode value at the address above (jump to 0x0217) JP535 --> What the opcode actually does... JP (jump) instuction. (535 is 0x0217 in DEC)) |
|
|
|
|
|
#217 (permalink) |
|
Registered User
Join Date: Nov 2009
Location: United States
Posts: 2
|
I am attempting to make a Chip8 Emulator using XNA... it works to a point, but the graphics do not draw right.... and I am about 80% sure all the other opp codes are working correctly, so the way I collect my info must not work right... CPU: Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CCE
{
public class Chip8CPU
{
public byte[] V;
public byte[] Memory;
public UInt16 Opcode = 0, I = 0, PC = 0x200;
public Stack<UInt16> OldPC;
public byte DelayTimer;
public byte SoundTimer;
public Chip8CPU()
{
V = new byte[16];
Memory = new byte[0xFFF];
OldPC = new Stack<UInt16>(0x10);
for (int i = 0; i < 80; i++)
Memory[i] = Font[i];
}
public void UpdateTimers(Game1 game)
{
if (DelayTimer > 0)
DelayTimer--;
if (SoundTimer > 0)
SoundTimer--;
if (SoundTimer > 0)
Beep(game);
}
private void Beep(Game1 game)
{
game.debugStream.WriteLine("-- BEEP!");
}
public void Run(Game1 game)
{
Opcode = Convert.ToUInt16((Memory[PC] << 8) + Memory[PC + 1]);
game.oppStream.WriteLine(@"PC: {0}[{1}] ML: {2} MH: {3} Op: {4}[{5}]",
PC, Convert.ToString(PC, 16),
Convert.ToString(Memory[PC] << 8, 16),
Convert.ToString(Memory[PC + 1], 16),
Opcode.ToString("####"), Convert.ToString(Opcode, 16));
switch (Opcode & 0xF000)
{
case 0x0000:
{
switch (Opcode & 0x000F)
{
case 0x0000: //Clear Screen
{
game.pixels = new Dictionary<int, Dictionary<int, byte>>();
game.graphics.GraphicsDevice.Clear(game.BackgroundColor);
break;
}
case 0x000E: //Returns from Sub-Rutine
{
PC = OldPC.Pop();
break;
}
}
PC += 2;
break;
}
case 0x1000: //Jump to Address NNN
{
PC = Convert.ToUInt16(Opcode & 0x0FFF);
break;
}
case 0x2000: //Calls Sub-Rutine @ NNN
{
OldPC.Push(PC);
PC = Convert.ToUInt16(Opcode & 0x0FFF);
break;
}
case 0x3000: //Skips next Instruction if VX == VN
{
if (V[Opcode & 0x0F00 >> 8] == Convert.ToByte(Opcode & 0x00FF))
PC += 4;
else
PC += 2;
break;
}
case 0x4000: //Skips next Instruction if VX != VN
{
if (V[Opcode & 0x0F00 >> 8] != Convert.ToByte(Opcode & 0x00FF))
PC += 4;
else
PC += 2;
break;
}
case 0x5000: //Skips next Instruction if VX == VY
{
if (V[Opcode & 0x0F00 >> 8] == Convert.ToByte(V[Opcode & 0x00F0 >> 4]))
PC += 4;
else
PC += 2;
break;
}
case 0x6000: //Sets VX to NN
{
V[Opcode & 0x0F00 >> 8] = Convert.ToByte(Opcode & 0x00FF);
PC += 2;
break;
}
case 0x7000: //Adds NN to VX
{
V[Opcode & 0x0F00 >> 8] += Convert.ToByte(Opcode & 0x00FF);
PC += 2;
break;
}
case 0x8000:
{
switch (Opcode & 0x000F)
{
case 0x0000: //Sets VX to VY
{
V[Opcode & 0x0F00 >> 8] = V[Opcode & 0x00F0 >> 4];
break;
}
case 0x0001: //Sets VX to VX OR VY
{
V[Opcode & 0x0F00 >> 8] |= V[Opcode & 0x00F0 >> 4];
break;
}
case 0x0002: ////Sets VX to VX & VY
{
V[Opcode & 0x0F00 >> 8] &= V[Opcode & 0x00F0 >> 4];
break;
}
case 0x0003: //Sets VX to VX OR VY
{
V[Opcode & 0x0F00 >> 8] ^= V[Opcode & 0x00F0 >> 4];
break;
}
case 0x0004: //Adds VY to VX, VF is set to 1 when there is a carry and 0 when there isn't
{
if ((V[Opcode & 0x0F00 >> 8] += V[Opcode & 0x00F0 >> 4]) > 255)
V[0xF] = 1;
V[Opcode & 0x0F00 >> 8] += V[Opcode & 0x00F0 >> 4];
break;
}
case 0x0005: //Subtracts VY from VX, VF is set to 0 when there is a borrow and 1 when there isn't
{
if ((V[Opcode & 0x0F00 >> 8] -= V[Opcode & 0x00F0 >> 4]) < 0)
V[0xF] = 1;
V[Opcode & 0x0F00 >> 8] -= V[Opcode & 0x00F0 >> 4];
break;
}
case 0x0006: //Shifts VX right by one, VF is set to least significant bit of VX BEFORE shift
{
V[0xF] = Convert.ToByte((V[Opcode & 0x0F00 >> 8]) & 0x1);
V[Opcode & 0x0F00 >> 8] >>= 1;
break;
}
case 0x0007: //Sets VX to VY - VX, VF is set to 0 when there is a borow and 1 when there isn't
{
if ((V[Opcode & 0x00F0 >> 4] - V[Opcode & 0x0F00 >> 8]) < 0)
V[0xF] = 1;
V[Opcode & 0x0F00 >> 8] = Convert.ToByte(V[Opcode & 0x00F0 >> 4] - V[Opcode & 0x0F00 >> 8]);
break;
}
case 0x000E: //Shifts VX left by one, VF is set to most signinficant bit of VX BEFORE shift
{
V[0xF] = Convert.ToByte((V[Opcode & 0x0F00] >> 8) & 0x80);
(V[Opcode & 0x0F00 >> 8]) <<= 1;
break;
}
}
PC += 2;
break;
}
case 0x9000: //Skips the next Instruction if VX != VY
{
if (V[Opcode & 0x0F00 >> 8] != V[Opcode & 0x00F0 >> 4])
PC += 4;
else
PC += 2;
break;
}
case 0xA000: //Sets I to the address NNN
{
I = Convert.ToUInt16(Opcode & 0x0FFF);
PC += 2;
break;
}
case 0xB000: //Jumps to address NNN + V0
{
PC = Convert.ToUInt16((Opcode & 0x0FFF) + V[0]);
break;
}
case 0xC000: //Sets VX to a random number & NN
{
Random r = new Random();
V[Opcode & 0x0F00 >> 8] = Convert.ToByte(r.Next(0x0, 0xFFF) + (Opcode & 0x00FF));
PC += 2;
break;
}
case 0xD000: //Draws a sprite at Coordinate(VX, VY) that has a width of 8 pixels and a height of N pixels
//When Pixel if flipped VF is set to 1 and 0 when it isn't
{
int scale = 10;
byte sX = Convert.ToByte(V[Opcode & 0x0F00 >> 8]);
byte sY = Convert.ToByte(V[Opcode & 0x00F0 >> 4]);
byte SpriteHeight = Convert.ToByte(Opcode & 0x000F);
for (int yline = 0; yline < SpriteHeight; yline++)
{
byte Data = Memory[I + yline];
for (int xpixel = 0; xpixel < 8; xpixel++)
{
if ((Data & (0x80 >> xpixel)) != 0)
{
int x = sX + (xpixel * scale);
int y = sY + (yline * scale);
if (game.pixels.ContainsKey(x))
{
if (game.pixels[x].ContainsKey(y))
game.pixels[x][y] ^= 1;
else
game.pixels[x].Add(y, 1);
}
else
{
Dictionary<int, byte> newy = new Dictionary<int, byte>();
newy.Add(y, 1);
game.pixels.Add(x, newy);
}
game.debugStream.WriteLine(
"-- SWITCH FLAG | DATA " +
"BaseXY[{0},{1}] : " +
"PixelXY[{2},{3}] : " +
"FinalXY[{4},{5}] : " +
"Point<{6}> " +
"FLAG: {7}",
sX, sY,
xpixel, yline,
x, y,
sX + xpixel + (sY + yline) * 64,
game.pixels[x][y]);
}
}
}
PC += 2;
break;
}
case 0xE000:
{
switch (Opcode & 0x00FF)
{
case 0x009E: //Skips the next instruction if the key in VX is pressed
{
if (game.KeyStates[V[(Opcode & 0x0F00) >> 8]] > 0)
PC += 4;
else
PC += 2;
break;
}
case 0x00A1: //Skips the next instruction if the key in VX isn't pressed
{
if (game.KeyStates[V[(Opcode & 0x0F00) >> 8]] == 0)
PC += 4;
else
PC += 2;
break;
}
}
break;
}
case 0xF000:
{
switch (Opcode & 0x00FF)
{
case 0x0007: //Sets VX to the value of the Delay Timer
{
V[(Opcode & 0x0F00) >> 8] = DelayTimer;
break;
}
case 0x000A: //A key press is awaited then stored in VX
{
bool submited = false;
for (byte i = 0; i < game.KeyStates.Length; i++)
{
if (game.KeyStates[i] == 1)
{
submited = true;
V[(Opcode & 0x0F00) >> 8] = game.KeyStates[i];
}
}
if (!submited)
PC -= 2;
break;
}
case 0x0015: //Sets the Delay Timer to VX
{
DelayTimer = V[(Opcode & 0x0F00) >> 8];
break;
}
case 0x0018: //Sets the Sound Timer to VX
{
SoundTimer = V[(Opcode & 0x0F00) >> 8];
break;
}
case 0x001E: //Adds VX to I
{
I += V[Opcode & 0x0F00 >> 8];
break;
}
case 0x0029: //Sets I to the location of the sprite for the character in VX
{
I = Convert.ToUInt16(V[Opcode & 0x0F00 >> 8] * 5);
break;
}
case 0x0030://Sets I to the location of the sprite for the character in VX
{
I = Convert.ToUInt16(V[Opcode & 0x0F00 >> 8] * 10);
break;
}
case 0x0033: //Stores the binary coded decimal in VX at the address I, I + 1, I + 2
{
Memory[i] = Convert.ToByte(V[(Opcode & 0x0f00) >> 8] / 100);
Memory[I + 1] = Convert.ToByte((V[(Opcode & 0x0f00) >> 8] / 10) % 10);
Memory[I + 2] = Convert.ToByte((V[(Opcode & 0x0f00) >> 8] % 100) % 10);
break;
}
case 0x0055: //Stores V0 to VX starting at I
{
for (int i = 0; i < ((Opcode & 0x0F00) >> 8); i++)
Memory[I + i] = V[i];
break;
}
case 0x0065: //Fills V0 to VX from memory starting at I
{
for (int i = 0; i < ((Opcode & 0x0F00) >> 8); i++)
V[i] = Memory[I + i];
break;
}
default:
{
game.oppStream.WriteLine(" -- OPP NOT IMPLEMENTED -- {0}[{1}]", Opcode, Convert.ToString(Convert.ToInt32(Opcode), 16));
break;
}
}
PC += 2;
break;
}
default:
{
game.oppStream.WriteLine(" -- OPP NOT IMPLEMENTED -- {0}[{1}]", Opcode, Convert.ToString(Convert.ToInt32(Opcode), 16));
PC += 2;
break;
}
}
}
byte[] Font = new byte[]
{
0xF0, 0x90, 0x90, 0x90, 0xF0,// 0 Num
0x20, 0x60, 0x20, 0x20, 0x70,// 1 Num
0xF0, 0x10, 0xF0, 0x80, 0xF0,// 2 Num
0xF0, 0x10, 0xF0, 0x10, 0xF0,// 3 Num
0x90, 0x90, 0xF0, 0x10, 0x10,// 4 Num
0xF0, 0x80, 0xF0, 0x10, 0xF0,// 5 Num
0xF0, 0x80, 0xF0, 0x90, 0xF0,// 6 Num
0xF0, 0x10, 0x20, 0x40, 0x40,// 7 Num
0xF0, 0x90, 0xF0, 0x90, 0xF0,// 8 Num
0xF0, 0x90, 0xF0, 0x10, 0xF0,// 9 Num
0xF0, 0x90, 0xF0, 0x90, 0x90,// A Num
0xE0, 0x90, 0xE0, 0x90, 0xE0,// B Num
0xF0, 0x80, 0x80, 0x80, 0xF0,// C Num
0xE0, 0x90, 0x90, 0x90, 0xE0,// D Num
0xF0, 0x80, 0xF0, 0x80, 0xF0,// E Num
0xF0, 0x80, 0xF0, 0x80, 0x80,// F Num
};
}
}
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
namespace CCE
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
public GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
public Rectangle viewportRect;
public Dictionary<int, Dictionary<int, byte>> pixels;
public Chip8CPU CPU;
public byte[] KeyStates;
public Color SpriteColor = Color.Gray;
public Color BackgroundColor = Color.Black;
string GameFile = String.Empty;
System.IO.FileStream gameStream;
public System.IO.StreamWriter oppStream;
public System.IO.StreamWriter debugStream;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
// TODO: Add your initialization logic here
this.Exiting += new EventHandler(Game1_Exiting);
debugStream = new System.IO.StreamWriter("C:/debug.txt");
oppStream = new System.IO.StreamWriter("C:/opps.txt");
base.Initialize();
}
void Game1_Exiting(object sender, EventArgs e)
{
debugStream.Close();
oppStream.Close();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
// TODO: use this.Content to load your game content here
viewportRect = new Rectangle(0, 0, graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height);
pixels = new Dictionary<int, Dictionary<int, byte>>();
CPU = new Chip8CPU();
KeyStates = new byte[16];
while (!GetGame())
GetGame();
LoadGame();
}
public bool GetGame()
{
System.Windows.Forms.OpenFileDialog fileDialog = new System.Windows.Forms.OpenFileDialog();
fileDialog.DefaultExt = "Chip8 (.ch8) | *.ch8 | All Files | *.*";
if (fileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
GameFile = fileDialog.FileName;
gameStream = new System.IO.FileStream(GameFile, System.IO.FileMode.Open, System.IO.FileAccess.Read);
}
if (System.IO.File.Exists(GameFile))
return true;
return false;
}
public void LoadGame()
{
System.IO.BinaryReader reader = new System.IO.BinaryReader(gameStream);
reader.Read(CPU.Memory, 0x200, Convert.ToInt32(reader.BaseStream.Length));
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
// TODO: Add your update logic here
if (Keyboard.GetState().IsKeyDown(Keys.NumPad7))
KeyStates[1] = 1;
else if (Keyboard.GetState().IsKeyDown(Keys.NumPad8))
KeyStates[2] = 1;
else if (Keyboard.GetState().IsKeyDown(Keys.NumPad9))
KeyStates[3] = 1;
else if (Keyboard.GetState().IsKeyDown(Keys.NumPad4))
KeyStates[4] = 1;
else if (Keyboard.GetState().IsKeyDown(Keys.NumPad5))
KeyStates[5] = 1;
else if (Keyboard.GetState().IsKeyDown(Keys.NumPad6))
KeyStates[6] = 1;
else if (Keyboard.GetState().IsKeyDown(Keys.NumPad4))
KeyStates[7] = 1;
else if (Keyboard.GetState().IsKeyDown(Keys.NumPad2))
KeyStates[8] = 1;
else if (Keyboard.GetState().IsKeyDown(Keys.NumPad3))
KeyStates[9] = 1;
else if (Keyboard.GetState().IsKeyDown(Keys.NumPad0))
KeyStates[0xA] = 1;
else if (Keyboard.GetState().IsKeyDown(Keys.OemPeriod))
KeyStates[0] = 1;
else if (Keyboard.GetState().IsKeyDown(Keys.Enter))
KeyStates[0xB] = 1;
else if (Keyboard.GetState().IsKeyDown(Keys.Divide))
KeyStates[0xC] = 1;
else if (Keyboard.GetState().IsKeyDown(Keys.Multiply))
KeyStates[0xD] = 1;
else if (Keyboard.GetState().IsKeyDown(Keys.Subtract))
KeyStates[0xE] = 1;
else if (Keyboard.GetState().IsKeyDown(Keys.Add))
KeyStates[0xF] = 1;
else
{
for (int i = 0; i < KeyStates.Length; i++)
{
KeyStates[i] = 0;
}
}
//for (int i = 0; i < 5; i++)
{
CPU.Run(this);
CPU.UpdateTimers(this);
}
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(BackgroundColor);
// TODO: Add your drawing code here
spriteBatch.Begin();
foreach (KeyValuePair<int, Dictionary<int, byte>> xpix in pixels)
{
Dictionary<int, byte> ylines = pixels[xpix.Key];
foreach (KeyValuePair<int, byte> ypix in ylines)
{
byte switched = ylines[ypix.Key];
Texture2D pixel = new Texture2D(graphics.GraphicsDevice, 9, 9, 1, TextureUsage.None, SurfaceFormat.Color);
Color[] pixelColors = new Color[pixel.Width * pixel.Height];
for (int i = 0; i < pixelColors.Length; i++)
pixelColors[i] = (switched == 1 ? SpriteColor : BackgroundColor);
pixel.SetData(pixelColors);
spriteBatch.Draw(pixel, new Vector2(xpix.Key, ypix.Key), Color.White);
debugStream.WriteLine("-- DRAW AT XY ({0},{1})", xpix.Key, ypix.Key);
}
}
spriteBatch.End();
base.Draw(gameTime);
}
}
}
ALSO, it seems to only want to draw pixels in a 5x9 area of blocks... (each block being 9x9 pixels)... thanks for any help! - Z - |
|
|
|
|
|
#218 (permalink) |
|
Emu author
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Join Date: Apr 2001
Location: Cleveland OH, USA
Posts: 1,184
|
I didn't check the whole thing yet, but you made a mistake on this opcode: Code:
case 0x000E: //Shifts VX left by one, VF is set to most signinficant bit of VX BEFORE shift
{
V[0xF] = Convert.ToByte((V[Opcode & 0x0F00] >> 8) & 0x80);
(V[Opcode & 0x0F00 >> 8]) <<= 1;
break;
}
|
|
|
|
|
|
#220 (permalink) | |
|
You're already dead...
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Join Date: Sep 2007
Location: Post-Apocalyptic Earth
Posts: 3,908
|
any pics of it running on your Zune HD? its always cool to see emus running on portable hw
__________________
Quote:
check out my blog ![]() |
|
|
|
|
![]() |
| Thread Tools | |
| Display Modes | |
|
|