Notice
Recent Posts
Recent Comments
Link
250x250
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- CS/자료구조/Singly_Linked_List
- forensic
- Tree/RBTree/Insertion
- Tree/RBTree/Deletion
- CS/자료구조/Priority_Queue
- Tree/Binary_Search_Tree
- reversing
- codeengn
- Tree/AVL
- CS/자료구조/Stack
- Tree/BST
- CS/자료구조/Circular_Queue
- Tree/AVL/Deletion
- CS/자료구조/Queue
- 코드엔진
- ctf
- Tree/Traversal
- CS/자료구조/Circular_Linked_List
- tree
- Tree/AVL/Insertion
- 리버싱
- Tree/RBTree
- UTCTF
- CS/자료구조/Doubly_Linked_List
- Tree/Binary_Tree
- CS/자료구조/Linked_List
Archives
- Today
- Total
SuperVingo
3. CPU Implementation Code 본문
728x90
Initialize
void Chip8::Initialize()
{
// Random Initialize
srand(time(NULL));
// Reset the status of chip8
pc = 0x200;
opcode = 0;
I = 0;
sp = 0;
// Copy Hex Sprite to Interpreter Area
for (int i = 0; i < 80; i++)
mem[0x050 + i] = chip8_hex[i];
}
Cycle Code
void Chip8::ChipCycle()
{
// Fetch opcode from [pc], 2bytes
opcode = mem[pc] << 8 | mem[pc + 1];
// Decode & Execute
switch (opcode & 0xF000) {
case 0x0000:
{
switch (opcode & 0x000F) {
case 0x0000: // 0x00E0 - CLS
{
// Clear The Display
for (int i = 0; i < 64 * 32; i++)
gfx[i] = 0;
drawFlag = true;
pc += 2;
break;
}
case 0x000E: // 0x00EE - RET
{
// Return From Subroutine
sp--;
pc = stack[sp];
pc += 2;
break;
}
default: // Unknown
{
printf("0x%04X is Unknown Instruction.", opcode);
break;
}
}
break;
}
case 0x1000: // 0x1nnn - JP Addr
{
// Jump to Addr
pc = (opcode & 0x0FFF);
break;
}
case 0x2000: // 0x2nnn - CALL Addr
{
// Call to Addr
stack[sp] = pc;
sp++;
pc = (opcode & 0x0FFF);
break;
}
case 0x3000: // 0x3xkk - SE Vx, kk
{
// Skip Next Instruction if Vx == kk
if (V[(opcode & 0x0F00) >> 8] == (opcode & 0x00FF))
pc += 4;
else
pc += 2;
break;
}
case 0x4000: // 0x4xkk - SNE Vx, kk
{
// Skip Next Instruction if Vx != kk
if (V[(opcode & 0x0F00) >> 8] != (opcode & 0x00FF))
pc += 4;
else
pc += 2;
break;
}
case 0x5000: // 0x5xy0 - SE Vx, Vy
{
// Skip Next Instruction if Vx == Vy
if (V[(opcode & 0x0F00) >> 8] == V[(opcode & 0x00F0) >> 4])
pc += 4;
else
pc += 2;
break;
}
case 0x6000: // 0x6xkk - LD Vx, kk
{
// Vx = kk
V[(opcode & 0x0F00) >> 8] = (opcode & 0x00FF);
pc += 2;
break;
}
case 0x7000: // 0x7xkk - ADD Vx, kk
{
// Vx = Vx + kk
V[(opcode & 0x0F00) >> 8] += (opcode & 0x00FF);
pc += 2;
break;
}
case 0x8000:
{
switch (opcode & 0x000F) {
case 0x0000: // 0x8xy0 - LD Vx, Vy
{
// Vx = Vy
V[(opcode & 0x0F00) >> 8] = V[(opcode & 0x00F0) >> 4];
pc += 2;
break;
}
case 0x0001: // 0x8xy1 - OR Vx, Vy
{
// Vx = Vx | Vy
V[(opcode & 0x0F00) >> 8] |= V[(opcode & 0x00F0) >> 4];
pc += 2;
break;
}
case 0x0002: // 0x8xy2 - AND Vx, Vy
{
// Vx = Vx & Vy
V[(opcode & 0x0F00) >> 8] &= V[(opcode & 0x00F0) >> 4];
pc += 2;
break;
}
case 0x0003: // 0x8xy3 - XOR Vx, Vy
{
// Vx = Vx ^ Vy
V[(opcode & 0x0F00) >> 8] ^= V[(opcode & 0x00F0) >> 4];
pc += 2;
break;
}
case 0x0004: // 0x8xy4 - ADD Vx, Vy
{
// Vx = Vx + Vy, if carry, VF is set to 1. Otherwise 0.
if (V[(opcode & 0x0F00) >> 8] > (0xFF - V[(opcode & 0x00F0) >> 4]))
V[0xF] = 1;
else
V[0xF] = 0;
V[(opcode & 0x0F00) >> 8] += V[(opcode & 0x00F0) >> 4];
pc += 2;
break;
}
case 0x0005: // 0x8xy5 - SUB Vx, Vy
{
// Vx = Vx - Vy, if Vx > Vy, VF is set to 1. Otherwise 0.
if (V[(opcode & 0x00F0) >> 4] > V[(opcode & 0x0F00) >> 8])
V[0xF] = 0;
else
V[0xF] = 1;
V[(opcode & 0x0F00) >> 8] -= V[(opcode & 0x00F0) >> 4];
pc += 2;
break;
}
case 0x0006: // 0x8xy6 - SHR Vx
{
// Vx = Vx SHR 1, if LSB of Vx is set to 1, VF is set to 1. Otherwise 0.
V[0xF] = V[(opcode & 0x0F00) >> 8] & 0x1;
V[(opcode & 0x0F00) >> 8] >>= 1;
pc += 2;
break;
}
case 0x0007: // 0x8xy7 - SUBN Vx, Vy
{
// Vx = Vy - Vx, if Vy > Vx, VF is set to 1. Otherwise 0.
if (V[(opcode & 0x0F00) >> 8] > V[(opcode & 0x00F0) >> 4])
V[0xF] = 0;
else
V[0xF] = 1;
V[(opcode & 0x0F00) >> 8] = V[(opcode & 0x00F0) >> 4] - V[(opcode & 0x0F00) >> 8];
pc += 2;
break;
}
case 0x000E: // 0x8xyE - SHL Vx
{
// Vx = Vx SHL 1, if MSB of Vx is set to 1, VF is set to 1. Otherwise 0.
V[0xF] = V[(opcode & 0x0F00) >> 8] >> 7;
V[(opcode & 0x0F00) >> 8] <<= 1;
pc += 2;
break;
}
default: // Unknown Instruction
{
printf("0x%04X is Unknown Instruction.", opcode);
break;
}
}
break;
}
case 0x9000: // 0x9xy0 - SNE Vx, Vy
{
// Skip next instruction if Vx != Vy
if (V[(opcode & 0x0F00) >> 8] != V[(opcode & 0x00F0) >> 4])
pc += 4;
else
pc += 2;
break;
}
case 0xA000: // 0xAnnn - LD I, Addr
{
// I = Addr
I = (opcode & 0x0FFF);
pc += 2;
break;
}
case 0xB000: // 0xBnnn - JP V0, addr
{
// Jump to addr + v0
pc = (opcode & 0x0FFF) + V[0];
break;
}
case 0xC000: // 0xCxkk - RND Vx, kk
{
// Vx = Rnd AND kk
V[(opcode & 0x0F00) >> 8] = (rand() % 0xFF) & (opcode & 0x00FF);
pc += 2;
break;
}
case 0xD000: // 0xDxyn - DRW Vx, Vy, nibble
{
// Display n bytes sprite, starting at I, (Vx, Vy), set VF = Collision
unsigned char vx = V[(opcode & 0x0F00) >> 8];
unsigned char vy = V[(opcode & 0x00F0) >> 4];
unsigned char n = (opcode & 0x000F);
// Clear Collision
V[0xF] = 0;
for (int y = 0; y < n; y++)
{
unsigned char t = mem[I + y];
for (int x = 0; x < 0x8; x++)
{
if (t & (0x80 >> x)) {
//Collision Check
if (gfx[64 * (vy + y) + vx + x] == 1)
V[0xF] = 1;
gfx[64 * (vy + y) + vx + x] ^= 1;
}
}
}
drawFlag = true;
pc += 2;
break;
}
case 0xE000:
{
switch (opcode & 0x00FF) {
case 0x009E: // 0xEx9E - SKP Vx
{
// Skip Next Instruction if Vx == key
if (key[V[(opcode & 0x0F00) >> 8]] != 0)
pc += 4;
else
pc += 2;
break;
}
case 0x00A1: // 0xExA1 - SKNP Vx
{
// Skip Next Instruction if Vx != Key
if (key[V[(opcode & 0x0F00) >> 8]] == 0)
pc += 4;
else
pc += 2;
break;
}
default: // Unknown Instruction
{
printf("0x%04X is Unknown Instruction.", opcode);
break;
}
}
break;
}
case 0xF000:
{
switch (opcode & 0x00FF) {
case 0x0007: // 0xFx07 - LD Vx, DT
{
// Vx = Delay Timer
V[(opcode & 0x0F00) >> 8] = delay_timer;
pc += 2;
break;
}
case 0x000A: // 0xFx0A - LD Vx, K
{
// Waiting for key input, and store in Vx
bool flag = false;
for (int i = 0; i < 0x10; i++)
{
if (key[i] != 0)
{
V[(opcode ^ 0x0F00) >> 8] = i;
flag = true;
}
}
// if key was not pressed, try next cycle
if (!flag)
break;
pc += 2;
break;
}
case 0x0015: // 0xFx15 - LD DT, Vx
{
// Delay Timer = Vx
delay_timer = V[(opcode & 0x0F00) >> 8];
pc += 2;
break;
}
case 0x0018: // 0xFx18 - LD ST, Vx
{
// Sound Timer = Vx
sound_timer = V[(opcode & 0x0F00) >> 8];
pc += 2;
break;
}
case 0x001E: // 0xFx1E - ADD I, Vx
{
// I = I + Vx
if (I + V[(opcode & 0x0F00) >> 8] > 0xFFF)
V[0xF] = 1;
else
V[0xF] = 0;
I += V[(opcode & 0x0F00) >> 8];
pc += 2;
break;
}
case 0x0029: // 0xFx29 - LD, F, Vx
{
// I = The hex digit corresponding Vx
I = 0x50 + V[(opcode & 0x0F00) >> 8] * 5;
pc += 2;
break;
}
case 0x0033: // 0xFx33 - LD B, Vx
{
// [I, I+1, I+2] = Vx BCD
mem[I] = (V[(opcode & 0x0F00) >> 8]) / 100;
mem[I + 1] = ((V[(opcode & 0x0F00) >> 8]) % 100) / 10;
mem[I + 2] = (V[(opcode & 0x0F00) >> 8]) % 10;
pc += 2;
break;
}
case 0x0055: // 0xFx55 - LD [I], Vx
{
// I ~ I+0xF = V[0x0-0xF]
for (int i = 0; i <= ((opcode & 0x0F00) >> 8); i++)
mem[I + i] = V[i];
I += ((opcode & 0x0F00) >> 8) + 1;
pc += 2;
break;
}
case 0x0065: // 0xFx65 - LD Vx, [I]
{
// V[0x0-0xF] = I ~ I+0xF
for (int i = 0; i <= ((opcode & 0x0F00) >> 8); i++)
V[i] = mem[I + i];
I += ((opcode & 0x0F00) >> 8) + 1;
pc += 2;
break;
}
default: // Unknown Instruction
{
printf("0x%04X is Unknown Instruction.", opcode);
break;
}
}
break;
}
default: // Unreachable
{
printf("0x%04X is Unknown Instruction.", opcode);
break;
}
}
if (delay_timer > 0)
--delay_timer;
if (sound_timer > 0)
{
if (sound_timer == 1)
//printf("BEEP!\n");
--sound_timer;
}
}
728x90
'Emulator[에뮬레이터] > CHIP-8' 카테고리의 다른 글
4. Graphic 관련 - GLUT (0) | 2024.06.06 |
---|---|
2. CPU Specification (0) | 2024.06.04 |
1. 에뮬레이터 코드 흐름 (0) | 2024.06.03 |
0. CHIP-8 에뮬레이터 제작 (0) | 2024.06.02 |