Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package main
- // Binary apgbpal creates a 56-byte file named "test.pal" in the current working
- // directory. I hope it might be an Analogue Pocket GB Palette file, but I don't
- // know that for sure yet.
- // apgbpal is licensed under 0BSD.
- //
- // Zero-Clause BSD
- // =============
- //
- // Permission to use, copy, modify, and/or distribute this software for
- // any purpose with or without fee is hereby granted.
- //
- // THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL
- // WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
- // OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE
- // FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
- // DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
- // AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
- // OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- import (
- "fmt"
- "log"
- "os"
- "strconv"
- "strings"
- )
- type RGBA struct {
- R byte
- G byte
- B byte
- A byte
- }
- func (c RGBA) Bytes() [4]byte {
- return [4]byte{c.R, c.G, c.B, c.A}
- }
- func HexByteAt(str string, index int) (byte, error) {
- if len(str) < index+2 {
- return 0, fmt.Errorf("no hex byte at %d in too short string %q", index, str)
- }
- big, err := strconv.ParseUint(str[index:index+1], 16, 8)
- if err != nil {
- return 0, fmt.Errorf("can't parse hex byte at %d in string %q: %w", index, str, err)
- }
- return byte(big), nil
- }
- func ParseRGBA(str string) (RGBA, error) {
- s := strings.TrimSpace(str)
- s = strings.ToLower(s)
- s, _ = strings.CutPrefix(s, "#")
- var ret RGBA
- switch len(s) {
- case 6:
- ret.A = 0xFF
- case 8:
- var err error
- ret.A, err = HexByteAt(s, 6)
- if err != nil {
- return RGBA{}, fmt.Errorf("can't parse alpha channel: %v", err)
- }
- default:
- return RGBA{}, fmt.Errorf("%q is not an RGBA value: wrong length after trimming", str)
- }
- var err error
- if ret.R, err = HexByteAt(s, 0); err != nil {
- return RGBA{}, fmt.Errorf("can't parse red channel: %v", err)
- }
- if ret.G, err = HexByteAt(s, 2); err != nil {
- return RGBA{}, fmt.Errorf("can't parse green channel: %v", err)
- }
- if ret.B, err = HexByteAt(s, 4); err != nil {
- return RGBA{}, fmt.Errorf("can't parse blue channel: %v", err)
- }
- return ret, nil
- }
- type BGPal [4]RGBA
- func (b BGPal) Bytes() [20]byte {
- var ret [20]byte
- ret[0] = 'b'
- ret[1] = 'g'
- ret[2] = ':'
- for c := 0; c < 4; c++ {
- bb := b[c].Bytes()
- for i := 0; i < 4; i++ {
- ret[3+i+4*c] = bb[i]
- }
- }
- ret[19] = '\n'
- return ret
- }
- func MustParseBGPal(strs []string) BGPal {
- if len(strs) != 4 {
- log.Fatalf("MustParseBGPal requires length 4, got %d", len(strs))
- }
- var ret BGPal
- for i := 0; i < 4; i++ {
- var err error
- ret[i], err = ParseRGBA(strs[i])
- if err != nil {
- log.Fatalf("MustParseBGPal can't parse at %d: %v", i, err)
- }
- }
- return ret
- }
- type OBJPal [3]RGBA
- func (o OBJPal) Bytes(indexchar byte) [18]byte {
- var ret [18]byte
- ret[0] = 'o'
- ret[1] = 'b'
- ret[2] = 'j'
- ret[3] = indexchar
- ret[4] = ':'
- for c := 0; c < 3; c++ {
- oo := o[c].Bytes()
- for i := 0; i < 4; i++ {
- ret[5+i+4*c] = oo[i]
- }
- }
- ret[17] = '\n'
- return ret
- }
- func MustParseOBJPal(strs []string) OBJPal {
- if len(strs) == 4 {
- log.Println("Discarding index 0 of OBJ pal")
- strs = strs[1:]
- }
- if len(strs) != 3 {
- log.Fatalf("MustParseObjPal requires length 3, got %d", len(strs))
- }
- var ret OBJPal
- for i := 0; i < 3; i++ {
- var err error
- ret[i], err = ParseRGBA(strs[i])
- if err != nil {
- log.Fatalf("MustParseOBJPal can't parse at %d: %v", i, err)
- }
- }
- return ret
- }
- type APGBPal struct {
- BG BGPal
- OBJ0 OBJPal
- OBJ1 OBJPal
- }
- func (a APGBPal) Bytes() [56]byte {
- var ret [56]byte
- for i, b := range a.BG.Bytes() {
- ret[i] = b
- }
- for i, b := range a.OBJ0.Bytes('0') {
- ret[i+20] = b
- }
- for i, b := range a.OBJ1.Bytes('1') {
- ret[i+38] = b
- }
- return ret
- }
- func main() {
- f, err := os.OpenFile(
- "test.pal",
- os.O_WRONLY|os.O_CREATE|os.O_EXCL,
- 0644)
- if err != nil {
- log.Fatalf("can't create test.pal: %v", err)
- }
- aUpPal := APGBPal{
- BG: MustParseBGPal([]string{"ffffff", "ff8484", "943a3a", "000000"}),
- OBJ0: MustParseOBJPal([]string{"7bff31", "008400", "000000"}),
- OBJ1: MustParseOBJPal([]string{"63a5ff", "0000ff", "000000"}),
- }
- palb := aUpPal.Bytes()
- n, err := f.Write(palb[:])
- if err != nil {
- log.Fatalf("can't save test.pal: %v", err)
- }
- if n != 56 {
- log.Fatalf("unexpected write length: %d", n)
- }
- f.Close()
- os.Exit(0)
- }
Advertisement