Skip to content

Instantly share code, notes, and snippets.

@samfromcadott
Last active January 13, 2023 09:39
Show Gist options
  • Save samfromcadott/1e68da53c8e6e054648e72e74f66a325 to your computer and use it in GitHub Desktop.
Save samfromcadott/1e68da53c8e6e054648e72e74f66a325 to your computer and use it in GitHub Desktop.
Free camera script for Silent Hill in BizHawk
-- 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