Last active
January 13, 2023 09:39
-
-
Save samfromcadott/1e68da53c8e6e054648e72e74f66a325 to your computer and use it in GitHub Desktop.
Free camera script for Silent Hill in BizHawk
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Free camera script for Silent Hill in BizHawk | |
-- Only tested with the North American version | |
-- | |
-- L3+R3 to toggle on and off | |
-- | |
-- Submit improvements at https://gist.github.com/samfromcadott/ | |
-- Fell free to adapt this for other games | |
-- | |
-- Copyright 2021 Sam Jackson | |
----------------------------- | |
-- Options | |
----------------------------- | |
lookSpeed = 15 | |
moveSpeed = 200 | |
-- Memory addresses | |
----------------------------- | |
harryAddress = { | |
x = 0x0BA024, | |
y = 0x0BA028, | |
z = 0x0BA02C, | |
yaw = 0x0BA032 | |
} | |
camAddress = { | |
pitch = 0x0B9D88, | |
yaw = 0x0B9D8A, | |
roll = 0x0B9D8C, | |
x = 0x0B9D20, | |
y = 0x0B9D24, | |
z = 0x0B9D28 | |
} | |
function radian(angle) | |
-- Converts from Silent Hill's angles (4096 per rotation) to radians | |
return angle * math.pi/2048 | |
end | |
function initCam() | |
return { | |
pitch = memory.read_u16_le(camAddress.pitch), | |
yaw = memory.read_u16_le(camAddress.yaw), | |
roll = memory.read_u16_le(camAddress.roll), | |
x = memory.read_s32_le(camAddress.x), | |
y = memory.read_s32_le(camAddress.y), | |
z = memory.read_s32_le(camAddress.z) | |
} | |
end | |
function initHarry() | |
return { | |
x = memory.read_s32_le(harryAddress.x), | |
y = memory.read_s32_le(harryAddress.y), | |
z = memory.read_s32_le(harryAddress.z), | |
yaw = memory.read_u16_le(harryAddress.yaw) | |
} | |
end | |
function switchMode() | |
-- Check if the player is trying to toggle free look | |
if joypad.getimmediate()["P1 L3"] and joypad.getimmediate()["P1 R3"] then | |
freeCam = not freeCam | |
camera = initCam() | |
if freeCam then | |
harry = initHarry() | |
end | |
end | |
end | |
function lockHarry() | |
-- Keep Harry's location and yaw constant so he doesn't screw up stuff | |
memory.write_s32_le(harryAddress.x, harry.x) | |
memory.write_s32_le(harryAddress.y, harry.y) | |
memory.write_s32_le(harryAddress.z, harry.z) | |
memory.write_u16_le(harryAddress.yaw, harry.yaw) | |
end | |
function move() | |
-- Update the camera location using left joystick | |
local front = {x = 0.0, y = 0.0, z = 0.0} | |
local right = {x = 0.0, y = 0.0, z = 0.0} | |
local up = {x = 0.0, y = 1.0, z = 0.0} -- Silent Hill uses y+ as the up direction | |
-- Create the facing vector | |
front.x = math.sin(radian(camera.yaw))*math.cos(radian(camera.pitch)) | |
front.y = math.sin(radian(camera.pitch)) | |
front.z = math.cos(radian(camera.yaw))*math.cos(radian(camera.pitch)) | |
-- The right vector should be the cross product of the front and the up vector | |
right.x = front.y*up.z - front.z*up.y | |
right.y = front.y*up.x - front.x*up.z | |
right.z = front.x*up.y - front.y*up.x | |
-- Move camera | |
camera.x = camera.x + (front.x * moveSpeed) * getJoyStick('L').y | |
camera.y = camera.y - (front.y * moveSpeed) * getJoyStick('L').y | |
camera.z = camera.z + (front.z * moveSpeed) * getJoyStick('L').y | |
camera.x = camera.x - (right.x * moveSpeed) * getJoyStick('L').x | |
camera.y = camera.y + (right.y * moveSpeed) * getJoyStick('L').x | |
camera.z = camera.z - (right.z * moveSpeed) * getJoyStick('L').x | |
memory.write_s32_le(camAddress.x, camera.x) | |
memory.write_s32_le(camAddress.y, camera.y) | |
memory.write_s32_le(camAddress.z, camera.z) | |
end | |
function look() | |
-- Update the camera rotation using right joystick | |
camera.pitch = (camera.pitch + getJoyStick('R').y * lookSpeed)%4096 | |
camera.yaw = (camera.yaw + getJoyStick('R').x * lookSpeed)%4096 | |
camera.roll = 0 | |
memory.write_u16_le(camAddress.pitch, camera.pitch) | |
memory.write_u16_le(camAddress.yaw, camera.yaw) | |
memory.write_u16_le(camAddress.roll, camera.roll) | |
end | |
function getJoyStick(stick) | |
-- Gets the direction the joystick is moved | |
-- stick argument should be 'L' or 'R' | |
local dir = {x = 0, y = 0} | |
if input.get()["X1 "..stick.."StickUp"] then | |
dir.y = 1 | |
elseif input.get()["X1 "..stick.."StickDown"] then | |
dir.y = -1 | |
end | |
if input.get()["X1 "..stick.."StickRight"] then | |
dir.x = 1 | |
elseif input.get()["X1 "..stick.."StickLeft"] then | |
dir.x = -1 | |
end | |
return dir | |
end | |
-- Start up | |
----------------------------- | |
camera = initCam() | |
harry = initHarry() | |
freeCam = false | |
-- Main loop | |
----------------------------- | |
while true do | |
switchMode() | |
if freeCam then | |
lockHarry() | |
look() | |
move() | |
end | |
emu.frameadvance() | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment