From af7bce11d0a7d7f6171e465e1dcd238aa910e2df Mon Sep 17 00:00:00 2001 From: Jairinho Date: Wed, 23 Feb 2022 18:28:48 -0300 Subject: [PATCH] more and more instructions --- chip8/chip8.go | 18 +++++++++-- chip8/instructions.go | 75 ++++++++++++++++++++++++++++++++++++++----- 2 files changed, 83 insertions(+), 10 deletions(-) diff --git a/chip8/chip8.go b/chip8/chip8.go index 14a1488..37ee8d7 100644 --- a/chip8/chip8.go +++ b/chip8/chip8.go @@ -47,7 +47,9 @@ func (emulator *Emulator) Reset() { copy(emulator.Memory[ProgramAddress:], emulator.ROM) } -func (emulator *Emulator) Step() { +func (emulator *Emulator) Cycle() { + pc := emulator.PC + emulator.Timer.Delay = uint8(math.Max(0, float64(emulator.Timer.Delay)-1)) emulator.Timer.Sound = uint8(math.Max(0, float64(emulator.Timer.Sound)-1)) @@ -73,19 +75,26 @@ func (emulator *Emulator) Step() { case 0x6: // 6xkk - LD Vx, byte emulator.LoadByte(x, kk) case 0x7: // 7xkk - ADD Vx, byte - emulator.Add(x, kk) + emulator.AddByte(x, kk) case 0x8: switch instruction & 0x000F { case 0x0: // 8xy0 - LD Vx, Vy emulator.LoadRegister(x, y) case 0x1: // 8xy1 - OR Vx, Vy + emulator.Or(x, y) case 0x2: // 8xy2 - AND Vx, Vy + emulator.And(x, y) case 0x3: // 8xy3 - XOR Vx, Vy + emulator.Xor(x, y) case 0x4: // 8xy4 - ADD Vx, Vy + emulator.AddRegisters(x, y) case 0x5: // 8xy5 - SUB Vx, Vy + emulator.Sub(x, y) case 0x6: // 8xy6 - SHR Vx {, Vy} + emulator.ShiftRight(x) case 0x7: // 8xy7 - SUBN Vx, Vy case 0xE: // 8xyE - SHL Vx {, Vy} + emulator.ShiftLeft(x) } case 0x9: // 9xy0 - SNE Vx, Vy case 0xA: // Annn - LD I, addr @@ -110,4 +119,9 @@ func (emulator *Emulator) Step() { case 0x65: // LD Vx, [I] } } + + // if the program counter is unchanged and isn't a loop, read next instruction + if emulator.PC == pc && nnn != pc { + emulator.PC += InstructionSize + } } diff --git a/chip8/instructions.go b/chip8/instructions.go index c567801..a58b174 100644 --- a/chip8/instructions.go +++ b/chip8/instructions.go @@ -2,7 +2,6 @@ package chip8 func (emulator *Emulator) ClearScreen() { // TODO: clear the screen buffer - emulator.PC += InstructionSize } func (emulator *Emulator) Return() { @@ -31,8 +30,6 @@ func (emulator *Emulator) Call(nnn uint16) { // increments the program counter by 2. func (emulator *Emulator) SkipEqual(x uint8, kk uint8) { if emulator.V[x] == kk { - emulator.PC += InstructionSize * 2 - } else { emulator.PC += InstructionSize } } @@ -43,8 +40,6 @@ func (emulator *Emulator) SkipEqual(x uint8, kk uint8) { // increments the program counter by 2. func (emulator *Emulator) SkipNotEqual(x uint8, kk uint8) { if emulator.V[x] != kk { - emulator.PC += InstructionSize * 2 - } else { emulator.PC += InstructionSize } } @@ -55,8 +50,6 @@ func (emulator *Emulator) SkipNotEqual(x uint8, kk uint8) { // increments the program counter by 2. func (emulator *Emulator) SkipRegistersEqual(x uint8, y uint8) { if emulator.V[x] == emulator.V[y] { - emulator.PC += InstructionSize * 2 - } else { emulator.PC += InstructionSize } } @@ -71,7 +64,7 @@ func (emulator *Emulator) LoadByte(x uint8, kk uint8) { // Set Vx = Vx + kk. // // Adds the value kk to the value of register Vx, then stores the result in Vx. -func (emulator *Emulator) Add(x uint8, kk uint8) { +func (emulator *Emulator) AddByte(x uint8, kk uint8) { emulator.V[x] += kk } @@ -81,3 +74,69 @@ func (emulator *Emulator) Add(x uint8, kk uint8) { func (emulator *Emulator) LoadRegister(x uint8, y uint8) { emulator.V[x] = emulator.V[y] } + +// Set Vx = Vx OR Vy. +// +// Performs a bitwise OR on the values of Vx and Vy, then stores the result in Vx. +// A bitwise OR compares the corrseponding bits from two values, and if either bit is 1, +// then the same bit in the result is also 1. Otherwise, it is 0. +func (emulator *Emulator) Or(x uint8, y uint8) { + emulator.V[x] |= emulator.V[y] +} + +// Set Vx = Vx AND Vy. +// +// Performs a bitwise AND on the values of Vx and Vy, then stores the result in Vx. +// A bitwise AND compares the corrseponding bits from two values, and if both bits are 1, +// then the same bit in the result is also 1. Otherwise, it is 0. +func (emulator *Emulator) And(x uint8, y uint8) { + emulator.V[x] &= emulator.V[y] +} + +// Set Vx = Vx XOR Vy. +// +// Performs a bitwise exclusive OR on the values of Vx and Vy, then stores the result in Vx. +// An exclusive OR compares the corrseponding bits from two values, and if the bits are not +// both the same, then the corresponding bit in the result is set to 1. Otherwise, it is 0. +func (emulator *Emulator) Xor(x uint8, y uint8) { + emulator.V[x] ^= emulator.V[y] +} + +// Set Vx = Vx + Vy, set VF = carry. +// +// The values of Vx and Vy are added together. +// If the result is greater than 8 bits (i.e., > 255,) VF is set to 1, +// otherwise 0. Only the lowest 8 bits of the result are kept, and stored in Vx. +func (emulator *Emulator) AddRegisters(x uint8, y uint8) { + sum := uint16(emulator.V[x]) + uint16(emulator.V[y]) + emulator.V[x] = uint8(sum) + emulator.V[0xF] = uint8(sum >> 8) +} + +// SUB Vx, Vy +// Set Vx = Vx - Vy, set VF = NOT borrow. +// +// If Vx > Vy, then VF is set to 1, otherwise 0. +// Then Vy is subtracted from Vx, and the results stored in Vx. +func (emulator *Emulator) Sub(x uint8, y uint8) { + emulator.V[0xF] = map[bool]uint8{true: 1, false: 0}[emulator.V[x] > emulator.V[y]] + emulator.V[x] -= emulator.V[y] +} + +// Set Vx = Vx SHR 1. +// +// If the least-significant bit of Vx is 1, then VF is set to 1, otherwise 0. +// Then Vx is divided by 2. +func (emulator *Emulator) ShiftRight(x uint8) { + emulator.V[0xF] = emulator.V[x] & 0b00000001 + emulator.V[x] >>= 1 +} + +// Set Vx = Vx SHL 1. +// +// If the most-significant bit of Vx is 1, then VF is set to 1, otherwise to 0. +// Then Vx is multiplied by 2. +func (emulator *Emulator) ShiftLeft(x uint8) { + emulator.V[0xF] = emulator.V[x] & 0b10000000 + emulator.V[x] <<= 1 +}