// Copyright 2021-2024 Sebastian Lederer. See the file LICENSE.md for details package main import ( // "fmt" "image/color" "github.com/hajimehoshi/ebiten/v2" ) const VmemWords = 32768 const PaletteSlots = 16 const FB_RA = 0 const FB_WA = 1 const FB_IO = 2 const FB_PS = 3 const FB_PD = 4 const FB_CTL= 5 const PixelMask = 0b11110000000000000000000000000000 const PixelPerWord = 8 const VmemWidth = 32 const BitsPerPixel = 4 const ScreenWidth = 640 const ScreenHeight = 400 const WordsPerLine = ScreenWidth / PixelPerWord type Framebuffer struct { framebuffer *ebiten.Image palette [PaletteSlots] color.Color readAddr word writeAddr word paletteSlot word vmem [VmemWords]word readCount int } func (f *Framebuffer) initialize() { f.framebuffer = ebiten.NewImage(ScreenWidth, ScreenHeight) for i := 0; i > (VmemWidth - BitsPerPixel) value = value << BitsPerPixel col := f.palette[pixel] //fmt.Printf("set pixel %v, %v\n", x,y) f.framebuffer.Set(int(x), int(y), col) x = x + 1 } f.writeAddr += 1 } func (f *Framebuffer) readPalette() word { return word(0) } func (f *Framebuffer) writePalette(value word) { // 4 bits per color channel r := uint8((value & 0b111100000000) >> 8) g := uint8((value & 0b000011110000) >> 4) b := uint8((value & 0b000000001111) >> 0) // scale to 0-255 r = r << 4 g = g << 4 b = b << 4 f.palette[f.paletteSlot] = color.RGBA{r,g,b,0} } func (f *Framebuffer) readCtl() word { if f.readCount == 0 { f.readCount = 1000 return word(0) } else { f.readCount -= 1 return word(1) } } func (f *Framebuffer) writeCtl(value word) { }