rendered paste body#import <fcntl.h> // For open()
#import <sys/types.h>
#import <sys/stat.h> // For fstat() "to get he file length"
#import <sys/mman.h> // For mmap()
#import <stdio.h>
#import <stdlib.h>
#import <string.h>
#import <unistd.h> // close()
//#ifdef HAVE_DEBUG
#define DEBUG_PRINT(format , ... ) printf ( "[DEBUG " __FILE__ ":%d] " format "\n" , __LINE__, ## __VA_ARGS__ );
//#else
//#define DEBUG_PRINT( format , args... )
//#endif
#define bswap16(x) (((((short)(x)) >> 8) & 0xff) | ((((short)(x)) & 0xff) << 8))
#define n1(x) (x&0xF000>>12)
#define n2(x) (x&0x0F00>> 8)
#define n3(x) (x&0x00F0>> 4)
#define n4(x) (x&0x000F )
void process8(short opcode);
void dumpreg(void);
unsigned char V[16]; // CPU registers
unsigned short *rom; // rom file
unsigned short opcode; // current opcode
unsigned int ip; // instruction pointer
int main(int a, char**b)
{
int fd;
struct stat statbuf; // for the file length
fd = open("Chip8Test",O_RDONLY);
if (fd == -1) return 1; //TODO return value explanation
fstat(fd,&statbuf);
rom = mmap(NULL, statbuf.st_size , PROT_READ, MAP_PRIVATE, fd, 0);
if (rom == MAP_FAILED) return 3;
DEBUG_PRINT("Opened and mmap()'d rom file");
while ( 1 )
{
short type;
memcpy(&opcode,rom +ip,2);
opcode = bswap16(opcode);
type = opcode & 0xF000;
/* parse the opcode here */
switch(type) {
case 0x8000 : process8(opcode);
case 0x1000 : ip = (opcode & 0x0FFF) -1 ; break; //1NNN Jump to the address NNN of the file
case 0x3000 :if(V[n2(opcode)]== (opcode&0x00FF)) ip++; break; //3XKK Skip next instruction if VX == KK
case 0x6000 : V[ n2(opcode) ] = (opcode&0x00FF); break; //6XKK VX = KK
case 0x7000 : V[ n2(opcode) ]+= (opcode&0x00FF); break; //7XKK VX = VX + KK
case 0xC000 : V[ n2(opcode) ] = rand() + (opcode&0x00FF); break;//CXKK VX = Random number AND KK
case 0x0000 : goto out;
default : DEBUG_PRINT("Unknown opcode ip:%d opcode:%x",ip,opcode)
}
ip++;
}
out:
/* Dump the registers */
dumpreg();
// cleanup
munmap(rom,statbuf.st_size);
close(fd);
return 0;
}
void process8(short opcode)
{
short type = opcode & 0x000F;
/* parse the opcode here */
switch(type) {
case 0 : V[ n2(opcode) ] = V[ n3(opcode) ]; break; //8XY0 VX = VY
case 1 : V[ n2(opcode) ] |= V[ n3(opcode) ]; break; //8XY1 VX = VX OR VY
case 2 : V[ n2(opcode) ] &= V[ n3(opcode) ]; break; //8XY2 VX = VX AND VY
case 3 : V[ n2(opcode) ] ^= V[ n3(opcode) ]; break; //8XY3 VX = VX XOR VY
case 4 : V[ n2(opcode) ] += V[ n3(opcode) ]; //8XY4 VX = VX + VY,
if ( V[ n2(opcode) ] < V[ n3(opcode) ] ) // Sets VF to 1 if there is a carry, 0 if there isn't
V[15] = 1;
else
V[15] = 0;
break;
case 5 : V[ n2(opcode) ] -= V[ n3(opcode) ]; //8XY5 VX = VX - VY,
if ( V[ n2(opcode) ] > V[ n3(opcode) ] ) // VF is set to 0 if there is a borrow, 1 if there isn't.
V[15] = 0;
else
V[15] = 1;
break;
case 6 : V[15] = opcode&0x0001; V[ n2(opcode) ] >>= 1; break; //8X06 VX = VX SHIFT RIGHT 1, VF is set to the lost bit.
case 7 : V[ n2(opcode) ] = V[ n3(opcode) ] - V[ n2(opcode) ]; //8XY7 VX = VY - VX,
if ( V[ n2(opcode) ] < V[ n3(opcode) ] ) // VF is set to 0 if there is a borrow, 1 if there isn't.
V[15] = 0;
else
V[15] = 1;
break;
case 0xE: V[15] = opcode&0x8000; V[ n2(opcode) ] <<= 1; break; //8X0E VX = VX SHIFT LEFT 1 , VF is set to the lost bit.
default : DEBUG_PRINT("Unknown opcode ip:%d opcode:%x",ip,opcode)
}
}
void dumpreg(void)
{
int i;
for(i=0; i<16; i++)
printf("Register V%x : 0x%x\n",i,V[i]);
}