Skip to content

Commit

Permalink
Add Sonic Adventure DX and Sonic Adventure 2: Battle scripts, provide…
Browse files Browse the repository at this point in the history
…d by Tales and modified slightly.
  • Loading branch information
yoshifan committed Jan 10, 2018
1 parent 3acb69f commit 2fe240e
Show file tree
Hide file tree
Showing 6 changed files with 577 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,6 @@ The primary authors of this GitHub repository are not affiliated with Dolphin, C

Masterjun, for writing the Dolphin + Cheat Engine RAM watch script that this project was based on: http://tasvideos.org/forum/viewtopic.php?t=14379 (2013.08.26)

Tales, for providing the Sonic Adventure DX and Sonic Adventure 2: Battle scripts that were added to this repository (with slight modifications).

aldelaro, for the Dolphin + Cheat Engine tutorial I've linked a few times in these docs.
6 changes: 6 additions & 0 deletions docs/tutorial/run.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
- Metroid Prime, North American version (GM8E01) [revision 0-00](http://www.metroid2002.com/version_differences_version_number.php)

- If you're not sure whether you have 0-00: Right-click the game in Dolphin, click Properties, and click the Info tab. Revision should be 0.

- Sonic Adventure DX: Director's Cut, North American version (GXSE8P)

- Sonic Adventure 2: Battle, North American version (GSNE8P)

- Super Mario Galaxy; North American (RMGE01), European (RMGP01), or Japanese (RMGJ01) version

Expand Down Expand Up @@ -82,6 +86,8 @@
--- | --- | --- | --- | ---
F-Zero GX | North America | `'fzerogx'` | `'na'` | `'racerInfo'`
Metroid Prime | North America 0-00 | `'metroidprime'` | `'na_0_00'` | `'positionAndVelocity'`
Sonic Adventure DX: Director's Cut | North America | `'sonicadventuredx'` | `'na'` | `'coordsAndInputs'`
Sonic Adventure 2: Battle | North America | `'sonicadventure2battle'` | `'na'` | `'coordsAndInputs'`
Super Mario Galaxy | North America | `'supermariogalaxy'` | `'na'` | `'positionAndInputs'`
Super Mario Galaxy | Europe | `'supermariogalaxy'` | `'eu'` | `'positionAndInputs'`
Super Mario Galaxy | Japan | `'supermariogalaxy'` | `'jp'` | `'positionAndInputs'`
Expand Down
167 changes: 167 additions & 0 deletions games/sonicadventure2battle.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
package.loaded.utils = nil
local utils = require 'utils'
local subclass = utils.subclass

package.loaded.dolphin = nil
local dolphin = require 'dolphin'

local MyGame = subclass(dolphin.DolphinGame)

MyGame.supportedGameVersions = {
na = 'GSNE8P',
}

MyGame.layoutModuleNames = {'sonicadventure2battle_layouts'}
MyGame.framerate = 60

function MyGame:init(options)
dolphin.DolphinGame.init(self, options)

self.startAddress = self:getGameStartAddress()
end


local valuetypes = require "valuetypes"
local V = valuetypes.V
local GV = MyGame.blockValues
local MV = valuetypes.MV
local Block = valuetypes.Block
local Value = valuetypes.Value
local FloatType = valuetypes.FloatTypeBE
local IntType = valuetypes.IntTypeBE
local ByteType = valuetypes.ByteType
local BinaryType = valuetypes.BinaryType

package.loaded.layouts = nil
local layoutsModule = require 'layouts'

local StaticValue = subclass(valuetypes.MemoryValue)
function StaticValue:getAddress()
return self.game.startAddress + self.offset
end

-- Game addresses

GV.facingAngle = MV("Facing Angle", 0xC5D5AC, StaticValue, IntType)

GV.stSpeed = MV(
"StSpeed", 0xC5D704, StaticValue, FloatType)
GV.fSpeed = MV(
"FSpeed", 0xC5D724, StaticValue, FloatType)
GV.vSpeed = MV(
"VSpeed", 0xC5D728, StaticValue, FloatType)
GV.xPos = MV(
"XPos", 0xC5D5B4, StaticValue, FloatType)
GV.yPos = MV(
"YPos", 0xC5D5B8, StaticValue, FloatType)
GV.zPos = MV(
"ZPos", 0xC5D5BC, StaticValue, FloatType)


-- Inputs

GV.ABXYS = MV("ABXY & Start", 0x2BAB78,
StaticValue, BinaryType, {binarySize=8, binaryStartBit=7})
GV.DZ = MV("D-Pad & Z", 0x2BAB79,
StaticValue, BinaryType, {binarySize=8, binaryStartBit=7})

GV.stickX =
MV("X Stick", 0x2BAB7A, StaticValue, ByteType)
GV.stickY =
MV("Y Stick", 0x2BAB7B, StaticValue, ByteType)
GV.xCStick =
MV("X C-Stick", 0x2BAB7C, StaticValue, ByteType)
GV.yCStick =
MV("Y C-Stick", 0x2BAB7D, StaticValue, ByteType)
GV.lShoulder =
MV("L Shoulder", 0x2BAB7E, StaticValue, ByteType)
GV.rShoulder =
MV("R Shoulder", 0x2BAB7F, StaticValue, ByteType)

function MyGame:displaySpeed()
local stspd = self.stSpeed:get()
local fspd = self.fSpeed:get()
local vspd = self.vSpeed:get()
return string.format("Speed\n St: %f\n F: %f\n V: %f", stspd, fspd, vspd)
end

function MyGame:displayRotation()
local yrot = self.facingAngle:get()
return string.format("Rotation\n Y: %d", yrot)
end

function MyGame:displayPosition()
local xpos = self.xPos:get()
local ypos = self.yPos:get()
local zpos = self.zPos:get()
return string.format("Position\n X: %f\n Y: %f\n Z: %f", xpos, ypos, zpos)
end

function MyGame:displayInputTime()
local address = 0x013458A8
return string.format(" %d", utils.readIntLE(address))
end

function MyGame:getButton(button)
-- Return 1 if button is pressed, 0 otherwise.
local value = nil
if button == "A" then value = self.ABXYS:get()[8]
elseif button == "B" then value = self.ABXYS:get()[7]
elseif button == "X" then value = self.ABXYS:get()[6]
elseif button == "Y" then value = self.ABXYS:get()[5]
elseif button == "S" then value = self.ABXYS:get()[4]
elseif button == "Z" then value = self.DZ:get()[4]
elseif button == "^" then value = self.DZ:get()[5]
elseif button == "v" then value = self.DZ:get()[6]
elseif button == "<" then value = self.DZ:get()[7]
elseif button == ">" then value = self.DZ:get()[8]
elseif button == "L" then value = self.DZ:get()[2]
elseif button == "R" then value = self.DZ:get()[3]
else error("Button code not recognized: " .. tostring(button))
end

return value
end

function MyGame:buttonDisplay(button)
-- Return the button character ("A", "B" etc.) if the button is pressed,
-- or a space character " " otherwise.
local value = self:getButton(button)
if value == 1 then
return button
else
return " "
end
end

function MyGame:displayAllButtons()
local s = ""
for _, button in pairs{"A", "B", "X", "Y", "S", "Z", "L", "R", "v", "<", ">", "^"} do
s = s..self:buttonDisplay(button)
end
return s
end


MyGame.ControllerStickImage = subclass(layoutsModule.StickInputImage)
function MyGame.ControllerStickImage:init(window, game, options)
options = options or {}
options.max = options.max or 255
options.min = options.min or 0
options.square = options.square or true

layoutsModule.StickInputImage.init(
self, window,
game.stickX, game.stickY, options)
end

MyGame.ControllerLRImage = subclass(layoutsModule.AnalogTriggerInputImage)
function MyGame.ControllerLRImage:init(window, game, options)
options = options or {}
options.max = options.max or 255

layoutsModule.AnalogTriggerInputImage.init(
self, window, game.lShoulder, game.rShoulder, options)
end

return MyGame
93 changes: 93 additions & 0 deletions games/sonicadventure2battle_layouts.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package.loaded.utils = nil
local utils = require 'utils'
local subclass = utils.subclass

package.loaded.layouts = nil
local layoutsModule = require 'layouts'
local Layout = layoutsModule.Layout

local layouts = {}

local fixedWidthFontName = "Consolas"

local inputColor = 0x880000

layouts.addressTest = subclass(Layout)
-- Displays some key addresses, as computed by the Lua framework.
-- We can double check these addresses in Cheat Engine's Memory View.
function layouts.addressTest:init()

self:setUpdatesPerSecond(5)

self.window:setSize(450, 200)

self:addLabel{x=6, y=6}
self:addItem(
function()
local lines = {}
table.insert(
lines, "startAddress: "..utils.intToHexStr(self.game.startAddress))
table.insert(
lines,
"FSpeed addr: "..utils.intToHexStr(self.game.fSpeed:getAddress()))
return table.concat(lines, '\n')
end
)

end


layouts.coordsAndInputs = subclass(Layout)
-- General use layout for TASing and stuff.
-- Speed, position, rotation, inputs.
--
-- updatesPerSecond:
-- How often this display should be updated.
-- Set this higher to see more frequent updates. The game runs at
-- 60 FPS, so it doesn't make sense to set this much higher than 60.
-- Set this lower if Dolphin is stuttering too much.
-- Set to 0 to use breakpoint updates (should update on every frame more
-- reliably compared to 60, but may make Dolphin stutter more).
function layouts.coordsAndInputs:init(updatesPerSecond)

updatesPerSecond = updatesPerSecond or 60

local game = self.game
self.margin = 6
if updatesPerSecond == 0 then
self:setBreakpointUpdateMethod()
else
self:setUpdatesPerSecond(updatesPerSecond)
end
self:activateAutoPositioningY()

self.window:setSize(220, 460)
self.labelDefaults = {fontSize=fontSize, fontName=fixedWidthFontName}
self.itemDisplayDefaults = {narrow=true}

self:addLabel()
self:addItem(function(...) return self.game:displaySpeed(...) end)
self:addItem(function(...) return self.game:displayPosition(...) end)
self:addItem(function(...) return self.game:displayRotation(...) end)

self:addItem("Input Frames Count")
self:addItem(function(...) return self.game:displayInputTime(...) end)

self:addLabel{fontColor=inputColor}
self:addItem("Buttons")
self:addItem(function(...) return self.game:displayAllButtons(...) end)

self:addLabel{foregroundColor=inputColor}
self:addImage(
self.game.ControllerLRImage, {game}, {foregroundColor=inputColor})

self:addLabel{foregroundColor=inputColor}
self:addImage(
self.game.ControllerStickImage, {game}, {foregroundColor=inputColor})

end


return {
layouts = layouts,
}
Loading

0 comments on commit 2fe240e

Please sign in to comment.