zoukankan      html  css  js  c++  java
  • 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写成函数,为了效率,使用inline
    15     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 }
  • 相关阅读:
    java01 java基础知识
    01 开发准备 启动PHP服务与环境配置
    Axure 9.0 使用教程2-函数分类
    Axure 9.0 使用教程1-软件概述
    Python 字符串 列表 元组 字典 集合学习总结
    Python 函数定义 调用 迭代器 生成器 递归和推导式
    Python习题
    Python 条件 循环 及其他语句
    Python 字典
    Python 字符串
  • 原文地址:https://www.cnblogs.com/wolfred7464/p/3825085.html
Copyright © 2011-2022 走看看