Browse Source

The core of the emulator

master
MisterCyb 1 month ago
parent
commit
11e7dabc4b
6 changed files with 1864 additions and 1 deletions
  1. 93
    0
      CHIP8.c
  2. 302
    0
      Machine.c
  3. 28
    0
      Machine.h
  4. 1289
    0
      MonochromeLib.c
  5. 151
    0
      MonochromeLib.h
  6. 1
    1
      README.md

+ 93
- 0
CHIP8.c View File

@@ -0,0 +1,93 @@
/*****************************************************************/
/* */
/* CASIO fx-9860G SDK Library */
/* */
/* File name : [ProjectName].c */
/* */
/* Copyright (c) 2006 CASIO COMPUTER CO., LTD. */
/* */
/*****************************************************************/
#include "fxlib.h"
#include "Machine.h"


//****************************************************************************
// AddIn_main (Sample program main function)
//
// param : isAppli : 1 = This application is launched by MAIN MENU.
// : 0 = This application is launched by a strip in eACT application.
//
// OptionNum : Strip number (0~3)
// (This parameter is only used when isAppli parameter is 0.)
//
// retval : 1 = No error / 0 = Error
//
//****************************************************************************
int AddIn_main(int isAppli, unsigned short OptionNum)
{
Machine_State state;

Machine_Init(&state);

/* This is a little program made for testing purposes */
state.Memory[512] = 0x60; // LD V0, 00
state.Memory[513] = 0x00;
state.Memory[514] = 0x61; // LD V1, 00
state.Memory[515] = 0x00;
state.Memory[516] = 0x62; // LD V2, 0F (=15)
state.Memory[517] = 0x0F;
state.Memory[518] = 0x00; // CLR
state.Memory[519] = 0xE0;
state.Memory[520] = 0xF1; // LD F, V1
state.Memory[521] = 0x29;
state.Memory[522] = 0xD0; // DRAW V0, V0, 5
state.Memory[523] = 0x05;
state.Memory[524] = 0x71; // ADD V1, 1
state.Memory[525] = 0x01;
state.Memory[526] = 0x81; // AND V1, V2
state.Memory[527] = 0x22;
state.Memory[528] = 0x12; // JP 206 (=518)
state.Memory[529] = 0x06;

while(!IsKeyDown(KEY_CTRL_EXIT)){
Machine_Update(&state);
}

return 1;
}




//****************************************************************************
//************** ****************
//************** Notice! ****************
//************** ****************
//************** Please do not change the following source. ****************
//************** ****************
//****************************************************************************


#pragma section _BR_Size
unsigned long BR_Size;
#pragma section


#pragma section _TOP

//****************************************************************************
// InitializeSystem
//
// param : isAppli : 1 = Application / 0 = eActivity
// OptionNum : Option Number (only eActivity)
//
// retval : 1 = No error / 0 = Error
//
//****************************************************************************
int InitializeSystem(int isAppli, unsigned short OptionNum)
{
return INIT_ADDIN_APPLICATION(isAppli, OptionNum);
}

#pragma section


+ 302
- 0
Machine.c View File

@@ -0,0 +1,302 @@
#include "fxlib.h"
#include "MonochromeLib.h"
#include "Machine.h"

#include <stdlib.h>

const byte chip8_font[80] = { //80 bytes = 16 characters * 5 bytes
0xF0, 0x90, 0x90, 0x90, 0xF0, //0
0x20, 0x60, 0x20, 0x20, 0x70, //1
0xF0, 0x10, 0xF0, 0x80, 0xF0, //2
0xF0, 0x10, 0xF0, 0x10, 0xF0, //3
0x90, 0x90, 0xF0, 0x10, 0x10, //4
0xF0, 0x80, 0xF0, 0x10, 0xF0, //5
0xF0, 0x80, 0xF0, 0x90, 0xF0, //6
0xF0, 0x10, 0x20, 0x40, 0x40, //7
0xF0, 0x90, 0xF0, 0x90, 0xF0, //8
0xF0, 0x90, 0xF0, 0x10, 0xF0, //9
0xF0, 0x90, 0xF0, 0x90, 0x90, //A
0xE0, 0x90, 0xE0, 0x90, 0xE0, //B
0xF0, 0x80, 0x80, 0x80, 0xF0, //C
0xE0, 0x90, 0x90, 0x90, 0xE0, //D
0xF0, 0x80, 0xF0, 0x80, 0xF0, //E
0xF0, 0x80, 0xF0, 0x80, 0x80 //F
};

void Machine_Init(Machine_State* state){
int i;

state->PC = 0x200;
state->SP = 0x00;
state->I = 0x00;
state->DT = 0x00;
state->ST = 0x00;

for(i = 0; i < sizeof(state->Memory); i++){
/* Put the fontset into memory */
if(i < sizeof(chip8_font))
state->Memory[i] = chip8_font[i];
/* Clear the memory */
else
state->Memory[i] = 0;
}
/* Clear the stack and the V registers */
for(i = 0; i < 16; i++){
state->Stack[i] = 0;
state->V[i] = 0;
}
/* Clear the screen */
ML_clear_screen();
ML_display_vram();
}

void Machine_Update(Machine_State* state){
int i, x, y, j;
byte line;

switch(state->Memory[state->PC] & 0xF0){

/* Call a subroutine */
case 0x00:
switch(state->Memory[state->PC+1]){
// Clear the screen
case 0xE0:
ML_clear_vram();
ML_display_vram();
break;
// Return from a call
case 0xEE:
state->PC = state->Stack[state->SP--]-2;
break;
}
break;

/* JP addr */
case 0x10:
state->PC = ((state->Memory[state->PC] & 0x0F) << 8 | state->Memory[state->PC+1]) - 2;
break;

/* CALL addr */
case 0x20:
state->Stack[state->SP] = state->PC;
state->SP++;
state->PC = ((state->Memory[state->PC] & 0x0F) << 8 | state->Memory[state->PC+1]) - 2;
break;

/* SE Vx, byte */
case 0x30:
if(state->V[state->Memory[state->PC] & 0x0F] == state->Memory[state->PC+1])
state->PC += 2;
break;

/* SNE Vx, byte */
case 0x40:
if(state->V[state->Memory[state->PC] & 0x0F] != state->Memory[state->PC+1])
state->PC += 2;
break;

/* SE Vx, Vy */
case 0x50:
if(state->V[state->Memory[state->PC] & 0x0F] == state->V[state->Memory[state->PC+1] >> 4])
state->PC += 2;
break;

/* LD Vx, byte */
case 0x60:
state->V[state->Memory[state->PC] & 0x0F] = state->Memory[state->PC+1];
break;

/* ADD Vx, byte */
case 0x70:
state->V[state->Memory[state->PC] & 0x0F] += state->Memory[state->PC+1];
break;

/* Vx - Vy instructions */
case 0x80:
switch(state->Memory[state->PC + 1] & 0x0F){
/* LD Vx, Vy */
case 0:
state->V[state->Memory[state->PC] & 0x0F] = state->V[state->Memory[state->PC + 1] >> 4];
break;

/* OR Vx, Vy */
case 1:
state->V[state->Memory[state->PC] & 0x0F] |= state->V[state->Memory[state->PC + 1] >> 4];
break;

/* AND Vx, Vy */
case 2:
state->V[state->Memory[state->PC] & 0x0F] &= state->V[state->Memory[state->PC + 1] >> 4];
break;

/* XOR Vx, Vy */
case 3:
state->V[state->Memory[state->PC] & 0x0F] ^= state->V[state->Memory[state->PC + 1] >> 4];
break;

/* ADD Vx, Vy */
case 4:
// If there's a carry
state->V[15] = (state->V[state->Memory[state->PC] & 0x0F] + state->V[state->Memory[state->PC + 1] >> 4] >= 256);

state->V[state->Memory[state->PC] & 0x0F] += state->V[state->Memory[state->PC + 1] >> 4];
break;

/* SUB Vx, Vy */
case 5:
// If Vx > Vy
state->V[15] = (state->V[state->Memory[state->PC] & 0x0F] > state->V[state->Memory[state->PC + 1] >> 4]);

state->V[state->Memory[state->PC] & 0x0F] -= state->V[state->Memory[state->PC + 1] >> 4];
break;

/* SHR Vx */
case 6:
state->V[15] = state->V[state->Memory[state->PC] & 0x0F] & 0x01;

state->V[state->Memory[state->PC] & 0x0F] >>= 1;
break;

/* SUBN Vx, Vy */
case 7:
// If Vx < Vy
state->V[15] = (state->V[state->Memory[state->PC] & 0x0F] < state->V[state->Memory[state->PC + 1] >> 4]);

state->V[state->Memory[state->PC] & 0x0F] -= state->V[state->Memory[state->PC + 1] >> 4];
break;

/* SHL Vx */
case 14:
state->V[15] = state->V[state->Memory[state->PC] & 0x0F] >> 7;

state->V[state->Memory[state->PC] & 0x0F] <<= 1;
break;
}
break;
/* SNE Vx, Vy */
case 0x90:
if(state->V[state->Memory[state->PC] & 0x0F] != state->V[state->Memory[state->PC+1] >> 4])
state->PC += 2;
break;

/* LD I, addr */
case 0xA0:
state->I = (state->Memory[state->PC] & 0x0F << 8) | state->Memory[state->PC+1];
break;

/* JP V0, addr */
case 0xB0:
state->PC = ((state->Memory[state->PC] & 0x0F) << 8 | state->Memory[state->PC+1]) + state->V[0] - 2;
break;

/* RND Vx, byte */
case 0xC0:
state->V[state->Memory[state->PC] & 0x0F] = (rand() * 255 / RAND_MAX);
state->V[state->Memory[state->PC] & 0x0F] &= state->Memory[state->PC+1];
break;

/* DRAW Vx, Vy, nibble */
case 0xD0:
x = state->V[state->Memory[state->PC] & 0x0F];
y = state->V[state->Memory[state->PC + 1] >> 4];

for(i = 0; i < state->Memory[state->PC + 1] & 0x0F; i++){
line = state->Memory[state->I + i];
for(j = 0; j < 8; j++){
if((line >> (7-j) & 0x01) == 1)
ML_pixel((x + j) % SCREEN_WIDTH, (y + i) % SCREEN_HEIGHT, ML_XOR);
}
}

// Update the screen
ML_display_vram();
break;

/* SKP/SKNP Vx */
case 0xE0:
if(state->Memory[state->PC+1] == 0x9E && isKeyPressed(state->V[state->Memory[state->PC] & 0x0F]))
state->PC += 2;

if(state->Memory[state->PC+1] == 0xA1 && !isKeyPressed(state->V[state->Memory[state->PC] & 0x0F]))
state->PC += 2;
break;

/* Other instructions */
case 0xF0:
switch(state->Memory[state->PC+1]){
/* LD Vx, DT */
case 0x07:
state->V[state->Memory[state->PC] & 0x0F] = state->DT;
break;

/* LD Vx, K */
case 0x0A:
state->V[state->Memory[state->PC] & 0x0F] = getKeyPressed();
break;

/* LD DT, Vx */
case 0x15:
state->DT = state->V[state->Memory[state->PC] & 0x0F];
break;

/* LD ST, Vx */
case 0x18:
state->ST = state->V[state->Memory[state->PC] & 0x0F];
break;

/* ADD I, Vx */
case 0x1E:
state->I += state->V[state->Memory[state->PC] & 0x0F];
break;

/* LD F, Vx */
case 0x29:
state->I = state->V[state->Memory[state->PC] & 0x0F] * 5;
break;

/* LD B, Vx */
case 0x33:
state->Memory[state->I] = state->V[state->Memory[state->PC] & 0x0F] / 100;
state->Memory[state->I+1] = state->V[state->Memory[state->PC] & 0x0F] / 10 % 10;
state->Memory[state->I+2] = state->V[state->Memory[state->PC] & 0x0F] % 10;
break;

/* LD [I], Vx */
case 0x55:
for(i = 0; i < state->V[state->Memory[state->PC] & 0x0F]; i++)
state->Memory[i] = state->V[i];
break;

/* LD Vx, [I] */
case 0x65:
for(i = 0; i < state->V[state->Memory[state->PC] & 0x0F]; i++)
state->V[i] = state->Memory[i];
break;
}
break;
}

/* Update the timers */
if(state->DT > 0) state->DT--;
if(state->ST > 0) state->ST--;

/* Update PC */
state->PC += 2;
state->PC &= 0x0FFF;
}

int isKeyPressed(int key){
return 0;
}


int getKeyPressed(){
return 0;
}

+ 28
- 0
Machine.h View File

@@ -0,0 +1,28 @@
#ifndef _MACHINE_H_
#define _MACHINE_H_

#define SCREEN_WIDTH 64
#define SCREEN_HEIGHT 32

typedef unsigned char byte;
typedef unsigned short word;

typedef struct Machine_State Machine_State;
struct Machine_State{
byte Memory[4096];
byte V[16];
word Stack[16];
byte DT;
byte ST;
word I;
word PC;
word SP;
};

void Machine_Init(Machine_State* state);
void Machine_Update(Machine_State* state);
int isKeyPressed(int key);
int getKeyPressed();

#endif

+ 1289
- 0
MonochromeLib.c
File diff suppressed because it is too large
View File


+ 151
- 0
MonochromeLib.h View File

@@ -0,0 +1,151 @@
/*************************************************************/
/** MonochromeLib - monochrome graphic library for fx-9860G **/
/** MonochromeLib is free software **/
/** **/
/** @author Pierre "PierrotLL" Le Gall **/
/** @contact legallpierre89@gmail.com **/
/** **/
/** @file MonochromeLib.h **/
/** Include header for MonochromeLib **/
/** **/
/** @date 11-22-2011 **/
/*************************************************************/

#ifndef MONOCHROMELIB
#define MONOCHROMELIB

/****************************************************/
/** uncomment #define of functions you want to use **/
/****************************************************/

// #define ML_ALL //Auto define all functions

#define ML_CLEAR_VRAM
#define ML_CLEAR_SCREEN
#define ML_DISPLAY_VRAM

// #define ML_SET_CONTRAST
// #define ML_GET_CONTRAST

#define ML_PIXEL
// #define ML_POINT
#define ML_PIXEL_TEST

// #define ML_LINE
// #define ML_HORIZONTAL_LINE
// #define ML_VERTICAL_LINE

//#define ML_RECTANGLE

// #define ML_POLYGON
// #define ML_FILLED_POLYGON

// #define ML_CIRCLE
// #define ML_FILLED_CIRCLE

// #define ML_ELLIPSE
// #define ML_ELLIPSE_IN_RECT
// #define ML_FILLED_ELLIPSE
// #define ML_FILLED_ELLIPSE_IN_RECT

// #define ML_HORIZONTAL_SCROLL
// #define ML_VERTICAL_SCROLL

// #define ML_BMP_OR
// #define ML_BMP_AND
#define ML_BMP_XOR
// #define ML_BMP_OR_CL
// #define ML_BMP_AND_CL
// #define ML_BMP_XOR_CL

// #define ML_BMP_8_OR
// #define ML_BMP_8_AND
// #define ML_BMP_8_XOR
// #define ML_BMP_8_OR_CL
// #define ML_BMP_8_AND_CL
// #define ML_BMP_8_XOR_CL

// #define ML_BMP_16_OR
// #define ML_BMP_16_AND
// #define ML_BMP_16_XOR
// #define ML_BMP_16_OR_CL
// #define ML_BMP_16_AND_CL
// #define ML_BMP_16_XOR_CL


/**************************/
/** Functions prototypes **/
/**************************/

#ifdef __cplusplus
extern "C" {
#endif

#define ML_SCREEN_WIDTH 128
#define ML_SCREEN_HEIGHT 64

#define ML_CONTRAST_MIN 130
#define ML_CONTRAST_NORMAL 168
#define ML_CONTRAST_MAX 190
typedef enum {ML_TRANSPARENT=-1, ML_WHITE, ML_BLACK, ML_XOR, ML_CHECKER} ML_Color;

char* ML_vram_adress();

void ML_clear_vram();
void ML_clear_screen();
void ML_display_vram();

void ML_set_contrast(unsigned char contrast);
unsigned char ML_get_contrast();

void ML_pixel(int x, int y, ML_Color color);
void ML_point(int x, int y, int width, ML_Color color);
ML_Color ML_pixel_test(int x, int y);

void ML_line(int x1, int y1, int x2, int y2, ML_Color color);
void ML_horizontal_line(int y, int x1, int x2, ML_Color color);
void ML_vertical_line(int x, int y1, int y2, ML_Color color);

void ML_rectangle(int x1, int y1, int x2, int y2, int border_width, ML_Color border_color, ML_Color fill_color);

void ML_polygon(const int *x, const int *y, int nb_vertices, ML_Color color);
void ML_filled_polygon(const int *x, const int *y, int nb_vertices, ML_Color color);

void ML_circle(int x, int y, int radius, ML_Color color);
void ML_filled_circle(int x, int y, int radius, ML_Color color);

void ML_ellipse(int x, int y, int radius1, int radius2, ML_Color color);
void ML_ellipse_in_rect(int x1, int y1, int x2, int y2, ML_Color color);
void ML_filled_ellipse(int x, int y, int radius1, int radius2, ML_Color color);
void ML_filled_ellipse_in_rect(int x, int y, int radius1, int radius2, ML_Color color);

void ML_horizontal_scroll(int scroll);
void ML_vertical_scroll(int scroll);

void ML_bmp_or(const unsigned char *bmp, int x, int y, int width, int height);
void ML_bmp_and(const unsigned char *bmp, int x, int y, int width, int height);
void ML_bmp_xor(const unsigned char *bmp, int x, int y, int width, int height);
void ML_bmp_or_cl(const unsigned char *bmp, int x, int y, int width, int height);
void ML_bmp_and_cl(const unsigned char *bmp, int x, int y, int width, int height);
void ML_bmp_xor_cl(const unsigned char *bmp, int x, int y, int width, int height);

void ML_bmp_8_or(const unsigned char *bmp, int x, int y);
void ML_bmp_8_and(const unsigned char *bmp, int x, int y);
void ML_bmp_8_xor(const unsigned char *bmp, int x, int y);
void ML_bmp_8_or_cl(const unsigned char *bmp, int x, int y);
void ML_bmp_8_and_cl(const unsigned char *bmp, int x, int y);
void ML_bmp_8_xor_cl(const unsigned char *bmp, int x, int y);

void ML_bmp_16_or(const unsigned short *bmp, int x, int y);
void ML_bmp_16_and(const unsigned short *bmp, int x, int y);
void ML_bmp_16_xor(const unsigned short *bmp, int x, int y);
void ML_bmp_16_or_cl(const unsigned short *bmp, int x, int y);
void ML_bmp_16_and_cl(const unsigned short *bmp, int x, int y);
void ML_bmp_16_xor_cl(const unsigned short *bmp, int x, int y);

#ifdef __cplusplus
}
#endif


#endif //MONOCHROMELIB

+ 1
- 1
README.md View File

@@ -1,3 +1,3 @@
# Chip8_Emulator

This addin is a Chip 8 Emulator.
This addin is a Chip 8 Emulator for Casio written in C based on MonochromeLib.

Loading…
Cancel
Save