|
|
@ -3,6 +3,7 @@ package main |
|
|
|
import ( |
|
|
|
"flag" |
|
|
|
"fmt" |
|
|
|
"io/ioutil" |
|
|
|
) |
|
|
|
|
|
|
|
type chip8 struct { |
|
|
@ -67,6 +68,85 @@ func (c *chip8) emulateCycle() { |
|
|
|
c.v[pos] = byte(c.opcode) |
|
|
|
c.pc += 2 |
|
|
|
break |
|
|
|
case 0x7000: |
|
|
|
c.v[c.opcode&0x0F00>>8] += byte(c.opcode) |
|
|
|
c.pc += 2 |
|
|
|
break |
|
|
|
case 0x8000: |
|
|
|
switch c.opcode & 0x000F { |
|
|
|
case 0x0004: // 0x8XY4
|
|
|
|
if c.v[(c.opcode&0x00F0)>>4] > (0xFF - c.v[c.opcode&0x0F00]) { |
|
|
|
c.v[0xF] = 1 |
|
|
|
} else { |
|
|
|
c.v[0xF] = 0 |
|
|
|
} |
|
|
|
c.v[(c.opcode&0x0F00)>>8] += c.v[(c.opcode&0x00F0)>>4] |
|
|
|
c.pc += 2 |
|
|
|
break |
|
|
|
default: |
|
|
|
fmt.Printf("Unknown opcode [0x8000]: 0x%X\n", c.opcode) |
|
|
|
} |
|
|
|
case 0xA000: |
|
|
|
// set index to NNN position
|
|
|
|
c.index = c.opcode & 0x0FFF |
|
|
|
c.pc += 2 |
|
|
|
break |
|
|
|
case 0xD000: |
|
|
|
x := uint16(c.v[(c.opcode&0x0F00)>>8]) |
|
|
|
y := uint16(c.v[(c.opcode&0x00F0)>>4]) |
|
|
|
height := c.opcode & 0x000F |
|
|
|
|
|
|
|
var pixel byte |
|
|
|
c.v[0xF] = 0 |
|
|
|
for yline := uint16(0); yline < height; yline++ { |
|
|
|
pixel = c.memory[c.index+yline] |
|
|
|
for xline := uint16(0); xline < 8; xline++ { |
|
|
|
if (pixel & (0x80 >> xline)) != 0 { |
|
|
|
if c.gfx[(x+xline+((y+yline)*64))] == 1 { |
|
|
|
c.v[0xF] = 1 |
|
|
|
} |
|
|
|
c.gfx[x+xline+((y+yline)*64)] ^= 1 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
c.drawFlag = true |
|
|
|
c.pc += 2 |
|
|
|
break |
|
|
|
case 0xE000: |
|
|
|
switch c.opcode & 0x00FF { |
|
|
|
case 0x009E: |
|
|
|
if c.key[c.v[(c.opcode&0x0F00)>>8]] != 0 { |
|
|
|
c.pc += 4 |
|
|
|
} else { |
|
|
|
c.pc += 2 |
|
|
|
} |
|
|
|
break |
|
|
|
} |
|
|
|
break |
|
|
|
case 0xF000: |
|
|
|
x := (c.opcode & 0x0F00) >> 8 |
|
|
|
fmt.Printf("F: 0x%X\n", c.opcode) |
|
|
|
switch c.opcode & 0x00FF { |
|
|
|
case 0x0029: |
|
|
|
// TODO
|
|
|
|
// c.index = uint16(c.v[x]) *
|
|
|
|
c.pc += 2 |
|
|
|
break |
|
|
|
case 0x0033: |
|
|
|
c.memory[c.index] = c.v[x] / 100 |
|
|
|
c.memory[c.index+1] = (c.v[x] / 10) % 10 |
|
|
|
c.memory[c.index+2] = (c.v[x] / 100) % 10 |
|
|
|
c.pc += 2 |
|
|
|
break |
|
|
|
case 0x0065: |
|
|
|
for i := uint16(0); i < x+1; i++ { |
|
|
|
c.v[i] = c.memory[c.index+i] |
|
|
|
} |
|
|
|
c.pc += 2 |
|
|
|
break |
|
|
|
} |
|
|
|
break |
|
|
|
default: |
|
|
|
fmt.Printf("Unknown opcode: 0x%X\n", c.opcode) |
|
|
|
} |
|
|
@ -84,9 +164,37 @@ func (c *chip8) emulateCycle() { |
|
|
|
} |
|
|
|
|
|
|
|
func (c *chip8) loadGame(filepath string) error { |
|
|
|
buffer, err := ioutil.ReadFile(filepath) |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
} |
|
|
|
|
|
|
|
for i := 0; i < len(buffer); i++ { |
|
|
|
// 0x200 == 512
|
|
|
|
c.memory[512+i] = buffer[i] |
|
|
|
} |
|
|
|
return nil |
|
|
|
} |
|
|
|
|
|
|
|
var fontSet = [80]byte{ |
|
|
|
0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
|
|
|
|
0x20, 0x60, 0x20, 0x20, 0x70, // 1
|
|
|
|
0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
|
|
|
|
0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
|
|
|
|
0x90, 0x90, 0xF0, 0x10, 0x10, // 4
|
|
|
|
0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
|
|
|
|
0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
|
|
|
|
0xF0, 0x10, 0x20, 0x40, 0x40, // 7
|
|
|
|
0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
|
|
|
|
0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
|
|
|
|
0xF0, 0x90, 0xF0, 0x90, 0x90, // A
|
|
|
|
0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
|
|
|
|
0xF0, 0x80, 0x80, 0x80, 0xF0, // C
|
|
|
|
0xE0, 0x90, 0x90, 0x90, 0xE0, // D
|
|
|
|
0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
|
|
|
|
0xF0, 0x80, 0xF0, 0x80, 0x80, // F
|
|
|
|
} |
|
|
|
|
|
|
|
func (c *chip8) drawGraphics() { |
|
|
|
|
|
|
|
} |
|
|
|