diff --git a/SourceCodePro.ttf b/SourceCodePro.ttf new file mode 100644 index 0000000..4d66828 Binary files /dev/null and b/SourceCodePro.ttf differ diff --git a/gb/cartridge.go b/cartridge.go similarity index 98% rename from gb/cartridge.go rename to cartridge.go index 9676426..525d31d 100644 --- a/gb/cartridge.go +++ b/cartridge.go @@ -1,4 +1,4 @@ -package gb +package main import ( "bytes" @@ -282,11 +282,12 @@ func Insert(filename string) Cartridge { cartridge.SGBSupport = (header.SGBFlag == 0x03) cartridge.ROMSize = 32 * (1 << header.ROMSize) cartridge.RAMSize = ramSizes[header.RAMSize] - if header.DestinationCode == 0x00 { + switch header.DestinationCode { + case 0x00: cartridge.Destination = "Japan (and possibly overseas)" - } else if header.DestinationCode == 0x01 { + case 0x01: cartridge.Destination = "Overseas only" - } else { + default: cartridge.Destination = "UNKNOWN" } cartridge.Version = int(header.MaskROMVersionNumber) diff --git a/gb/cartridge_test.go b/cartridge_test.go similarity index 97% rename from gb/cartridge_test.go rename to cartridge_test.go index e0521a9..d4ef39a 100644 --- a/gb/cartridge_test.go +++ b/cartridge_test.go @@ -1,4 +1,4 @@ -package gb +package main import ( "testing" diff --git a/gb/cpu.go b/cpu.go similarity index 93% rename from gb/cpu.go rename to cpu.go index 7bd7637..f70fd35 100644 --- a/gb/cpu.go +++ b/cpu.go @@ -1,4 +1,4 @@ -package gb +package main type Cpu struct { A uint8 diff --git a/go.mod b/go.mod index 1d0f249..3d0f5cf 100644 --- a/go.mod +++ b/go.mod @@ -2,13 +2,11 @@ module gb-player go 1.24.5 -require ( - github.com/AllenDang/cimgui-go v1.3.1 - github.com/stretchr/testify v1.10.0 -) +require github.com/stretchr/testify v1.10.0 require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/veandco/go-sdl2 v0.4.40 gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 6c61551..85469e5 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,11 @@ -github.com/AllenDang/cimgui-go v1.3.1 h1:2f33a7GHJwRofH0CRQbUTXywazfph/K5LQLKyOBv24k= -github.com/AllenDang/cimgui-go v1.3.1/go.mod h1:Fuj3G2E3zd2bMQxmhuSPSFFl41MwS+MhyZ6DHgYq/YM= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/veandco/go-sdl2 v0.4.40 h1:fZv6wC3zz1Xt167P09gazawnpa0KY5LM7JAvKpX9d/U= +github.com/veandco/go-sdl2 v0.4.40/go.mod h1:OROqMhHD43nT4/i9crJukyVecjPNYYuCofep6SNiAjY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/main.go b/main.go index 22934f6..bdea31a 100644 --- a/main.go +++ b/main.go @@ -5,78 +5,123 @@ import ( "log" "runtime" - "gb-player/gb" - - "github.com/AllenDang/cimgui-go/backend" - "github.com/AllenDang/cimgui-go/backend/sdlbackend" - "github.com/AllenDang/cimgui-go/imgui" + "github.com/veandco/go-sdl2/sdl" + "github.com/veandco/go-sdl2/ttf" ) -var currentBackend backend.Backend[sdlbackend.SDLWindowFlags] +var renderer *sdl.Renderer +var font *ttf.Font func init() { runtime.LockOSThread() } -func showDebugWindow() { - imgui.Text(fmt.Sprintf("Framerate: %.1f FPS", imgui.CurrentIO().Framerate())) -} - -func showROMWindow(cartridge *gb.Cartridge) { - imgui.Begin("ROM") - - imgui.Text(fmt.Sprintf("Title: %s", cartridge.Title)) - imgui.Text(fmt.Sprintf("Mapper: %s", cartridge.Mapper)) - imgui.Text(fmt.Sprintf("Licensee: %s", cartridge.Licensee)) - if cartridge.SGBSupport { - imgui.Text("Super Game Boy support?: Yes") - } else { - imgui.Text("Super Game Boy support?: No") - } - imgui.Text(fmt.Sprintf("ROM size: %d bytes", cartridge.ROMSize)) - imgui.Text(fmt.Sprintf("RAM size: %s", cartridge.RAMSize)) - imgui.Text(fmt.Sprintf("Publication: %s", cartridge.Destination)) - imgui.Text(fmt.Sprintf("ROM version: %d", cartridge.Version)) - - imgui.End() -} - -func showCPUWindow(cpu *gb.Cpu) { - imgui.Begin("CPU") - - imgui.Text(fmt.Sprintf("PC: %d", cpu.PC)) - - imgui.End() -} - func main() { - currentBackend, err := backend.CreateBackend(sdlbackend.NewSDLBackend()) + if err := sdl.Init(sdl.INIT_EVERYTHING); err != nil { + log.Fatal(err) + } + defer sdl.Quit() + + if err := ttf.Init(); err != nil { + log.Fatal((err)) + } + defer ttf.Quit() + + window, err := sdl.CreateWindow( + "GB Player", + sdl.WINDOWPOS_UNDEFINED, + sdl.WINDOWPOS_UNDEFINED, + 800, 600, + sdl.WINDOW_SHOWN) + if err != nil { + panic(err) + } + defer window.Destroy() + + renderer, err = sdl.CreateRenderer(window, -1, 0) + if err != nil { + panic(err) + } + defer renderer.Destroy() + renderer.RenderSetVSync(true) + + font, err = ttf.OpenFont("SourceCodePro.ttf", 18) if err != nil { log.Fatal(err) } + defer font.Close() + font.SetStyle(ttf.STYLE_BOLD) - currentBackend.SetBgColor(imgui.NewVec4(0.45, 0.55, 0.6, 1.0)) + var fps float64 + var frameCount uint32 + var startTicks = sdl.GetTicks64() + var now uint64 + var last uint64 - currentBackend.CreateWindow("GB Player", 1200, 900) + cartridge := Insert("rom.gb") + fmt.Println(cartridge) - currentBackend.SetDropCallback(func(p []string) { - fmt.Printf("drop triggered: %v", p) - }) + running := true + for running { + for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() { + switch event.(type) { + case *sdl.QuitEvent: + println("Quit") + running = false + } + } - currentBackend.SetCloseCallback(func() { - fmt.Println("window is closing") - }) + last = now + now = sdl.GetPerformanceCounter() + deltaTime := float64((now - last) * 1000.0 / sdl.GetPerformanceFrequency()) + _ = deltaTime - cartridge := gb.Insert("rom.gb") - cpu := gb.Reset() + // Clear screen + renderer.SetDrawColor(0x63, 0x94, 0xED, 0xff) + renderer.Clear() - currentBackend.Run(func() { - imgui.ClearSizeCallbackPool() + // Update state + rect := sdl.Rect{X: 100, Y: 100, W: 200, H: 150} + renderer.SetDrawColor(0, 0, 255, 255) + renderer.FillRect(&rect) - gb.Tick(&cpu) + drawDebugWindow(fps) - showDebugWindow() - showROMWindow(&cartridge) - showCPUWindow(&cpu) - }) + // Present to screen + renderer.Present() + + // Calculate framerate + frameCount++ + currentTicks := sdl.GetTicks64() + elapsed := currentTicks - startTicks + + if elapsed >= 1000 { + fps = float64(frameCount) / (float64(elapsed) / 1000.0) + + // Reset counters + frameCount = 0 + startTicks = currentTicks + } + } +} + +func drawDebugWindow(fps float64) { + var textSurface *sdl.Surface + var textTexture *sdl.Texture + + // FPS + textSurface, err := font.RenderUTF8Blended(fmt.Sprintf("FPS: %.2f", fps), sdl.Color{R: 0, G: 0, B: 0, A: 255}) + if err != nil { + log.Fatal(err) + } + defer textSurface.Free() + + textTexture, err = renderer.CreateTextureFromSurface(textSurface) + if err != nil { + log.Fatal(err) + } + defer textTexture.Destroy() + + textRect := sdl.Rect{X: 0, Y: 0, W: textSurface.W, H: textSurface.H} + renderer.Copy(textTexture, nil, &textRect) }