Skip to content

Instantly share code, notes, and snippets.

@Jimmy-Z
Last active December 12, 2020 07:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jimmy-Z/3aa5b83c6bc33bc6065ed5087de787be to your computer and use it in GitHub Desktop.
Save Jimmy-Z/3aa5b83c6bc33bc6065ed5087de787be to your computer and use it in GitHub Desktop.
RetroArch input overlay for gameboy on 2160*1080 phone
"use strict";
const writeFile = require("fs").writeFileSync
// from gamepads/flat
const image_dir = "assets"
const image_map = {
"up": "dpad-up_psx_no-mark",
"down": "dpad-down_psx_no-mark",
"left": "dpad-left_psx_no-mark",
"right": "dpad-right_psx_no-mark",
"a": "A",
"b": "B",
}
// vp_w/h: viewpoint size, w/h: core canvas size
function write_gb(name, vp_w, vp_h, w, h, la){
const headers = [
"overlays = 1",
"overlay0_full_screen = true",
"overlay0_normalized = true",
"overlay0_alpha_mod = 2.0",
];
let n_descs = 0;
const descs = [];
// dpad
function addBtn(img, x, y, shape, rx, ry, key){
// normalized = false is not working for me
// descs.push(`overlay0_desc${id} = "${key},${x},${y},${shape},${rx},${ry}"`);
descs.push(`overlay0_desc${n_descs} = "${key},${x/vp_w},${y/vp_h},${shape},${rx/vp_w},${ry/vp_h}"`);
if (img !== false){
// descs.push(`overlay0_desc${n_descs}_overlay = ${images[img]}`);
if (img == true){
img = key;
const mapped = image_map[img];
if (mapped !== undefined){
img = mapped
}
}
descs.push(`overlay0_desc${n_descs}_overlay = ${image_dir}/${img}.png`);
}
++n_descs;
}
// integer scale
const scale = Math.min(Math.floor(vp_w / w), Math.floor(vp_h / h))
const scaled_w = w * scale
const scaled_h = h * scale
console.error(`scale = ${scale}`)
console.error(`scaled width = ${scaled_w}`)
console.error(`scaled height = ${scaled_h}`)
// assume landscape centered canvas
const border_w = (vp_w - scaled_w) / 2
console.error(`border width = ${border_w}`)
// margin for image, the actual hit box covers the entire border
const d_pad_margin = border_w / 8 / 2
// btn center distance
const d_pad_center_radius = border_w / 32 / 2
// up/down btn image height, the left/right width
const d_pad_img_h = border_w / 2 - d_pad_margin - d_pad_center_radius
// the btn image resolution is very strange
const d_pad_img_w = d_pad_img_h * 74 / 86;
// width of up btn / width of entire d pad (AKA border width)
const d_pad_ratio = 1 / 3;
const d_pad_btn_w = border_w * d_pad_ratio
// height/width of the diagonal hit box, also height of compliment hit box for up/down btn
const d_pad_btn_h = border_w * (1 - d_pad_ratio) / 2
// radial hit box with image
addBtn(true, border_w/2, vp_h/2-d_pad_center_radius-d_pad_img_h/2, "radial", d_pad_img_w/2, d_pad_img_h/2, "up");
addBtn(true, border_w/2, vp_h/2+d_pad_center_radius+d_pad_img_h/2, "radial", d_pad_img_w/2, d_pad_img_h/2, "down");
addBtn(true, border_w/2-d_pad_center_radius-d_pad_img_h/2, vp_h/2, "radial", d_pad_img_h/2, d_pad_img_w/2, "left");
addBtn(true, border_w/2+d_pad_center_radius+d_pad_img_h/2, vp_h/2, "radial", d_pad_img_h/2, d_pad_img_w/2, "right");
// complimentary rect hit box
addBtn(false, border_w/2, vp_h/2-d_pad_btn_w/2-d_pad_btn_h/2, "rect", d_pad_btn_w/2, d_pad_btn_h/2, "up");
addBtn(false, border_w/2, vp_h/2+d_pad_btn_w/2+d_pad_btn_h/2, "rect", d_pad_btn_w/2, d_pad_btn_h/2, "down");
addBtn(false, border_w/2-d_pad_btn_w/2-d_pad_btn_h/2, vp_h/2, "rect", d_pad_btn_h/2, d_pad_btn_w/2, "left");
addBtn(false, border_w/2+d_pad_btn_w/2+d_pad_btn_h/2, vp_h/2, "rect", d_pad_btn_h/2, d_pad_btn_w/2, "right");
// diagonal hit box
addBtn(false, d_pad_btn_h/2, vp_h/2-d_pad_btn_w/2-d_pad_btn_h/2, "rect", d_pad_btn_h/2, d_pad_btn_h/2, "left|up");
addBtn(false, border_w-d_pad_btn_h/2, vp_h/2-d_pad_btn_w/2-d_pad_btn_h/2, "rect", d_pad_btn_h/2, d_pad_btn_h/2, "right|up");
addBtn(false, d_pad_btn_h/2, vp_h/2+d_pad_btn_w/2+d_pad_btn_h/2, "rect", d_pad_btn_h/2, d_pad_btn_h/2, "left|down");
addBtn(false, border_w-d_pad_btn_h/2, vp_h/2+d_pad_btn_w/2+d_pad_btn_h/2, "rect", d_pad_btn_h/2, d_pad_btn_h/2, "right|down");
// a/b btn
const ab_dist_x = border_w / 2;
const ab_dist_y = ab_dist_x / 3;
const ab_radius = Math.sqrt(ab_dist_x * ab_dist_x + ab_dist_y * ab_dist_y) * 2 / 5;
addBtn(true, vp_w-border_w/2+ab_dist_x/2, vp_h/2-ab_dist_y/2, "radial", ab_radius, ab_radius, "a");
addBtn(true, vp_w-border_w/2-ab_dist_x/2, vp_h/2+ab_dist_y/2, "radial", ab_radius, ab_radius, "b");
// hit box for a+b
const ab_both_radius = ab_radius / 2;
addBtn(false, vp_w-border_w/2, vp_h/2, "radial", ab_both_radius, ab_both_radius, "a|b");
// use corners of core canvas (+ up/down border) for menu/abss/select/start
const scr_btn_margin = vp_h / 24;
addBtn(false, border_w+scaled_w/6, vp_h/6, "rect", scaled_w/6-scr_btn_margin, vp_h/6-scr_btn_margin, "menu_toggle");
addBtn(false, vp_w-border_w-scaled_w/6, vp_h/6, "rect", scaled_w/6-scr_btn_margin, vp_h/6-scr_btn_margin, la ? "a|b|start|select" : "toggle_fast_forward");
addBtn(false, border_w+scaled_w/6, vp_h*5/6, "rect", scaled_w/6-scr_btn_margin, vp_h/6-scr_btn_margin, "select");
addBtn(false, vp_w-border_w-scaled_w/6, vp_h*5/6, "rect", scaled_w/6-scr_btn_margin, vp_h/6-scr_btn_margin, "start");
writeFile(`${name}.cfg`,
headers.join("\n") + `\noverlay0_descs = ${n_descs}\n` + descs.join("\n") + "\n",
{encoding: "ascii"})
}
write_gb("gameboy-landscape-2160x1080", 2160, 1080, 160, 144, false);
write_gb("gameboy-landscape-la-2160x1080", 2160, 1080, 160, 144, true);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment