@@ 0,0 1,99 @@
+package main
+
+var reservedMem []byte = []byte{
+ 0b11110000,
+ 0b10010000,
+ 0b10010000,
+ 0b10010000,
+ 0b11110000,
+
+ 0b00100000,
+ 0b01100000,
+ 0b00100000,
+ 0b00100000,
+ 0b01110000,
+
+ 0b11110000,
+ 0b00010000,
+ 0b11110000,
+ 0b10000000,
+ 0b11110000,
+
+ 0b11110000,
+ 0b00010000,
+ 0b11110000,
+ 0b00010000,
+ 0b11110000,
+
+ 0b10010000,
+ 0b10010000,
+ 0b11110000,
+ 0b00010000,
+ 0b00010000,
+
+ 0b11110000,
+ 0b10000000,
+ 0b11110000,
+ 0b00010000,
+ 0b11110000,
+
+ 0b11110000,
+ 0b10000000,
+ 0b11110000,
+ 0b10010000,
+ 0b11110000,
+
+ 0b11110000,
+ 0b00010000,
+ 0b00100000,
+ 0b01000000,
+ 0b01000000,
+
+ 0b11110000,
+ 0b10010000,
+ 0b11110000,
+ 0b10010000,
+ 0b11110000,
+
+ 0b11110000,
+ 0b10010000,
+ 0b11110000,
+ 0b00010000,
+ 0b11110000,
+
+ 0b11110000,
+ 0b10010000,
+ 0b11110000,
+ 0b10010000,
+ 0b10010000,
+
+ 0b11100000,
+ 0b10010000,
+ 0b11100000,
+ 0b10010000,
+ 0b11100000,
+
+ 0b11110000,
+ 0b10000000,
+ 0b10000000,
+ 0b10000000,
+ 0b11110000,
+
+ 0b11100000,
+ 0b10010000,
+ 0b10010000,
+ 0b10010000,
+ 0b11100000,
+
+ 0b11110000,
+ 0b10000000,
+ 0b11110000,
+ 0b10000000,
+ 0b11110000,
+
+ 0b11110000,
+ 0b10000000,
+ 0b11110000,
+ 0b10000000,
+ 0b10000000,
+}
@@ 1,9 1,8 @@
package main
import (
- "fmt"
+ "encoding/binary"
"math"
- "time"
"github.com/faiface/pixel"
"github.com/faiface/pixel/pixelgl"
@@ 24,10 23,19 @@ type Chip8 struct {
st byte
pc uint16
sp byte
+
+ display *Display
+}
+
+func (c *Chip8) initMem() {
+ copy(c.mem[:], reservedMem)
}
func (c *Chip8) LoadRom(rom []byte) error {
+ c.initMem()
copy(c.mem[romStart:], rom)
+
+ c.pc = romStart
return nil
}
@@ 39,13 47,7 @@ func run() {
VSync: true,
}
- d.buffer[0] = 1
- d.buffer[2] = 1
-
- d.buffer[64] = 1
- d.buffer[64+4] = 1
-
- d.buffer[31*64] = 1
+ VM.display = d
win, err := pixelgl.NewWindow(cfg)
if err != nil {
@@ 55,26 57,79 @@ func run() {
win.Clear(colornames.Black)
go func() {
- i := 10
- ticker := time.NewTicker(time.Second)
- for {
- select {
- case <-ticker.C:
- d.buffer[i] = 1
- i += 2
- fmt.Println(i)
+ /*
+ i := 10
+ ticker := time.NewTicker(time.Second)
+ for {
+ select {
+ case <-ticker.C:
+ d.buffer[i] = 1
+ i += 2
+ fmt.Println(i)
+ }
}
+ */
+ for {
+ VM.fetchExecute()
}
}()
for !win.Closed() {
+ if d.clear {
+ win.Clear(colornames.Black)
+ d.clear = false
+ }
+
sprite := pixel.NewSprite(d, d.Bounds())
sprite.Draw(win, pixel.IM.Moved(win.Bounds().Center()))
+
+ // JustPressed, JustReleased
+ if win.Pressed(pixelgl.KeyQ) {
+ //
+ }
win.Update()
}
}
-func (c *Chip8) Run() {
+func (c *Chip8) fetchExecute() {
+ cmd := binary.BigEndian.Uint16(c.mem[c.pc : c.pc+2])
+
+ nextPc := c.pc + 2
+ switch {
+ case cmd>>12 == 0x1:
+ nextPc = cmd & 0x0FFF
+ case cmd>>12 == 0x6:
+ reg := (cmd & 0x0F00) >> 8
+ c.v[reg] = byte(cmd & 0x00FF)
+ case cmd>>12 == 0xA:
+ c.i = cmd & 0x0FFF
+ case cmd>>12 == 0xD:
+ vx := byte((cmd & 0x0F00) >> 8)
+ vy := byte((cmd & 0x00F0) >> 4)
+ n := byte((cmd & 0x000F) >> 0)
+ c.drawSprite(c.v[vx], c.v[vy], n)
+ }
+
+ c.pc = nextPc
+}
+
+func (c *Chip8) drawSprite(x, y, n byte) {
+ for dy := byte(0); dy < n; dy++ {
+ row := c.mem[c.i+uint16(dy)]
+
+ for dx := byte(0); dx < 8; dx++ {
+ pixel := (row >> (7 - dx)) & 0x1
+ erased := c.display.Put(x+dx, y+dy, pixel)
+ if erased != 0 {
+ c.v[0xF] = 1
+ }
+ }
+ }
+}
+
+var VM *Chip8 = &Chip8{}
+
+func Run() {
pixelgl.Run(run)
}
@@ 82,7 137,8 @@ type Display struct {
bounds pixel.Rect
xm, ym float64
buffer []byte
- modeX, modeY int
+ modeX, modeY byte
+ clear bool
}
func NewDisplay(w, h float64) *Display {
@@ 93,9 149,10 @@ func NewDisplay(w, h float64) *Display {
bounds: pixel.R(0, 0, w, h),
xm: w / float64(modeX),
ym: h / float64(modeY),
- modeX: modeX,
- modeY: modeY,
+ modeX: byte(modeX),
+ modeY: byte(modeY),
buffer: make([]byte, modeX*modeY),
+ clear: true,
}
}
@@ 107,12 164,29 @@ func (d Display) Color(at pixel.Vec) pixel.RGBA {
x := int(math.Floor(at.X / d.xm))
y := int(math.Floor(at.Y / d.ym))
- y = d.modeY - y - 1
+ y = int(d.modeY) - y - 1
- idx := y*d.modeX + x
+ idx := y*int(d.modeX) + x
set := d.buffer[idx]
if set == 1 {
return pixel.RGB(1, 1, 1)
}
return pixel.RGB(255, 255, 255)
}
+
+func (d *Display) Put(x, y, v byte) (erased byte) {
+ x = x % d.modeX
+ y = y % d.modeY
+
+ idx := int(y)*int(d.modeX) + int(x)
+
+ if d.buffer[idx] == v {
+ erased = 1
+ }
+ d.buffer[idx] = d.buffer[idx] ^ v
+ return
+}
+
+func (d *Display) Clear() {
+ d.clear = true
+}