n64tutorial/main.go
2025-12-01 11:49:02 +01:00

106 lines
2.4 KiB
Go

package main
import (
"embed"
"fmt"
"image"
"image/color"
"io"
"github.com/clktmr/n64/drivers/cartfs"
"github.com/clktmr/n64/drivers/controller"
"github.com/clktmr/n64/drivers/display"
"github.com/clktmr/n64/drivers/draw"
"github.com/clktmr/n64/drivers/rspq/mixer"
"github.com/clktmr/n64/fonts/gomono12"
_ "github.com/clktmr/n64/machine"
"github.com/clktmr/n64/rcp/audio"
"github.com/clktmr/n64/rcp/serial/joybus"
"github.com/clktmr/n64/rcp/texture"
"github.com/clktmr/n64/rcp/video"
)
var (
//go:embed gopher-anim.CI8 squeak.pcm_s16be
_tutorialFiles embed.FS
tutorialFiles cartfs.FS = cartfs.Embed(_tutorialFiles)
)
var face = gomono12.NewFace()
var background = &image.Uniform{color.RGBA{0x7f, 0x7f, 0xaf, 0x0}}
func main() {
// Enable video output
video.Setup(false)
// Allocate framebuffer
display := display.NewDisplay(image.Pt(320, 240), video.BPP16)
controllers := make(chan [4]controller.Controller)
go func() {
var states [4]controller.Controller
for {
controller.Poll(&states)
controllers <- states
}
}()
gopherFile, err := tutorialFiles.Open("gopher-anim.CI8")
if err != nil {
panic(err)
}
gopherTexture, err := texture.Load(gopherFile)
if err != nil {
panic(err)
}
gopherRect := image.Rect(0, 0, 128, 128)
blows := 0
audio.Start(48000)
mixer.Init()
go func() {
audio.Buffer.ReadFrom(mixer.Output)
}()
squeakFile, err := tutorialFiles.Open("squeak.pcm_s16be")
if err != nil {
panic(err)
}
squeakReader := squeakFile.(io.ReadSeeker)
squeakSource := mixer.NewSource(squeakReader, 16000)
for {
fb := display.Swap() // Blocks until next VBlank
input := <-controllers
textarea := fb.Bounds().Inset(15)
pt := textarea.Min.Add(image.Pt(0, int(face.Ascent)))
draw.Src.Draw(fb, fb.Bounds(), background, fb.Bounds().Min)
text := fmt.Appendln(nil, "N⁶⁴ - Get N or Get Out ♫")
text = fmt.Appendln(text, input[0].Down())
text = fmt.Appendf(text, "blows: %v/8\n", blows)
pt = draw.DrawText(fb, textarea, face, pt, image.Black, nil, text)
gopherFrame := image.Point{}
if blows < 8 {
if input[0].Pressed()&joybus.ButtonA != 0 {
blows++
squeakReader.Seek(0, io.SeekStart)
mixer.SetSource(0, squeakSource)
}
if input[0].Down()&joybus.ButtonA != 0 {
gopherFrame.X += 128 // blowing gopher
}
} else {
gopherFrame.X += 256 // happy gopher
}
draw.Over.Draw(fb, gopherRect.Add(pt), gopherTexture, gopherFrame)
draw.Flush() // Blocks until everything is drawn
}
}