Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class CHIP8 {
- public:
- typedef unsigned char reg_t; // 8-bit register datatype
- typedef unsigned char mem_t; // 8-bit memory datatype
- typedef unsigned short ptr_t; // 16-bit pointer datatype
- typedef unsigned short inst_t; // 16-bit instruction datatype
- const inst_t *program; // stored program memory
- std::vector<mem_t> memory; // read/write data memory
- ptr_t program_counter;
- enum {nreg=16};
- reg_t V[nreg]; // registers
- ptr_t I; // memory pointer register
- bool done; // set to true when the program hits 0xFFFF instruction
- // Set up a simulator to run this program, with this much memory, starting from this program address
- CHIP8(const inst_t *program_,ptr_t memory_length=100,ptr_t program_start=0)
- :program(program_),
- memory(memory_length),
- program_counter(program_start),
- I(0),
- done(false)
- {}
- void error(const char *what) {
- fprintf(stderr,"CHIP-8 error: %s\n",what);
- done=true;
- }
- // Execute one instruction
- void step(void) {
- inst_t fetch=program[program_counter++]; // the next instruction
- inst_t opcode=(fetch>>12)&0xF; // high bits
- inst_t X=(fetch>>8)&0xF; // destination register
- inst_t Y=(fetch>>4)&0xF; // optional other parts of instruction
- inst_t NN=(fetch)&0xFF;
- inst_t NNN=(fetch)&0xFF;
- switch(opcode) {
- case 0x1: // jump
- program_counter = NNN;
- break;
- case 0x3:
- if (V[X] == NN) program_counter++;
- break;
- case 0x5: // cond
- if (V[X] == V[Y]) program_counter++;
- break;
- case 0x6: // const
- V[X] = NN;
- break;
- case 0x7: // const
- V[X] += NN;
- break;
- case 0x8: // math
- switch (fetch & 0xF) {
- case 0x4: V[X] += V[Y]; break; // add
- case 0x5:
- V[X] -= V[Y];
- if(V[X] - V[Y] < 0) {
- V[0xF] = 0;
- }
- else {
- V[0xF] = 1;
- }
- break; // subtract
- case 0x0: V[X] = V[Y]; break; // assign
- default: error("Unknown arithmetic instruction"); break;
- }
- break;
- case 0xA:
- I = NNN;
- break;
- case 0xF: // special functions
- if (NN==0xFA) { int r; std::cin>>r; V[X]=r; break; }
- if (NN==0xFD) { std::cout<<(int)V[X]<<"\n"; break; }
- if (NN==0xFF) { done=true; break; }
- if (NN==0x1E) {
- if (I+V[X] > 0xFFF) {
- V[0xF] = 1;
- }
- else {
- V[0xF] = 0;
- }
- I += V[X];
- break;
- }
- if (NN==0x55) { // dump
- unsigned int reg_num = 0;
- for(unsigned int i_offset = I; i_offset < X; ++i_offset) {
- memory[i_offset] = V[reg_num];
- reg_num++;
- }
- break;
- }
- if (NN==0x65) { // load
- unsigned int reg_num = 0;
- for(unsigned int i_offset = I; i_offset < X; ++i_offset) {
- V[reg_num] = memory[i_offset];
- reg_num++;
- }
- break;
- }
- // intentional fall-through here:
- default: error("unimplemented instruction"); break;
- }
- }
- // Print the machine state (debugging)
- void print(void) {
- printf(" pc: %04x (%04x) V0=%02x V1=%02x V2=%02x V5=%02x VF=%02x\n",
- program_counter,program[program_counter],V[0],V[1],V[2],V[5],V[0xF]);
- }
- };
- // Stored program, in program memory
- const CHIP8::inst_t instructions[]={
- 0xF2FA, // read input into V2 [LOOP BOUND]
- 0x6502, // V5 = 2 [LOOP COUNTER]
- 0x6101, // V1 = 1 - constant
- // 0xFaFD, // print V5 [LOOP START]
- 0xF065, // V0 = memeory[I]
- 0x8300, // V3 = V0
- 0x3300, // V3 == 0?
- 0x1003, // jmp loop begin
- 0xF7FD, // Print V5
- 0x8750, // V7 = V5
- 0x8754, // V7 += V5 [LOOP2 COUNTER] [LOOP2 START]
- 0x6001, // V0 = 1
- 0xF055, // Store V0 to memory @ I
- 0xF11E, // I++
- 0x8870, // V8 = V7
- 0x8285, // V2 -= V8
- 0x8284, // V2 += V8
- 0x3F00, // VF == 0?
- 0x1009, // Jump to loop2 start
- 0x7501, // V5++
- 0x5520, // V5 == V2? yes -> skip next instruction | no -> loop
- 0x1003, // jump to loop beginning [LOOP END]
- 0xFFFF // end program
- };
- long foo(void)
- {
- CHIP8 sim(instructions,1000,0);
- while (!sim.done) {
- sim.print();
- sim.step();
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement