首页 > 代码库 > C++版 Chip8游戏模拟器
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
把代码贴一下吧。
1 #ifndef __CHIP8_H__ 2 #define __CHIP8_H__ 3 4 class Chip8 5 { 6 public: 7 bool drawFlag; 8 void emulateCycle(); 9 bool loadApplication(const char* fileName);10 unsigned char gfx[64 * 32];11 unsigned char key[16];12 13 private:14 //35条opcode写成函数,为了效率,使用inline15 inline void op_0NNN();16 inline void op_00E0();17 inline void op_00EE();18 inline void op_1NNN();19 inline void op_2NNN();20 inline void op_3XNN();21 inline void op_4XNN();22 inline void op_5XY0();23 inline void op_6XNN();24 inline void op_7XNN();25 inline void op_8XY0();26 inline void op_8XY1();27 inline void op_8XY2();28 inline void op_8XY3();29 inline void op_8XY4();30 inline void op_8XY5();31 inline void op_8XY6();32 inline void op_8XY7();33 inline void op_8XYE();34 inline void op_9XY0();35 inline void op_ANNN();36 inline void op_BNNN();37 inline void op_CXNN();38 inline void op_DXYN();39 inline void op_EX9E();40 inline void op_EXA1();41 inline void op_FX07();42 inline void op_FX0A();43 inline void op_FX15();44 inline void op_FX18();45 inline void op_FX1E();46 inline void op_FX29();47 inline void op_FX33();48 inline void op_FX55();49 inline void op_FX65();50 51 void init();52 53 unsigned short pc;54 unsigned short opcode;55 unsigned short I;56 unsigned short sp;57 58 unsigned char V[16];59 unsigned short stack[16];60 unsigned char memory[4096];61 62 unsigned char delay_timer;63 unsigned char sound_timer;64 };65 66 #endif
1 #define _CRT_SECURE_NO_WARNINGS 1 2 3 #include "Chip8.h" 4 #include <string.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <time.h> 8 9 unsigned char fontset[80] = 10 { 11 0xF0, 0x90, 0x90, 0x90, 0xF0, //0 12 0x20, 0x60, 0x20, 0x20, 0x70, //1 13 0xF0, 0x10, 0xF0, 0x80, 0xF0, //2 14 0xF0, 0x10, 0xF0, 0x10, 0xF0, //3 15 0x90, 0x90, 0xF0, 0x10, 0x10, //4 16 0xF0, 0x80, 0xF0, 0x10, 0xF0, //5 17 0xF0, 0x80, 0xF0, 0x90, 0xF0, //6 18 0xF0, 0x10, 0x20, 0x40, 0x40, //7 19 0xF0, 0x90, 0xF0, 0x90, 0xF0, //8 20 0xF0, 0x90, 0xF0, 0x10, 0xF0, //9 21 0xF0, 0x90, 0xF0, 0x90, 0x90, //A 22 0xE0, 0x90, 0xE0, 0x90, 0xE0, //B 23 0xF0, 0x80, 0x80, 0x80, 0xF0, //C 24 0xE0, 0x90, 0x90, 0x90, 0xE0, //D 25 0xF0, 0x80, 0xF0, 0x80, 0xF0, //E 26 0xF0, 0x80, 0xF0, 0x80, 0x80 //F 27 }; 28 29 void Chip8::init() 30 { 31 pc = 0x200; 32 opcode = 0; 33 I = 0; 34 sp = 0; 35 delay_timer = 0; 36 sound_timer = 0; 37 drawFlag = true; 38 39 memset(memory, 0, sizeof(memory)); 40 memset(V, 0, sizeof(V)); 41 memset(gfx, 0, sizeof(gfx)); 42 memset(stack, 0, sizeof(stack)); 43 memset(key, 0, sizeof(key)); 44 45 for(int i = 0; i < 80; ++i) { 46 memory[i] = fontset[i]; 47 } 48 srand((unsigned int)time(NULL)); 49 } 50 51 bool Chip8::loadApplication(const char* fileName) 52 { 53 init(); 54 FILE* file = fopen(fileName, "rb"); 55 fseek(file, 0, SEEK_END); 56 int fileSize = ftell(file); 57 rewind(file); 58 char* buffer = (char*)malloc(sizeof(char) * fileSize); 59 fread(buffer, sizeof(char), fileSize, file); 60 for(int i = 0; i < fileSize; ++i) { 61 memory[512+i] = buffer[i]; 62 } 63 fclose(file); 64 free(buffer); 65 return true; 66 } 67 68 void Chip8::emulateCycle() 69 { 70 opcode = memory[pc] << 8 | memory[pc+1]; 71 switch(opcode & 0xF000) { 72 case 0x0000: 73 switch(opcode & 0x000F) { 74 case 0x0000: 75 op_00E0(); break; 76 case 0x000E: 77 op_00EE(); break; 78 } 79 break; 80 case 0x1000: 81 op_1NNN(); break; 82 case 0x2000: 83 op_2NNN(); break; 84 case 0x3000: 85 op_3XNN(); break; 86 case 0x4000: 87 op_4XNN(); break; 88 case 0x5000: 89 op_5XY0(); break; 90 case 0x6000: 91 op_6XNN(); break; 92 case 0x7000: 93 op_7XNN(); break; 94 case 0x8000: 95 switch(opcode & 0x000F) { 96 case 0x0000: 97 op_8XY0(); break; 98 case 0x0001: 99 op_8XY1(); break;100 case 0x0002:101 op_8XY2(); break;102 case 0x0003:103 op_8XY3(); break;104 case 0x0004:105 op_8XY4(); break;106 case 0x0005:107 op_8XY5(); break;108 case 0x0006:109 op_8XY6(); break;110 case 0x0007:111 op_8XY7(); break;112 case 0x000E:113 op_8XYE(); break;114 }115 break;116 case 0x9000:117 op_9XY0(); break;118 case 0xA000:119 op_ANNN(); break;120 case 0xB000:121 op_BNNN(); break;122 case 0xC000:123 op_CXNN(); break;124 case 0xD000:125 op_DXYN(); break;126 case 0xE000:127 switch(opcode & 0x000F) {128 case 0x000E:129 op_EX9E(); break;130 case 0x0001:131 op_EXA1(); break;132 }133 break;134 case 0xF000:135 switch(opcode & 0x00FF) {136 case 0x0007:137 op_FX07(); break;138 case 0x000A:139 op_FX0A(); break;140 case 0x0015:141 op_FX15(); break;142 case 0x0018:143 op_FX18(); break;144 case 0x001E:145 op_FX1E(); break;146 case 0x0029:147 op_FX29(); break;148 case 0x0033:149 op_FX33(); break;150 case 0x0055:151 op_FX55(); break;152 case 0x0065:153 op_FX65(); break;154 }155 }156 if(delay_timer > 0) {157 --delay_timer;158 }159 if(sound_timer > 0) {160 --sound_timer;161 }162 }163 164 void Chip8::op_0NNN()165 {166 }167 168 void Chip8::op_00E0()169 {170 memset(gfx, 0, sizeof(gfx));171 drawFlag = true;172 pc += 2;173 }174 175 void Chip8::op_00EE()176 {177 pc = stack[--sp] + 2;178 }179 180 void Chip8::op_1NNN()181 {182 pc = opcode & 0x0FFF;183 }184 185 void Chip8::op_2NNN()186 {187 stack[sp++] = pc;188 pc = opcode & 0x0FFF;189 }190 191 void Chip8::op_3XNN()192 {193 pc += (V[(opcode & 0x0F00) >> 8] == (opcode & 0x00FF)) ? 4 : 2;194 }195 196 void Chip8::op_4XNN()197 {198 pc += (V[(opcode & 0x0F00) >> 8] != (opcode & 0x00FF)) ? 4 : 2;199 }200 201 void Chip8::op_5XY0()202 {203 pc += (V[(opcode & 0x0F00) >> 8] == V[(opcode & 0x00F0) >> 4]) ? 4 : 2;204 }205 206 void Chip8::op_6XNN()207 {208 V[(opcode & 0x0F00) >> 8] = opcode & 0x00FF;209 pc += 2;210 }211 212 void Chip8::op_7XNN()213 {214 V[(opcode & 0x0F00) >> 8] += opcode & 0x00FF;215 pc += 2;216 }217 218 void Chip8::op_8XY0()219 {220 V[(opcode & 0x0F00) >> 8] = V[(opcode & 0x00F0) >> 4];221 pc += 2;222 }223 224 void Chip8::op_8XY1()225 {226 V[(opcode & 0x0F00) >> 8] |= V[(opcode & 0x00F0) >> 4];227 pc += 2;228 }229 230 void Chip8::op_8XY2()231 {232 V[(opcode & 0x0F00) >> 8] &= V[(opcode & 0x00F0) >> 4];233 pc += 2;234 }235 236 void Chip8::op_8XY3()237 {238 V[(opcode & 0x0F00) >> 8] ^= V[(opcode & 0x00F0) >> 4];239 pc += 2;240 }241 242 void Chip8::op_8XY4()243 {244 V[0xF] = V[(opcode & 0x00F0) >> 4] > (0xFF - V[(opcode &0x0F00) >> 8]);245 V[(opcode & 0x0F00) >> 8] += V[(opcode & 0x00F0) >> 4];246 pc += 2;247 }248 249 void Chip8::op_8XY5()250 {251 V[0xF] = !(V[(opcode & 0x00F0) >> 4] > V[(opcode & 0x0F00) >> 8]);252 V[(opcode & 0x0F00) >> 8] -= V[(opcode & 0x00F0) >> 4];253 pc += 2;254 }255 256 void Chip8::op_8XY6()257 {258 V[0xF] = V[(opcode & 0x0F00) >> 8] & 0x1;259 V[(opcode & 0x0F00) >> 8] >>= 1;260 pc += 2;261 }262 263 void Chip8::op_8XY7()264 {265 V[0xF] = !(V[(opcode & 0x0F00) >> 8] > V[(opcode & 0x00F0) >> 4]);266 V[(opcode & 0x0F00) >> 8] = V[(opcode & 0x00F0) >> 4] - V[(opcode & 0x0F00) >> 8];267 pc += 2;268 }269 270 void Chip8::op_8XYE()271 {272 V[0xF] = V[(opcode & 0x0F00) >> 8] >> 7;273 V[(opcode & 0x0F00) >> 8] <<= 1;274 pc += 2;275 }276 277 void Chip8::op_9XY0()278 {279 pc += (V[(opcode & 0x0F00) >> 8] != V[(opcode & 0x00F0) >> 4]) ? 4 : 2;280 }281 282 void Chip8::op_ANNN()283 {284 I = opcode & 0x0FFF;285 pc += 2;286 }287 288 void Chip8::op_BNNN()289 {290 pc = (opcode & 0x0FFF) + V[0];291 }292 293 void Chip8::op_CXNN()294 {295 V[(opcode & 0x0F00) >> 8] = (rand() % 0xFF) & (opcode & 0x00FF);296 pc += 2;297 }298 299 void Chip8::op_DXYN()300 {301 unsigned short x = V[(opcode & 0x0F00) >> 8];302 unsigned short y = V[(opcode & 0x00F0) >> 4];303 unsigned short height = opcode & 0x000F;304 unsigned short pixel = 0;305 V[0xF] = 0;306 for(int yline = 0; yline < height; ++yline) {307 pixel = memory[I+yline];308 for(int xline = 0; xline < 8; ++xline) {309 if((pixel & (0x80 >> xline)) != 0)310 {311 if(gfx[(x + xline + ((y + yline) * 64))] == 1)312 {313 V[0xF] = 1;314 }315 gfx[x + xline + ((y + yline) * 64)] ^= 1;316 }317 }318 }319 drawFlag = true;320 pc += 2;321 }322 323 void Chip8::op_EX9E()324 {325 pc += (key[V[(opcode & 0x0F00) >> 8]]) ? 4 : 2;326 }327 328 void Chip8::op_EXA1()329 {330 pc += (key[V[(opcode & 0x0F00) >> 8]]) ? 2 : 4;331 }332 333 void Chip8::op_FX07()334 {335 V[(opcode & 0x0F00) >> 8] = delay_timer;336 pc += 2;337 }338 339 void Chip8::op_FX0A()340 {341 bool keyPress = false;342 343 for(int i = 0; i < 16; ++i)344 {345 if(key[i] != 0)346 {347 V[(opcode & 0x0F00) >> 8] = i;348 keyPress = true;349 }350 }351 352 if(!keyPress) {353 return;354 }355 pc += 2;356 }357 358 void Chip8::op_FX15()359 {360 delay_timer = V[(opcode & 0x0F00) >> 8];361 pc += 2;362 }363 364 void Chip8::op_FX18()365 {366 sound_timer = V[(opcode & 0x0F00) >> 8];367 pc += 2;368 }369 370 void Chip8::op_FX1E()371 {372 V[0xF] = (I + V[(opcode & 0x0F00) >> 8]) > 0xFFF;373 I += V[(opcode & 0x0F00) >> 8];374 pc += 2;375 }376 377 void Chip8::op_FX29()378 {379 I = V[(opcode & 0x0F00) >> 8] * 5;380 pc += 2;381 }382 383 void Chip8::op_FX33()384 {385 unsigned short vx = V[(opcode & 0x0F00) >> 8];386 memory[I] = vx / 100;387 memory[I+1] = vx / 10 % 10;388 memory[I+2] = vx % 10;389 pc += 2;390 }391 392 void Chip8::op_FX55()393 {394 unsigned short vx = V[(opcode & 0x0F00) >> 8];395 for(int i = 0; i <= vx; ++i) {396 memory[I+i] = V[i];397 }398 I += ((opcode & 0x0F00) >> 8) + 1;399 pc += 2;400 }401 402 void Chip8::op_FX65()403 {404 unsigned short vx = V[(opcode & 0x0F00) >> 8];405 for(int i = 0; i <= vx; ++i) {406 V[i] = memory[I+i];407 }408 I += ((opcode & 0x0F00) >> 8) + 1;409 pc += 2;410 }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。