C++版 Chip8游戏模拟器
很早就想写个FC模拟器,但真是一件艰难的事情。。
所以先写个Chip8模拟器,日后再继续研究FC模拟器。
Chip8只有35条指令,属于RISC指令集,4k内存,2k显存,16个寄存器(其中15个通用寄存器),支持16个按键,没有中断,但是有两个计时器。
读了下面两个链接,就完全能理解了。
http://www.cnblogs.com/YiranXie/category/539179.html
http://en.wikipedia.org/wiki/CHIP-8
把代码贴一下吧。
#ifndef __CHIP8_H__
#define __CHIP8_H__ class Chip8
{
public:
bool drawFlag;
void emulateCycle();
bool loadApplication(const char* fileName);
unsigned char gfx[ * ];
unsigned char key[]; private:
//35条opcode写成函数,为了效率,使用inline
inline void op_0NNN();
inline void op_00E0();
inline void op_00EE();
inline void op_1NNN();
inline void op_2NNN();
inline void op_3XNN();
inline void op_4XNN();
inline void op_5XY0();
inline void op_6XNN();
inline void op_7XNN();
inline void op_8XY0();
inline void op_8XY1();
inline void op_8XY2();
inline void op_8XY3();
inline void op_8XY4();
inline void op_8XY5();
inline void op_8XY6();
inline void op_8XY7();
inline void op_8XYE();
inline void op_9XY0();
inline void op_ANNN();
inline void op_BNNN();
inline void op_CXNN();
inline void op_DXYN();
inline void op_EX9E();
inline void op_EXA1();
inline void op_FX07();
inline void op_FX0A();
inline void op_FX15();
inline void op_FX18();
inline void op_FX1E();
inline void op_FX29();
inline void op_FX33();
inline void op_FX55();
inline void op_FX65(); void init(); unsigned short pc;
unsigned short opcode;
unsigned short I;
unsigned short sp; unsigned char V[];
unsigned short stack[];
unsigned char memory[]; unsigned char delay_timer;
unsigned char sound_timer;
}; #endif
#define _CRT_SECURE_NO_WARNINGS 1 #include "Chip8.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h> unsigned char fontset[] =
{
0xF0, 0x90, 0x90, 0x90, 0xF0, //
0x20, 0x60, 0x20, 0x20, 0x70, //
0xF0, 0x10, 0xF0, 0x80, 0xF0, //
0xF0, 0x10, 0xF0, 0x10, 0xF0, //
0x90, 0x90, 0xF0, 0x10, 0x10, //
0xF0, 0x80, 0xF0, 0x10, 0xF0, //
0xF0, 0x80, 0xF0, 0x90, 0xF0, //
0xF0, 0x10, 0x20, 0x40, 0x40, //
0xF0, 0x90, 0xF0, 0x90, 0xF0, //
0xF0, 0x90, 0xF0, 0x10, 0xF0, //
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 Chip8::init()
{
pc = 0x200;
opcode = ;
I = ;
sp = ;
delay_timer = ;
sound_timer = ;
drawFlag = true; memset(memory, , sizeof(memory));
memset(V, , sizeof(V));
memset(gfx, , sizeof(gfx));
memset(stack, , sizeof(stack));
memset(key, , sizeof(key)); for(int i = ; i < ; ++i) {
memory[i] = fontset[i];
}
srand((unsigned int)time(NULL));
} bool Chip8::loadApplication(const char* fileName)
{
init();
FILE* file = fopen(fileName, "rb");
fseek(file, , SEEK_END);
int fileSize = ftell(file);
rewind(file);
char* buffer = (char*)malloc(sizeof(char) * fileSize);
fread(buffer, sizeof(char), fileSize, file);
for(int i = ; i < fileSize; ++i) {
memory[+i] = buffer[i];
}
fclose(file);
free(buffer);
return true;
} void Chip8::emulateCycle()
{
opcode = memory[pc] << | memory[pc+];
switch(opcode & 0xF000) {
case 0x0000:
switch(opcode & 0x000F) {
case 0x0000:
op_00E0(); break;
case 0x000E:
op_00EE(); break;
}
break;
case 0x1000:
op_1NNN(); break;
case 0x2000:
op_2NNN(); break;
case 0x3000:
op_3XNN(); break;
case 0x4000:
op_4XNN(); break;
case 0x5000:
op_5XY0(); break;
case 0x6000:
op_6XNN(); break;
case 0x7000:
op_7XNN(); break;
case 0x8000:
switch(opcode & 0x000F) {
case 0x0000:
op_8XY0(); break;
case 0x0001:
op_8XY1(); break;
case 0x0002:
op_8XY2(); break;
case 0x0003:
op_8XY3(); break;
case 0x0004:
op_8XY4(); break;
case 0x0005:
op_8XY5(); break;
case 0x0006:
op_8XY6(); break;
case 0x0007:
op_8XY7(); break;
case 0x000E:
op_8XYE(); break;
}
break;
case 0x9000:
op_9XY0(); break;
case 0xA000:
op_ANNN(); break;
case 0xB000:
op_BNNN(); break;
case 0xC000:
op_CXNN(); break;
case 0xD000:
op_DXYN(); break;
case 0xE000:
switch(opcode & 0x000F) {
case 0x000E:
op_EX9E(); break;
case 0x0001:
op_EXA1(); break;
}
break;
case 0xF000:
switch(opcode & 0x00FF) {
case 0x0007:
op_FX07(); break;
case 0x000A:
op_FX0A(); break;
case 0x0015:
op_FX15(); break;
case 0x0018:
op_FX18(); break;
case 0x001E:
op_FX1E(); break;
case 0x0029:
op_FX29(); break;
case 0x0033:
op_FX33(); break;
case 0x0055:
op_FX55(); break;
case 0x0065:
op_FX65(); break;
}
}
if(delay_timer > ) {
--delay_timer;
}
if(sound_timer > ) {
--sound_timer;
}
} void Chip8::op_0NNN()
{
} void Chip8::op_00E0()
{
memset(gfx, , sizeof(gfx));
drawFlag = true;
pc += ;
} void Chip8::op_00EE()
{
pc = stack[--sp] + ;
} void Chip8::op_1NNN()
{
pc = opcode & 0x0FFF;
} void Chip8::op_2NNN()
{
stack[sp++] = pc;
pc = opcode & 0x0FFF;
} void Chip8::op_3XNN()
{
pc += (V[(opcode & 0x0F00) >> ] == (opcode & 0x00FF)) ? : ;
} void Chip8::op_4XNN()
{
pc += (V[(opcode & 0x0F00) >> ] != (opcode & 0x00FF)) ? : ;
} void Chip8::op_5XY0()
{
pc += (V[(opcode & 0x0F00) >> ] == V[(opcode & 0x00F0) >> ]) ? : ;
} void Chip8::op_6XNN()
{
V[(opcode & 0x0F00) >> ] = opcode & 0x00FF;
pc += ;
} void Chip8::op_7XNN()
{
V[(opcode & 0x0F00) >> ] += opcode & 0x00FF;
pc += ;
} void Chip8::op_8XY0()
{
V[(opcode & 0x0F00) >> ] = V[(opcode & 0x00F0) >> ];
pc += ;
} void Chip8::op_8XY1()
{
V[(opcode & 0x0F00) >> ] |= V[(opcode & 0x00F0) >> ];
pc += ;
} void Chip8::op_8XY2()
{
V[(opcode & 0x0F00) >> ] &= V[(opcode & 0x00F0) >> ];
pc += ;
} void Chip8::op_8XY3()
{
V[(opcode & 0x0F00) >> ] ^= V[(opcode & 0x00F0) >> ];
pc += ;
} void Chip8::op_8XY4()
{
V[0xF] = V[(opcode & 0x00F0) >> ] > (0xFF - V[(opcode &0x0F00) >> ]);
V[(opcode & 0x0F00) >> ] += V[(opcode & 0x00F0) >> ];
pc += ;
} void Chip8::op_8XY5()
{
V[0xF] = !(V[(opcode & 0x00F0) >> ] > V[(opcode & 0x0F00) >> ]);
V[(opcode & 0x0F00) >> ] -= V[(opcode & 0x00F0) >> ];
pc += ;
} void Chip8::op_8XY6()
{
V[0xF] = V[(opcode & 0x0F00) >> ] & 0x1;
V[(opcode & 0x0F00) >> ] >>= ;
pc += ;
} void Chip8::op_8XY7()
{
V[0xF] = !(V[(opcode & 0x0F00) >> ] > V[(opcode & 0x00F0) >> ]);
V[(opcode & 0x0F00) >> ] = V[(opcode & 0x00F0) >> ] - V[(opcode & 0x0F00) >> ];
pc += ;
} void Chip8::op_8XYE()
{
V[0xF] = V[(opcode & 0x0F00) >> ] >> ;
V[(opcode & 0x0F00) >> ] <<= ;
pc += ;
} void Chip8::op_9XY0()
{
pc += (V[(opcode & 0x0F00) >> ] != V[(opcode & 0x00F0) >> ]) ? : ;
} void Chip8::op_ANNN()
{
I = opcode & 0x0FFF;
pc += ;
} void Chip8::op_BNNN()
{
pc = (opcode & 0x0FFF) + V[];
} void Chip8::op_CXNN()
{
V[(opcode & 0x0F00) >> ] = (rand() % 0xFF) & (opcode & 0x00FF);
pc += ;
} void Chip8::op_DXYN()
{
unsigned short x = V[(opcode & 0x0F00) >> ];
unsigned short y = V[(opcode & 0x00F0) >> ];
unsigned short height = opcode & 0x000F;
unsigned short pixel = ;
V[0xF] = ;
for(int yline = ; yline < height; ++yline) {
pixel = memory[I+yline];
for(int xline = ; xline < ; ++xline) {
if((pixel & (0x80 >> xline)) != )
{
if(gfx[(x + xline + ((y + yline) * ))] == )
{
V[0xF] = ;
}
gfx[x + xline + ((y + yline) * )] ^= ;
}
}
}
drawFlag = true;
pc += ;
} void Chip8::op_EX9E()
{
pc += (key[V[(opcode & 0x0F00) >> ]]) ? : ;
} void Chip8::op_EXA1()
{
pc += (key[V[(opcode & 0x0F00) >> ]]) ? : ;
} void Chip8::op_FX07()
{
V[(opcode & 0x0F00) >> ] = delay_timer;
pc += ;
} void Chip8::op_FX0A()
{
bool keyPress = false; for(int i = ; i < ; ++i)
{
if(key[i] != )
{
V[(opcode & 0x0F00) >> ] = i;
keyPress = true;
}
} if(!keyPress) {
return;
}
pc += ;
} void Chip8::op_FX15()
{
delay_timer = V[(opcode & 0x0F00) >> ];
pc += ;
} void Chip8::op_FX18()
{
sound_timer = V[(opcode & 0x0F00) >> ];
pc += ;
} void Chip8::op_FX1E()
{
V[0xF] = (I + V[(opcode & 0x0F00) >> ]) > 0xFFF;
I += V[(opcode & 0x0F00) >> ];
pc += ;
} void Chip8::op_FX29()
{
I = V[(opcode & 0x0F00) >> ] * ;
pc += ;
} void Chip8::op_FX33()
{
unsigned short vx = V[(opcode & 0x0F00) >> ];
memory[I] = vx / ;
memory[I+] = vx / % ;
memory[I+] = vx % ;
pc += ;
} void Chip8::op_FX55()
{
unsigned short vx = V[(opcode & 0x0F00) >> ];
for(int i = ; i <= vx; ++i) {
memory[I+i] = V[i];
}
I += ((opcode & 0x0F00) >> ) + ;
pc += ;
} void Chip8::op_FX65()
{
unsigned short vx = V[(opcode & 0x0F00) >> ];
for(int i = ; i <= vx; ++i) {
V[i] = memory[I+i];
}
I += ((opcode & 0x0F00) >> ) + ;
pc += ;
}
C++版 Chip8游戏模拟器的更多相关文章
- Swift版iOS游戏框架Sprite Kit基础教程下册
Swift版iOS游戏框架Sprite Kit基础教程下册 试读下载地址:http://pan.baidu.com/s/1qWBdV0C 介绍:本教程是国内唯一的Swift版的Spritekit教程. ...
- android版猜拳游戏源码分享
android版猜拳游戏源码分享安卓版猜拳游戏源码,该文件中带有安装测试包的,这个游戏源码比较简单的,现在有两个代码,一个自定义VIEW的,一个就是普通的imageView图片,游戏非常适合一些新手的 ...
- 《Genesis-3D开源游戏引擎--横版格斗游戏制作教程:简介及目录》(附上完整工程文件)
介绍:讲述如何使用Genesis-3D来制作一个横版格斗游戏,涉及如何制作连招系统,如何使用包围盒实现碰撞检测,软键盘的制作,场景切换,技能读表,简单怪物AI等等,并为您提供这个框架的全套资源,源码以 ...
- 一个用 C 语言写的迷你版 2048 游戏,仅仅有 500个字符
Jay Chan 用 C 语言写的一个迷你版 2048 游戏,仅仅有 487 个字符. 来围观吧 M[16],X=16,W,k;main(){T(system("stty cbreak&qu ...
- 简易2D横版RPG游戏制作
Unity学习笔记1 简易2D横版RPG游戏制作 http://m.blog.csdn.net/article/details?id=24601905
- Cocos2d-x 3.x版2048游戏开发
Cocos2d-x 3.x版2048游戏开发 本篇博客给大家介绍怎样高速开发2048这样一款休闲游戏,理解整个2048游戏的开发流程.从本篇博客你将能够学习到下面内容: 这里注明一下,本教程来自极客学 ...
- 相当牛X的java版星际游戏
分享一款牛人用java写的经典游戏,目录结构如下: 虽然只能算一个Demo,但是用到了很多Java基础技术和算法: Java2D,双缓冲,A星寻路,粒子系统,动画效果,处理图片,Swing ui ,U ...
- Beat 'Em Up Game Starter Kit (横版格斗游戏) cocos2d-x游戏源代码
浓缩精华.专注战斗! 游戏的本质是什么?界面?养成?NoNo! 游戏来源于对实战和比赛的模拟,所以它的本源就是对抗.就是战斗! 是挥洒热血的一种方式! 一个游戏最复杂最难做的是什么?UI?商城? ...
- 创业游戏模拟器 Startup 游戏试玩
买的正版游戏,还在beta阶段.因为对这种经营类的游戏挺感兴趣,结合自己也是做这个行当的.算是一次性通关了吧.我来评价一下这个游戏.足足玩了有5个多小时.从1级玩到15级.解锁了所有的内容.员工从1个 ...
随机推荐
- android90 bind方式启动服务service调用service里的方法
package com.itheima.banzheng; import com.itheima.banzheng.LeaderService.ZhouMi; import android.os.Bu ...
- Demo1_iOS9网络适配_改用更安全的HTTPS
iOS9把所有的http请求都改为https了:iOS9系统发送的网络请求将统一 使用TLS 1.2 SSL.采用TLS 1.2 协议,目的是 强制增强数据访问安全,而且 系统 Foundation ...
- iOS 并行编程:GCD Dispatch Queues
1 简介 1.1 功能 Grand Central Dispatch(GCD)技术让任务并行排队执行,根据可用的处理资源,安排他们在任何可用的处理器核心上执行任务.任务可以是一个函数 ...
- SQL查询数据库表字段值不为空或Null的所有列
) set @TableName = 'Agency' -- 表名 declare @querySql nvarchar(max) set @querySql = 'select ' ) declar ...
- 开始C#之旅
注释 /// <summary> /// 3.文档注释 /// </summary> private static void Test() { Console.WriteLin ...
- jQuery滑过头像图片展示个人信息效果
这是一款经典的jQuery图片插件,同时,也可以是一款jQuery提示框插件.这款jQuery插件的功能是当你把鼠标滑过头像图片缩略图时,即可弹出头像对应用户的详细个人信息,弹出的标签虽然不大,但是还 ...
- HTML DOM对象
HTML DOM对象 Document对象每个载入浏览器的HTML文档都会成为Document对象Document对象让我们可以从javascript中操作文档中的所有元素Document对象是win ...
- group by java实现
public static void abc(List list,String... sortName) throws Exception{ Map<String,List<Object& ...
- Java 泛型类型的一些限制
由于泛型类型在运行时被消除,因此,对于如何使用泛型类型是有一些限制的. 限制1:不能使用new E() 不能使用泛型类型参数创建实例.例如,下面的语句是错误的: E object = new E(); ...
- spring定时任务的配置
定时任务配置分为三个步骤: 1.定义任务 2.任务执行策略配置 3.启动任务 1.定义任务 <!--要定时执行的方法--> <bean id="testTaskJob&qu ...