internal/gamepaddb: generate respective controller dbs for each platform

Replace singular embedded controller database file with separate generated
files for each supported platform. The controller database file is some
~500KB, so this change should reduce the overall binary size per
platform.
This commit is contained in:
Kenny Goodin 2024-03-26 12:07:23 -04:00
parent dc77c655af
commit 5fd91e2750
8 changed files with 335 additions and 49 deletions

View File

@ -1,49 +0,0 @@
// Copyright 2024 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !js && !microsoftgdk && !nintendosdk && !playstation5
package gamepaddb
import (
_ "embed"
)
// gamecontrollerdb.txt is downloaded at https://github.com/mdqinc/SDL_GameControllerDB.
// To update the database file, run:
//
// curl --location --remote-name https://raw.githubusercontent.com/mdqinc/SDL_GameControllerDB/master/gamecontrollerdb.txt
//go:embed gamecontrollerdb.txt
var gamecontrollerdb_txt []byte
var additionalGLFWGamepads = []byte(`
78696e70757401000000000000000000,XInput Gamepad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,
78696e70757402000000000000000000,XInput Wheel (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,
78696e70757403000000000000000000,XInput Arcade Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,
78696e70757404000000000000000000,XInput Flight Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,
78696e70757405000000000000000000,XInput Dance Pad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,
78696e70757406000000000000000000,XInput Guitar (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,
78696e70757408000000000000000000,XInput Drum Kit (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,
`)
func init() {
if err := Update(gamecontrollerdb_txt); err != nil {
panic(err)
}
if err := Update(additionalGLFWGamepads); err != nil {
panic(err)
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,23 @@
{{.License}}
{{.DoNotEdit}}
{{.BuildTag}}
package gamepaddb
func init() {
if err := Update(controllerBytes); err != nil {
panic(err)
}
{{if eq .SDLPlatform "Windows" }}
if err := Update(glfwControllerBytes); err != nil {
panic(err)
}
{{end}}}
var controllerBytes = []byte{ {{ range $index, $element := .ControllerBytes }}{{ if $index }},{{ end }}{{ $element }}{{ end }} }
{{if eq .SDLPlatform "Windows" }}
var glfwControllerBytes = []byte{ {{ range $index, $element := .GLFWGamePads }}{{ if $index }},{{ end }}{{ $element }}{{ end }} }
{{end}}

View File

@ -0,0 +1,161 @@
// Copyright 2024 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build ignore
// This program generates platform-specific controller dbs. It can be invoked by running
// go generate
package main
import (
"bytes"
_ "embed"
"fmt"
"log"
"os"
"path/filepath"
"strings"
"text/template"
)
const license = `// Copyright 2024 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
`
// gamecontrollerdb.txt is downloaded at https://github.com/mdqinc/SDL_GameControllerDB.
// To update the database file, run:
//
// curl --location --remote-name https://raw.githubusercontent.com/mdqinc/SDL_GameControllerDB/master/gamecontrollerdb.txt
//go:embed gamecontrollerdb.txt
var gamecontrollerdb_txt []byte
// additional GLFW gamepads for Windows
var additionalGLFWGamepads = []byte(`
78696e70757401000000000000000000,XInput Gamepad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,
78696e70757402000000000000000000,XInput Wheel (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,
78696e70757403000000000000000000,XInput Arcade Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,
78696e70757404000000000000000000,XInput Flight Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,
78696e70757405000000000000000000,XInput Dance Pad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,
78696e70757406000000000000000000,XInput Guitar (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,
78696e70757408000000000000000000,XInput Drum Kit (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,
`)
//go:generate go run gen_dbs.go
func main() {
// Follow the standard comment rule (https://pkg.go.dev/cmd/go#hdr-Generate_Go_files_by_processing_source).
doNotEdit := "// Code generated by gen_dbs.go using 'go generate'. DO NOT EDIT."
type gamePadPlatform struct {
genFileName string
buildTag string
}
supported := map[string]gamePadPlatform{
"Windows": {
genFileName: "windows",
buildTag: "//go:build windows && !microsoftgdk",
},
"Mac OS X": {
genFileName: "macos_darwin",
buildTag: "//go:build darwin && !ios",
},
"Linux": {
genFileName: "linbsd",
buildTag: "//go:build (freebsd || (linux && !android) || netbsd || openbsd) && !nintendosdk && !playstation5",
},
"iOS": {
genFileName: "ios",
buildTag: "//go:build ios",
},
"Android": {
genFileName: "android",
buildTag: "//go:build android",
},
}
tmpl, err := template.ParseFiles("gamepaddb_tmpl.tpl")
if err != nil {
log.Fatal(err)
}
controllerDbs := splitControllerDb(gamecontrollerdb_txt)
for sdlName, platform := range supported {
path := filepath.Join("internal", "gamepaddb", fmt.Sprintf("db_%s.go", platform.genFileName))
f, err := os.Create(path)
if err != nil {
log.Fatal(err)
}
defer f.Close()
controllerDb, ok := controllerDbs[sdlName]
if !ok {
log.Fatalf("failed to find controller db for platform %s in gamecontrollerdb_txt", sdlName)
}
err = tmpl.Execute(f, struct {
License string
DoNotEdit string
BuildTag string
SDLPlatform string
ControllerBytes []byte
GLFWGamePads []byte
}{
License: license,
DoNotEdit: doNotEdit,
BuildTag: platform.buildTag,
SDLPlatform: sdlName,
ControllerBytes: controllerDb,
GLFWGamePads: additionalGLFWGamepads,
})
if err != nil {
log.Fatal(err)
}
}
}
// splitControllerDb maps the game controller db into respective controller definition byte slices for
// each platform
func splitControllerDb(controllerDb []byte) map[string][]byte {
dbs := map[string][]byte{}
// split at #, skip first 3 header chunks
chunks := bytes.Split(controllerDb, []byte{'#'})[3:]
for _, chunk := range chunks {
// find each platform string
lines := bytes.Split(chunk, []byte{'\n'})
if len(lines) == 0 {
continue
}
platform := strings.TrimSpace(string(lines[0]))
// count platform string len + space + newline
bytesRead := len(lines[0]) + 1
dbs[platform] = chunk[bytesRead:]
}
return dbs
}