Merge branch 'master' into release
# Conflicts resolved: # BizHawk.Client.EmuHawk/tools/TAStudio/BookmarksBranchesBox.cs # References/OpenTK.dll.config
This commit is contained in:
commit
84facd4c03
|
@ -12,6 +12,7 @@ svnrev.cs
|
|||
**/ipch/**
|
||||
|
||||
*.ilk
|
||||
*.il
|
||||
*.tlog
|
||||
*.obj
|
||||
*.o
|
||||
|
@ -73,3 +74,8 @@ ExternalCoreProjects/Virtu/bin/*.*
|
|||
libsnes/vs2015/libsnes.VC.db
|
||||
waterbox/**/*.wbx
|
||||
waterbox/**/*.wbx.in
|
||||
/BizHawkTool_template.zip
|
||||
|
||||
mono_crash*
|
||||
|
||||
.idea
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
#!/bin/sh
|
||||
cd "$(dirname "$0")"
|
||||
if [ "$(ps -C "mono" -o "cmd" --no-headers | grep "EmuHawk.exe")" ]; then
|
||||
echo "EmuHawk is already running, exiting..."
|
||||
exit 0
|
||||
fi
|
||||
libpath=""
|
||||
if [ "$(command -v lsb_release)" ]; then
|
||||
case "$(lsb_release -i | cut -c17- | tr -d "\n")" in
|
||||
"Arch"|"ManjaroLinux") libpath="/usr/lib/wine";;
|
||||
"Debian"|"LinuxMint") libpath="/usr/lib/x86_64-linux-gnu/wine";;
|
||||
"Ubuntu") libpath="/usr/lib/x86_64-linux-gnu/wine"; export MONO_WINFORMS_XIM_STYLE=disabled;; # see https://bugzilla.xamarin.com/show_bug.cgi?id=28047#c9
|
||||
esac
|
||||
else
|
||||
printf "Distro does not provide LSB release info API! (You've met with a terrible fate, haven't you?)\n"
|
||||
fi
|
||||
if [ -z "$libpath" ]; then
|
||||
printf "%s\n" "Unknown distro, assuming WINE library location is /usr/lib/wine..."
|
||||
libpath="/usr/lib/wine"
|
||||
fi
|
||||
LD_LIBRARY_PATH="$libpath" mono ./EmuHawk.exe >EmuHawkMono_laststdout.txt
|
|
@ -1,448 +1,522 @@
|
|||
-- Gargoyles, Genesis (BizHawk)
|
||||
-- feos, 2015-2016
|
||||
|
||||
--== Shortcuts ==--
|
||||
rb = memory.read_u8
|
||||
rw = memory.read_u16_be
|
||||
rws = memory.read_s16_be
|
||||
r24 = memory.read_u24_be
|
||||
rl = memory.read_u32_be
|
||||
box = gui.drawBox
|
||||
text = gui.pixelText
|
||||
line = gui.drawLine
|
||||
AND = bit.band
|
||||
SHIFT = bit.rshift
|
||||
|
||||
--== RAM addresses ==--
|
||||
levnum = 0xff00ba
|
||||
LevelFlr = 0xff00c0
|
||||
LevelCon = 0xff00c4
|
||||
mapline_tab = 0xff0244
|
||||
GlobalBase = 0xff1c76
|
||||
GolBase = 0xff2c76
|
||||
MapA_Buff = 0xff4af0
|
||||
|
||||
--== Camera Hack ==--
|
||||
camhack = false
|
||||
div = 1 -- scale
|
||||
size = 16/div -- block size
|
||||
|
||||
--== Block cache ==--
|
||||
col = 0 -- block color
|
||||
opout = 0x33000000 -- outer opacity
|
||||
opin = 0x66000000 -- inner opacity
|
||||
op = 0xff000000
|
||||
cache = {}
|
||||
|
||||
--== Other stuff ==--
|
||||
XposLast = 0
|
||||
YposLast = 0
|
||||
room = 0
|
||||
workinglast = 0
|
||||
lagcount = emu.lagcount()
|
||||
gui.defaultPixelFont("fceux")
|
||||
|
||||
function main()
|
||||
rnd1 = rl (0xff001c)
|
||||
rnd2 = rw (0xff0020)
|
||||
working = rb (0xff0073)
|
||||
xblocks = rw (0xff00d4)
|
||||
mapw = rw (0xff00d4)*8
|
||||
maph = rw (0xff00d6)*8
|
||||
Xpos = rws(0xff0106)
|
||||
Ypos = rws(0xff0108)
|
||||
camx = rws(0xff010c)+16
|
||||
camy = rws(0xff010e)+16
|
||||
run = rb (0xff1699)
|
||||
inv = rw (0xff16d2)
|
||||
health = rws(0xff2cc6)
|
||||
backx = camx
|
||||
backy = camy
|
||||
Xspd = Xpos-XposLast
|
||||
Yspd = Ypos-YposLast
|
||||
facing = AND(rb(GolBase+0x48),2) -- object flag 1
|
||||
|
||||
Background()
|
||||
CamhackHUD()
|
||||
Objects()
|
||||
PlayerBoxes()
|
||||
HUD()
|
||||
RoomTime()
|
||||
Input()
|
||||
end
|
||||
|
||||
function RoomTime()
|
||||
local start11 = 894--767
|
||||
local start12 = 2294
|
||||
local start13 = 4101
|
||||
local startl4 = 6000
|
||||
timer = emu.framecount()
|
||||
|
||||
if timer < start11 then room = timer
|
||||
elseif timer < start12 then room = timer - start11
|
||||
elseif timer < start13 then room = timer - start12
|
||||
elseif timer < startl4 then room = timer - start13
|
||||
end
|
||||
text(160,214,"room cnt: "..room, "white")
|
||||
end
|
||||
|
||||
function HUD()
|
||||
text(1, 0,emu.framecount(), framecol)
|
||||
text(1,20,emu.lagcount(), "red")
|
||||
text(1,30,movie.rerecordcount(),"orange")
|
||||
|
||||
if working>0 then return end
|
||||
if rndlast ~= rnd1 then rndcol = "red" else rndcol = "white" end
|
||||
|
||||
text( 0,214,"rnd: ","yellow")
|
||||
text( 26,214,string.format("%08X %04X",rnd1,rnd2),rndcol)
|
||||
text(277, 0,string.format(
|
||||
"x: %4d\ny: %4d\ndx: %3d\ndy: %3d\nhp: %3d\nrun:%3d\ninv:%3d",
|
||||
Xpos,Ypos,Xspd,Yspd,health,run,inv)
|
||||
)
|
||||
end
|
||||
|
||||
function CamhackHUD()
|
||||
if working==0 then
|
||||
-- screen edge
|
||||
box((backx-camx- 1)/div,
|
||||
(backy-camy- 1)/div,
|
||||
(backx-camx+320)/div,
|
||||
(backy-camy+224)/div,
|
||||
0xff0000ff)
|
||||
-- map edge
|
||||
box( 0-camx/div+size,
|
||||
0-camy/div+size,
|
||||
mapw/div-camx/div,
|
||||
maph/div-camy/div,
|
||||
0xff0000ff)
|
||||
end
|
||||
|
||||
text(260,206,string.format("cHack: %s\nscale: %d",ch,div))
|
||||
end
|
||||
|
||||
function Background()
|
||||
if working>0 then
|
||||
cache = {}
|
||||
return
|
||||
end
|
||||
|
||||
if camhack then
|
||||
camx = Xpos-320/2*div
|
||||
camy = Ypos-224/2*div
|
||||
box(0,0,320,240,0,0x66000000)
|
||||
ch = "on"
|
||||
else
|
||||
ch = "off"
|
||||
end
|
||||
|
||||
local border = 0
|
||||
local offset = 32
|
||||
local basex = camx+border
|
||||
local basey = camy+border
|
||||
local basei = PosToIndex(basex-offset,basey-offset)
|
||||
local boundx = 320*div-border
|
||||
local boundy = 224*div-border
|
||||
local xblockstockeck = ((camx+boundx+offset)-(basex-offset))/size/div
|
||||
local yblockstockeck = ((camy+boundy+offset)-(basey-offset))/size/div
|
||||
|
||||
for yblock = 0,yblockstockeck do
|
||||
for xblock = 0,xblockstockeck do
|
||||
local i = yblock*xblocks+xblock+basei
|
||||
local x = basex+xblock*size*div
|
||||
local y = basey+yblock*size*div
|
||||
|
||||
if InBounds(x,basex-offset,camx+boundx+offset) then
|
||||
local unit = cache[i]
|
||||
|
||||
if unit == nil or workinglast>0 then
|
||||
if InBounds(x,basex,camx+boundx)
|
||||
and InBounds(y,basey,camy+boundy)
|
||||
then cache[i] = GetBlock(x,y)
|
||||
end
|
||||
else
|
||||
if not InBounds(x,basex,camx+boundx)
|
||||
and not InBounds(y,basey,camy+boundy)
|
||||
then cache[i] = nil
|
||||
end
|
||||
end
|
||||
|
||||
if unit ~= nil then
|
||||
DrawBG(unit,x,y)
|
||||
end
|
||||
elseif cache[i] ~= nil
|
||||
then cache[i] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function DrawBG(unit, x, y)
|
||||
local val= 0
|
||||
local x1 = x/div-camx/div-(camx%16)/div
|
||||
local x2 = x1+size-1
|
||||
local y1 = y/div-camy/div-(camy%16)/div
|
||||
local y2 = y1+size-1
|
||||
|
||||
if unit.contour ~= nil then
|
||||
box(x1,y1,x2,y2,0x5500ff00,0x5500ff00)
|
||||
|
||||
for pixel=0,15 do
|
||||
val = unit.contour[pixel]
|
||||
if val>0 then
|
||||
gui.drawPixel(
|
||||
x1+pixel/div,
|
||||
y1+val/div-1/div,
|
||||
0xffffff00)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if unit.block>0 then
|
||||
local Fn = DrawBlock[unit.block] or DrawBlockDefault
|
||||
Fn(x1,y1,x2,y2)
|
||||
box(x1,y1,x2,y2,col+opin,col+opout)
|
||||
end
|
||||
end
|
||||
|
||||
function GetBlock(x,y)
|
||||
if working>0 then return nil end
|
||||
|
||||
local final = { contour={}, block=0 }
|
||||
|
||||
if x>0 and x<mapw
|
||||
and y>0 and y<maph then
|
||||
local pixels = 0
|
||||
local x1 = x/div-camx/div
|
||||
local x2 = x1+size-1
|
||||
local y1 = y/div-camy/div
|
||||
local y2 = y1+size-1
|
||||
local d4 = rw(mapline_tab+SHIFT(y,4)*2)
|
||||
local a1 = r24(LevelFlr+1)
|
||||
local d1 = SHIFT(rw(MapA_Buff+d4+SHIFT(x,4)*2),1)
|
||||
final.block = rb(a1+d1+2)
|
||||
d1 = rw(a1+d1)
|
||||
a1 = r24(LevelCon+1)+d1
|
||||
|
||||
if rb(a1)>0 or rb(a1+8)>0 then
|
||||
for pixel=0,15 do
|
||||
final.contour[pixel] = rb(a1+pixel)
|
||||
end
|
||||
else
|
||||
final.contour = nil
|
||||
end
|
||||
else
|
||||
return nil
|
||||
end
|
||||
|
||||
return final
|
||||
end
|
||||
|
||||
function PosToIndex(x,y)
|
||||
return math.floor(x/16)+math.floor(y/16)*xblocks
|
||||
end
|
||||
|
||||
function IndexToPos(i)
|
||||
return { x=(i%xblocks)*16, y=math.floor(i/xblocks)*16 }
|
||||
end
|
||||
|
||||
function InBounds(x,minimum,maximum)
|
||||
if x>=minimum and x<=maximum
|
||||
then return true
|
||||
else return false
|
||||
end
|
||||
end
|
||||
|
||||
DrawBlock = {
|
||||
[0x80] = function(x1,y1,x2,y2) -- WALL
|
||||
col = 0x00ffffff -- white
|
||||
line(x1,y1,x1,y2,col+op) -- left
|
||||
line(x2,y1,x2,y2,col+op) -- right
|
||||
end,
|
||||
[0x81] = function(x1,y1,x2,y2) -- CEILING
|
||||
col = 0x00ffffff -- white
|
||||
line(x1,y2,x2,y2,col+op) -- bottom
|
||||
end,
|
||||
[0x82] = function(x1,y1,x2,y2) -- CLIMB_U
|
||||
col = 0x0000ffff -- cyan
|
||||
line(x1,y2,x2,y2,col+op) -- bottom
|
||||
end,
|
||||
[0x83] = function(x1,y1,x2,y2) -- CLIMB_R
|
||||
col = 0x0000ffff -- cyan
|
||||
line(x1,y1,x1,y2,col+op) -- left
|
||||
end,
|
||||
[0x84] = function(x1,y1,x2,y2) -- CLIMB_L
|
||||
col = 0x0000ffff -- cyan
|
||||
line(x2,y1,x2,y2,col+op) -- right
|
||||
end,
|
||||
[0x85] = function(x1,y1,x2,y2) -- CLIMB_LR
|
||||
col = 0x0000ffff -- cyan
|
||||
line(x1,y1,x1,y2,col+op) -- left
|
||||
line(x2,y1,x2,y2,col+op) -- right
|
||||
end,
|
||||
[0x86] = function(x1,y1,x2,y2) -- CLIMB_R_STAND_R
|
||||
col = 0x00ffffff -- white
|
||||
line(x1,y1,x2,y1,col+op) -- top
|
||||
col = 0x0000ffff -- cyan
|
||||
line(x1,y1,x1,y2,col+op) -- left
|
||||
end,
|
||||
[0x87] = function(x1,y1,x2,y2) -- CLIMB_L_STAND_L
|
||||
col = 0x00ffffff -- white
|
||||
line(x1,y1,x2,y1,col+op) -- top
|
||||
col = 0x0000ffff -- cyan
|
||||
line(x2,y1,x2,y2,col+op) -- right
|
||||
end,
|
||||
[0x88] = function(x1,y1,x2,y2) -- CLIMB_LR_STAND_LR
|
||||
col = 0x00ffffff -- white
|
||||
line(x1,y1,x2,y1,col+op) -- top
|
||||
col = 0x00ff00ff -- cyan
|
||||
line(x1,y1,x1,y2,col+op) -- left
|
||||
col = 0x0000ffff -- cyan
|
||||
line(x2,y1,x2,y2,col+op) -- right
|
||||
end,
|
||||
[0x70] = function(x1,y1,x2,y2) -- GRAB_SWING
|
||||
col = 0x0000ff00 -- green
|
||||
box(x1,y1,x2,y2,col,col+opout)
|
||||
end,
|
||||
[0x7f] = function(x1,y1,x2,y2) -- EXIT
|
||||
col = 0x00ffff00 -- yellow
|
||||
end,
|
||||
[0xd0] = function(x1,y1,x2,y2) -- SPIKES
|
||||
col = 0x00ff0000 -- red
|
||||
box(x1,y1,x2,y2,col,col+opout)
|
||||
end,
|
||||
[0xd1] = function(x1,y1,x2,y2) -- SPIKES
|
||||
col = 0x00ff0000 -- red
|
||||
box(x1,y1,x2,y2,col,col+opout)
|
||||
end
|
||||
}
|
||||
|
||||
function DrawBlockDefault(x1,y1,x2,y2)-- LEVEL_SPECIFIC
|
||||
col = 0x00ff8800 -- orange
|
||||
box(x1,y1,x2,y2,col+opin,col+opout)
|
||||
end
|
||||
|
||||
function Objects()
|
||||
if working>0 then return end
|
||||
|
||||
for i=0,63 do
|
||||
local base = GlobalBase+i*128
|
||||
local flag2 = AND(rb(base+0x49),0x10) -- active
|
||||
|
||||
if flag2==0x10 then
|
||||
local xpos = rw (base+0x00)
|
||||
local ypos = rw (base+0x02)
|
||||
local dmg = rb (base+0x10)
|
||||
local type = rw (base+0x40)
|
||||
local hp = rw (base+0x50)
|
||||
local cRAM = r24(base+0x75) -- pointer to 4 collision boxes per object
|
||||
local col = 0 -- collision color
|
||||
local xscr = (xpos-camx)/div
|
||||
local yscr = (ypos-camy)/div
|
||||
|
||||
for boxx=0,4 do
|
||||
local x1 = (rws(cRAM+boxx*8+0)-camx)/div
|
||||
local y1 = (rws(cRAM+boxx*8+2)-camy)/div
|
||||
local x2 = (rws(cRAM+boxx*8+4)-camx)/div
|
||||
local y2 = (rws(cRAM+boxx*8+6)-camy)/div
|
||||
|
||||
if boxx==0 then
|
||||
col = 0xff00ff00 -- body
|
||||
if type==282 or type==258 then hp = 1 end -- archer hp doesn't matter
|
||||
if hp>0 and type>0 then
|
||||
text(x1+2,y1+1,string.format("%d",hp),col,0x88000000,"gens")
|
||||
end
|
||||
elseif boxx==1 then
|
||||
col = 0xffffff00 -- floor
|
||||
elseif boxx==2 then
|
||||
if dmg>0
|
||||
then col = 0xffff0000 -- projectile
|
||||
else col = 0xff8800ff -- item
|
||||
end
|
||||
if dmg>0 then
|
||||
text(x1+2,y2+1,string.format("%d",dmg),col,0x88000000,"gens")
|
||||
end
|
||||
else
|
||||
col = 0xffffffff -- other
|
||||
end
|
||||
|
||||
if x1~=0x8888 and x2<320 and x1>0 and y2<224 and y1>0 then
|
||||
box(x1,y1,x2,y2,col)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function PlayerBoxes()
|
||||
if working>0 then return end
|
||||
|
||||
local xx = (Xpos-camx)/div
|
||||
local yy = (Ypos-camy)/div
|
||||
local col = 0xff00ffff
|
||||
local swcol = col -- usual detection
|
||||
|
||||
if Yspd>0 then -- gimme swings to grab!
|
||||
swcol = 0xff00ff00
|
||||
elseif Yspd==0 then -- can tell that too
|
||||
swcol = 0xffffffff
|
||||
end
|
||||
|
||||
if facing==2 then
|
||||
box(xx-0xf /div-2,yy-0x2c/div-1,xx-0xf /div+0,yy-0x2c/div+1,swcol) -- lefttop
|
||||
else
|
||||
box(xx+0xf /div-1,yy-0x2c/div-1,xx+0xf /div+1,yy-0x2c/div+1,swcol) -- rightttop
|
||||
end
|
||||
|
||||
box(xx -1,yy-0x2c/div-1,xx +1,yy-0x2c/div+1,col) -- top
|
||||
box(xx-0xf /div-2,yy-0x1f/div-1,xx-0xf /div+0,yy-0x1f/div+1,col) -- left
|
||||
box(xx+0x10/div-1,yy-0x1f/div-1,xx+0x10/div+1,yy-0x1f/div+1,col) -- right
|
||||
-- box(xx -1,yy-0x1f/div-1,xx +1,yy-0x1f/div+1,col) -- center
|
||||
box(xx -1,yy-0x0f/div-1,xx +1,yy-0x0f/div+1,col) -- bottom
|
||||
box(xx -1,yy -1,xx +1,yy +1,0xffffff00) -- feet
|
||||
-- box(xx -1,yy+0x10/div-1,xx +1,yy+0x10/div+1,col) -- ground
|
||||
end
|
||||
|
||||
function Input()
|
||||
local i,u,d,l,r,a,b,c,s
|
||||
|
||||
if movie.isloaded() then
|
||||
i = movie.getinput(emu.framecount()-1)
|
||||
else
|
||||
i = joypad.getimmediate()
|
||||
end
|
||||
|
||||
if i["P1 Up" ] then u = "U" else u = " " end
|
||||
if i["P1 Down" ] then d = "D" else d = " " end
|
||||
if i["P1 Left" ] then l = "L" else l = " " end
|
||||
if i["P1 Right"] then r = "R" else r = " " end
|
||||
if i["P1 A" ] then a = "A" else a = " " end
|
||||
if i["P1 B" ] then b = "B" else b = " " end
|
||||
if i["P1 C" ] then c = "C" else c = " " end
|
||||
if i["P1 Start"] then s = "S" else s = " " end
|
||||
|
||||
text(1,10,u..d..l..r..a..b..c..s,"yellow")
|
||||
end
|
||||
|
||||
event.onframeend(function()
|
||||
emu.setislagged(rb(0xfff6d4)==0)
|
||||
|
||||
if rb(0xfff6d4)==0 then
|
||||
lagcount = lagcount+1
|
||||
framecol = "red"
|
||||
else
|
||||
framecol = "white"
|
||||
end
|
||||
|
||||
emu.setlagcount(lagcount)
|
||||
|
||||
rndlast = rnd1
|
||||
workinglast = working
|
||||
XposLast = Xpos
|
||||
YposLast = Ypos
|
||||
end)
|
||||
|
||||
while true do
|
||||
main()
|
||||
emu.frameadvance()
|
||||
-- Gargoyles, Genesis (BizHawk)
|
||||
-- feos, 2015-2017
|
||||
|
||||
--== Shortcuts ==--
|
||||
local rb = memory.read_u8
|
||||
local rw = memory.read_u16_be
|
||||
local rws = memory.read_s16_be
|
||||
local r24 = memory.read_u24_be
|
||||
local rl = memory.read_u32_be
|
||||
local box = gui.drawBox
|
||||
local text = gui.text
|
||||
local ptext = gui.pixelText
|
||||
local line = gui.drawLine
|
||||
local AND = bit.band
|
||||
local SHIFT = bit.rshift
|
||||
|
||||
--== RAM addresses ==--
|
||||
local levnum = 0xff00ba
|
||||
local LevelFlr = 0xff00c0
|
||||
local LevelCon = 0xff00c4
|
||||
local mapline_tab = 0xff0244
|
||||
local GlobalBase = 0xff1c76
|
||||
local GolBase = 0xff2c76
|
||||
local MapA_Buff = 0xff4af0
|
||||
|
||||
--== Camera Hack ==--
|
||||
local camhack = false
|
||||
local div = 1 -- scale
|
||||
local size = 16/div -- block size
|
||||
|
||||
--== Block cache ==--
|
||||
local col = 0 -- block color
|
||||
local opout = 0x33000000 -- outer opacity
|
||||
local opin = 0x66000000 -- inner opacity
|
||||
local op = 0xff000000
|
||||
local cache = {}
|
||||
|
||||
--== Other stuff ==--
|
||||
local MsgCutoff = 20
|
||||
local MsgTime = 1
|
||||
local MsgStep = 14
|
||||
local MsgOffs = 2
|
||||
local MsgTable = {}
|
||||
local XposLast = 0
|
||||
local YposLast = 0
|
||||
local room = 0
|
||||
local workinglast = 0
|
||||
local wSize = client.getwindowsize()
|
||||
local lagcount = emu.lagcount()
|
||||
gui.defaultTextBackground(0xff000000)
|
||||
|
||||
--== Object types ==--
|
||||
local types = {
|
||||
"Goliath","Orb","Health1PLR","Health2PLR","Health1NME","Health2NME","Numeral",
|
||||
"BigExplode","SmallExplode","GlassDebris","MetalDebris","WoodDebris",
|
||||
"WallDebris","SignPiece","SteamVent","BreakWall","SkyLight","BreakLight",
|
||||
"ThrowCrate","BreakEdgeLeft","BreakEdgeRight","Spark","Spark2","Sparks",
|
||||
"Sparks2","Fireball","HomingProj1","HorzProj1","VertProj1","DirProj1",
|
||||
"DirProj2","DropMine","Scratch","Icon","RaptorBot","SniperBot","SpiderBot",
|
||||
"WaspBot","Xanatos","PlasmaBot","RabidHH","MorningStar","Archer","Arrow",
|
||||
"Valkyrie","Axe","WeaponExp","Couldron","SpittingCouldron","FireballHead",
|
||||
"FireballTrail","BigFireballHead","BigFireballTrail","Oil","OilGenerator",
|
||||
"Claw","Stump","StumpBubble","StumpFire","ClawStump","StumpFireGen","Vent",
|
||||
"VentSparks","Chain","FlameLick","Floor","MutVikBody","MutVikHead",
|
||||
"MutVikHammer","EyeOfOdin","EyeOfOdinTrail","L1BreakWall","Catapult",
|
||||
"L1BreakFloor","Gate","GateCrusher","Weight","WeightCrusher","WallFire",
|
||||
"Balista","BalistaLog","PasteWall","FlameBoulder","CastlePiece",
|
||||
"MutantSpiderBot","MutSpiLegs","MutSpiHead","MutSpiHeadFlame","MutSpiProj",
|
||||
"MutSpiElecV","MutSpiElecH","PlasmaBall","PlasmaBallTail","PlasmaDeadHead",
|
||||
"VertFlame","WallFlame","FloorFlame","OPPlatform","OPLink","OPOrb",
|
||||
"Furnace","RobotGenerator","RockGenerator","BigRock","MediumRock",
|
||||
"SmallRock","BigCouldronGen","BigCouldron","Trough","TroughGen","Energizer",
|
||||
"Demona","TrajectoryProj","WallPaste","EdgePaste","Tentacle","Infuser",
|
||||
"BigGuns","BigGunsProj","HighSignPole","HighSign","LowLight","L5Skylight",
|
||||
"L5Wall","ElecGenerator","Electricity","WaspGenerator","TunnelEdge",
|
||||
"ForegroundPost","Sorcerer","LightningTop","LightningBot","MDemonaWallFire",
|
||||
"MDemonaFloorFire","EyeRooftopUp","EyeRooftopDn","EyeRaptor"
|
||||
}
|
||||
|
||||
local function RoomTime()
|
||||
local start11 = 894--767
|
||||
local start12 = 2294
|
||||
local start13 = 5468 -- 4254 -- 4101
|
||||
local startl4 = 5506
|
||||
local startl5 = 7117
|
||||
local startl6 = 8412
|
||||
local startl7 = 17117
|
||||
local timer = emu.framecount()
|
||||
if timer < start11 then room = timer
|
||||
elseif timer < start12 then room = timer - start11
|
||||
elseif timer < start13 then room = timer - start12
|
||||
elseif timer < startl4 then room = timer - start13
|
||||
elseif timer < startl5 then room = timer - startl4
|
||||
elseif timer < startl6 then room = timer - startl5
|
||||
elseif timer < startl7 then room = timer - startl6
|
||||
end
|
||||
text(2, 2, string.format("cx:%5d\ncy:%5d\nroom:%d", camx, camy, room), "white", "bottomright")
|
||||
end
|
||||
|
||||
local function HUD()
|
||||
--if working > 0 then return end
|
||||
local rndcol = "white"
|
||||
if rndlast ~= rnd1 then rndcol = "red" end
|
||||
text(0, 2, string.format("RNG:%08X %04X", rnd1, rnd2), rndcol, "bottomleft")
|
||||
text(2, 0, string.format(
|
||||
"x: %4d\ny: %4d\ndx: %3d\ndy: %3d\nhp: %3d\nrun:%3d\ninv:%3d",
|
||||
Xpos, Ypos, Xspd, Yspd, health, run, inv),
|
||||
"white", "topright")
|
||||
end
|
||||
|
||||
local function CamhackHUD()
|
||||
if working == 0 then
|
||||
-- screen edge
|
||||
box((backx-camx- 1)/div,
|
||||
(backy-camy- 1)/div,
|
||||
(backx-camx+320)/div,
|
||||
(backy-camy+224)/div,
|
||||
0xff0000ff, 0)
|
||||
-- map edge
|
||||
box( 0-camx/div+size,
|
||||
0-camy/div+size,
|
||||
mapw/div-camx/div,
|
||||
maph/div-camy/div,
|
||||
0xff0000ff, 0)
|
||||
end
|
||||
if camhack or div > 1 then
|
||||
text(0, 0, string.format("div:%d", div), "white", "topleft")
|
||||
end
|
||||
end
|
||||
|
||||
local function PosToIndex(x, y)
|
||||
return math.floor(x/16)+math.floor(y/16)*xblocks
|
||||
end
|
||||
|
||||
local function IndexToPos(i)
|
||||
return { x=(i%xblocks)*16, y=math.floor(i/xblocks)*16 }
|
||||
end
|
||||
|
||||
local function InBounds(x, minimum, maximum)
|
||||
if x >= minimum and x <= maximum
|
||||
then return true
|
||||
else return false
|
||||
end
|
||||
end
|
||||
|
||||
local function GetBlock(x, y)
|
||||
if working > 0 then return nil end
|
||||
local final = { contour={}, block=0 }
|
||||
if x > 0 and x < mapw
|
||||
and y > 0 and y < maph then
|
||||
local pixels = 0
|
||||
local x1 = x/div-camx/div
|
||||
local x2 = x1+size-1
|
||||
local y1 = y/div-camy/div
|
||||
local y2 = y1+size-1
|
||||
local d4 = rw(mapline_tab+SHIFT(y, 4)*2)
|
||||
local a1 = r24(LevelFlr+1)
|
||||
local d1 = SHIFT(rw(MapA_Buff+d4+SHIFT(x, 4)*2), 1)
|
||||
final.block = rb(a1+d1+2)
|
||||
d1 = rw(a1+d1)
|
||||
a1 = r24(LevelCon+1)+d1
|
||||
if rb(a1) > 0 or rb(a1+8) > 0 then
|
||||
for pixel=0, 15 do
|
||||
final.contour[pixel] = rb(a1+pixel)
|
||||
end
|
||||
else
|
||||
final.contour = nil
|
||||
end
|
||||
else
|
||||
return nil
|
||||
end
|
||||
return final
|
||||
end
|
||||
|
||||
local DrawBlock = {
|
||||
[0x80] = function(x1, y1, x2, y2) -- WALL
|
||||
col = 0x00ffffff -- white
|
||||
line(x1, y1, x1, y2, col+op) -- left
|
||||
line(x2, y1, x2, y2, col+op) -- right
|
||||
end,
|
||||
[0x81] = function(x1, y1, x2, y2) -- CEILING
|
||||
col = 0x00ffffff -- white
|
||||
line(x1, y2, x2, y2, col+op) -- bottom
|
||||
end,
|
||||
[0x82] = function(x1, y1, x2, y2) -- CLIMB_U
|
||||
col = 0x0000ffff -- cyan
|
||||
line(x1, y2, x2, y2, col+op) -- bottom
|
||||
end,
|
||||
[0x83] = function(x1, y1, x2, y2) -- CLIMB_R
|
||||
col = 0x0000ffff -- cyan
|
||||
line(x1, y1, x1, y2, col+op) -- left
|
||||
end,
|
||||
[0x84] = function(x1, y1, x2, y2) -- CLIMB_L
|
||||
col = 0x0000ffff -- cyan
|
||||
line(x2, y1, x2, y2, col+op) -- right
|
||||
end,
|
||||
[0x85] = function(x1, y1, x2, y2) -- CLIMB_LR
|
||||
col = 0x0000ffff -- cyan
|
||||
line(x1, y1, x1, y2, col+op) -- left
|
||||
line(x2, y1, x2, y2, col+op) -- right
|
||||
end,
|
||||
[0x86] = function(x1, y1, x2, y2) -- CLIMB_R_STAND_R
|
||||
col = 0x00ffffff -- white
|
||||
line(x1, y1, x2, y1, col+op) -- top
|
||||
col = 0x0000ffff -- cyan
|
||||
line(x1, y1, x1, y2, col+op) -- left
|
||||
end,
|
||||
[0x87] = function(x1, y1, x2, y2) -- CLIMB_L_STAND_L
|
||||
col = 0x00ffffff -- white
|
||||
line(x1, y1, x2, y1, col+op) -- top
|
||||
col = 0x0000ffff -- cyan
|
||||
line(x2, y1, x2, y2, col+op) -- right
|
||||
end,
|
||||
[0x88] = function(x1, y1, x2, y2) -- CLIMB_LR_STAND_LR
|
||||
col = 0x00ffffff -- white
|
||||
line(x1, y1, x2, y1, col+op) -- top
|
||||
col = 0x00ff00ff -- cyan
|
||||
line(x1, y1, x1, y2, col+op) -- left
|
||||
col = 0x0000ffff -- cyan
|
||||
line(x2, y1, x2, y2, col+op) -- right
|
||||
end,
|
||||
[0x70] = function(x1, y1, x2, y2) -- GRAB_SWING
|
||||
col = 0x0000ff00 -- green
|
||||
box(x1, y1, x2, y2, col, col+opout)
|
||||
end,
|
||||
[0x7f] = function(x1, y1, x2, y2) -- EXIT
|
||||
col = 0x00ffff00 -- yellow
|
||||
end,
|
||||
[0xd0] = function(x1, y1, x2, y2) -- SPIKES
|
||||
col = 0x00ff0000 -- red
|
||||
box(x1, y1, x2, y2, col, col+opout)
|
||||
end,
|
||||
[0xd1] = function(x1, y1, x2, y2) -- SPIKES
|
||||
col = 0x00ff0000 -- red
|
||||
box(x1, y1, x2, y2, col, col+opout)
|
||||
end
|
||||
}
|
||||
|
||||
local function DrawBlockDefault(x1, y1, x2, y2) -- LEVEL_SPECIFIC
|
||||
col = 0x00ff8800 -- orange
|
||||
box(x1, y1, x2, y2, col+opin, col+opout)
|
||||
end
|
||||
|
||||
local function DrawBG(unit, x, y)
|
||||
local val= 0
|
||||
local x1 = x/div-camx/div-(camx%16)/div
|
||||
local x2 = x1+size-1
|
||||
local y1 = y/div-camy/div-(camy%16)/div
|
||||
local y2 = y1+size-1
|
||||
if unit.contour ~= nil then
|
||||
box(x1, y1, x2, y2, 0x5500ff00, 0x5500ff00)
|
||||
for pixel=0, 15 do
|
||||
val = unit.contour[pixel]
|
||||
--[ [--
|
||||
if val > 0 then
|
||||
gui.drawPixel(
|
||||
x1+pixel/div,
|
||||
y1+val/div-1/div,
|
||||
0xffffff00)
|
||||
end
|
||||
--]]--
|
||||
end
|
||||
end
|
||||
if unit.block > 0 then
|
||||
local Fn = DrawBlock[unit.block] or DrawBlockDefault
|
||||
Fn(x1, y1, x2, y2)
|
||||
box(x1, y1, x2, y2, col+opin, col+opout)
|
||||
end
|
||||
end
|
||||
|
||||
local function Background()
|
||||
if working > 0 then
|
||||
cache = {}
|
||||
return
|
||||
end
|
||||
if camhack then
|
||||
camx = Xpos-320/2*div
|
||||
camy = Ypos-224/2*div
|
||||
box(0, 0, 320, 240, 0, 0x66000000)
|
||||
end
|
||||
local border = 0
|
||||
local offset = 32
|
||||
local basex = camx+border
|
||||
local basey = camy+border
|
||||
local basei = PosToIndex(basex-offset, basey-offset)
|
||||
local boundx = 320*div-border
|
||||
local boundy = 224*div-border
|
||||
local xblockstockeck = ((camx+boundx+offset)-(basex-offset))/size/div
|
||||
local yblockstockeck = ((camy+boundy+offset)-(basey-offset))/size/div
|
||||
for yblock = 0, yblockstockeck do
|
||||
for xblock = 0, xblockstockeck do
|
||||
local i = yblock*xblocks+xblock+basei
|
||||
local x = basex+xblock*size*div
|
||||
local y = basey+yblock*size*div
|
||||
if InBounds(x, basex-offset, camx+boundx+offset) then
|
||||
local unit = cache[i]
|
||||
if unit == nil or workinglast > 0 then
|
||||
if InBounds(x, basex, camx+boundx)
|
||||
and InBounds(y, basey, camy+boundy)
|
||||
then cache[i] = GetBlock(x, y)
|
||||
end
|
||||
else
|
||||
if not InBounds(x, basex, camx+boundx)
|
||||
and not InBounds(y, basey, camy+boundy)
|
||||
then cache[i] = nil
|
||||
end
|
||||
end
|
||||
if unit ~= nil then
|
||||
DrawBG(unit, x, y)
|
||||
end
|
||||
elseif cache[i] ~= nil
|
||||
then cache[i] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
CamhackHUD()
|
||||
end
|
||||
|
||||
local function Clamp(v, vmin, vmax)
|
||||
if v < vmin then v = vmin end
|
||||
if v > vmax then v = vmax end
|
||||
return v
|
||||
end
|
||||
|
||||
local function Objects()
|
||||
if working > 0 then return end
|
||||
for i=0, 63 do
|
||||
local base = GlobalBase+i*128
|
||||
local flag2 = AND(rb(base+0x49), 0x10) -- active
|
||||
if flag2 == 0x10 then
|
||||
local xpos = rw (base+0x00)
|
||||
local ypos = rw (base+0x02)
|
||||
local state = rw (base+0x0c)
|
||||
local dmg = rb (base+0x10)
|
||||
local id = rw (base+0x40)
|
||||
local hp = rw (base+0x50)
|
||||
local cRAM = r24(base+0x75) -- pointer to 4 collision boxes per object
|
||||
local xscr = (xpos-camx)/div
|
||||
local yscr = (ypos-camy)/div
|
||||
local num = id/6
|
||||
local name = types[num]
|
||||
local col = 0 -- collision color
|
||||
for boxx=0, 4 do
|
||||
local x0 = rw (cRAM+boxx*8)
|
||||
local x1 = (rws(cRAM+boxx*8+0)-camx)/div
|
||||
local y1 = (rws(cRAM+boxx*8+2)-camy)/div
|
||||
local x2 = (rws(cRAM+boxx*8+4)-camx)/div
|
||||
local y2 = (rws(cRAM+boxx*8+6)-camy)/div
|
||||
if boxx == 0 then
|
||||
col = 0xff00ff00 -- body
|
||||
-- archer hp doesn't matter
|
||||
if id == 282 or id == 258 then hp = 1 end
|
||||
if hp > 0 and id > 0 and x0 ~= 0x8888 then
|
||||
local xx = Clamp(xscr, 0, 318-string.len(name)*4)
|
||||
local yy = Clamp(yscr, 0, 214)
|
||||
ptext(xx, yy+2, string.format("%d", hp), col)
|
||||
end
|
||||
elseif boxx == 1 then
|
||||
col = 0xffffff00 -- floor
|
||||
elseif boxx == 2 then
|
||||
if dmg > 0
|
||||
then col = 0xffff0000 -- projectile
|
||||
else col = 0xff8800ff -- item
|
||||
end
|
||||
if dmg > 0 then
|
||||
text(x1*wSize+2, y2*wSize+1,
|
||||
string.format("%d", dmg), col, 0x88000000)
|
||||
end
|
||||
else
|
||||
col = 0xffffffff -- other
|
||||
end
|
||||
if x1 ~= 0x8888
|
||||
and x1 <= 320 and x2 >= 0
|
||||
and y1 <= 224 and y2 >= 0 then
|
||||
box(x1, y1, x2, y2, col, 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function PostRndRoll()
|
||||
for i = 1,#MsgTable do
|
||||
if MsgTable[i] and MsgTable[i].index == i then
|
||||
local base = MsgTable[i].base
|
||||
local xpos = rw(base+0x00)
|
||||
local ypos = rw(base+0x02)
|
||||
local id = rw(base+0x40)
|
||||
local x = (xpos-camx)/div
|
||||
local y = (ypos-camy)/div
|
||||
local num = id/6
|
||||
local ymsg = 0
|
||||
local yoffs = math.floor((i-1)/MsgCutoff)*14
|
||||
local name = types[num]
|
||||
local color = 0xffffff00
|
||||
|
||||
if base == GolBase then
|
||||
name = "Goliath"
|
||||
elseif not name then
|
||||
name = string.format("%X", base)
|
||||
color = 0xff00ffff
|
||||
end
|
||||
if y < 224/2 then
|
||||
yoffs = -yoffs
|
||||
ymsg = 210
|
||||
end
|
||||
|
||||
x = Clamp(x, 2, 320-string.len(name)*4)
|
||||
y = Clamp(y, 20, 214)
|
||||
|
||||
line ((i-1)%MsgCutoff*MsgStep+3 +MsgOffs, ymsg+yoffs+4, x, y, color-0x88000000)
|
||||
ptext((i-1)%MsgCutoff*MsgStep*wSize+MsgOffs, ymsg+yoffs, i, color)
|
||||
|
||||
MsgTable[i].timer = MsgTable[i].timer-1
|
||||
if MsgTable[i].timer <= 0 then
|
||||
MsgTable[i] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function PlayerBoxes()
|
||||
if working > 0 then return end
|
||||
local xx = (Xpos-camx)/div
|
||||
local yy = (Ypos-camy)/div
|
||||
local col = 0xff00ffff
|
||||
local swcol = col -- usual detection
|
||||
if Yspd > 0 then -- gimme swings to grab!
|
||||
swcol = 0xff00ff00
|
||||
elseif Yspd == 0 then -- can tell that too
|
||||
swcol = 0xffffffff
|
||||
end
|
||||
if facing == 2
|
||||
then box(xx-0xf /div-2, yy-0x2c/div-1, xx-0xf/div+0, yy-0x2c/div+1, swcol, 0) -- lefttop
|
||||
else box(xx+0xf /div , yy-0x2c/div-1, xx+0xf/div+2, yy-0x2c/div+1, swcol, 0) -- rightttop
|
||||
end
|
||||
box(xx -1, yy-0x2c/div-1, xx +1, yy-0x2c/div+1, col, 0) -- top
|
||||
box(xx-0xf /div-2, yy-0x1f/div-1, xx-0xf /div+0, yy-0x1f/div+1, col, 0) -- left
|
||||
box(xx+0x10/div-1, yy-0x1f/div-1, xx+0x10/div+1, yy-0x1f/div+1, col, 0) -- right
|
||||
-- box(xx -1, yy-0x1f/div-1, xx +1, yy-0x1f/div+1, col, 0) -- center
|
||||
box(xx -1, yy-0x0f/div-1, xx +1, yy-0x0f/div+1, col, 0) -- bottom
|
||||
box(xx -1, yy -1, xx +1, yy +1,0xffffff00, 0) -- feet
|
||||
-- box(xx -1, yy+0x10/div-1, xx +1, yy+0x10/div+1, col, 0) -- ground
|
||||
end
|
||||
|
||||
local function Input()
|
||||
local i, u, d, l, r, a, b, c, s
|
||||
if movie.isloaded()
|
||||
then i = movie.getinput(emu.framecount()-1)
|
||||
else i = joypad.getimmediate()
|
||||
end
|
||||
if i["P1 Up" ] then u = "U" else u = " " end
|
||||
if i["P1 Down" ] then d = "D" else d = " " end
|
||||
if i["P1 Left" ] then l = "L" else l = " " end
|
||||
if i["P1 Right"] then r = "R" else r = " " end
|
||||
if i["P1 A" ] then a = "A" else a = " " end
|
||||
if i["P1 B" ] then b = "B" else b = " " end
|
||||
if i["P1 C" ] then c = "C" else c = " " end
|
||||
if i["P1 Start"] then s = "S" else s = " " end
|
||||
text(1, 10, u..d..l..r..a..b..c..s, "yellow")
|
||||
end
|
||||
|
||||
event.onframeend(function()
|
||||
emu.setislagged(rb(0xfff6d4) == 0)
|
||||
if rb(0xfff6d4) == 0 then
|
||||
lagcount = lagcount+1
|
||||
framecol = "red"
|
||||
else
|
||||
framecol = "white"
|
||||
end
|
||||
emu.setlagcount(lagcount)
|
||||
wSize = client.getwindowsize()
|
||||
rndlast = rnd1
|
||||
workinglast = working
|
||||
XposLast = Xpos
|
||||
YposLast = Ypos
|
||||
end)
|
||||
|
||||
event.onmemoryexecute(function()
|
||||
local a0 = AND(emu.getregister("M68K A0"), 0xffffff)
|
||||
if a0 ~= 0xff4044 then
|
||||
for i = 1, 200 do
|
||||
if MsgTable[i] == nil then
|
||||
MsgTable[i] = { index = i, timer = MsgTime, base = a0 }
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end, 0x257A, "RNGseed")
|
||||
|
||||
local function main()
|
||||
rnd1 = rl (0xff001c)
|
||||
rnd2 = rw (0xff0020)
|
||||
working = rb (0xff0073)
|
||||
xblocks = rw (0xff00d4)
|
||||
mapw = rw (0xff00d4)*8
|
||||
maph = rw (0xff00d6)*8
|
||||
Xpos = rws(0xff0106)
|
||||
Ypos = rws(0xff0108)
|
||||
camx = rws(0xff010c)+16
|
||||
camy = rws(0xff010e)+16
|
||||
run = rb (0xff1699)
|
||||
inv = rw (0xff16d2)
|
||||
health = rws(0xff2cc6)
|
||||
backx = camx
|
||||
backy = camy
|
||||
Xspd = Xpos-XposLast
|
||||
Yspd = Ypos-YposLast
|
||||
facing = AND(rb(GolBase+0x48), 2) -- object flag 1
|
||||
if working > 0 then MsgTable = {} end
|
||||
Background()
|
||||
PlayerBoxes()
|
||||
Objects()
|
||||
PostRndRoll()
|
||||
HUD()
|
||||
RoomTime()
|
||||
end
|
||||
|
||||
while true do
|
||||
main()
|
||||
emu.frameadvance()
|
||||
end
|
|
@ -21,11 +21,13 @@
|
|||
#include gamedb_sega_md.txt
|
||||
#include gamedb_snes.txt
|
||||
#include gamedb_user.txt
|
||||
#include gamedb_vectrex.txt
|
||||
#include gamedb_ws.txt
|
||||
#include gamedb_wsc.txt
|
||||
#include gamedb_zxspectrum.txt
|
||||
#include gamedb_amstradcpc.txt
|
||||
#include gamedb_ngp.txt
|
||||
#include gamedb_channelf.txt
|
||||
|
||||
; ************ TI-83 ************
|
||||
|
||||
|
|
|
@ -50,9 +50,9 @@ sha1:a65f487740069640952803218b70580b2fb724b7 A-Team, The (Atari) (Prototype) (
|
|||
sha1:821cffe5f5940b2951f280d07d2691e140f54ad2 A-Team, The (Atari) (Prototype) (PAL-60) [!] A26 m=F8;NTSC=true
|
||||
sha1:53413577afe7def1d390e3892c45822405513c07 A-Team, The (Atari) (Prototype) [!] A26 m=F8;NTSC=true
|
||||
sha1:3607f46475f4b1b8989f7327f90ca53a4ac0e9fe A-VCS-tec Challenge (beta 5) (PD) A26 m=F8;NTSC=true
|
||||
sha1:d7c62df8300a68b21ce672cfaa4d0f2f4b3d0ce1 Acid Drop (1992) (Salu) (PAL) [!] A26 m=F6;PAL=true
|
||||
sha1:66216ed98295f3fde35a0cc9398b4f2fc79f2375 Acid Drop (1992) (Salu) (PAL) [b1] A26 m=F8;PAL=true
|
||||
sha1:2ad5e47e360842bb5f9c23bbe2c19866d890f427 Acid Drop (NTSC Conversion) (TJ) A26 m=F8;NTSC=true
|
||||
sha1:d7c62df8300a68b21ce672cfaa4d0f2f4b3d0ce1 Acid Drop (1992) (Salu) (PAL) [!] A26 SP_RESET=true;m=F6;PAL=true
|
||||
sha1:66216ed98295f3fde35a0cc9398b4f2fc79f2375 Acid Drop (1992) (Salu) (PAL) [b1] A26 SP_RESET=true;m=F8;PAL=true
|
||||
sha1:2ad5e47e360842bb5f9c23bbe2c19866d890f427 Acid Drop (NTSC Conversion) (TJ) A26 SP_RESET=true;m=F8;NTSC=true
|
||||
sha1:9e6fb047ee9fa0a454ca23673ed9693430032dc6 Action Force (1983) (Parker Bros) (PAL) [!] A26 m=4K;PAL=true
|
||||
sha1:bfcc35feee3713f5028122844d027c88a84772b6 2 Pak Special Red - Motocross,Boom Bang (1990) (PAL) [!] A26 m=F6;PAL=true
|
||||
sha1:8a503416ca6f2404bc52382e337f31238bba9534 3-D Corridor Demo 2 (29-03-2003) (MP) A26 m=4K;NTSC=true
|
||||
|
@ -68,13 +68,13 @@ sha1:317a7b8693af44095c23437253a32cc748824ccf Adventure (Color Scrolling) [h1]
|
|||
sha1:4ffe36c5113305714e27c72d7f3abecc9b08a630 Adventure (New Graphics) [h1] A26 m=4K;NTSC=true
|
||||
sha1:0b0875ad1bd494c9dd8de4ff0a06938e699f60d5 Adventure 34 by Kurt Howe (Adventure Hack) A26 m=4K;NTSC=true
|
||||
sha1:8501444b12f7f9e2103cd2bcf0c8d3f5b7536569 Adventure II (Adventure Hack) A26 m=4K;NTSC=true
|
||||
sha1:03a495c7bfa0671e24aa4d9460d232731f68cb43 Adventures of Tron (1983) (Mattel) A26 m=4K;NTSC=true
|
||||
sha1:03a495c7bfa0671e24aa4d9460d232731f68cb43 Adventures of Tron (1983) (Mattel) A26 SP_RESET=true;m=4K;NTSC=true
|
||||
sha1:6e420544bf91f603639188824a2b570738bb7e02 Adventures on GX-12 (Telegames) (PAL) [!] A26 m=4K;PAL=true
|
||||
sha1:3b02e7dacb418c44d0d3dc77d60a9663b90b0fbc Air Raid (Men-A-Vision) A26 m=4K;NTSC=true
|
||||
sha1:e65a0c6c5a1f9f05ebcfaaa7b2c9ee6625bf2d83 Air Raiders (1982) (Mattel) (PAL) [p1][!] A26 m=4K;PAL=true
|
||||
sha1:29f5c73d1fe806a4284547274dd73f9972a7ed70 Air Raiders (1982) (Mattel) [!] A26 m=4K;NTSC=true
|
||||
sha1:a9a51405b521ae0b465f521fa098e8b3aedd018b Air Raiders (1982) (Mattel) [a1][!] A26 m=4K;NTSC=true
|
||||
sha1:39a98b42f0670dfe6a842645f09f24583ae8ee60 Air Raiders (1982) (Mattel) [h1] A26 m=4K;NTSC=true
|
||||
sha1:e65a0c6c5a1f9f05ebcfaaa7b2c9ee6625bf2d83 Air Raiders (1982) (Mattel) (PAL) [p1][!] A26 SP_RESET=true;m=4K;PAL=true
|
||||
sha1:29f5c73d1fe806a4284547274dd73f9972a7ed70 Air Raiders (1982) (Mattel) [!] A26 SP_RESET=true;m=4K;NTSC=true
|
||||
sha1:a9a51405b521ae0b465f521fa098e8b3aedd018b Air Raiders (1982) (Mattel) [a1][!] A26 SP_RESET=true;m=4K;NTSC=true
|
||||
sha1:39a98b42f0670dfe6a842645f09f24583ae8ee60 Air Raiders (1982) (Mattel) [h1] A26 SP_RESET=true;m=4K;NTSC=true
|
||||
sha1:b96c7a509bf610f61f82377bfd506db3dba2b423 Air-Sea Battle (1977) (Atari) (PAL) [!] A26 m=2K;PAL=true
|
||||
sha1:a746fdc82b336a9d499bf17f50b41e0193ba595e Air-Sea Battle (1977) (Atari) [!] A26 m=2K;NTSC=true
|
||||
sha1:d3897fc60585e420ae816a2db909400f6cbadd88 Air-Sea Battle (1977) (Atari) [o1] A26 m=2K;NTSC=true
|
||||
|
@ -323,9 +323,9 @@ sha1:67387d0d3d48a44800c44860bf15339a81f41aa9 Bugs (1982) (Data Age) [!] A26 m
|
|||
sha1:a8aedea627c67c38032cdde441fb98dad226916a Bugs (1983) (Gameworld) (PAL) [!] A26 m=4K;PAL=true
|
||||
sha1:9c0e13af336a986c271fe828fafdca250afba647 Bugs Bunny (Atari) (Prototype) [!] A26 m=F8;NTSC=true
|
||||
sha1:13534da5c382ed20d070ffe93f35c4c11b36e1bc Bullet Demo (20-12-2002) (CT) A26 m=4K;NTSC=true
|
||||
sha1:5614c32e76c8b272c38c16720ebbb1818d3d3103 Bump 'N' Jump (1983) (Mattel) [b1] A26 m=F6;NTSC=true
|
||||
sha1:1819ef408c1216c83dcfeceec28d13f6ea5ca477 Bump 'N' Jump (1983) (Mattel) A26 m=E7;NTSC=true
|
||||
sha1:35bc4048f58bb170313872a0bce44fb1ca3217cc Bump 'N' Jump (Telegames) (PAL) [!] A26 m=F8;PAL=true
|
||||
sha1:5614c32e76c8b272c38c16720ebbb1818d3d3103 Bump 'N' Jump (1983) (Mattel) [b1] A26 SP_RESET=true;m=F6;NTSC=true
|
||||
sha1:1819ef408c1216c83dcfeceec28d13f6ea5ca477 Bump 'N' Jump (1983) (Mattel) A26 SP_RESET=true;m=E7;NTSC=true
|
||||
sha1:35bc4048f58bb170313872a0bce44fb1ca3217cc Bump 'N' Jump (Telegames) (PAL) [!] A26 SP_RESET=true;m=F8;PAL=true
|
||||
sha1:ad48f4952e867a2b97900d965b69f50fddf8ba2d Bumper Bash (1983) (Spectravideo) (PAL) [!] A26 m=4K;PAL=true
|
||||
sha1:6c199782c79686dc0cbce6d5fe805f276a86a3f5 Bumper Bash (1983) (Spectravideo) A26 m=4K;NTSC=true
|
||||
sha1:49e01b8048ae344cb65838f6b1c1de0e1f416f29 Burgertime (1982) (Mattel) A26 SP_RESET=true;m=E7;NTSC=true
|
||||
|
@ -855,8 +855,8 @@ sha1:6b9e591cc53844795725fc66c564f0364d1fbe40 Frogger II - Threedeep! (1983) (P
|
|||
sha1:bce92de22fc8950f0eebb643d96fe9fa5dba2b72 Frogger II - Threedeep! (1984) (Parker Bros) (PAL) [!] A26 m=E0;PAL=true
|
||||
sha1:5215cf9051e833482e115d16ff90fee5f01c3e84 Frogger Preview (1982) (Starpath) [a1] A26 m=AR;NTSC=true
|
||||
sha1:2edb64be1bb6f4215f520ec2f487b19f29724b8d Frogger Preview (1982) (Starpath) A26 m=AR;NTSC=true
|
||||
sha1:7682b4b6d45865b7eec1244e5d76f0f2efdb17e7 Frogs and Flies (1982) (Mattel) (PAL) [p1][!] A26 m=4K;PAL=true
|
||||
sha1:f344d5a8dc895c5a2ae0288f3c6cb66650e49167 Frogs and Flies (1982) (Mattel) [!] A26 m=4K;NTSC=true
|
||||
sha1:7682b4b6d45865b7eec1244e5d76f0f2efdb17e7 Frogs and Flies (1982) (Mattel) (PAL) [p1][!] A26 SP_RESET=true;m=4K;PAL=true
|
||||
sha1:f344d5a8dc895c5a2ae0288f3c6cb66650e49167 Frogs and Flies (1982) (Mattel) [!] A26 SP_RESET=true;m=4K;NTSC=true
|
||||
sha1:cf32bfcd7f2c3b7d2a6ad2f298aea2dfad8242e7 Front Line (1982) (Coleco) A26 m=F8;NTSC=true
|
||||
sha1:58a6f82434ccf49ca420596809ce9545373845a2 Frostbite (1983) (Activision) (PAL) [!] A26 m=4K;PAL=true
|
||||
sha1:8ad03667bbf73d3c7760cb82f2c4442f8745483c Frostbite (1983) (Activision) (PAL) [p1][!] A26 m=4K;PAL=true
|
||||
|
@ -1256,9 +1256,9 @@ sha1:128c3a98d78b043edabe8964cf7998955342fa2d Kiss Meets Pacman (Cody Pittman)
|
|||
sha1:45623a1c8fb5074de98c37f005edd5b1d0937dae Klax (1990) (Atari) (PAL) [!] A26 m=F6SC;PAL=true
|
||||
sha1:3162259c6dbfbb57a2ea41d849155702151ee39b Klax (1990) (Atari) A26 m=F6SC;NTSC=true
|
||||
sha1:759597d1d779cfdfd7aa30fd28a59acc58ca2533 Knight on the Town (1982) (Playaround) A26 m=4K;NTSC=true
|
||||
sha1:2f550743e237f6dc8c75c389a01b02e9a396fdad Kool Aid Man (1982) (Mattel) A26 m=4K;NTSC=true
|
||||
sha1:f5c193ed00bf557ddd5ab698d92a7483b89c6519 Kool Aid Man (Fixed) (15-11-2002) (CT) A26 m=4K;NTSC=true
|
||||
sha1:38f55fc76bec14eb661a7b594301c271aa5f5f3b Kool Aid Man (PAL Conversion) (16-11-2002) (Fabrizio Zavagli) A26 m=4K;NTSC=true
|
||||
sha1:2f550743e237f6dc8c75c389a01b02e9a396fdad Kool Aid Man (1982) (Mattel) A26 SP_RESET=true;m=4K;NTSC=true
|
||||
sha1:f5c193ed00bf557ddd5ab698d92a7483b89c6519 Kool Aid Man (Fixed) (15-11-2002) (CT) A26 SP_RESET=true;m=4K;NTSC=true
|
||||
sha1:38f55fc76bec14eb661a7b594301c271aa5f5f3b Kool Aid Man (PAL Conversion) (16-11-2002) (Fabrizio Zavagli) A26 SP_RESET=true;m=4K;NTSC=true
|
||||
sha1:82e64366795b011c2a2f1755bf899cc2c0617fe8 Krieg Der Sterne (Atlantis-Ariola) (PAL) [!] A26 m=4K;PAL=true
|
||||
sha1:4bdf1cf73316bdb0002606facf11b6ddcb287207 Krull (1983) (Atari) [!] A26 m=F8;NTSC=true
|
||||
sha1:07a1c1b1a2297c4edde0e16f610b5ec23c775217 Krull (CCE) A26 m=F8;NTSC=true
|
||||
|
@ -1305,9 +1305,9 @@ sha1:4f3e51f68c10d2fa7c4b9764b0cb81fdded0fde4 Lilly Adventure (Starsoft) (NTSC
|
|||
sha1:63f4776aa4c35d124001918b733cdb4d46dfbe9b Lilly Adventure (Starsoft) (PAL) [!] A26 m=4K;PAL=true
|
||||
sha1:5425578808363ee72dbba6195533549679137777 Lines Demo (Eckhard Stolberg) (PAL) (PD) A26 m=2K;PAL=true
|
||||
sha1:fe208ad775cbf9523e7a99632b9f10f2c9c7aa87 Lochjaw (1982) (Apollo) A26 m=4K;NTSC=true
|
||||
sha1:119171935ed9ea877de4f2a68aee31cd55bc697d Lock 'N' Chase (1982) (Mattel) (PAL) [p1][!] A26 m=4K;PAL=true
|
||||
sha1:fc3d75d46d917457aa1701bf47844817d0ba96c3 Lock 'N' Chase (1982) (Mattel) [!] A26 m=4K;NTSC=true
|
||||
sha1:075ec3678ceabbee46a7d576fdd199a4ab908cc0 Lock 'N' Chase (1982) (Telegames) (PAL) [!] A26 m=4K;PAL=true
|
||||
sha1:119171935ed9ea877de4f2a68aee31cd55bc697d Lock 'N' Chase (1982) (Mattel) (PAL) [p1][!] A26 SP_RESET=true;m=4K;PAL=true
|
||||
sha1:fc3d75d46d917457aa1701bf47844817d0ba96c3 Lock 'N' Chase (1982) (Mattel) [!] A26 SP_RESET=true;m=4K;NTSC=true
|
||||
sha1:075ec3678ceabbee46a7d576fdd199a4ab908cc0 Lock 'N' Chase (1982) (Telegames) (PAL) [!] A26 SP_RESET=true;m=4K;PAL=true
|
||||
sha1:ef02fdb94ac092247bfcd5f556e01a68c06a4832 Lord of The Rings (1983) (Parker Bros) (Prototype) A26 m=E0;NTSC=true
|
||||
sha1:43575ed97f8a585c5bae6fb1a7b2133c87b4d256 Lord of the Rings - Fellowship of the Ring by Adam Thornton (Dark Mage Hack) (PD) [a1] A26 m=4K;NTSC=true
|
||||
sha1:721514e5c31c8f2b30b4a2bf2cda69a810cac75b Lord of the Rings - Fellowship of the Ring by Adam Thornton (Dark Mage Hack) (PD) A26 m=4K;NTSC=true
|
||||
|
@ -1359,8 +1359,8 @@ sha1:6ef010513e01520560616994cbe3f10995490996 Max3 (2001) (Maxime Beauvais) (PD
|
|||
sha1:a2b13017d759346174e3d8dd53b6347222d3b85d Maze (AKA Slot Racers) (1978) (Sears) [!] A26 m=2K;NTSC=true
|
||||
sha1:05f8d0e9f9bec192dfe5947965039817c8c390df Maze (AKA Slot Racers) (1978) (Sears) [o1] A26 m=2K;NTSC=true
|
||||
sha1:365a3af336d71f8f80345de9fcebb100f5141182 Maze 003 Demo (PD) A26 m=4K;NTSC=true
|
||||
sha1:4a255c1d277f9ceb98dfe61ec2c6f7537ca4e7bf Maze Craze (1978) (Atari) (PAL) [!] A26 m=4K;PAL=true
|
||||
sha1:aba25089d87cd6fee8d206b880baa5d938aae255 Maze Craze (1978) (Atari) A26 m=4K;NTSC=true
|
||||
sha1:4a255c1d277f9ceb98dfe61ec2c6f7537ca4e7bf Maze Craze (1978) (Atari) (PAL) [!] A26 SP_FRAME=true;m=4K;PAL=true
|
||||
sha1:aba25089d87cd6fee8d206b880baa5d938aae255 Maze Craze (1978) (Atari) A26 SP_FRAME=true;m=4K;NTSC=true
|
||||
sha1:43c309177fde4adf59c99ba5d3865df2a588a79e Maze Demo 1 (PD) A26 m=4K;NTSC=true
|
||||
sha1:648e91958afdf264e8e6b45521ecb542fb340586 Maze Demo 2 (PD) A26 m=4K;NTSC=true
|
||||
sha1:0103b35b1aef6b10c1c0a44b213ebf30af708df6 McDonald's (1983) (Parker Bros) (Prototype) [!] A26 m=4K;NTSC=true
|
||||
|
@ -1559,9 +1559,9 @@ sha1:03eb4a3b3db04c1782e1a91d27ea515163d258fb Oink! (CCE) A26 m=4K;NTSC=true
|
|||
sha1:7feef3965706bc64f0f0a940149b2523e0735ce6 Okie Dokie (4K) (PD) A26 m=4K;NTSC=true
|
||||
sha1:7bd1cbddefcf3bd24da570be015234d0c444a7e5 Okie Dokie (Older) (PD) A26 m=2K;NTSC=true
|
||||
sha1:8a47b1930971f271a935c50d423e152aaea6ac59 Okie Dokie (PD) A26 m=2K;NTSC=true
|
||||
sha1:ca4f26716120d2e4ba531c2ea50b570b9980756e Omega Race (1983) (CBS Electronics) [o1] A26 m=F6SC;NTSC=true
|
||||
sha1:dcaab259e7617c7ac7d349893451896a9ca0e292 Omega Race (1983) (CBS Electronics) A26 m=FA;NTSC=true
|
||||
sha1:c7a9ecad6c1a82048de54d33b231abd89fb08bd8 Omega Race JS (TJ) A26 m=FA;NTSC=true
|
||||
sha1:ca4f26716120d2e4ba531c2ea50b570b9980756e Omega Race (1983) (CBS Electronics) [o1] A26 SP_RESET=true;m=F6SC;NTSC=true
|
||||
sha1:dcaab259e7617c7ac7d349893451896a9ca0e292 Omega Race (1983) (CBS Electronics) A26 SP_RESET=true;m=FA;NTSC=true
|
||||
sha1:c7a9ecad6c1a82048de54d33b231abd89fb08bd8 Omega Race JS (TJ) A26 SP_RESET=true;m=FA;NTSC=true
|
||||
sha1:fbf180f8f35178099244bc1ae341ccff87838907 One Blue Bar Demo (PD) A26 m=4K;NTSC=true
|
||||
sha1:e52ca6e73c931ef71c63e164704fb398086e4308 One On One by Angelino (Basketball Hack) A26 m=2K;NTSC=true
|
||||
sha1:98007f26356b4032a2ae4e9fddea5a38a988eb13 Oscar's Trash Race (1983) (Atari) (PAL) [!] A26 m=F8;PAL=true
|
||||
|
@ -2302,8 +2302,8 @@ sha1:7c2a2ddbdef639ed2985ce66ae717b2285a94ae0 Star Raiders (1982) (Atari) (PAL)
|
|||
sha1:e10cce1a438c82bd499e1eb31a3f07d7254198f5 Star Raiders (1982) (Atari) A26 m=F8;NTSC=true
|
||||
sha1:d2b6290afb81bad126321d923d222c26e2de5fa8 Star Ship - Outer Space (1977) [o1] A26 m=2K;NTSC=true
|
||||
sha1:878e78ed46e29c44949d0904a2198826e412ed81 Star Ship - Outer Space (1977) A26 m=2K;NTSC=true
|
||||
sha1:de05d1ca8ad1e7a85df3faf25b1aa90b159afded Star Strike (1982) (Mattel) A26 m=4K;NTSC=true
|
||||
sha1:a0e29405a92773bf3baa2845788a8add8f3bc0b1 Star Strike (Telegames) (PAL) [!] A26 m=4K;PAL=true
|
||||
sha1:de05d1ca8ad1e7a85df3faf25b1aa90b159afded Star Strike (1982) (Mattel) A26 SP_RESET=true;m=4K;NTSC=true
|
||||
sha1:a0e29405a92773bf3baa2845788a8add8f3bc0b1 Star Strike (Telegames) (PAL) [!] A26 SP_RESET=true;m=4K;PAL=true
|
||||
sha1:667a528e8cf3fd7f533cf67993f48bcc3c100e0d Star Trek - Strategic Operations Simulator (1983) (Sega) (PAL) [!] A26 m=F8;PAL=true
|
||||
sha1:61a3ebbffa0bfb761295c66e189b62915f4818d9 Star Trek - Strategic Operations Simulator (1983) (Sega) A26 m=F8;NTSC=true
|
||||
sha1:417bb89e1117413321ffba48a17e005b2687680b Star Voyager (1982) (CCE) [!] A26 m=4K;NTSC=true
|
||||
|
@ -2554,8 +2554,8 @@ sha1:ccf422636180f24becaa8af0cc391f95e599a330 Tunnel Demo (28-03-2003) (AD) A26
|
|||
sha1:0f6552a0afe40cc1c448313569db8c9a8cda6d21 Tunnel Demo (Cycling Colours 2) (29-03-2003) (AD) A26 m=4K;NTSC=true
|
||||
sha1:8dad50a3918c7462811c2def42f289cd123822af Tunnel Demo (Red Spiral) (30-03-2003) (AD) A26 m=4K;NTSC=true
|
||||
sha1:4df103678f9c88b017e64f1e14e741fc6e15340c Tunnel Demo 2 (27-03-2003) (CT) A26 m=4K;NTSC=true
|
||||
sha1:fc1a0b58765a7dcbd8e33562e1074ddd9e0ac624 Tunnel Runner (1983) (CBS Electronics) [!] A26 m=FA;NTSC=true
|
||||
sha1:460094d7689ac0c4435b72e3e390f4b6f2ef112c Tunnel Runner (1983) (CBS Electronics) [a1][!] A26 m=FA;NTSC=true
|
||||
sha1:fc1a0b58765a7dcbd8e33562e1074ddd9e0ac624 Tunnel Runner (1983) (CBS Electronics) [!] A26 SP_RESET=true;m=FA;NTSC=true
|
||||
sha1:460094d7689ac0c4435b72e3e390f4b6f2ef112c Tunnel Runner (1983) (CBS Electronics) [a1][!] A26 SP_RESET=true;m=FA;NTSC=true
|
||||
sha1:0921fab66ce4b712701326ce105e1a84ac47b497 Turbo (Coleco) Prototype Fake v0.1 (TJ) A26 m=2K;NTSC=true
|
||||
sha1:b594a9acedd4734070776bf69d0f08abb5c261bf Turbo WIP (TJ) A26 m=F8;NTSC=true
|
||||
sha1:1162fe46977f01b4d25efab813e0d05ec90aeadc Turmoil (1982) (20th Century Fox) [!] A26 m=4K;NTSC=true
|
||||
|
@ -2596,7 +2596,7 @@ sha1:082a7bc7d0fdbf307501cd146e18ed3d03b9ec0f Vertical Ship Demo 1 (PD) A26 m=
|
|||
sha1:1d641abfb95e3b4b7abaad42a8760c8c9ce993a6 Vertically Scrolling Playfield (02-02-2003) (Aaron Bergstrom) A26 m=4K;NTSC=true
|
||||
sha1:24c1c6e1a495137bec53818c2cd8bd83c8336d21 Video Checkers (1978) (Atari) (PAL) [!] A26 m=4K;PAL=true
|
||||
sha1:babae88a832b76d8c5af6ea63b8f10a0da5bb992 Video Checkers (1978) (Atari) A26 m=4K;NTSC=true
|
||||
sha1:043ef523e4fcb9fc2fc2fda21f15671bf8620fc3 Video Chess (1978) (Atari) A26 m=4K;NTSC=true
|
||||
sha1:043ef523e4fcb9fc2fc2fda21f15671bf8620fc3 Video Chess (1978) (Atari) A26 SP_FRAME=true;m=4K;NTSC=true
|
||||
sha1:3f2ad3666eb713b20484e3677d8e1cac8fbd323e Video Cube (CCE) A26 m=4K;NTSC=true
|
||||
sha1:1554b146d076b64776bf49136cea01f60eeba4c1 Video Jogger (Exus) (PAL) A26 m=4K;PAL=true
|
||||
sha1:19d4f52d399c2ab70e411be51b715341db7a41bf Video Life (CommaVid) [h1] A26 m=CV;NTSC=true
|
||||
|
@ -2699,3 +2699,4 @@ sha1:00CCF622E7BA4D0A39DCBABAB771CE815B0FB8FE Boulder Dash (2005) (Andrew Davie
|
|||
sha1:650DA2339D41D1D2F180A6CAFE8DC311AC588ACD Boulder Dash Intro Tune (2005) (Erik Ehrling) A26 m=4K;NTSC=true
|
||||
sha1:F28E52921646A18467577370808454F494C15EFE 0840 EconoBanking A26 m=0840;NTSC=true
|
||||
sha1:2A9647E27AB27E6CF82B3BF122EDF212FA34AE86 Halo2600 Final A26 m=m4K
|
||||
sha1:341BB93E67C21063F3910845D1AF59FEA129FF21 Bang! A26 m=F4SC
|
|
@ -0,0 +1,58 @@
|
|||
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
|
||||
;;; Type: NO-INTRO
|
||||
;;; Source: Fairchild - Channel F - 20120223-000000
|
||||
;;; FileGen: 2019-04-16 13:59:49 (UTC)
|
||||
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
|
||||
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
|
||||
;;; Bad Dumps
|
||||
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
|
||||
;
|
||||
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
|
||||
;;; Hacks
|
||||
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
|
||||
;
|
||||
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
|
||||
;;; Over Dumps
|
||||
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
|
||||
;
|
||||
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
|
||||
;;; Translated
|
||||
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
|
||||
;
|
||||
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
|
||||
;;; Believed Good
|
||||
;;;;;;;;;;--------------------------------------------------;;;;;;;;;;
|
||||
F7BF7D55A7660FFA80D08AD1BA903FF7 Alien Invasion (USA) ChannelF USA
|
||||
D89B48AE8C906488CAAC2B2AE1D63D88 Backgammon, Acey-Deucey (USA) ChannelF USA
|
||||
4FA83F734C139963AA02BDBB7A52E500 Baseball (USA) ChannelF USA
|
||||
25E231E7A464A32B4715BFB47AF89240 Bowling (USA) ChannelF USA
|
||||
BB7F7BBBE21F142591CDCAFA98D7F6E4 Casino Poker (USA) ChannelF USA
|
||||
35D61D40EF7EC337CBA092AABAC74DBD Checkers (USA) ChannelF USA
|
||||
54CF17C48707467295749490D458EAFB Demonstration Cartridge (USA) ChannelF USA
|
||||
F6916B665893AA8138CDE57C37E50ADA Demonstration Cartridge 2 (USA) ChannelF USA
|
||||
4F11F13CBCA685CB20E888F87B3B1586 Desert Fox, Shooting Gallery (USA) ChannelF USA
|
||||
6FFEDAED3C5CD8BA74D98901849CC451 Dodge It (USA) ChannelF USA
|
||||
F80AF74B09D058B90E719BB7DFBDD50E Drag Race (USA) ChannelF USA
|
||||
9E0711B140E22729687DB1E1354980AB Galactic Space Wars, Lunar Lander (USA) ChannelF USA
|
||||
0124CD0B61DF5502AABD59029CCB6D5A Hangman (USA) ChannelF USA
|
||||
4C10FA5C7316C59EFA241043FC67DFA8 Magic Numbers - Mind Reader + Nim (USA) ChannelF USA
|
||||
A8E6103FCAE4D0F9E14D9EDCFC3FC493 Math Quiz I - Addition + Subtraction (USA) ChannelF USA
|
||||
86B77EAFDF7B806E19E01724987E384F Math Quiz II - Multiplication + Division (USA) ChannelF USA
|
||||
6565DF74539476D66FD78DE1BAC0259C Maze, Jailbreak, Blind-man's-bluff, Trailblazer (USA) ChannelF USA
|
||||
53E4CC2DA0F2C167E0692B794CB7692C Maze, Jailbreak, Blind-man's-bluff, Trailblazer (USA) (Alt 1) ChannelF USA
|
||||
2B3CA549E27579E4519A765FD8F52D0F Memory Match 1 & 2 (USA) ChannelF USA
|
||||
1FBD86DCCA0E4619963B902C48AE77F2 Muehle, Tontauben-Schiessen, Kreatives Malspiel, Videoscope (Germany) ChannelF Germany
|
||||
C2A44D22D3865B036479E9311C74D3AD Ordtaevling (Sweden) ChannelF Sweden
|
||||
E90339B7068C6227D54F3C0CA637E017 Pinball Challenge (USA) ChannelF USA
|
||||
5CBCDA1C44F0DAD02B0DFE209B6325D5 Pinball Challenge (USA) (Alt 1) ChannelF USA
|
||||
9A894D745356A050F95410983C3BC54A Pro Football (USA) ChannelF USA
|
||||
913ECBAA30816C6D78DE8651251761FC Rat' Mal (Germany) ChannelF Germany
|
||||
3783B6AC359E21B99CFA17773AA811C6 Robot War, Torpedo Alley (USA) ChannelF USA
|
||||
5568205F926333914DEDC8EF8BF16AF2 Schach (Germany) ChannelF Germany
|
||||
DFB66EE145FAB65062FDEADAFC8DC34C Slot Machine (USA) ChannelF USA
|
||||
4CB12EDAE37DF23851884B82CA410754 Sonar Search (USA) ChannelF USA
|
||||
32CCA8FF09041A39251D7AADE21EE22F Space War (USA) ChannelF USA
|
||||
1B409FE1154584F4D1AB76B344A73D99 Spitfire (USA) ChannelF USA
|
||||
7E5C26A6D1F9A90C68669A9800BA522D Tic-Tac-Toe, Shooting Gallery, Doodle, Quadra-Doodle (USA) ChannelF USA
|
||||
B074C867F235FB69CED96C6916673B45 Video Blackjack (USA) ChannelF USA
|
||||
90A9B3952568F91502A7088BFB0AE07E Video Whizball (USA) ChannelF USA
|
|
@ -0,0 +1,3 @@
|
|||
SHA1:67F8513958C04E936B135740ED4EC6E6FA1763D5 Clean Sweep VEC
|
||||
SHA1:38E38B5C60466146D4648F8929B5CE3A08DCBE0D Scramble VEC
|
||||
|
Binary file not shown.
|
@ -37,6 +37,10 @@
|
|||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.SQLite, Version=1.0.105.2, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=AMD64">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\Users\uptho\Documents\BizHawk-2.3\dll\System.Data.SQLite.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
|
@ -48,6 +52,19 @@
|
|||
<ItemGroup>
|
||||
<Compile Include="Attributes\BizHawkExternalToolUsageAttribute.cs" />
|
||||
<Compile Include="Attributes\BizHawkExternalToolAttribute.cs" />
|
||||
<Compile Include="Classes\ApiInjector.cs" />
|
||||
<Compile Include="Classes\Api\EmuApi.cs" />
|
||||
<Compile Include="Classes\Api\GameInfoApi.cs" />
|
||||
<Compile Include="Classes\Api\MemApi.cs" />
|
||||
<Compile Include="Classes\Api\MemApiBase.cs" />
|
||||
<Compile Include="Classes\Api\PluginBase.cs" />
|
||||
<Compile Include="Classes\Api\JoypadApi.cs" />
|
||||
<Compile Include="Classes\Api\MemEventsApi.cs" />
|
||||
<Compile Include="Classes\Api\MemorySaveStateApi.cs" />
|
||||
<Compile Include="Classes\Api\MovieApi.cs" />
|
||||
<Compile Include="Classes\Api\SqlApi.cs" />
|
||||
<Compile Include="Classes\Api\UserDataApi.cs" />
|
||||
<Compile Include="Classes\BasicApiProvider.cs" />
|
||||
<Compile Include="Classes\BizHawkSystemIdToCoreSystemEnumConverter.cs" />
|
||||
<Compile Include="Classes\Events\EventArgs\BeforeQuickLoadEventArgs.cs" />
|
||||
<Compile Include="Classes\Events\EventArgs\BeforeQuickSaveEventArgs.cs" />
|
||||
|
@ -62,7 +79,25 @@
|
|||
<Compile Include="Enums\BizHawkExternalToolUsage.cs" />
|
||||
<Compile Include="Classes\ClientApi.cs" />
|
||||
<Compile Include="Classes\ExternalToolManager.cs" />
|
||||
<Compile Include="Interfaces\Api\IComm.cs" />
|
||||
<Compile Include="Interfaces\Api\IInput.cs" />
|
||||
<Compile Include="Interfaces\Api\ITool.cs" />
|
||||
<Compile Include="Interfaces\Api\ISaveState.cs" />
|
||||
<Compile Include="Interfaces\Api\IUserData.cs" />
|
||||
<Compile Include="Interfaces\Api\ISql.cs" />
|
||||
<Compile Include="Interfaces\Api\IMovie.cs" />
|
||||
<Compile Include="Interfaces\Api\IMemorySavestate.cs" />
|
||||
<Compile Include="Interfaces\Api\IMemEvents.cs" />
|
||||
<Compile Include="Interfaces\Api\IEmu.cs" />
|
||||
<Compile Include="Interfaces\Api\IExternalApi.cs" />
|
||||
<Compile Include="Interfaces\Api\IJoypad.cs" />
|
||||
<Compile Include="Interfaces\IExternalApiProvider.cs" />
|
||||
<Compile Include="Interfaces\IExternalToolForm.cs" />
|
||||
<Compile Include="Interfaces\Api\IGameInfo.cs" />
|
||||
<Compile Include="Interfaces\Api\IGui.cs" />
|
||||
<Compile Include="Interfaces\Api\IMem.cs" />
|
||||
<Compile Include="Interfaces\IPlugin.cs" />
|
||||
<Compile Include="Interfaces\Api\IApiContainer.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -95,4 +130,4 @@
|
|||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
</Project>
|
|
@ -0,0 +1,459 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BizHawk.Client.Common;
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
||||
using BizHawk.Emulation.Cores.Nintendo.NES;
|
||||
using BizHawk.Emulation.Cores.Nintendo.SNES;
|
||||
using BizHawk.Emulation.Cores.PCEngine;
|
||||
using BizHawk.Emulation.Cores.Consoles.Sega.gpgx;
|
||||
using BizHawk.Emulation.Cores.Sega.MasterSystem;
|
||||
using BizHawk.Emulation.Cores.WonderSwan;
|
||||
using BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES;
|
||||
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
[Description("A library for interacting with the currently loaded emulator core")]
|
||||
public sealed class EmuApi : IEmu
|
||||
{
|
||||
private static class EmuStatic
|
||||
{
|
||||
public static void DisplayVsync(bool enabled)
|
||||
{
|
||||
Global.Config.VSync = enabled;
|
||||
}
|
||||
public static string GetSystemId()
|
||||
{
|
||||
return Global.Game.System;
|
||||
}
|
||||
public static void LimitFramerate(bool enabled)
|
||||
{
|
||||
Global.Config.ClockThrottle = enabled;
|
||||
}
|
||||
|
||||
public static void MinimizeFrameskip(bool enabled)
|
||||
{
|
||||
Global.Config.AutoMinimizeSkipping = enabled;
|
||||
}
|
||||
|
||||
}
|
||||
[RequiredService]
|
||||
private IEmulator Emulator { get; set; }
|
||||
|
||||
[OptionalService]
|
||||
private IDebuggable DebuggableCore { get; set; }
|
||||
|
||||
[OptionalService]
|
||||
private IDisassemblable DisassemblableCore { get; set; }
|
||||
|
||||
[OptionalService]
|
||||
private IMemoryDomains MemoryDomains { get; set; }
|
||||
|
||||
[OptionalService]
|
||||
private IInputPollable InputPollableCore { get; set; }
|
||||
|
||||
[OptionalService]
|
||||
private IRegionable RegionableCore { get; set; }
|
||||
|
||||
[OptionalService]
|
||||
private IBoardInfo BoardInfo { get; set; }
|
||||
|
||||
public Action FrameAdvanceCallback { get; set; }
|
||||
public Action YieldCallback { get; set; }
|
||||
|
||||
public EmuApi()
|
||||
{ }
|
||||
|
||||
public void DisplayVsync(bool enabled)
|
||||
{
|
||||
EmuStatic.DisplayVsync(enabled);
|
||||
}
|
||||
|
||||
public void FrameAdvance()
|
||||
{
|
||||
FrameAdvanceCallback();
|
||||
}
|
||||
|
||||
public int FrameCount()
|
||||
{
|
||||
return Emulator.Frame;
|
||||
}
|
||||
|
||||
public object Disassemble(uint pc, string name = "")
|
||||
{
|
||||
try
|
||||
{
|
||||
if (DisassemblableCore == null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
MemoryDomain domain = MemoryDomains.SystemBus;
|
||||
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
domain = MemoryDomains[name];
|
||||
}
|
||||
|
||||
int l;
|
||||
var d = DisassemblableCore.Disassemble(domain, pc, out l);
|
||||
return new { disasm = d, length = l };
|
||||
}
|
||||
catch (NotImplementedException)
|
||||
{
|
||||
Console.WriteLine($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDisassemblable.Disassemble)}()");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public ulong? GetRegister(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (DebuggableCore == null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
var registers = DebuggableCore.GetCpuFlagsAndRegisters();
|
||||
ulong? value = null;
|
||||
if (registers.ContainsKey(name)) value = registers[name].Value;
|
||||
return value;
|
||||
}
|
||||
catch (NotImplementedException)
|
||||
{
|
||||
Console.WriteLine($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.GetCpuFlagsAndRegisters)}()");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<string, ulong> GetRegisters()
|
||||
{
|
||||
var table = new Dictionary<string, ulong>();
|
||||
|
||||
try
|
||||
{
|
||||
if (DebuggableCore == null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
foreach (var kvp in DebuggableCore.GetCpuFlagsAndRegisters())
|
||||
{
|
||||
table[kvp.Key] = kvp.Value.Value;
|
||||
}
|
||||
}
|
||||
catch (NotImplementedException)
|
||||
{
|
||||
Console.WriteLine($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.GetCpuFlagsAndRegisters)}()");
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
public void SetRegister(string register, int value)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (DebuggableCore == null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
DebuggableCore.SetCpuRegister(register, value);
|
||||
}
|
||||
catch (NotImplementedException)
|
||||
{
|
||||
Console.WriteLine($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.SetCpuRegister)}()");
|
||||
}
|
||||
}
|
||||
|
||||
public long TotalExecutedycles()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (DebuggableCore == null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
return DebuggableCore.TotalExecutedCycles;
|
||||
}
|
||||
catch (NotImplementedException)
|
||||
{
|
||||
Console.WriteLine($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.TotalExecutedCycles)}()");
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public string GetSystemId()
|
||||
{
|
||||
return EmuStatic.GetSystemId();
|
||||
}
|
||||
|
||||
public bool IsLagged()
|
||||
{
|
||||
if (InputPollableCore != null)
|
||||
{
|
||||
return InputPollableCore.IsLagFrame;
|
||||
}
|
||||
|
||||
Console.WriteLine($"Can not get lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}");
|
||||
return false;
|
||||
}
|
||||
|
||||
public void SetIsLagged(bool value = true)
|
||||
{
|
||||
if (InputPollableCore != null)
|
||||
{
|
||||
InputPollableCore.IsLagFrame = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Can not set lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}");
|
||||
}
|
||||
}
|
||||
|
||||
public int LagCount()
|
||||
{
|
||||
if (InputPollableCore != null)
|
||||
{
|
||||
return InputPollableCore.LagCount;
|
||||
}
|
||||
|
||||
Console.WriteLine($"Can not get lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}");
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void SetLagCount(int count)
|
||||
{
|
||||
if (InputPollableCore != null)
|
||||
{
|
||||
InputPollableCore.LagCount = count;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Can not set lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}");
|
||||
}
|
||||
}
|
||||
|
||||
public void LimitFramerate(bool enabled)
|
||||
{
|
||||
EmuStatic.LimitFramerate(enabled);
|
||||
}
|
||||
|
||||
public void MinimizeFrameskip(bool enabled)
|
||||
{
|
||||
EmuStatic.MinimizeFrameskip(enabled);
|
||||
}
|
||||
|
||||
public void Yield()
|
||||
{
|
||||
YieldCallback();
|
||||
}
|
||||
|
||||
public string GetDisplayType()
|
||||
{
|
||||
if (RegionableCore != null)
|
||||
{
|
||||
return RegionableCore.Region.ToString();
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public string GetBoardName()
|
||||
{
|
||||
if (BoardInfo != null)
|
||||
{
|
||||
return BoardInfo.BoardName;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
public object GetSettings()
|
||||
{
|
||||
if (Emulator is GPGX)
|
||||
{
|
||||
var gpgx = Emulator as GPGX;
|
||||
return gpgx.GetSettings();
|
||||
}
|
||||
else if (Emulator is LibsnesCore)
|
||||
{
|
||||
var snes = Emulator as LibsnesCore;
|
||||
return snes.GetSettings();
|
||||
}
|
||||
else if (Emulator is NES)
|
||||
{
|
||||
var nes = Emulator as NES;
|
||||
return nes.GetSettings();
|
||||
}
|
||||
else if (Emulator is QuickNES)
|
||||
{
|
||||
var quicknes = Emulator as QuickNES;
|
||||
return quicknes.GetSettings();
|
||||
}
|
||||
else if (Emulator is PCEngine)
|
||||
{
|
||||
var pce = Emulator as PCEngine;
|
||||
return pce.GetSettings();
|
||||
}
|
||||
else if (Emulator is SMS)
|
||||
{
|
||||
var sms = Emulator as SMS;
|
||||
return sms.GetSettings();
|
||||
}
|
||||
else if (Emulator is WonderSwan)
|
||||
{
|
||||
var ws = Emulator as WonderSwan;
|
||||
return ws.GetSettings();
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public bool PutSettings(object settings)
|
||||
{
|
||||
if (Emulator is GPGX)
|
||||
{
|
||||
var gpgx = Emulator as GPGX;
|
||||
return gpgx.PutSettings(settings as GPGX.GPGXSettings);
|
||||
}
|
||||
else if (Emulator is LibsnesCore)
|
||||
{
|
||||
var snes = Emulator as LibsnesCore;
|
||||
return snes.PutSettings(settings as LibsnesCore.SnesSettings);
|
||||
}
|
||||
else if (Emulator is NES)
|
||||
{
|
||||
var nes = Emulator as NES;
|
||||
return nes.PutSettings(settings as NES.NESSettings);
|
||||
}
|
||||
else if (Emulator is QuickNES)
|
||||
{
|
||||
var quicknes = Emulator as QuickNES;
|
||||
return quicknes.PutSettings(settings as QuickNES.QuickNESSettings);
|
||||
}
|
||||
else if (Emulator is PCEngine)
|
||||
{
|
||||
var pce = Emulator as PCEngine;
|
||||
return pce.PutSettings(settings as PCEngine.PCESettings);
|
||||
}
|
||||
else if (Emulator is SMS)
|
||||
{
|
||||
var sms = Emulator as SMS;
|
||||
return sms.PutSettings(settings as SMS.SMSSettings);
|
||||
}
|
||||
else if (Emulator is WonderSwan)
|
||||
{
|
||||
var ws = Emulator as WonderSwan;
|
||||
return ws.PutSettings(settings as WonderSwan.Settings);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public void SetRenderPlanes(params bool[] luaParam)
|
||||
{
|
||||
if (Emulator is GPGX)
|
||||
{
|
||||
var gpgx = Emulator as GPGX;
|
||||
var s = gpgx.GetSettings();
|
||||
s.DrawBGA = luaParam[0];
|
||||
s.DrawBGB = luaParam[1];
|
||||
s.DrawBGW = luaParam[2];
|
||||
s.DrawObj = luaParam[3];
|
||||
gpgx.PutSettings(s);
|
||||
|
||||
}
|
||||
else if (Emulator is LibsnesCore)
|
||||
{
|
||||
var snes = Emulator as LibsnesCore;
|
||||
var s = snes.GetSettings();
|
||||
s.ShowBG1_0 = s.ShowBG1_1 = luaParam[0];
|
||||
s.ShowBG2_0 = s.ShowBG2_1 = luaParam[1];
|
||||
s.ShowBG3_0 = s.ShowBG3_1 = luaParam[2];
|
||||
s.ShowBG4_0 = s.ShowBG4_1 = luaParam[3];
|
||||
s.ShowOBJ_0 = luaParam[4];
|
||||
s.ShowOBJ_1 = luaParam[5];
|
||||
s.ShowOBJ_2 = luaParam[6];
|
||||
s.ShowOBJ_3 = luaParam[7];
|
||||
snes.PutSettings(s);
|
||||
}
|
||||
else if (Emulator is NES)
|
||||
{
|
||||
// in the future, we could do something more arbitrary here.
|
||||
// but this isn't any worse than the old system
|
||||
var nes = Emulator as NES;
|
||||
var s = nes.GetSettings();
|
||||
s.DispSprites = luaParam[0];
|
||||
s.DispBackground = luaParam[1];
|
||||
nes.PutSettings(s);
|
||||
}
|
||||
else if (Emulator is QuickNES)
|
||||
{
|
||||
var quicknes = Emulator as QuickNES;
|
||||
var s = quicknes.GetSettings();
|
||||
|
||||
// this core doesn't support disabling BG
|
||||
bool showsp = GetSetting(0, luaParam);
|
||||
if (showsp && s.NumSprites == 0)
|
||||
{
|
||||
s.NumSprites = 8;
|
||||
}
|
||||
else if (!showsp && s.NumSprites > 0)
|
||||
{
|
||||
s.NumSprites = 0;
|
||||
}
|
||||
|
||||
quicknes.PutSettings(s);
|
||||
}
|
||||
else if (Emulator is PCEngine)
|
||||
{
|
||||
var pce = Emulator as PCEngine;
|
||||
var s = pce.GetSettings();
|
||||
s.ShowOBJ1 = GetSetting(0, luaParam);
|
||||
s.ShowBG1 = GetSetting(1, luaParam);
|
||||
if (luaParam.Length > 2)
|
||||
{
|
||||
s.ShowOBJ2 = GetSetting(2, luaParam);
|
||||
s.ShowBG2 = GetSetting(3, luaParam);
|
||||
}
|
||||
|
||||
pce.PutSettings(s);
|
||||
}
|
||||
else if (Emulator is SMS)
|
||||
{
|
||||
var sms = Emulator as SMS;
|
||||
var s = sms.GetSettings();
|
||||
s.DispOBJ = GetSetting(0, luaParam);
|
||||
s.DispBG = GetSetting(1, luaParam);
|
||||
sms.PutSettings(s);
|
||||
}
|
||||
else if (Emulator is WonderSwan)
|
||||
{
|
||||
var ws = Emulator as WonderSwan;
|
||||
var s = ws.GetSettings();
|
||||
s.EnableSprites = GetSetting(0, luaParam);
|
||||
s.EnableFG = GetSetting(1, luaParam);
|
||||
s.EnableBG = GetSetting(2, luaParam);
|
||||
ws.PutSettings(s);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool GetSetting(int index, bool[] settings)
|
||||
{
|
||||
if (index < settings.Length)
|
||||
{
|
||||
return settings[index];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
using BizHawk.Client.Common;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
public sealed class GameInfoApi : IGameInfo
|
||||
{
|
||||
[OptionalService]
|
||||
private IBoardInfo BoardInfo { get; set; }
|
||||
|
||||
public GameInfoApi()
|
||||
{ }
|
||||
|
||||
public string GetRomName()
|
||||
{
|
||||
if (Global.Game != null)
|
||||
{
|
||||
return Global.Game.Name ?? "";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public string GetRomHash()
|
||||
{
|
||||
if (Global.Game != null)
|
||||
{
|
||||
return Global.Game.Hash ?? "";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public bool InDatabase()
|
||||
{
|
||||
if (Global.Game != null)
|
||||
{
|
||||
return !Global.Game.NotInDatabase;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public string GetStatus()
|
||||
{
|
||||
if (Global.Game != null)
|
||||
{
|
||||
return Global.Game.Status.ToString();
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public bool IsStatusBad()
|
||||
{
|
||||
if (Global.Game != null)
|
||||
{
|
||||
return Global.Game.IsRomStatusBad();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public string GetBoardType()
|
||||
{
|
||||
return BoardInfo?.BoardName ?? "";
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetOptions()
|
||||
{
|
||||
var options = new Dictionary<string, string>();
|
||||
|
||||
if (Global.Game != null)
|
||||
{
|
||||
foreach (var option in Global.Game.GetOptionsDict())
|
||||
{
|
||||
options[option.Key] = option.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,222 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BizHawk.Client.Common;
|
||||
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
public sealed class JoypadApi : IJoypad
|
||||
{
|
||||
public JoypadApi()
|
||||
{ }
|
||||
|
||||
public Dictionary<string,dynamic> Get(int? controller = null)
|
||||
{
|
||||
var buttons = new Dictionary<string, dynamic>();
|
||||
var adaptor = Global.AutofireStickyXORAdapter;
|
||||
foreach (var button in adaptor.Source.Definition.BoolButtons)
|
||||
{
|
||||
if (!controller.HasValue)
|
||||
{
|
||||
buttons[button] = adaptor.IsPressed(button);
|
||||
}
|
||||
else if (button.Length >= 3 && button.Substring(0, 2) == $"P{controller}")
|
||||
{
|
||||
buttons[button.Substring(3)] = adaptor.IsPressed($"P{controller} {button.Substring(3)}");
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var button in adaptor.Source.Definition.FloatControls)
|
||||
{
|
||||
if (controller == null)
|
||||
{
|
||||
buttons[button] = adaptor.GetFloat(button);
|
||||
}
|
||||
else if (button.Length >= 3 && button.Substring(0, 2) == $"P{controller}")
|
||||
{
|
||||
buttons[button.Substring(3)] = adaptor.GetFloat($"P{controller} {button.Substring(3)}");
|
||||
}
|
||||
}
|
||||
|
||||
buttons["clear"] = null;
|
||||
buttons["getluafunctionslist"] = null;
|
||||
buttons["output"] = null;
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
// TODO: what about float controls?
|
||||
public Dictionary<string, dynamic> GetImmediate()
|
||||
{
|
||||
var buttons = new Dictionary<string, dynamic>();
|
||||
var adaptor = Global.ActiveController;
|
||||
foreach (var button in adaptor.Definition.BoolButtons)
|
||||
{
|
||||
buttons[button] = adaptor.IsPressed(button);
|
||||
}
|
||||
foreach (var button in adaptor.Definition.FloatControls)
|
||||
{
|
||||
buttons[button] = adaptor.GetFloat(button);
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
public void SetFromMnemonicStr(string inputLogEntry)
|
||||
{
|
||||
try
|
||||
{
|
||||
var lg = Global.MovieSession.MovieControllerInstance();
|
||||
lg.SetControllersAsMnemonic(inputLogEntry);
|
||||
|
||||
foreach (var button in lg.Definition.BoolButtons)
|
||||
{
|
||||
Global.LuaAndAdaptor.SetButton(button, lg.IsPressed(button));
|
||||
}
|
||||
|
||||
foreach (var floatButton in lg.Definition.FloatControls)
|
||||
{
|
||||
Global.LuaAndAdaptor.SetFloat(floatButton, lg.GetFloat(floatButton));
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Console.WriteLine($"invalid mnemonic string: {inputLogEntry}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Set(Dictionary<string,bool> buttons, int? controller = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var button in buttons.Keys)
|
||||
{
|
||||
var invert = false;
|
||||
bool? theValue;
|
||||
var theValueStr = buttons[button].ToString();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(theValueStr))
|
||||
{
|
||||
if (theValueStr.ToLower() == "false")
|
||||
{
|
||||
theValue = false;
|
||||
}
|
||||
else if (theValueStr.ToLower() == "true")
|
||||
{
|
||||
theValue = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
invert = true;
|
||||
theValue = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
theValue = null;
|
||||
}
|
||||
|
||||
var toPress = button.ToString();
|
||||
if (controller.HasValue)
|
||||
{
|
||||
toPress = $"P{controller} {button}";
|
||||
}
|
||||
|
||||
if (!invert)
|
||||
{
|
||||
if (theValue.HasValue) // Force
|
||||
{
|
||||
Global.LuaAndAdaptor.SetButton(toPress, theValue.Value);
|
||||
Global.ActiveController.Overrides(Global.LuaAndAdaptor);
|
||||
}
|
||||
else // Unset
|
||||
{
|
||||
Global.LuaAndAdaptor.UnSet(toPress);
|
||||
Global.ActiveController.Overrides(Global.LuaAndAdaptor);
|
||||
}
|
||||
}
|
||||
else // Inverse
|
||||
{
|
||||
Global.LuaAndAdaptor.SetInverse(toPress);
|
||||
Global.ActiveController.Overrides(Global.LuaAndAdaptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
/*Eat it*/
|
||||
}
|
||||
}
|
||||
public void Set(string button, bool? state = null, int? controller = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var toPress = button;
|
||||
if (controller.HasValue)
|
||||
{
|
||||
toPress = $"P{controller} {button}";
|
||||
}
|
||||
if (state.HasValue)
|
||||
Global.LuaAndAdaptor.SetButton(toPress, state.Value);
|
||||
else
|
||||
Global.LuaAndAdaptor.UnSet(toPress);
|
||||
Global.ActiveController.Overrides(Global.LuaAndAdaptor);
|
||||
}
|
||||
catch
|
||||
{
|
||||
/*Eat it*/
|
||||
}
|
||||
}
|
||||
public void SetAnalog(Dictionary<string,float> controls, object controller = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var name in controls.Keys)
|
||||
{
|
||||
var theValueStr = controls[name].ToString();
|
||||
float? theValue = null;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(theValueStr))
|
||||
{
|
||||
float f;
|
||||
if (float.TryParse(theValueStr, out f))
|
||||
{
|
||||
theValue = f;
|
||||
}
|
||||
}
|
||||
|
||||
if (controller == null)
|
||||
{
|
||||
Global.StickyXORAdapter.SetFloat(name.ToString(), theValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
Global.StickyXORAdapter.SetFloat($"P{controller} {name}", theValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
/*Eat it*/
|
||||
}
|
||||
}
|
||||
public void SetAnalog(string control, float? value = null, object controller = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (controller == null)
|
||||
{
|
||||
Global.StickyXORAdapter.SetFloat(control, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Global.StickyXORAdapter.SetFloat($"P{controller} {control}", value);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
/*Eat it*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,288 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
||||
using BizHawk.Common.BufferExtensions;
|
||||
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
public sealed class MemApi : MemApiBase, IMem
|
||||
{
|
||||
private MemoryDomain _currentMemoryDomain;
|
||||
private bool _isBigEndian = false;
|
||||
public MemApi()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
protected override MemoryDomain Domain
|
||||
{
|
||||
get
|
||||
{
|
||||
if (MemoryDomainCore != null)
|
||||
{
|
||||
if (_currentMemoryDomain == null)
|
||||
{
|
||||
_currentMemoryDomain = MemoryDomainCore.HasSystemBus
|
||||
? MemoryDomainCore.SystemBus
|
||||
: MemoryDomainCore.MainMemory;
|
||||
}
|
||||
|
||||
return _currentMemoryDomain;
|
||||
}
|
||||
|
||||
var error = $"Error: {Emulator.Attributes().CoreName} does not implement memory domains";
|
||||
Console.WriteLine(error);
|
||||
throw new NotImplementedException(error);
|
||||
}
|
||||
}
|
||||
|
||||
#region Unique Library Methods
|
||||
|
||||
public void SetBigEndian(bool enabled = true)
|
||||
{
|
||||
_isBigEndian = enabled;
|
||||
}
|
||||
|
||||
public List<string> GetMemoryDomainList()
|
||||
{
|
||||
var list = new List<string>();
|
||||
|
||||
foreach (var domain in DomainList)
|
||||
{
|
||||
list.Add(domain.Name);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public uint GetMemoryDomainSize(string name = "")
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
return (uint)Domain.Size;
|
||||
}
|
||||
|
||||
return (uint)DomainList[VerifyMemoryDomain(name)].Size;
|
||||
}
|
||||
|
||||
public string GetCurrentMemoryDomain()
|
||||
{
|
||||
return Domain.Name;
|
||||
}
|
||||
|
||||
public uint GetCurrentMemoryDomainSize()
|
||||
{
|
||||
return (uint)Domain.Size;
|
||||
}
|
||||
|
||||
public bool UseMemoryDomain(string domain)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (DomainList[domain] != null)
|
||||
{
|
||||
_currentMemoryDomain = DomainList[domain];
|
||||
return true;
|
||||
}
|
||||
|
||||
Console.WriteLine($"Unable to find domain: {domain}");
|
||||
return false;
|
||||
}
|
||||
catch // Just in case
|
||||
{
|
||||
Console.WriteLine($"Unable to find domain: {domain}");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public string HashRegion(long addr, int count, string domain = null)
|
||||
{
|
||||
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
||||
|
||||
// checks
|
||||
if (addr < 0 || addr >= d.Size)
|
||||
{
|
||||
string error = $"Address {addr} is outside the bounds of domain {d.Name}";
|
||||
Console.WriteLine(error);
|
||||
throw new ArgumentOutOfRangeException(error);
|
||||
}
|
||||
if (addr + count > d.Size)
|
||||
{
|
||||
string error = $"Address {addr} + count {count} is outside the bounds of domain {d.Name}";
|
||||
Console.WriteLine(error);
|
||||
throw new ArgumentOutOfRangeException(error);
|
||||
}
|
||||
|
||||
byte[] data = new byte[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
data[i] = d.PeekByte(addr + i);
|
||||
}
|
||||
|
||||
using (var hasher = System.Security.Cryptography.SHA256.Create())
|
||||
{
|
||||
return hasher.ComputeHash(data).BytesToHexString();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Endian Handling
|
||||
|
||||
private int ReadSigned(long addr, int size, string domain = null)
|
||||
{
|
||||
if (_isBigEndian) return ReadSignedBig(addr, size, domain);
|
||||
else return ReadSignedLittle(addr, size, domain);
|
||||
}
|
||||
|
||||
private uint ReadUnsigned(long addr, int size, string domain = null)
|
||||
{
|
||||
if (_isBigEndian) return ReadUnsignedBig(addr, size, domain);
|
||||
else return ReadUnsignedLittle(addr, size, domain);
|
||||
}
|
||||
|
||||
private void WriteSigned(long addr, int value, int size, string domain = null)
|
||||
{
|
||||
if (_isBigEndian) WriteSignedBig(addr, value, size, domain);
|
||||
else WriteSignedLittle(addr, value, size, domain);
|
||||
}
|
||||
|
||||
private void WriteUnsigned(long addr, uint value, int size, string domain = null)
|
||||
{
|
||||
if (_isBigEndian) WriteUnsignedBig(addr, value, size, domain);
|
||||
else WriteUnsignedLittle(addr, value, size, domain);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Common Special and Legacy Methods
|
||||
|
||||
public uint ReadByte(long addr, string domain = null)
|
||||
{
|
||||
return ReadUnsignedByte(addr, domain);
|
||||
}
|
||||
|
||||
public void WriteByte(long addr, uint value, string domain = null)
|
||||
{
|
||||
WriteUnsignedByte(addr, value, domain);
|
||||
}
|
||||
|
||||
public new List<byte> ReadByteRange(long addr, int length, string domain = null)
|
||||
{
|
||||
return base.ReadByteRange(addr, length, domain);
|
||||
}
|
||||
|
||||
public new void WriteByteRange(long addr, List<byte> memoryblock, string domain = null)
|
||||
{
|
||||
base.WriteByteRange(addr, memoryblock, domain);
|
||||
}
|
||||
|
||||
public float ReadFloat(long addr, string domain = null)
|
||||
{
|
||||
return base.ReadFloat(addr, _isBigEndian, domain);
|
||||
}
|
||||
|
||||
public void WriteFloat(long addr, double value, string domain = null)
|
||||
{
|
||||
base.WriteFloat(addr, value, _isBigEndian, domain);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 1 Byte
|
||||
|
||||
public int ReadS8(long addr, string domain = null)
|
||||
{
|
||||
return (sbyte)ReadUnsignedByte(addr, domain);
|
||||
}
|
||||
|
||||
public uint ReadU8(long addr, string domain = null)
|
||||
{
|
||||
return (byte)ReadUnsignedByte(addr, domain);
|
||||
}
|
||||
|
||||
public void WriteS8(long addr, int value, string domain = null)
|
||||
{
|
||||
WriteSigned(addr, value, 1, domain);
|
||||
}
|
||||
|
||||
public void WriteU8(long addr, uint value, string domain = null)
|
||||
{
|
||||
WriteUnsignedByte(addr, value, domain);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 2 Byte
|
||||
public int ReadS16(long addr, string domain = null)
|
||||
{
|
||||
return (short)ReadSigned(addr, 2, domain);
|
||||
}
|
||||
|
||||
public void WriteS16(long addr, int value, string domain = null)
|
||||
{
|
||||
WriteSigned(addr, value, 2, domain);
|
||||
}
|
||||
|
||||
public uint ReadU16(long addr, string domain = null)
|
||||
{
|
||||
return (ushort)ReadUnsigned(addr, 2, domain);
|
||||
}
|
||||
|
||||
public void WriteU16(long addr, uint value, string domain = null)
|
||||
{
|
||||
WriteUnsigned(addr, value, 2, domain);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 3 Byte
|
||||
|
||||
public int ReadS24(long addr, string domain = null)
|
||||
{
|
||||
return ReadSigned(addr, 3, domain);
|
||||
}
|
||||
public void WriteS24(long addr, int value, string domain = null)
|
||||
{
|
||||
WriteSigned(addr, value, 3, domain);
|
||||
}
|
||||
|
||||
public uint ReadU24(long addr, string domain = null)
|
||||
{
|
||||
return ReadUnsigned(addr, 3, domain);
|
||||
}
|
||||
|
||||
public void WriteU24(long addr, uint value, string domain = null)
|
||||
{
|
||||
WriteUnsigned(addr, value, 3, domain);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 4 Byte
|
||||
|
||||
public int ReadS32(long addr, string domain = null)
|
||||
{
|
||||
return ReadSigned(addr, 4, domain);
|
||||
}
|
||||
|
||||
public void WriteS32(long addr, int value, string domain = null)
|
||||
{
|
||||
WriteSigned(addr, value, 4, domain);
|
||||
}
|
||||
|
||||
public uint ReadU32(long addr, string domain = null)
|
||||
{
|
||||
return ReadUnsigned(addr, 4, domain);
|
||||
}
|
||||
|
||||
public void WriteU32(long addr, uint value, string domain = null)
|
||||
{
|
||||
WriteUnsigned(addr, value, 4, domain);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,240 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
||||
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for the Memory and MainMemory plugin libraries
|
||||
/// </summary>
|
||||
public abstract class MemApiBase : IExternalApi
|
||||
{
|
||||
[RequiredService]
|
||||
protected IEmulator Emulator { get; set; }
|
||||
|
||||
[OptionalService]
|
||||
protected IMemoryDomains MemoryDomainCore { get; set; }
|
||||
|
||||
protected abstract MemoryDomain Domain { get; }
|
||||
|
||||
protected MemApiBase()
|
||||
{ }
|
||||
|
||||
protected IMemoryDomains DomainList
|
||||
{
|
||||
get
|
||||
{
|
||||
if (MemoryDomainCore != null)
|
||||
{
|
||||
return MemoryDomainCore;
|
||||
}
|
||||
|
||||
var error = $"Error: {Emulator.Attributes().CoreName} does not implement memory domains";
|
||||
Console.WriteLine(error);
|
||||
throw new NotImplementedException(error);
|
||||
}
|
||||
}
|
||||
|
||||
public string VerifyMemoryDomain(string domain)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (DomainList[domain] == null)
|
||||
{
|
||||
Console.WriteLine($"Unable to find domain: {domain}, falling back to current");
|
||||
return Domain.Name;
|
||||
}
|
||||
|
||||
return domain;
|
||||
}
|
||||
catch // Just in case
|
||||
{
|
||||
Console.WriteLine($"Unable to find domain: {domain}, falling back to current");
|
||||
}
|
||||
|
||||
return Domain.Name;
|
||||
}
|
||||
|
||||
protected uint ReadUnsignedByte(long addr, string domain = null)
|
||||
{
|
||||
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
||||
if (addr < d.Size)
|
||||
{
|
||||
return d.PeekByte(addr);
|
||||
}
|
||||
|
||||
Console.WriteLine($"Warning: attempted read of {addr} outside the memory size of {d.Size}");
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected void WriteUnsignedByte(long addr, uint v, string domain = null)
|
||||
{
|
||||
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
||||
if (d.CanPoke())
|
||||
{
|
||||
if (addr < d.Size)
|
||||
{
|
||||
d.PokeByte(addr, (byte)v);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Warning: attempted write to {addr} outside the memory size of {d.Size}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Error: the domain {d.Name} is not writable");
|
||||
}
|
||||
}
|
||||
|
||||
protected static int U2S(uint u, int size)
|
||||
{
|
||||
var s = (int)u;
|
||||
s <<= 8 * (4 - size);
|
||||
s >>= 8 * (4 - size);
|
||||
return s;
|
||||
}
|
||||
|
||||
protected int ReadSignedLittle(long addr, int size, string domain = null)
|
||||
{
|
||||
return U2S(ReadUnsignedLittle(addr, size, domain), size);
|
||||
}
|
||||
|
||||
protected uint ReadUnsignedLittle(long addr, int size, string domain = null)
|
||||
{
|
||||
uint v = 0;
|
||||
for (var i = 0; i < size; ++i)
|
||||
{
|
||||
v |= ReadUnsignedByte(addr + i, domain) << (8 * i);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
protected int ReadSignedBig(long addr, int size, string domain = null)
|
||||
{
|
||||
return U2S(ReadUnsignedBig(addr, size, domain), size);
|
||||
}
|
||||
|
||||
protected uint ReadUnsignedBig(long addr, int size, string domain = null)
|
||||
{
|
||||
uint v = 0;
|
||||
for (var i = 0; i < size; ++i)
|
||||
{
|
||||
v |= ReadUnsignedByte(addr + i, domain) << (8 * (size - 1 - i));
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
protected void WriteSignedLittle(long addr, int v, int size, string domain = null)
|
||||
{
|
||||
WriteUnsignedLittle(addr, (uint)v, size, domain);
|
||||
}
|
||||
|
||||
protected void WriteUnsignedLittle(long addr, uint v, int size, string domain = null)
|
||||
{
|
||||
for (var i = 0; i < size; ++i)
|
||||
{
|
||||
WriteUnsignedByte(addr + i, (v >> (8 * i)) & 0xFF, domain);
|
||||
}
|
||||
}
|
||||
|
||||
protected void WriteSignedBig(long addr, int v, int size, string domain = null)
|
||||
{
|
||||
WriteUnsignedBig(addr, (uint)v, size, domain);
|
||||
}
|
||||
|
||||
protected void WriteUnsignedBig(long addr, uint v, int size, string domain = null)
|
||||
{
|
||||
for (var i = 0; i < size; ++i)
|
||||
{
|
||||
WriteUnsignedByte(addr + i, (v >> (8 * (size - 1 - i))) & 0xFF, domain);
|
||||
}
|
||||
}
|
||||
|
||||
#region public Library implementations
|
||||
|
||||
protected List<byte> ReadByteRange(long addr, int length, string domain = null)
|
||||
{
|
||||
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
||||
var lastAddr = length + addr;
|
||||
var list = new List<byte>();
|
||||
for (; addr <= lastAddr; addr++)
|
||||
{
|
||||
if (addr < d.Size)
|
||||
list.Add(d.PeekByte(addr));
|
||||
else {
|
||||
Console.WriteLine($"Warning: Attempted read {addr} outside memory domain size of {d.Size} in {nameof(ReadByteRange)}()");
|
||||
list.Add(0);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
protected void WriteByteRange(long addr, List<byte> memoryblock, string domain = null)
|
||||
{
|
||||
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
||||
if (d.CanPoke())
|
||||
{
|
||||
for (var i = 0; i < memoryblock.Count; i++)
|
||||
{
|
||||
if (addr < d.Size)
|
||||
{
|
||||
d.PokeByte(addr++, memoryblock[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Warning: Attempted write {addr} outside memory domain size of {d.Size} in {nameof(WriteByteRange)}()");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Error: the domain {d.Name} is not writable");
|
||||
}
|
||||
}
|
||||
|
||||
protected float ReadFloat(long addr, bool bigendian, string domain = null)
|
||||
{
|
||||
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
||||
if (addr < d.Size)
|
||||
{
|
||||
var val = d.PeekUint(addr, bigendian);
|
||||
var bytes = BitConverter.GetBytes(val);
|
||||
return BitConverter.ToSingle(bytes, 0);
|
||||
}
|
||||
|
||||
Console.WriteLine($"Warning: Attempted read {addr} outside memory size of {d.Size}");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected void WriteFloat(long addr, double value, bool bigendian, string domain = null)
|
||||
{
|
||||
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
||||
if (d.CanPoke())
|
||||
{
|
||||
if (addr < d.Size)
|
||||
{
|
||||
var dv = (float)value;
|
||||
var bytes = BitConverter.GetBytes(dv);
|
||||
var v = BitConverter.ToUInt32(bytes, 0);
|
||||
d.PokeUint(addr, v, bigendian);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Warning: Attempted write {addr} outside memory size of {d.Size}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Error: the domain {Domain.Name} is not writable");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
using System;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
||||
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
public sealed class MemEventsApi : IMemEvents
|
||||
{
|
||||
[RequiredService]
|
||||
private IDebuggable DebuggableCore { get; set; }
|
||||
|
||||
public MemEventsApi () : base()
|
||||
{ }
|
||||
|
||||
public void AddReadCallback(MemoryCallbackDelegate cb, uint? address, string domain)
|
||||
{
|
||||
if (DebuggableCore.MemoryCallbacksAvailable())
|
||||
{
|
||||
DebuggableCore.MemoryCallbacks.Add(new MemoryCallback(domain, MemoryCallbackType.Read, "Plugin Hook", cb, address, null));
|
||||
}
|
||||
}
|
||||
public void AddWriteCallback(MemoryCallbackDelegate cb, uint? address, string domain)
|
||||
{
|
||||
if (DebuggableCore.MemoryCallbacksAvailable())
|
||||
{
|
||||
DebuggableCore.MemoryCallbacks.Add(new MemoryCallback(domain, MemoryCallbackType.Write, "Plugin Hook", cb, address, null));
|
||||
}
|
||||
}
|
||||
public void AddExecCallback(MemoryCallbackDelegate cb, uint? address, string domain)
|
||||
{
|
||||
if (DebuggableCore.MemoryCallbacksAvailable() && DebuggableCore.MemoryCallbacks.ExecuteCallbacksAvailable)
|
||||
{
|
||||
DebuggableCore.MemoryCallbacks.Add(new MemoryCallback(domain, MemoryCallbackType.Execute, "Plugin Hook", cb, address, null));
|
||||
}
|
||||
}
|
||||
public void RemoveMemoryCallback(MemoryCallbackDelegate cb)
|
||||
{
|
||||
if (DebuggableCore.MemoryCallbacksAvailable())
|
||||
{
|
||||
DebuggableCore.MemoryCallbacks.Remove(cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
public sealed class MemorySaveStateApi : IMemorySaveState
|
||||
{
|
||||
public MemorySaveStateApi()
|
||||
{ }
|
||||
|
||||
[RequiredService]
|
||||
private IStatable StatableCore { get; set; }
|
||||
|
||||
private readonly Dictionary<Guid, byte[]> _memorySavestates = new Dictionary<Guid, byte[]>();
|
||||
|
||||
public string SaveCoreStateToMemory()
|
||||
{
|
||||
var guid = Guid.NewGuid();
|
||||
var bytes = (byte[])StatableCore.SaveStateBinary().Clone();
|
||||
|
||||
_memorySavestates.Add(guid, bytes);
|
||||
|
||||
return guid.ToString();
|
||||
}
|
||||
|
||||
public void LoadCoreStateFromMemory(string identifier)
|
||||
{
|
||||
var guid = new Guid(identifier);
|
||||
|
||||
try
|
||||
{
|
||||
var state = _memorySavestates[guid];
|
||||
|
||||
using (var ms = new MemoryStream(state))
|
||||
using (var br = new BinaryReader(ms))
|
||||
{
|
||||
StatableCore.LoadStateBinary(br);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine("Unable to find the given savestate in memory");
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteState(string identifier)
|
||||
{
|
||||
var guid = new Guid(identifier);
|
||||
_memorySavestates.Remove(guid);
|
||||
}
|
||||
|
||||
public void ClearInMemoryStates()
|
||||
{
|
||||
_memorySavestates.Clear();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,288 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using BizHawk.Client.Common;
|
||||
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
public sealed class MovieApi : IMovie
|
||||
{
|
||||
private static class MoviePluginStatic
|
||||
{
|
||||
public static string Filename()
|
||||
{
|
||||
return Global.MovieSession.Movie.Filename;
|
||||
}
|
||||
|
||||
public static bool GetReadOnly()
|
||||
{
|
||||
return Global.MovieSession.ReadOnly;
|
||||
}
|
||||
|
||||
public static ulong GetRerecordCount()
|
||||
{
|
||||
return Global.MovieSession.Movie.Rerecords;
|
||||
}
|
||||
|
||||
public static bool GetRerecordCounting()
|
||||
{
|
||||
return Global.MovieSession.Movie.IsCountingRerecords;
|
||||
}
|
||||
|
||||
public static bool IsLoaded()
|
||||
{
|
||||
return Global.MovieSession.Movie.IsActive;
|
||||
}
|
||||
|
||||
public static double Length()
|
||||
{
|
||||
return Global.MovieSession.Movie.FrameCount;
|
||||
}
|
||||
|
||||
public static string Mode()
|
||||
{
|
||||
if (Global.MovieSession.Movie.IsFinished)
|
||||
{
|
||||
return "FINISHED";
|
||||
}
|
||||
|
||||
if (Global.MovieSession.Movie.IsPlaying)
|
||||
{
|
||||
return "PLAY";
|
||||
}
|
||||
|
||||
if (Global.MovieSession.Movie.IsRecording)
|
||||
{
|
||||
return "RECORD";
|
||||
}
|
||||
|
||||
return "INACTIVE";
|
||||
}
|
||||
|
||||
public static void SetReadOnly(bool readOnly)
|
||||
{
|
||||
Global.MovieSession.ReadOnly = readOnly;
|
||||
}
|
||||
|
||||
public static void SetRerecordCount(double count)
|
||||
{
|
||||
// Lua numbers are always double, integer precision holds up
|
||||
// to 53 bits, so throw an error if it's bigger than that.
|
||||
const double PrecisionLimit = 9007199254740992d;
|
||||
|
||||
if (count > PrecisionLimit)
|
||||
{
|
||||
throw new Exception("Rerecord count exceeds Lua integer precision.");
|
||||
}
|
||||
|
||||
Global.MovieSession.Movie.Rerecords = (ulong)count;
|
||||
}
|
||||
|
||||
public static void SetRerecordCounting(bool counting)
|
||||
{
|
||||
Global.MovieSession.Movie.IsCountingRerecords = counting;
|
||||
}
|
||||
|
||||
public static void Stop()
|
||||
{
|
||||
Global.MovieSession.Movie.Stop();
|
||||
}
|
||||
|
||||
public static double GetFps()
|
||||
{
|
||||
if (Global.MovieSession.Movie.IsActive)
|
||||
{
|
||||
var movie = Global.MovieSession.Movie;
|
||||
var system = movie.HeaderEntries[HeaderKeys.PLATFORM];
|
||||
var pal = movie.HeaderEntries.ContainsKey(HeaderKeys.PAL) &&
|
||||
movie.HeaderEntries[HeaderKeys.PAL] == "1";
|
||||
|
||||
return new PlatformFrameRates()[system, pal];
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
}
|
||||
public MovieApi()
|
||||
{ }
|
||||
|
||||
public bool StartsFromSavestate()
|
||||
{
|
||||
return Global.MovieSession.Movie.IsActive && Global.MovieSession.Movie.StartsFromSavestate;
|
||||
}
|
||||
|
||||
public bool StartsFromSaveram()
|
||||
{
|
||||
return Global.MovieSession.Movie.IsActive && Global.MovieSession.Movie.StartsFromSaveRam;
|
||||
}
|
||||
|
||||
public Dictionary<string, dynamic> GetInput(int frame)
|
||||
{
|
||||
if (!Global.MovieSession.Movie.IsActive)
|
||||
{
|
||||
Console.WriteLine("No movie loaded");
|
||||
return null;
|
||||
}
|
||||
|
||||
var input = new Dictionary<string, dynamic>();
|
||||
var adapter = Global.MovieSession.Movie.GetInputState(frame);
|
||||
|
||||
if (adapter == null)
|
||||
{
|
||||
Console.WriteLine("Can't get input of the last frame of the movie. Use the previous frame");
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach (var button in adapter.Definition.BoolButtons)
|
||||
{
|
||||
input[button] = adapter.IsPressed(button);
|
||||
}
|
||||
|
||||
foreach (var button in adapter.Definition.FloatControls)
|
||||
{
|
||||
input[button] = adapter.GetFloat(button);
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
public string GetInputAsMnemonic(int frame)
|
||||
{
|
||||
if (Global.MovieSession.Movie.IsActive && frame < Global.MovieSession.Movie.InputLogLength)
|
||||
{
|
||||
var lg = Global.MovieSession.LogGeneratorInstance();
|
||||
lg.SetSource(Global.MovieSession.Movie.GetInputState(frame));
|
||||
return lg.GenerateLogEntry();
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public void Save(string filename = "")
|
||||
{
|
||||
if (!Global.MovieSession.Movie.IsActive)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filename))
|
||||
{
|
||||
filename += $".{Global.MovieSession.Movie.PreferredExtension}";
|
||||
var test = new FileInfo(filename);
|
||||
if (test.Exists)
|
||||
{
|
||||
Console.WriteLine($"File {filename} already exists, will not overwrite");
|
||||
return;
|
||||
}
|
||||
|
||||
Global.MovieSession.Movie.Filename = filename;
|
||||
}
|
||||
|
||||
Global.MovieSession.Movie.Save();
|
||||
}
|
||||
|
||||
public Dictionary<string,string> GetHeader()
|
||||
{
|
||||
var table = new Dictionary<string,string>();
|
||||
if (Global.MovieSession.Movie.IsActive)
|
||||
{
|
||||
foreach (var kvp in Global.MovieSession.Movie.HeaderEntries)
|
||||
{
|
||||
table[kvp.Key] = kvp.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
public List<string> GetComments()
|
||||
{
|
||||
var list = new List<string>(Global.MovieSession.Movie.Comments.Count);
|
||||
if (Global.MovieSession.Movie.IsActive)
|
||||
{
|
||||
for (int i = 0; i < Global.MovieSession.Movie.Comments.Count; i++)
|
||||
{
|
||||
list[i] = Global.MovieSession.Movie.Comments[i];
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<string> GetSubtitles()
|
||||
{
|
||||
var list = new List<string>(Global.MovieSession.Movie.Subtitles.Count);
|
||||
if (Global.MovieSession.Movie.IsActive)
|
||||
{
|
||||
for (int i = 0; i < Global.MovieSession.Movie.Subtitles.Count; i++)
|
||||
{
|
||||
list[i] = Global.MovieSession.Movie.Subtitles[i].ToString();
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public string Filename()
|
||||
{
|
||||
return MoviePluginStatic.Filename();
|
||||
}
|
||||
|
||||
public bool GetReadOnly()
|
||||
{
|
||||
return MoviePluginStatic.GetReadOnly();
|
||||
}
|
||||
|
||||
public ulong GetRerecordCount()
|
||||
{
|
||||
return MoviePluginStatic.GetRerecordCount();
|
||||
}
|
||||
|
||||
public bool GetRerecordCounting()
|
||||
{
|
||||
return MoviePluginStatic.GetRerecordCounting();
|
||||
}
|
||||
|
||||
public bool IsLoaded()
|
||||
{
|
||||
return MoviePluginStatic.IsLoaded();
|
||||
}
|
||||
|
||||
public double Length()
|
||||
{
|
||||
return MoviePluginStatic.Length();
|
||||
}
|
||||
|
||||
public string Mode()
|
||||
{
|
||||
return MoviePluginStatic.Mode();
|
||||
}
|
||||
|
||||
public void SetReadOnly(bool readOnly)
|
||||
{
|
||||
MoviePluginStatic.SetReadOnly(readOnly);
|
||||
}
|
||||
|
||||
public void SetRerecordCount(double count)
|
||||
{
|
||||
MoviePluginStatic.SetRerecordCount(count);
|
||||
}
|
||||
|
||||
public void SetRerecordCounting(bool counting)
|
||||
{
|
||||
MoviePluginStatic.SetRerecordCounting(counting);
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
MoviePluginStatic.Stop();
|
||||
}
|
||||
|
||||
public double GetFps()
|
||||
{
|
||||
return MoviePluginStatic.GetFps();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
public abstract class PluginBase : IPlugin
|
||||
{
|
||||
/// <summary>
|
||||
/// The base class from which all
|
||||
/// plugins will be derived
|
||||
///
|
||||
/// Actual plugins should implement
|
||||
/// one of the below callback methods
|
||||
/// or register memory callbacks in
|
||||
/// their Init function.
|
||||
/// </summary>
|
||||
protected IApiContainer _api;
|
||||
|
||||
public PluginBase() { }
|
||||
|
||||
public abstract string Name { get; }
|
||||
public abstract string Description { get; }
|
||||
|
||||
public bool Enabled => Running;
|
||||
public bool Paused => !Running;
|
||||
|
||||
public bool Running { get; set; }
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
Running = false;
|
||||
}
|
||||
|
||||
public void Toggle()
|
||||
{
|
||||
Running = !Running;
|
||||
}
|
||||
|
||||
public virtual void PreFrameCallback() { }
|
||||
public virtual void PostFrameCallback() { }
|
||||
public virtual void SaveStateCallback(string name) { }
|
||||
public virtual void LoadStateCallback(string name) { }
|
||||
public virtual void InputPollCallback() { }
|
||||
public virtual void ExitCallback() { }
|
||||
public virtual void Init (IApiContainer api)
|
||||
{
|
||||
_api = api;
|
||||
Running = true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data.SQLite;
|
||||
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
public sealed class SqlApi : ISql
|
||||
{
|
||||
public SqlApi() : base()
|
||||
{ }
|
||||
|
||||
SQLiteConnection m_dbConnection;
|
||||
string connectionString;
|
||||
|
||||
public string CreateDatabase(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
SQLiteConnection.CreateFile(name);
|
||||
return "Database Created Successfully";
|
||||
}
|
||||
catch (SQLiteException sqlEX)
|
||||
{
|
||||
return sqlEX.Message;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public string OpenDatabase(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
SQLiteConnectionStringBuilder connBuilder = new SQLiteConnectionStringBuilder();
|
||||
connBuilder.DataSource = name;
|
||||
connBuilder.Version = 3; //SQLite version
|
||||
connBuilder.JournalMode = SQLiteJournalModeEnum.Wal; //Allows for reads and writes to happen at the same time
|
||||
connBuilder.DefaultIsolationLevel = System.Data.IsolationLevel.ReadCommitted; //This only helps make the database lock left. May be pointless now
|
||||
connBuilder.SyncMode = SynchronizationModes.Off; //This shortens the delay for do synchronous calls.
|
||||
m_dbConnection = new SQLiteConnection(connBuilder.ToString());
|
||||
connectionString = connBuilder.ToString();
|
||||
m_dbConnection.Open();
|
||||
m_dbConnection.Close();
|
||||
return "Database Opened Successfully";
|
||||
}
|
||||
catch (SQLiteException sqlEX)
|
||||
{
|
||||
return sqlEX.Message;
|
||||
}
|
||||
}
|
||||
|
||||
public string WriteCommand(string query = "")
|
||||
{
|
||||
if (query == "")
|
||||
{
|
||||
return "query is empty";
|
||||
}
|
||||
try
|
||||
{
|
||||
m_dbConnection.Open();
|
||||
string sql = query;
|
||||
SQLiteCommand command = new SQLiteCommand(sql, m_dbConnection);
|
||||
command.ExecuteNonQuery();
|
||||
m_dbConnection.Close();
|
||||
|
||||
return "Command ran successfully";
|
||||
|
||||
}
|
||||
catch (NullReferenceException nullEX)
|
||||
{
|
||||
return "Database not open.";
|
||||
}
|
||||
catch (SQLiteException sqlEX)
|
||||
{
|
||||
m_dbConnection.Close();
|
||||
return sqlEX.Message;
|
||||
}
|
||||
}
|
||||
|
||||
public dynamic ReadCommand(string query = "")
|
||||
{
|
||||
if (query == "")
|
||||
{
|
||||
return "query is empty";
|
||||
}
|
||||
try
|
||||
{
|
||||
var table = new Dictionary<string, object>();
|
||||
m_dbConnection.Open();
|
||||
string sql = $"PRAGMA read_uncommitted =1;{query}";
|
||||
SQLiteCommand command = new SQLiteCommand(sql, m_dbConnection);
|
||||
SQLiteDataReader reader = command.ExecuteReader();
|
||||
bool rows = reader.HasRows;
|
||||
long rowCount = 0;
|
||||
var columns = new List<string>();
|
||||
for (int i = 0; i < reader.FieldCount; ++i) //Add all column names into list
|
||||
{
|
||||
columns.Add(reader.GetName(i));
|
||||
}
|
||||
while (reader.Read())
|
||||
{
|
||||
for (int i = 0; i < reader.FieldCount; ++i)
|
||||
{
|
||||
table[$"{columns[i]} {rowCount}"] = reader.GetValue(i);
|
||||
}
|
||||
rowCount += 1;
|
||||
}
|
||||
reader.Close();
|
||||
m_dbConnection.Close();
|
||||
if (rows == false)
|
||||
{
|
||||
return "No rows found";
|
||||
}
|
||||
|
||||
return table;
|
||||
|
||||
}
|
||||
catch (NullReferenceException)
|
||||
{
|
||||
return "Database not opened.";
|
||||
}
|
||||
catch (SQLiteException sqlEX)
|
||||
{
|
||||
m_dbConnection.Close();
|
||||
return sqlEX.Message;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
using BizHawk.Client.Common;
|
||||
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
public sealed class UserDataApi : IUserData
|
||||
{
|
||||
public UserDataApi() : base()
|
||||
{ }
|
||||
|
||||
public void Set(string name, object value)
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
var t = value.GetType();
|
||||
if (!t.IsPrimitive && t != typeof(string))
|
||||
{
|
||||
throw new InvalidOperationException("Invalid type for userdata");
|
||||
}
|
||||
}
|
||||
|
||||
Global.UserBag[name] = value;
|
||||
}
|
||||
|
||||
public object Get(string key)
|
||||
{
|
||||
if (Global.UserBag.ContainsKey(key))
|
||||
{
|
||||
return Global.UserBag[key];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
Global.UserBag.Clear();
|
||||
}
|
||||
|
||||
public bool Remove(string key)
|
||||
{
|
||||
return Global.UserBag.Remove(key);
|
||||
}
|
||||
|
||||
public bool ContainsKey(string key)
|
||||
{
|
||||
return Global.UserBag.ContainsKey(key);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
|
||||
using BizHawk.Common.ReflectionExtensions;
|
||||
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
/// <summary>
|
||||
/// injects Apis into other classes
|
||||
/// </summary>
|
||||
public static class ApiInjector
|
||||
{
|
||||
/// <summary>
|
||||
/// clears all Apis from a target
|
||||
/// </summary>
|
||||
public static void ClearApis(object target)
|
||||
{
|
||||
Type targetType = target.GetType();
|
||||
object[] tmp = new object[1];
|
||||
|
||||
foreach (var propinfo in
|
||||
targetType.GetPropertiesWithAttrib(typeof(RequiredApiAttribute))
|
||||
.Concat(targetType.GetPropertiesWithAttrib(typeof(OptionalApiAttribute))))
|
||||
{
|
||||
propinfo.GetSetMethod(true).Invoke(target, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Feeds the target its required Apis.
|
||||
/// </summary>
|
||||
/// <returns>false if update failed</returns>
|
||||
public static bool UpdateApis(IExternalApiProvider source, object target)
|
||||
{
|
||||
Type targetType = target.GetType();
|
||||
object[] tmp = new object[1];
|
||||
|
||||
foreach (var propinfo in targetType.GetPropertiesWithAttrib(typeof(RequiredApiAttribute)))
|
||||
{
|
||||
tmp[0] = source.GetApi(propinfo.PropertyType);
|
||||
if (tmp[0] == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
propinfo.GetSetMethod(true).Invoke(target, tmp);
|
||||
}
|
||||
|
||||
foreach (var propinfo in targetType.GetPropertiesWithAttrib(typeof(OptionalApiAttribute)))
|
||||
{
|
||||
tmp[0] = source.GetApi(propinfo.PropertyType);
|
||||
propinfo.GetSetMethod(true).Invoke(target, tmp);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether a target is available, considering its dependencies
|
||||
/// and the Apis provided by the emulator core.
|
||||
/// </summary>
|
||||
public static bool IsAvailable(IExternalApiProvider source, Type targetType)
|
||||
{
|
||||
return targetType.GetPropertiesWithAttrib(typeof(RequiredApiAttribute))
|
||||
.Select(pi => pi.PropertyType)
|
||||
.All(source.HasApi);
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class RequiredApiAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class OptionalApiAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
/// <summary>
|
||||
/// A generic implementation of IExternalApi provider that provides
|
||||
/// this functionality to any core.
|
||||
/// The provider will scan an IExternal and register all IExternalApis
|
||||
/// that the core object itself implements. In addition it provides
|
||||
/// a Register() method to allow the core to pass in any additional Apis
|
||||
/// </summary>
|
||||
/// <seealso cref="IExternalApiProvider"/>
|
||||
public class BasicApiProvider : IExternalApiProvider
|
||||
{
|
||||
private readonly Dictionary<Type, IExternalApi> _Apis = new Dictionary<Type, IExternalApi>();
|
||||
|
||||
public BasicApiProvider(IApiContainer container)
|
||||
{
|
||||
// simplified logic here doesn't scan for possible Apis; just adds what it knows is implemented by the PluginApi
|
||||
// this removes the possibility of automagically picking up a Api in a nested class, (find the type, then
|
||||
// find the field), but we're going to keep such logic out of the basic provider. Anything the passed
|
||||
// container doesn't implement directly needs to be added with Register()
|
||||
// this also fully allows apis that are not IExternalApi
|
||||
var libs = container.Libraries;
|
||||
|
||||
_Apis = libs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the client can call this to register an additional Api
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The <seealso cref="IExternalApi"/> to register</typeparam>
|
||||
public void Register<T>(T api)
|
||||
where T : IExternalApi
|
||||
{
|
||||
if (api == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(api));
|
||||
}
|
||||
|
||||
_Apis[typeof(T)] = api;
|
||||
}
|
||||
|
||||
public T GetApi<T>()
|
||||
where T : IExternalApi
|
||||
{
|
||||
return (T)GetApi(typeof(T));
|
||||
}
|
||||
|
||||
public object GetApi(Type t)
|
||||
{
|
||||
IExternalApi Api;
|
||||
KeyValuePair<Type, IExternalApi>[] k = _Apis.Where(kvp => t.IsAssignableFrom(kvp.Key)).ToArray();
|
||||
if (k.Length > 0)
|
||||
{
|
||||
return k[0].Value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool HasApi<T>()
|
||||
where T : IExternalApi
|
||||
{
|
||||
return HasApi(typeof(T));
|
||||
}
|
||||
|
||||
public bool HasApi(Type t)
|
||||
{
|
||||
return _Apis.ContainsKey(t);
|
||||
}
|
||||
|
||||
public IEnumerable<Type> AvailableApis
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Apis.Select(d => d.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -93,6 +93,9 @@ namespace BizHawk.Client.ApiHawk
|
|||
case "TI83":
|
||||
return CoreSystem.TI83;
|
||||
|
||||
case "VEC":
|
||||
return CoreSystem.Vectrex;
|
||||
|
||||
case "WSWAN":
|
||||
return CoreSystem.WonderSwan;
|
||||
|
||||
|
@ -102,6 +105,12 @@ namespace BizHawk.Client.ApiHawk
|
|||
case "AmstradCPC":
|
||||
return CoreSystem.AmstradCPC;
|
||||
|
||||
case "GGL":
|
||||
return CoreSystem.GGL;
|
||||
|
||||
case "ChannelF":
|
||||
return CoreSystem.ChannelF;
|
||||
|
||||
case "VB":
|
||||
case "NGP":
|
||||
case "DNGP":
|
||||
|
@ -112,7 +121,7 @@ namespace BizHawk.Client.ApiHawk
|
|||
return 0; // like I give a shit
|
||||
|
||||
default:
|
||||
throw new IndexOutOfRangeException(string.Format("{0} is missing in convert list", value));
|
||||
throw new IndexOutOfRangeException($"{value} is missing in convert list");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -218,7 +227,7 @@ namespace BizHawk.Client.ApiHawk
|
|||
return "AmstradCPC";
|
||||
|
||||
default:
|
||||
throw new IndexOutOfRangeException(string.Format("{0} is missing in convert list", value.ToString()));
|
||||
throw new IndexOutOfRangeException($"{value.ToString()} is missing in convert list");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ using System.Reflection;
|
|||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using BizHawk.Client.Common;
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Emulation.Cores.Nintendo.Gameboy;
|
||||
using BizHawk.Emulation.Cores.PCEngine;
|
||||
using BizHawk.Emulation.Cores.Sega.MasterSystem;
|
||||
|
@ -21,6 +22,9 @@ namespace BizHawk.Client.ApiHawk
|
|||
{
|
||||
#region Fields
|
||||
|
||||
private static IEmulator Emulator;
|
||||
private static IVideoProvider VideoProvider;
|
||||
|
||||
private static readonly Assembly clientAssembly;
|
||||
private static readonly object clientMainFormInstance;
|
||||
private static readonly Type mainFormClass;
|
||||
|
@ -68,24 +72,59 @@ namespace BizHawk.Client.ApiHawk
|
|||
mainFormClass = clientAssembly.GetType("BizHawk.Client.EmuHawk.MainForm");
|
||||
}
|
||||
|
||||
public static void UpdateEmulatorAndVP(IEmulator emu = null)
|
||||
{
|
||||
Emulator = emu;
|
||||
VideoProvider = Emulation.Common.IEmulatorExtensions.Extensions.AsVideoProviderOrDefault(emu);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
#region Helpers
|
||||
|
||||
private static void InvokeMainFormMethod(string name, dynamic[] paramList = null)
|
||||
{
|
||||
List<Type> typeList = new List<Type>();
|
||||
MethodInfo method;
|
||||
if (paramList != null)
|
||||
{
|
||||
foreach (var obj in paramList)
|
||||
{
|
||||
typeList.Add(obj.GetType());
|
||||
}
|
||||
method = mainFormClass.GetMethod(name, typeList.ToArray());
|
||||
}
|
||||
else method = mainFormClass.GetMethod(name);
|
||||
|
||||
if(method != null)
|
||||
method.Invoke(clientMainFormInstance, paramList);
|
||||
}
|
||||
|
||||
private static object GetMainFormField(string name)
|
||||
{
|
||||
return mainFormClass.GetField(name);
|
||||
}
|
||||
|
||||
private static void SetMainFormField(string name, object value)
|
||||
{
|
||||
mainFormClass.GetField(name).SetValue(clientMainFormInstance, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public
|
||||
/// <summary>
|
||||
/// THE FrameAdvance stuff
|
||||
/// </summary>
|
||||
public static void DoFrameAdvance()
|
||||
{
|
||||
MethodInfo method = mainFormClass.GetMethod("FrameAdvance");
|
||||
method.Invoke(clientMainFormInstance, null);
|
||||
InvokeMainFormMethod("FrameAdvance", null);
|
||||
|
||||
method = mainFormClass.GetMethod("StepRunLoop_Throttle", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
method.Invoke(clientMainFormInstance, null);
|
||||
InvokeMainFormMethod("StepRunLoop_Throttle", null);
|
||||
|
||||
method = mainFormClass.GetMethod("Render", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
method.Invoke(clientMainFormInstance, null);
|
||||
InvokeMainFormMethod("Render", null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -108,7 +147,7 @@ namespace BizHawk.Client.ApiHawk
|
|||
{
|
||||
if (player < 1 || player > RunningSystem.MaxControllers)
|
||||
{
|
||||
throw new IndexOutOfRangeException(string.Format("{0} does not support {1} controller(s)", RunningSystem.DisplayName, player));
|
||||
throw new IndexOutOfRangeException($"{RunningSystem.DisplayName} does not support {player} controller(s)");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -124,8 +163,7 @@ namespace BizHawk.Client.ApiHawk
|
|||
/// <param name="name">Savetate friendly name</param>
|
||||
public static void LoadState(string name)
|
||||
{
|
||||
MethodInfo method = mainFormClass.GetMethod("LoadState");
|
||||
method.Invoke(clientMainFormInstance, new object[] { Path.Combine(PathManager.GetSaveStatePath(Global.Game), string.Format("{0}.{1}", name, "State")), name, false, false });
|
||||
InvokeMainFormMethod("LoadState", new object[] { Path.Combine(PathManager.GetSaveStatePath(Global.Game), $"{name}.State"), name, false, false });
|
||||
}
|
||||
|
||||
|
||||
|
@ -194,12 +232,11 @@ namespace BizHawk.Client.ApiHawk
|
|||
/// <summary>
|
||||
/// Raise when a rom is successfully Loaded
|
||||
/// </summary>
|
||||
public static void OnRomLoaded()
|
||||
public static void OnRomLoaded(IEmulator emu)
|
||||
{
|
||||
if (RomLoaded != null)
|
||||
{
|
||||
RomLoaded(null, EventArgs.Empty);
|
||||
}
|
||||
Emulator = emu;
|
||||
VideoProvider = Emulation.Common.IEmulatorExtensions.Extensions.AsVideoProviderOrDefault(emu);
|
||||
RomLoaded?.Invoke(null, EventArgs.Empty);
|
||||
|
||||
allJoypads = new List<Joypad>(RunningSystem.MaxControllers);
|
||||
for (int i = 1; i <= RunningSystem.MaxControllers; i++)
|
||||
|
@ -215,10 +252,55 @@ namespace BizHawk.Client.ApiHawk
|
|||
/// <param name="name">Savetate friendly name</param>
|
||||
public static void SaveState(string name)
|
||||
{
|
||||
MethodInfo method = mainFormClass.GetMethod("SaveState");
|
||||
method.Invoke(clientMainFormInstance, new object[] { Path.Combine(PathManager.GetSaveStatePath(Global.Game), string.Format("{0}.{1}", name, "State")), name, false });
|
||||
InvokeMainFormMethod("SaveState", new object[] { Path.Combine(PathManager.GetSaveStatePath(Global.Game), $"{name}.State"), name, false });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the extra padding added to the 'native' surface so that you can draw HUD elements in predictable placements
|
||||
/// </summary>
|
||||
/// <param name="left">Left padding</param>
|
||||
/// <param name="top">Top padding</param>
|
||||
/// <param name="right">Right padding</param>
|
||||
/// <param name="bottom">Bottom padding</param>
|
||||
public static void SetGameExtraPadding(int left, int top, int right, int bottom)
|
||||
{
|
||||
FieldInfo f = clientAssembly.GetType("BizHawk.Client.EmuHawk.GlobalWin").GetField("DisplayManager");
|
||||
object displayManager = f.GetValue(null);
|
||||
f = f.FieldType.GetField("GameExtraPadding");
|
||||
f.SetValue(displayManager, new Padding(left, top, right, bottom));
|
||||
|
||||
InvokeMainFormMethod("FrameBufferResized");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the extra padding added to the 'native' surface so that you can draw HUD elements in predictable placements
|
||||
/// </summary>
|
||||
/// <param name="left">Left padding</param>
|
||||
public static void SetGameExtraPadding(int left)
|
||||
{
|
||||
SetGameExtraPadding(left, 0, 0, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the extra padding added to the 'native' surface so that you can draw HUD elements in predictable placements
|
||||
/// </summary>
|
||||
/// <param name="left">Left padding</param>
|
||||
/// <param name="top">Top padding</param>
|
||||
public static void SetGameExtraPadding(int left, int top)
|
||||
{
|
||||
SetGameExtraPadding(left, top, 0, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the extra padding added to the 'native' surface so that you can draw HUD elements in predictable placements
|
||||
/// </summary>
|
||||
/// <param name="left">Left padding</param>
|
||||
/// <param name="top">Top padding</param>
|
||||
/// <param name="right">Right padding</param>
|
||||
public static void SetGameExtraPadding(int left, int top, int right)
|
||||
{
|
||||
SetGameExtraPadding(left, top, right, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the extra padding added to the 'native' surface so that you can draw HUD elements in predictable placements
|
||||
|
@ -234,8 +316,7 @@ namespace BizHawk.Client.ApiHawk
|
|||
f = f.FieldType.GetField("ClientExtraPadding");
|
||||
f.SetValue(displayManager, new Padding(left, top, right, bottom));
|
||||
|
||||
MethodInfo resize = mainFormClass.GetMethod("FrameBufferResized");
|
||||
resize.Invoke(clientMainFormInstance, null);
|
||||
InvokeMainFormMethod("FrameBufferResized");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -268,7 +349,6 @@ namespace BizHawk.Client.ApiHawk
|
|||
SetExtraPadding(left, top, right, 0);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set inputs in specified <see cref="Joypad"/> to specified player
|
||||
/// </summary>
|
||||
|
@ -280,7 +360,7 @@ namespace BizHawk.Client.ApiHawk
|
|||
{
|
||||
if (player < 1 || player > RunningSystem.MaxControllers)
|
||||
{
|
||||
throw new IndexOutOfRangeException(string.Format("{0} does not support {1} controller(s)", RunningSystem.DisplayName, player));
|
||||
throw new IndexOutOfRangeException($"{RunningSystem.DisplayName} does not support {player} controller(s)");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -298,11 +378,11 @@ namespace BizHawk.Client.ApiHawk
|
|||
AutoFireStickyXorAdapter joypadAdaptor = Global.AutofireStickyXORAdapter;
|
||||
if (RunningSystem == SystemInfo.GB)
|
||||
{
|
||||
joypadAdaptor.SetSticky(string.Format("{0}", JoypadConverter.ConvertBack(button, RunningSystem)), true);
|
||||
joypadAdaptor.SetSticky($"{JoypadConverter.ConvertBack(button, RunningSystem)}", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
joypadAdaptor.SetSticky(string.Format("P{0} {1}", player, JoypadConverter.ConvertBack(button, RunningSystem)), true);
|
||||
joypadAdaptor.SetSticky($"P{player} {JoypadConverter.ConvertBack(button, RunningSystem)}", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -314,8 +394,8 @@ namespace BizHawk.Client.ApiHawk
|
|||
AutoFireStickyXorAdapter joypadAdaptor = Global.AutofireStickyXORAdapter;
|
||||
for (int i = 1; i <= RunningSystem.MaxControllers; i++)
|
||||
{
|
||||
joypadAdaptor.SetFloat(string.Format("P{0} X Axis", i), allJoypads[i - 1].AnalogX);
|
||||
joypadAdaptor.SetFloat(string.Format("P{0} Y Axis", i), allJoypads[i - 1].AnalogY);
|
||||
joypadAdaptor.SetFloat($"P{i} X Axis", allJoypads[i - 1].AnalogX);
|
||||
joypadAdaptor.SetFloat($"P{i} Y Axis", allJoypads[i - 1].AnalogY);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
@ -327,8 +407,7 @@ namespace BizHawk.Client.ApiHawk
|
|||
/// </summary>
|
||||
public static void UnpauseEmulation()
|
||||
{
|
||||
MethodInfo method = mainFormClass.GetMethod("UnpauseEmulator");
|
||||
method.Invoke(clientMainFormInstance, null);
|
||||
InvokeMainFormMethod("UnpauseEmulator", null);
|
||||
}
|
||||
#endregion Public
|
||||
|
||||
|
@ -369,12 +448,281 @@ namespace BizHawk.Client.ApiHawk
|
|||
{
|
||||
for (int i = 1; i <= RunningSystem.MaxControllers; i++)
|
||||
{
|
||||
allJoypads[i - 1].AnalogX = joypadAdaptor.GetFloat(string.Format("P{0} X Axis", i));
|
||||
allJoypads[i - 1].AnalogY = joypadAdaptor.GetFloat(string.Format("P{0} Y Axis", i));
|
||||
allJoypads[i - 1].AnalogX = joypadAdaptor.GetFloat($"P{i} X Axis");
|
||||
allJoypads[i - 1].AnalogY = joypadAdaptor.GetFloat($"P{i} Y Axis");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void CloseEmulator()
|
||||
{
|
||||
InvokeMainFormMethod("CloseEmulator");
|
||||
}
|
||||
|
||||
public static void CloseEmulatorWithCode(int exitCode)
|
||||
{
|
||||
InvokeMainFormMethod("CloseEmulator", new object[] {exitCode});
|
||||
}
|
||||
|
||||
public static int BorderHeight()
|
||||
{
|
||||
var point = new System.Drawing.Point(0, 0);
|
||||
Type t = clientAssembly.GetType("BizHawk.Client.EmuHawk.GlobalWin");
|
||||
FieldInfo f = t.GetField("DisplayManager");
|
||||
object displayManager = f.GetValue(null);
|
||||
MethodInfo m = t.GetMethod("TransFormPoint");
|
||||
point = (System.Drawing.Point) m.Invoke(displayManager, new object[] { point });
|
||||
return point.Y;
|
||||
}
|
||||
|
||||
public static int BorderWidth()
|
||||
{
|
||||
var point = new System.Drawing.Point(0, 0);
|
||||
Type t = clientAssembly.GetType("BizHawk.Client.EmuHawk.GlobalWin");
|
||||
FieldInfo f = t.GetField("DisplayManager");
|
||||
object displayManager = f.GetValue(null);
|
||||
MethodInfo m = t.GetMethod("TransFormPoint");
|
||||
point = (System.Drawing.Point)m.Invoke(displayManager, new object[] { point });
|
||||
return point.X;
|
||||
}
|
||||
|
||||
public static int BufferHeight()
|
||||
{
|
||||
return VideoProvider.BufferHeight;
|
||||
}
|
||||
|
||||
public static int BufferWidth()
|
||||
{
|
||||
return VideoProvider.BufferWidth;
|
||||
}
|
||||
|
||||
public static void ClearAutohold()
|
||||
{
|
||||
InvokeMainFormMethod("ClearHolds");
|
||||
}
|
||||
|
||||
public static void CloseRom()
|
||||
{
|
||||
InvokeMainFormMethod("CloseRom");
|
||||
}
|
||||
|
||||
public static void DisplayMessages(bool value)
|
||||
{
|
||||
Global.Config.DisplayMessages = value;
|
||||
}
|
||||
|
||||
public static void EnableRewind(bool enabled)
|
||||
{
|
||||
InvokeMainFormMethod("EnableRewind", new object[] {enabled});
|
||||
}
|
||||
|
||||
public static void FrameSkip(int numFrames)
|
||||
{
|
||||
if (numFrames > 0)
|
||||
{
|
||||
Global.Config.FrameSkip = numFrames;
|
||||
InvokeMainFormMethod("FrameSkipMessage");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Invalid frame skip value");
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetTargetScanlineIntensity()
|
||||
{
|
||||
return Global.Config.TargetScanlineFilterIntensity;
|
||||
}
|
||||
|
||||
public static int GetWindowSize()
|
||||
{
|
||||
return Global.Config.TargetZoomFactors[Emulator.SystemId];
|
||||
}
|
||||
|
||||
public static void SetSoundOn(bool enable)
|
||||
{
|
||||
Global.Config.SoundEnabled = enable;
|
||||
}
|
||||
|
||||
public static bool GetSoundOn()
|
||||
{
|
||||
return Global.Config.SoundEnabled;
|
||||
}
|
||||
|
||||
public static bool IsPaused()
|
||||
{
|
||||
return (bool) GetMainFormField("EmulatorPaused");
|
||||
}
|
||||
|
||||
public static bool IsTurbo()
|
||||
{
|
||||
return (bool)GetMainFormField("IsTurboing");
|
||||
}
|
||||
|
||||
public static bool IsSeeking()
|
||||
{
|
||||
return (bool)GetMainFormField("IsSeeking");
|
||||
}
|
||||
|
||||
public static void OpenRom(string path)
|
||||
{
|
||||
var ioa = OpenAdvancedSerializer.ParseWithLegacy(path);
|
||||
Type t = clientAssembly.GetType("BizHawk.Client.EmuHawk.GlobalWin.MainForm.LoadRomArgs");
|
||||
object o = Activator.CreateInstance(t);
|
||||
t.GetField("OpenAdvanced").SetValue(o, ioa);
|
||||
|
||||
InvokeMainFormMethod("LoadRom", new object[] {path, o});
|
||||
}
|
||||
|
||||
public static void Pause()
|
||||
{
|
||||
InvokeMainFormMethod("PauseEmulator");
|
||||
}
|
||||
|
||||
public static void PauseAv()
|
||||
{
|
||||
SetMainFormField("PauseAvi", true);
|
||||
}
|
||||
|
||||
public static void RebootCore()
|
||||
{
|
||||
InvokeMainFormMethod("RebootCore");
|
||||
}
|
||||
|
||||
public static void SaveRam()
|
||||
{
|
||||
InvokeMainFormMethod("FlushSaveRAM");
|
||||
}
|
||||
|
||||
public static int ScreenHeight()
|
||||
{
|
||||
Type t = GetMainFormField("PresentationPanel").GetType();
|
||||
object o = GetMainFormField("PresentationPanel");
|
||||
o = t.GetField("NativeSize").GetValue(o);
|
||||
t = t.GetField("NativeSize").GetType();
|
||||
|
||||
return (int) t.GetField("Height").GetValue(o);
|
||||
}
|
||||
|
||||
public static void Screenshot(string path = null)
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
InvokeMainFormMethod("TakeScreenshot");
|
||||
}
|
||||
else
|
||||
{
|
||||
InvokeMainFormMethod("TakeScreenshot", new object[] {path});
|
||||
}
|
||||
}
|
||||
|
||||
public static void ScreenshotToClipboard()
|
||||
{
|
||||
InvokeMainFormMethod("TakeScreenshotToClipboard");
|
||||
}
|
||||
|
||||
public static void SetTargetScanlineIntensity(int val)
|
||||
{
|
||||
Global.Config.TargetScanlineFilterIntensity = val;
|
||||
}
|
||||
|
||||
public static void SetScreenshotOSD(bool value)
|
||||
{
|
||||
Global.Config.Screenshot_CaptureOSD = value;
|
||||
}
|
||||
|
||||
public static int ScreenWidth()
|
||||
{
|
||||
Type t = GetMainFormField("PresentationPanel").GetType();
|
||||
object o = GetMainFormField("PresentationPanel");
|
||||
o = t.GetField("NativeSize").GetValue(o);
|
||||
t = t.GetField("NativeSize").GetType();
|
||||
|
||||
return (int) t.GetField("Width").GetValue(o);
|
||||
}
|
||||
|
||||
public static void SetWindowSize(int size)
|
||||
{
|
||||
if (size == 1 || size == 2 || size == 3 || size == 4 || size == 5 || size == 10)
|
||||
{
|
||||
Global.Config.TargetZoomFactors[Emulator.SystemId] = size;
|
||||
InvokeMainFormMethod("FrameBufferResized");
|
||||
Type t = clientAssembly.GetType("BizHawk.Client.EmuHawk.GlobalWin");
|
||||
FieldInfo f = t.GetField("OSD");
|
||||
object osd = f.GetValue(null);
|
||||
t = f.GetType();
|
||||
MethodInfo m = t.GetMethod("AddMessage");
|
||||
m.Invoke(osd, new Object[] { $"Window size set to {size}x" });
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Invalid window size");
|
||||
}
|
||||
}
|
||||
|
||||
public static void SpeedMode(int percent)
|
||||
{
|
||||
if (percent > 0 && percent < 6400)
|
||||
{
|
||||
InvokeMainFormMethod("ClickSpeedItem", new object[] {percent});
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Invalid speed value");
|
||||
}
|
||||
}
|
||||
|
||||
public static void TogglePause()
|
||||
{
|
||||
InvokeMainFormMethod("TogglePause");
|
||||
}
|
||||
|
||||
public static int TransformPointX(int x)
|
||||
{
|
||||
var point = new System.Drawing.Point(x, 0);
|
||||
Type t = clientAssembly.GetType("BizHawk.Client.EmuHawk.GlobalWin");
|
||||
FieldInfo f = t.GetField("DisplayManager");
|
||||
object displayManager = f.GetValue(null);
|
||||
MethodInfo m = t.GetMethod("TransFormPoint");
|
||||
point = (System.Drawing.Point)m.Invoke(displayManager, new object[] { point });
|
||||
return point.X;
|
||||
}
|
||||
|
||||
public static int TransformPointY(int y)
|
||||
{
|
||||
var point = new System.Drawing.Point(0, y);
|
||||
Type t = clientAssembly.GetType("BizHawk.Client.EmuHawk.GlobalWin");
|
||||
FieldInfo f = t.GetField("DisplayManager");
|
||||
object displayManager = f.GetValue(null);
|
||||
MethodInfo m = t.GetMethod("TransFormPoint");
|
||||
point = (System.Drawing.Point)m.Invoke(displayManager, new object[] { point });
|
||||
return point.Y;
|
||||
}
|
||||
|
||||
public static void Unpause()
|
||||
{
|
||||
InvokeMainFormMethod("UnpauseEmulator");
|
||||
}
|
||||
|
||||
public static void UnpauseAv()
|
||||
{
|
||||
SetMainFormField("PauseAvi", false);
|
||||
}
|
||||
|
||||
public static int Xpos()
|
||||
{
|
||||
object o = GetMainFormField("DesktopLocation");
|
||||
Type t = mainFormClass.GetField("DesktopLocation").GetType();
|
||||
return (int)t.GetField("X").GetValue(o);
|
||||
}
|
||||
|
||||
public static int Ypos()
|
||||
{
|
||||
object o = GetMainFormField("DesktopLocation");
|
||||
Type t = mainFormClass.GetField("DesktopLocation").GetType();
|
||||
return (int)t.GetField("Y").GetValue(o);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
@ -427,11 +775,11 @@ namespace BizHawk.Client.ApiHawk
|
|||
}
|
||||
else
|
||||
{
|
||||
return SystemInfo.DualGB;
|
||||
return SystemInfo.DualGB;
|
||||
}
|
||||
|
||||
default:
|
||||
return SystemInfo.FindByCoreSystem(SystemIdConverter.Convert(Global.Emulator.SystemId));
|
||||
return SystemInfo.FindByCoreSystem(SystemIdConverter.Convert(Global.Emulator.SystemId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ namespace BizHawk.Client.ApiHawk
|
|||
item.ToolTipText = attribute.Description;
|
||||
if (attribute.IconResourceName != "")
|
||||
{
|
||||
Stream s = externalToolFile.GetManifestResourceStream(string.Format("{0}.{1}", externalToolFile.GetName().Name, attribute.IconResourceName));
|
||||
Stream s = externalToolFile.GetManifestResourceStream($"{externalToolFile.GetName().Name}.{attribute.IconResourceName}");
|
||||
if (s != null)
|
||||
{
|
||||
item.Image = new Bitmap(s);
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace BizHawk.Client.ApiHawk
|
|||
{
|
||||
if (player < 1 || player > system.MaxControllers)
|
||||
{
|
||||
throw new InvalidOperationException(string.Format("{0} is invalid for {1}", player, system.DisplayName));
|
||||
throw new InvalidOperationException($"{player} is invalid for {system.DisplayName}");
|
||||
}
|
||||
|
||||
_System = system;
|
||||
|
|
|
@ -91,7 +91,7 @@ namespace BizHawk.Client.ApiHawk
|
|||
return JoypadButton.R;
|
||||
|
||||
default:
|
||||
throw new IndexOutOfRangeException(string.Format("{0} is missing in convert list", value));
|
||||
throw new IndexOutOfRangeException($"{value} is missing in convert list");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -210,7 +210,7 @@ namespace BizHawk.Client.ApiHawk
|
|||
return "R";
|
||||
|
||||
default:
|
||||
throw new IndexOutOfRangeException(string.Format("{0} is missing in convert list", value));
|
||||
throw new IndexOutOfRangeException($"{value} is missing in convert list");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
public interface IApiContainer
|
||||
{
|
||||
Dictionary<Type, IExternalApi> Libraries { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
public interface IComm : IExternalApi
|
||||
{
|
||||
#region Sockets
|
||||
string SocketServerScreenShot();
|
||||
string SocketServerScreenShotResponse();
|
||||
string SocketServerSend(string SendString);
|
||||
string SocketServerResponse();
|
||||
bool SocketServerSuccessful();
|
||||
void SocketServerSetTimeout(int timeout);
|
||||
#endregion
|
||||
|
||||
#region MemoryMappedFiles
|
||||
void MmfSetFilename(string filename);
|
||||
string MmfGetFilename();
|
||||
int MmfScreenshot();
|
||||
int MmfWrite(string mmf_filename, string outputString);
|
||||
string MmfRead(string mmf_filename, int expectedSize);
|
||||
#endregion
|
||||
|
||||
#region HTTP
|
||||
string HttpTest();
|
||||
string HttpTestGet();
|
||||
string HttpGet(string url);
|
||||
string HttpPost(string url, string payload);
|
||||
string HttpPostScreenshot();
|
||||
void HttpSetTimeout(int timeout);
|
||||
void HttpSetPostUrl(string url);
|
||||
void HttpSetGetUrl(string url);
|
||||
string HttpGetPostUrl();
|
||||
string HttpGetGetUrl();
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
public interface IEmu : IExternalApi
|
||||
{
|
||||
Action FrameAdvanceCallback { get; set; }
|
||||
Action YieldCallback { get; set; }
|
||||
void DisplayVsync(bool enabled);
|
||||
void FrameAdvance();
|
||||
int FrameCount();
|
||||
object Disassemble(uint pc, string name = "");
|
||||
ulong? GetRegister(string name);
|
||||
Dictionary<string, ulong> GetRegisters();
|
||||
void SetRegister(string register, int value);
|
||||
long TotalExecutedycles();
|
||||
string GetSystemId();
|
||||
bool IsLagged();
|
||||
void SetIsLagged(bool value = true);
|
||||
int LagCount();
|
||||
void SetLagCount(int count);
|
||||
void LimitFramerate(bool enabled);
|
||||
void MinimizeFrameskip(bool enabled);
|
||||
void Yield();
|
||||
string GetDisplayType();
|
||||
string GetBoardName();
|
||||
object GetSettings();
|
||||
bool PutSettings(object settings);
|
||||
void SetRenderPlanes(params bool[] param);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
/// <summary>
|
||||
/// This interface specifies that a client exposes a given interface, such as <see cref="BizHawk.Emulation.Common.IDebuggable"/>,
|
||||
/// for use by external tools.
|
||||
/// </summary>
|
||||
public interface IExternalApi
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
public interface IGameInfo : IExternalApi
|
||||
{
|
||||
string GetRomName();
|
||||
string GetRomHash();
|
||||
bool InDatabase();
|
||||
string GetStatus();
|
||||
bool IsStatusBad();
|
||||
string GetBoardType();
|
||||
Dictionary<string, string> GetOptions();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
public interface IGui : IExternalApi
|
||||
{
|
||||
#region Gui API
|
||||
void ToggleCompositingMode();
|
||||
ImageAttributes GetAttributes();
|
||||
void SetAttributes(ImageAttributes a);
|
||||
void DrawNew(string name, bool? clear = true);
|
||||
void DrawFinish();
|
||||
bool HasGUISurface { get; }
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
void SetPadding(int all);
|
||||
void SetPadding(int x, int y);
|
||||
void SetPadding(int l, int t, int r, int b);
|
||||
Padding GetPadding();
|
||||
#endregion
|
||||
|
||||
void AddMessage(string message);
|
||||
void ClearGraphics();
|
||||
void ClearText();
|
||||
void SetDefaultForegroundColor(Color color);
|
||||
void SetDefaultBackgroundColor(Color color);
|
||||
void SetDefaultTextBackground(Color color);
|
||||
void SetDefaultPixelFont(string fontfamily);
|
||||
void DrawBezier(Point p1, Point p2, Point p3, Point p4, Color? color = null);
|
||||
void DrawBeziers(Point[] points, Color? color = null);
|
||||
void DrawBox(int x, int y, int x2, int y2, Color? line = null, Color? background = null);
|
||||
void DrawEllipse(int x, int y, int width, int height, Color? line = null, Color? background = null);
|
||||
void DrawIcon(string path, int x, int y, int? width = null, int? height = null);
|
||||
void DrawImage(string path, int x, int y, int? width = null, int? height = null, bool cache = true);
|
||||
void ClearImageCache();
|
||||
void DrawImageRegion(string path, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int? dest_width = null, int? dest_height = null);
|
||||
void DrawLine(int x1, int y1, int x2, int y2, Color? color = null);
|
||||
void DrawAxis(int x, int y, int size, Color? color = null);
|
||||
void DrawPie(int x, int y, int width, int height, int startangle, int sweepangle, Color? line = null, Color? background = null);
|
||||
void DrawPixel(int x, int y, Color? color = null);
|
||||
void DrawPolygon(Point[] points, Color? line = null, Color? background = null);
|
||||
void DrawRectangle(int x, int y, int width, int height, Color? line = null, Color? background = null);
|
||||
void DrawString(int x, int y, string message, Color? forecolor = null, Color? backcolor = null, int? fontsize = null,
|
||||
string fontfamily = null, string fontstyle = null, string horizalign = null, string vertalign = null);
|
||||
void DrawText(int x, int y, string message, Color? forecolor = null, Color? backcolor = null, string fontfamily = null);
|
||||
void Text(int x, int y, string message, Color? forecolor = null, string anchor = null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
public interface IInput : IExternalApi
|
||||
{
|
||||
Dictionary<string, bool> Get();
|
||||
Dictionary<string, dynamic> GetMouse();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
public interface IJoypad : IExternalApi
|
||||
{
|
||||
Dictionary<string, dynamic> Get(int? controller = null);
|
||||
|
||||
// TODO: what about float controls?
|
||||
Dictionary<string, dynamic> GetImmediate();
|
||||
void SetFromMnemonicStr(string inputLogEntry);
|
||||
void Set(Dictionary<string, bool> buttons, int? controller = null);
|
||||
void Set(string button, bool? state = null, int? controller = null);
|
||||
void SetAnalog(Dictionary<string, float> controls, object controller = null);
|
||||
void SetAnalog(string control, float? value = null, object controller = null);
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
public interface IMem : IExternalApi
|
||||
{
|
||||
void SetBigEndian(bool enabled = true);
|
||||
|
||||
#region Domains
|
||||
List<string> GetMemoryDomainList();
|
||||
uint GetMemoryDomainSize(string name = "");
|
||||
string GetCurrentMemoryDomain();
|
||||
uint GetCurrentMemoryDomainSize();
|
||||
bool UseMemoryDomain(string domain);
|
||||
string HashRegion(long addr, int count, string domain = null);
|
||||
#endregion
|
||||
#region Read
|
||||
#region Special and Legacy Methods
|
||||
uint ReadByte(long addr, string domain = null);
|
||||
List<byte> ReadByteRange(long addr, int length, string domain = null);
|
||||
float ReadFloat(long addr, string domain = null);
|
||||
#endregion
|
||||
#region Signed
|
||||
int ReadS8(long addr, string domain = null);
|
||||
int ReadS16(long addr, string domain = null);
|
||||
int ReadS24(long addr, string domain = null);
|
||||
int ReadS32(long addr, string domain = null);
|
||||
#endregion
|
||||
#region Unsigned
|
||||
uint ReadU8(long addr, string domain = null);
|
||||
uint ReadU16(long addr, string domain = null);
|
||||
uint ReadU24(long addr, string domain = null);
|
||||
uint ReadU32(long addr, string domain = null);
|
||||
#endregion
|
||||
#endregion
|
||||
#region Write
|
||||
#region Special and Legacy Methods
|
||||
void WriteByte(long addr, uint value, string domain = null);
|
||||
void WriteByteRange(long addr, List<byte> memoryblock, string domain = null);
|
||||
void WriteFloat(long addr, double value, string domain = null);
|
||||
#endregion
|
||||
#region Signed
|
||||
void WriteS8(long addr, int value, string domain = null);
|
||||
void WriteS16(long addr, int value, string domain = null);
|
||||
void WriteS24(long addr, int value, string domain = null);
|
||||
void WriteS32(long addr, int value, string domain = null);
|
||||
#endregion
|
||||
#region Unigned
|
||||
void WriteU8(long addr, uint value, string domain = null);
|
||||
void WriteU16(long addr, uint value, string domain = null);
|
||||
void WriteU24(long addr, uint value, string domain = null);
|
||||
void WriteU32(long addr, uint value, string domain = null);
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
public interface IMemEvents : IExternalApi
|
||||
{
|
||||
void AddReadCallback(MemoryCallbackDelegate cb, uint? address, string domain);
|
||||
void AddWriteCallback(MemoryCallbackDelegate cb, uint? address, string domain);
|
||||
void AddExecCallback(MemoryCallbackDelegate cb, uint? address, string domain);
|
||||
void RemoveMemoryCallback(MemoryCallbackDelegate cb);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
public interface IMemorySaveState : IExternalApi
|
||||
{
|
||||
string SaveCoreStateToMemory();
|
||||
void LoadCoreStateFromMemory(string identifier);
|
||||
void DeleteState(string identifier);
|
||||
void ClearInMemoryStates();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
using System.Collections.Generic;
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
public interface IMovie : IExternalApi
|
||||
{
|
||||
bool StartsFromSavestate();
|
||||
bool StartsFromSaveram();
|
||||
string Filename();
|
||||
Dictionary<string, dynamic> GetInput(int frame);
|
||||
string GetInputAsMnemonic(int frame);
|
||||
bool GetReadOnly();
|
||||
ulong GetRerecordCount();
|
||||
bool GetRerecordCounting();
|
||||
bool IsLoaded();
|
||||
double Length();
|
||||
string Mode();
|
||||
void Save(string filename = "");
|
||||
void SetReadOnly(bool readOnly);
|
||||
void SetRerecordCount(double count);
|
||||
void SetRerecordCounting(bool counting);
|
||||
void Stop();
|
||||
double GetFps();
|
||||
Dictionary<string, string> GetHeader();
|
||||
List<string> GetComments();
|
||||
List<string> GetSubtitles();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
public interface ISaveState : IExternalApi
|
||||
{
|
||||
void Load(string path);
|
||||
void LoadSlot(int slotNum);
|
||||
void Save(string path);
|
||||
void SaveSlot(int slotNum);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
public interface ISql : IExternalApi
|
||||
{
|
||||
string CreateDatabase(string name);
|
||||
string OpenDatabase(string name);
|
||||
string WriteCommand(string query = "");
|
||||
dynamic ReadCommand(string query = "");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
public interface ITool : IExternalApi
|
||||
{
|
||||
Type GetTool(string name);
|
||||
object CreateInstance(string name);
|
||||
void OpenCheats();
|
||||
void OpenHexEditor();
|
||||
void OpenRamWatch();
|
||||
void OpenRamSearch();
|
||||
void OpenTasStudio();
|
||||
void OpenToolBox();
|
||||
void OpenTraceLogger();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
public interface IUserData : IExternalApi
|
||||
{
|
||||
void Set(string name, object value);
|
||||
object Get(string key);
|
||||
void Clear();
|
||||
bool Remove(string key);
|
||||
bool ContainsKey(string key);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
/// <summary>
|
||||
/// This interface defines the mechanism by which External tools can retrieve <seealso cref="IExternalApi" />
|
||||
/// from a client implementation
|
||||
/// An implementation should collect all available IExternalApi instances.
|
||||
/// This interface defines only the external interaction. This interface does not specify the means
|
||||
/// by which a api provider will be populated with available apis. However, an implementation
|
||||
/// by design must provide this mechanism
|
||||
/// </summary>
|
||||
/// <seealso cref="IExternalApi"/>
|
||||
public interface IExternalApiProvider
|
||||
{
|
||||
/// <summary>e
|
||||
/// Returns whether or not T is available
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The <seealso cref="IExternalApi" /> to check</typeparam>
|
||||
bool HasApi<T>() where T : IExternalApi;
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether or not t is available
|
||||
/// </summary>
|
||||
bool HasApi(Type t);
|
||||
|
||||
/// <summary>
|
||||
/// Returns an instance of T if T is available
|
||||
/// Else returns null
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The requested <seealso cref="IExternalApi" /></typeparam>
|
||||
T GetApi<T>() where T : IExternalApi;
|
||||
|
||||
/// <summary>
|
||||
/// Returns an instance of t if t is available
|
||||
/// Else returns null
|
||||
/// </summary>
|
||||
object GetApi(Type t);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of all currently registered Apis available to be retrieved
|
||||
/// </summary>
|
||||
IEnumerable<Type> AvailableApis { get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
interface IPlugin
|
||||
{
|
||||
void PreFrameCallback();
|
||||
void PostFrameCallback();
|
||||
void SaveStateCallback(string name);
|
||||
void LoadStateCallback(string name);
|
||||
void InputPollCallback();
|
||||
void Init(IApiContainer api);
|
||||
}
|
||||
}
|
|
@ -14,6 +14,8 @@
|
|||
along with SevenZipSharp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using BizHawk.Common;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
#if !WINCE && !MONO
|
||||
|
@ -61,7 +63,7 @@ namespace SevenZip
|
|||
/// 7z.dll (from the 7-zip distribution) supports every InArchiveFormat for encoding and decoding.
|
||||
/// </remarks>
|
||||
//private static string _libraryFileName = ConfigurationManager.AppSettings["7zLocation"] ?? Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "7z.dll");
|
||||
private static string _libraryFileName = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "7z.dll");
|
||||
private static string _libraryFileName = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "dll\\7z.dll");
|
||||
|
||||
#endif
|
||||
#if WINCE
|
||||
|
@ -87,6 +89,8 @@ namespace SevenZip
|
|||
// private static string _LibraryVersion;
|
||||
private static bool? _modifyCapabale;
|
||||
|
||||
private static readonly OSTailoredCode.ILinkedLibManager libLoader = OSTailoredCode.LinkedLibManager;
|
||||
|
||||
private static void InitUserInFormat(object user, InArchiveFormat format)
|
||||
{
|
||||
if (!_inArchives.ContainsKey(user))
|
||||
|
@ -148,16 +152,16 @@ namespace SevenZip
|
|||
//{
|
||||
// throw new SevenZipLibraryException("DLL file does not exist.");
|
||||
//}
|
||||
if ((_modulePtr = NativeMethods.LoadLibrary(_libraryFileName)) == IntPtr.Zero)
|
||||
if ((_modulePtr = libLoader.LoadPlatformSpecific(_libraryFileName)) == IntPtr.Zero)
|
||||
{
|
||||
//try a different directory
|
||||
string alternateFilename = Path.Combine(Path.Combine(Path.GetDirectoryName(_libraryFileName),"dll"),"7z.dll");
|
||||
if ((_modulePtr = NativeMethods.LoadLibrary(alternateFilename)) == IntPtr.Zero)
|
||||
if ((_modulePtr = libLoader.LoadPlatformSpecific(alternateFilename)) == IntPtr.Zero)
|
||||
throw new SevenZipLibraryException("failed to load library.");
|
||||
}
|
||||
if (NativeMethods.GetProcAddress(_modulePtr, "GetHandlerProperty") == IntPtr.Zero)
|
||||
if (libLoader.GetProcAddr(_modulePtr, "GetHandlerProperty") == IntPtr.Zero)
|
||||
{
|
||||
NativeMethods.FreeLibrary(_modulePtr);
|
||||
libLoader.FreePlatformSpecific(_modulePtr);
|
||||
throw new SevenZipLibraryException("library is invalid.");
|
||||
}
|
||||
}
|
||||
|
@ -431,7 +435,7 @@ namespace SevenZip
|
|||
if (_totalUsers == 0)
|
||||
{
|
||||
#if !WINCE && !MONO
|
||||
NativeMethods.FreeLibrary(_modulePtr);
|
||||
libLoader.FreePlatformSpecific(_modulePtr);
|
||||
|
||||
#endif
|
||||
_modulePtr = IntPtr.Zero;
|
||||
|
@ -466,7 +470,7 @@ namespace SevenZip
|
|||
}
|
||||
var createObject = (NativeMethods.CreateObjectDelegate)
|
||||
Marshal.GetDelegateForFunctionPointer(
|
||||
NativeMethods.GetProcAddress(_modulePtr, "CreateObject"),
|
||||
libLoader.GetProcAddr(_modulePtr, "CreateObject"),
|
||||
typeof(NativeMethods.CreateObjectDelegate));
|
||||
if (createObject == null)
|
||||
{
|
||||
|
@ -525,7 +529,7 @@ namespace SevenZip
|
|||
}
|
||||
var createObject = (NativeMethods.CreateObjectDelegate)
|
||||
Marshal.GetDelegateForFunctionPointer(
|
||||
NativeMethods.GetProcAddress(_modulePtr, "CreateObject"),
|
||||
libLoader.GetProcAddr(_modulePtr, "CreateObject"),
|
||||
typeof(NativeMethods.CreateObjectDelegate));
|
||||
if (createObject == null)
|
||||
{
|
||||
|
|
|
@ -35,18 +35,8 @@ namespace SevenZip
|
|||
[MarshalAs(UnmanagedType.Interface)] out object outObject);
|
||||
|
||||
#endregion
|
||||
|
||||
[DllImport("kernel32.dll", BestFitMapping = false, ThrowOnUnmappableChar = true)]
|
||||
public static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string fileName);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool FreeLibrary(IntPtr hModule);
|
||||
|
||||
[DllImport("kernel32.dll", BestFitMapping = false, ThrowOnUnmappableChar = true)]
|
||||
public static extern IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string procName);
|
||||
#endif
|
||||
|
||||
|
||||
#if WINCE
|
||||
[DllImport("7z.dll", EntryPoint="CreateObject")]
|
||||
public static extern int CreateCOMObject(
|
||||
|
|
|
@ -29,8 +29,11 @@
|
|||
WonderSwan,
|
||||
Libretro,
|
||||
VirtualBoy,
|
||||
Vectrex,
|
||||
NeoGeoPocket,
|
||||
ZXSpectrum,
|
||||
AmstradCPC
|
||||
AmstradCPC,
|
||||
GGL,
|
||||
ChannelF
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,8 +60,8 @@ namespace BizHawk.Client.Common
|
|||
public static BinaryStateLump BranchInputLog { get; private set; }
|
||||
[Name("Branches\\FrameBuffer", "bmp")]
|
||||
public static BinaryStateLump BranchFrameBuffer { get; private set; }
|
||||
[Name("Branches\\LagLog", "bin")]
|
||||
public static BinaryStateLump BranchLagLog { get; private set; }
|
||||
[Name("Branches\\CoreFrameBuffer", "bmp")]
|
||||
public static BinaryStateLump BranchCoreFrameBuffer { get; private set; }
|
||||
[Name("Branches\\Header", "json")]
|
||||
public static BinaryStateLump BranchHeader { get; private set; }
|
||||
[Name("Branches\\Markers", "txt")]
|
||||
|
@ -260,7 +260,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
if (abort)
|
||||
{
|
||||
throw new Exception("Essential zip section not found: " + lump.ReadName);
|
||||
throw new Exception($"Essential zip section not found: {lump.ReadName}");
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
</Reference>
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.IO.Compression" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
|
@ -141,6 +142,7 @@
|
|||
<Compile Include="inputAdapters\OverrideAdaptor.cs" />
|
||||
<Compile Include="inputAdapters\SimpleController.cs" />
|
||||
<Compile Include="inputAdapters\UDLRController.cs" />
|
||||
<Compile Include="input\PolarRectConversion.cs" />
|
||||
<Compile Include="IonicZipWriter.cs" />
|
||||
<Compile Include="IPS.cs" />
|
||||
<Compile Include="IZipWriter.cs" />
|
||||
|
@ -244,6 +246,7 @@
|
|||
<Compile Include="movie\tasproj\TasMovieRecord.cs" />
|
||||
<Compile Include="movie\tasproj\TasStateManagerSettings.cs" />
|
||||
<Compile Include="NESGameGenieEncoderDecoder.cs" />
|
||||
<Compile Include="OpenAdvanced.cs" />
|
||||
<Compile Include="PathManager.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="QuickBmpFile.cs" />
|
||||
|
@ -318,7 +321,6 @@
|
|||
<Name>BizHawk.Bizware.BizwareGL</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
if (required)
|
||||
{
|
||||
var fullmsg = $"Couldn't find required firmware \"{sysID}:{firmwareID}\". This is fatal{(msg != null ? ": " + msg : ".")}";
|
||||
var fullmsg = $"Couldn't find required firmware \"{sysID}:{firmwareID}\". This is fatal{(msg != null ? $": {msg}" : ".")}";
|
||||
throw new MissingFirmwareException(fullmsg);
|
||||
}
|
||||
|
||||
|
|
|
@ -129,8 +129,6 @@ namespace BizHawk.Client.Common
|
|||
/// <summary>
|
||||
/// Test to determine whether the supplied firmware file matches something in the firmware database
|
||||
/// </summary>
|
||||
/// <param name="f"></param>
|
||||
/// <returns></returns>
|
||||
public bool CanFileBeImported(string f)
|
||||
{
|
||||
try
|
||||
|
|
|
@ -154,12 +154,12 @@ namespace BizHawk.Client.Common
|
|||
return SystemInfo.ZXSpectrum;
|
||||
case "AmstradCPC":
|
||||
return SystemInfo.AmstradCPC;
|
||||
case "ChannelF":
|
||||
return SystemInfo.ChannelF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Dictionary<string, object> UserBag = new Dictionary<string, object>();
|
||||
|
||||
public static bool RunningOnUnix = Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ using Newtonsoft.Json;
|
|||
//this file contains some cumbersome self-"serialization" in order to gain a modicum of control over what the serialized output looks like
|
||||
//I don't want them to look like crufty json
|
||||
|
||||
namespace BizHawk.Client.EmuHawk
|
||||
namespace BizHawk.Client.Common
|
||||
{
|
||||
public interface IOpenAdvanced
|
||||
{
|
||||
|
@ -60,7 +60,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
else if (type == OpenAdvancedTypes.LibretroNoGame) ioa = new OpenAdvanced_LibretroNoGame();
|
||||
else ioa = null;
|
||||
if (ioa == null)
|
||||
throw new InvalidOperationException("IOpenAdvanced deserialization error");
|
||||
throw new InvalidOperationException($"{nameof(IOpenAdvanced)} deserialization error");
|
||||
ioa.Deserialize(token);
|
||||
return ioa;
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
}
|
||||
}
|
||||
|
||||
class OpenAdvanced_Libretro : IOpenAdvanced, IOpenAdvancedLibretro
|
||||
public class OpenAdvanced_Libretro : IOpenAdvanced, IOpenAdvancedLibretro
|
||||
{
|
||||
public OpenAdvanced_Libretro()
|
||||
{
|
||||
|
@ -87,7 +87,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
public Token token = new Token();
|
||||
|
||||
public string TypeName { get { return "Libretro"; } }
|
||||
public string DisplayName { get { return string.Format("{0}:{1}", Path.GetFileNameWithoutExtension(token.CorePath), token.Path); } }
|
||||
public string DisplayName { get { return $"{Path.GetFileNameWithoutExtension(token.CorePath)}:{token.Path}"; } }
|
||||
public string SimplePath { get { return token.Path; } }
|
||||
|
||||
public void Deserialize(string str)
|
||||
|
@ -103,7 +103,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
public string CorePath { get { return token.CorePath; } set { token.CorePath = value; } }
|
||||
}
|
||||
|
||||
class OpenAdvanced_LibretroNoGame : IOpenAdvanced, IOpenAdvancedLibretro
|
||||
public class OpenAdvanced_LibretroNoGame : IOpenAdvanced, IOpenAdvancedLibretro
|
||||
{
|
||||
//you might think ideally we'd fetch the libretro core name from the core info inside it
|
||||
//but that would involve spinning up excess libretro core instances, which probably isnt good for stability, no matter how much we wish otherwise, not to mention slow.
|
||||
|
@ -140,7 +140,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
public string CorePath { get { return _corePath; } set { _corePath = value; } }
|
||||
}
|
||||
|
||||
class OpenAdvanced_OpenRom : IOpenAdvanced
|
||||
public class OpenAdvanced_OpenRom : IOpenAdvanced
|
||||
{
|
||||
public OpenAdvanced_OpenRom()
|
||||
{}
|
|
@ -34,7 +34,7 @@ namespace BizHawk.Client.Common
|
|||
/// </summary>
|
||||
public static string MakeProgramRelativePath(string path)
|
||||
{
|
||||
return MakeAbsolutePath("%exe%/" + path, null);
|
||||
return MakeAbsolutePath($"%exe%/{path}", null);
|
||||
}
|
||||
|
||||
public static string GetDllDirectory()
|
||||
|
@ -262,13 +262,13 @@ namespace BizHawk.Client.Common
|
|||
var name = FilesystemSafeName(game);
|
||||
if (Global.MovieSession.Movie.IsActive)
|
||||
{
|
||||
name += "." + Path.GetFileNameWithoutExtension(Global.MovieSession.Movie.Filename);
|
||||
name += $".{Path.GetFileNameWithoutExtension(Global.MovieSession.Movie.Filename)}";
|
||||
}
|
||||
|
||||
var pathEntry = Global.Config.PathEntries[game.System, "Save RAM"] ??
|
||||
Global.Config.PathEntries[game.System, "Base"];
|
||||
|
||||
return Path.Combine(MakeAbsolutePath(pathEntry.Path, game.System), name) + ".SaveRAM";
|
||||
return $"{Path.Combine(MakeAbsolutePath(pathEntry.Path, game.System), name)}.SaveRAM";
|
||||
}
|
||||
|
||||
public static string AutoSaveRamPath(GameInfo game)
|
||||
|
@ -289,7 +289,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
if (Global.MovieSession.Movie.IsActive)
|
||||
{
|
||||
name = Path.Combine(name, "movie-" + Path.GetFileNameWithoutExtension(Global.MovieSession.Movie.Filename));
|
||||
name = Path.Combine(name, $"movie-{Path.GetFileNameWithoutExtension(Global.MovieSession.Movie.Filename)}");
|
||||
}
|
||||
|
||||
var pathEntry = Global.Config.PathEntries[game.System, "Save RAM"] ??
|
||||
|
@ -337,34 +337,34 @@ namespace BizHawk.Client.Common
|
|||
// Neshawk and Quicknes have incompatible savestates, store the name to keep them separate
|
||||
if (Global.Emulator.SystemId == "NES")
|
||||
{
|
||||
name += "." + Global.Emulator.Attributes().CoreName;
|
||||
name += $".{Global.Emulator.Attributes().CoreName}";
|
||||
}
|
||||
|
||||
// Gambatte and GBHawk have incompatible savestates, store the name to keep them separate
|
||||
if (Global.Emulator.SystemId == "GB")
|
||||
{
|
||||
name += "." + Global.Emulator.Attributes().CoreName;
|
||||
name += $".{Global.Emulator.Attributes().CoreName}";
|
||||
}
|
||||
|
||||
if (Global.Emulator is Snes9x) // Keep snes9x savestate away from libsnes, we want to not be too tedious so bsnes names will just have the profile name not the core name
|
||||
{
|
||||
name += "." + Global.Emulator.Attributes().CoreName;
|
||||
name += $".{Global.Emulator.Attributes().CoreName}";
|
||||
}
|
||||
|
||||
// Bsnes profiles have incompatible savestates so save the profile name
|
||||
if (Global.Emulator is LibsnesCore)
|
||||
{
|
||||
name += "." + (Global.Emulator as LibsnesCore).CurrentProfile;
|
||||
name += $".{((LibsnesCore)Global.Emulator).CurrentProfile}";
|
||||
}
|
||||
|
||||
if (Global.Emulator.SystemId == "GBA")
|
||||
{
|
||||
name += "." + Global.Emulator.Attributes().CoreName;
|
||||
name += $".{Global.Emulator.Attributes().CoreName}";
|
||||
}
|
||||
|
||||
if (Global.MovieSession.Movie.IsActive)
|
||||
{
|
||||
name += "." + Path.GetFileNameWithoutExtension(Global.MovieSession.Movie.Filename);
|
||||
name += $".{Path.GetFileNameWithoutExtension(Global.MovieSession.Movie.Filename)}";
|
||||
}
|
||||
|
||||
var pathEntry = Global.Config.PathEntries[game.System, "Savestates"] ??
|
||||
|
|
|
@ -14,8 +14,10 @@ using BizHawk.Emulation.Cores.Computers.Commodore64;
|
|||
using BizHawk.Emulation.Cores.Consoles.Sega.gpgx;
|
||||
using BizHawk.Emulation.Cores.Nintendo.Gameboy;
|
||||
using BizHawk.Emulation.Cores.Nintendo.GBHawk;
|
||||
using BizHawk.Emulation.Cores.Nintendo.GBHawkLink;
|
||||
using BizHawk.Emulation.Cores.Nintendo.SNES;
|
||||
using BizHawk.Emulation.Cores.PCEngine;
|
||||
using BizHawk.Emulation.Cores.Sega.GGHawkLink;
|
||||
using BizHawk.Emulation.Cores.Sega.Saturn;
|
||||
using BizHawk.Emulation.Cores.Sony.PSP;
|
||||
using BizHawk.Emulation.Cores.Sony.PSX;
|
||||
|
@ -26,6 +28,8 @@ using GPGX64 = BizHawk.Emulation.Cores.Consoles.Sega.gpgx;
|
|||
using BizHawk.Emulation.Cores.Consoles.Sega.Saturn;
|
||||
using BizHawk.Emulation.Cores.Consoles.NEC.PCFX;
|
||||
using BizHawk.Emulation.Cores.Computers.AmstradCPC;
|
||||
using BizHawk.Emulation.Cores.Consoles.Vectrex;
|
||||
using BizHawk.Emulation.Cores.Consoles.ChannelF;
|
||||
|
||||
namespace BizHawk.Client.Common
|
||||
{
|
||||
|
@ -169,7 +173,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
private bool HandleArchiveBinding(HawkFile file)
|
||||
{
|
||||
var romExtensions = new[] { "SMS", "SMC", "SFC", "PCE", "SGX", "GG", "SG", "BIN", "GEN", "MD", "SMD", "GB", "NES", "FDS", "ROM", "INT", "GBC", "UNF", "A78", "CRT", "COL", "XML", "Z64", "V64", "N64", "WS", "WSC", "GBA", "32X" };
|
||||
var romExtensions = new[] { "SMS", "SMC", "SFC", "PCE", "SGX", "GG", "SG", "BIN", "GEN", "MD", "SMD", "GB", "NES", "FDS", "ROM", "INT", "GBC", "UNF", "A78", "CRT", "COL", "XML", "Z64", "V64", "N64", "WS", "WSC", "GBA", "32X", "VEC" };
|
||||
|
||||
// try binding normal rom extensions first
|
||||
if (!file.IsBound)
|
||||
|
@ -217,7 +221,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
else if (discMountJob.OUT_ErrorLevel)
|
||||
{
|
||||
throw new InvalidOperationException("\r\n" + discMountJob.OUT_Log);
|
||||
throw new InvalidOperationException($"\r\n{discMountJob.OUT_Log}");
|
||||
}
|
||||
|
||||
else if (disc == null)
|
||||
|
@ -426,7 +430,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
if (discMountJob.OUT_ErrorLevel)
|
||||
{
|
||||
throw new InvalidOperationException("\r\n" + discMountJob.OUT_Log);
|
||||
throw new InvalidOperationException($"\r\n{discMountJob.OUT_Log}");
|
||||
}
|
||||
|
||||
if (disc == null)
|
||||
|
@ -494,7 +498,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
if (discMountJob.OUT_ErrorLevel)
|
||||
{
|
||||
throw new InvalidOperationException("\r\n" + discMountJob.OUT_Log);
|
||||
throw new InvalidOperationException($"\r\n{discMountJob.OUT_Log}");
|
||||
}
|
||||
|
||||
var disc = discMountJob.OUT_Disc;
|
||||
|
@ -630,7 +634,20 @@ namespace BizHawk.Client.Common
|
|||
|
||||
var left = Database.GetGameInfo(leftBytes, "left.gb");
|
||||
var right = Database.GetGameInfo(rightBytes, "right.gb");
|
||||
nextEmulator = new GambatteLink(
|
||||
if (Global.Config.GB_UseGBHawk)
|
||||
{
|
||||
nextEmulator = new GBHawkLink(
|
||||
nextComm,
|
||||
left,
|
||||
leftBytes,
|
||||
right,
|
||||
rightBytes,
|
||||
GetCoreSettings<GBHawkLink>(),
|
||||
GetCoreSyncSettings<GBHawkLink>());
|
||||
}
|
||||
else
|
||||
{
|
||||
nextEmulator = new GambatteLink(
|
||||
nextComm,
|
||||
left,
|
||||
leftBytes,
|
||||
|
@ -639,7 +656,8 @@ namespace BizHawk.Client.Common
|
|||
GetCoreSettings<GambatteLink>(),
|
||||
GetCoreSyncSettings<GambatteLink>(),
|
||||
Deterministic);
|
||||
|
||||
}
|
||||
|
||||
// other stuff todo
|
||||
break;
|
||||
case "AppleII":
|
||||
|
@ -713,7 +731,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
if (discMountJob.OUT_ErrorLevel)
|
||||
{
|
||||
throw new InvalidOperationException("\r\n" + discMountJob.OUT_Log);
|
||||
throw new InvalidOperationException($"\r\n{discMountJob.OUT_Log}");
|
||||
}
|
||||
|
||||
if (disc == null)
|
||||
|
@ -790,6 +808,22 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
nextEmulator = new GPGX(nextComm, null, genDiscs, GetCoreSettings<GPGX>(), GetCoreSyncSettings<GPGX>());
|
||||
break;
|
||||
case "Game Gear":
|
||||
var leftBytesGG = xmlGame.Assets.First().Value;
|
||||
var rightBytesGG = xmlGame.Assets.Skip(1).First().Value;
|
||||
|
||||
var leftGG = Database.GetGameInfo(leftBytesGG, "left.gg");
|
||||
var rightGG = Database.GetGameInfo(rightBytesGG, "right.gg");
|
||||
|
||||
nextEmulator = new GGHawkLink(
|
||||
nextComm,
|
||||
leftGG,
|
||||
leftBytesGG,
|
||||
rightGG,
|
||||
rightBytesGG,
|
||||
GetCoreSettings<GGHawkLink>(),
|
||||
GetCoreSyncSettings<GGHawkLink>());
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -850,6 +884,8 @@ namespace BizHawk.Client.Common
|
|||
rom.GameInfo.System = "NES";
|
||||
}
|
||||
|
||||
Console.WriteLine(rom.GameInfo.System);
|
||||
|
||||
if (string.IsNullOrEmpty(rom.GameInfo.System))
|
||||
{
|
||||
// Has the user picked a preference for this extension?
|
||||
|
@ -958,7 +994,14 @@ namespace BizHawk.Client.Common
|
|||
|
||||
if (preference == "neshawk")
|
||||
{
|
||||
core = CoreInventory.Instance["NES", "NesHawk"];
|
||||
if (Global.Config.UseSubNESHawk)
|
||||
{
|
||||
core = CoreInventory.Instance["NES", "SubNESHawk"];
|
||||
}
|
||||
else
|
||||
{
|
||||
core = CoreInventory.Instance["NES", "NesHawk"];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1039,6 +1082,9 @@ namespace BizHawk.Client.Common
|
|||
Deterministic);
|
||||
nextEmulator = zx;
|
||||
break;
|
||||
case "ChannelF":
|
||||
nextEmulator = new ChannelF(nextComm, game, rom.FileData, GetCoreSettings<ChannelF>(), GetCoreSyncSettings<ChannelF>());
|
||||
break;
|
||||
case "AmstradCPC":
|
||||
var cpc = new AmstradCPC(nextComm, Enumerable.Repeat(rom.RomData, 1), Enumerable.Repeat(rom.GameInfo, 1).ToList(), GetCoreSettings<AmstradCPC>(), GetCoreSyncSettings<AmstradCPC>());
|
||||
nextEmulator = cpc;
|
||||
|
@ -1072,6 +1118,9 @@ namespace BizHawk.Client.Common
|
|||
case "32X":
|
||||
core = CoreInventory.Instance["GEN", "PicoDrive"];
|
||||
break;
|
||||
case "VEC":
|
||||
core = CoreInventory.Instance["VEC", "VectrexHawk"];
|
||||
break;
|
||||
}
|
||||
|
||||
if (core != null)
|
||||
|
@ -1132,12 +1181,12 @@ namespace BizHawk.Client.Common
|
|||
// handle exceptions thrown by the new detected systems that bizhawk does not have cores for
|
||||
else if (ex is NoAvailableCoreException)
|
||||
{
|
||||
DoLoadErrorCallback(ex.Message + "\n\n" + ex, system);
|
||||
DoLoadErrorCallback($"{ex.Message}\n\n{ex}", system);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
DoLoadErrorCallback("A core accepted the rom, but threw an exception while loading it:\n\n" + ex, system);
|
||||
DoLoadErrorCallback($"A core accepted the rom, but threw an exception while loading it:\n\n{ex}", system);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -29,8 +29,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
var file = new FileInfo(
|
||||
PathManager.SaveStatePrefix(Global.Game) + "." + "QuickSave" + i + ".State");
|
||||
var file = new FileInfo($"{PathManager.SaveStatePrefix(Global.Game)}.QuickSave{i}.State");
|
||||
if (file.Directory != null && file.Directory.Exists == false)
|
||||
{
|
||||
file.Directory.Create();
|
||||
|
@ -108,8 +107,8 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
// Takes the .state and .bak files and swaps them
|
||||
var state = new FileInfo(path);
|
||||
var backup = new FileInfo(path + ".bak");
|
||||
var temp = new FileInfo(path + ".bak.tmp");
|
||||
var backup = new FileInfo($"{path}.bak");
|
||||
var temp = new FileInfo($"{path}.bak.tmp");
|
||||
|
||||
if (!state.Exists || !backup.Exists)
|
||||
{
|
||||
|
@ -121,9 +120,9 @@ namespace BizHawk.Client.Common
|
|||
temp.Delete();
|
||||
}
|
||||
|
||||
backup.CopyTo(path + ".bak.tmp");
|
||||
backup.CopyTo($"{path}.bak.tmp");
|
||||
backup.Delete();
|
||||
state.CopyTo(path + ".bak");
|
||||
state.CopyTo($"{path}.bak");
|
||||
state.Delete();
|
||||
temp.CopyTo(path);
|
||||
temp.Delete();
|
||||
|
|
|
@ -91,9 +91,9 @@ namespace BizHawk.Client.Common
|
|||
if (Global.MovieSession.Movie.IsActive && Global.MovieSession.Movie is TasMovie)
|
||||
{
|
||||
bs.PutLump(BinaryStateLump.LagLog,
|
||||
delegate(BinaryWriter bw)
|
||||
delegate(TextWriter tw)
|
||||
{
|
||||
(Global.MovieSession.Movie as TasMovie).TasLagLog.Save(bw);
|
||||
(Global.MovieSession.Movie as TasMovie).TasLagLog.Save(tw);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -195,9 +195,9 @@ namespace BizHawk.Client.Common
|
|||
|
||||
if (Global.MovieSession.Movie.IsActive && Global.MovieSession.Movie is TasMovie)
|
||||
{
|
||||
bl.GetLump(BinaryStateLump.LagLog, false, delegate(BinaryReader br, long length)
|
||||
bl.GetLump(BinaryStateLump.LagLog, false, delegate(TextReader tr)
|
||||
{
|
||||
((TasMovie)Global.MovieSession.Movie).TasLagLog.Load(br);
|
||||
((TasMovie)Global.MovieSession.Movie).TasLagLog.Load(tr);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -183,6 +183,11 @@ namespace BizHawk.Client.Common
|
|||
/// </summary>
|
||||
public static SystemInfo VirtualBoy { get; } = new SystemInfo("Virtual Boy", CoreSystem.VirtualBoy, 1);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="SystemInfo"/> instance for Vectrex
|
||||
/// </summary>
|
||||
public static SystemInfo Vectrex { get; } = new SystemInfo("Vextrex", CoreSystem.Vectrex, 2);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="SystemInfo"/> instance for TI-83
|
||||
/// </summary>
|
||||
|
@ -198,14 +203,24 @@ namespace BizHawk.Client.Common
|
|||
/// </summary>
|
||||
public static SystemInfo AmstradCPC { get; } = new SystemInfo("Amstrad CPC", CoreSystem.AmstradCPC, 2);
|
||||
|
||||
#endregion Get SystemInfo
|
||||
/// <summary>
|
||||
/// Gets the <see cref="SystemInfo"/> instance for GGL
|
||||
/// </summary>
|
||||
public static SystemInfo GGL { get; } = new SystemInfo("Game Gear Linked", CoreSystem.GGL, 2);
|
||||
|
||||
/// <summary>
|
||||
/// Get a <see cref="SystemInfo"/> by its <see cref="CoreSystem"/>
|
||||
/// </summary>
|
||||
/// <param name="system"><see cref="CoreSystem"/> you're looking for</param>
|
||||
/// <returns><see cref="SystemInfo"/></returns>
|
||||
public static SystemInfo FindByCoreSystem(CoreSystem system)
|
||||
/// <summary>
|
||||
/// Gets the <see cref="SystemInfo"/> instance for ChannelF
|
||||
/// </summary>
|
||||
public static SystemInfo ChannelF { get; } = new SystemInfo("Channel F", CoreSystem.ChannelF, 2);
|
||||
|
||||
#endregion Get SystemInfo
|
||||
|
||||
/// <summary>
|
||||
/// Get a <see cref="SystemInfo"/> by its <see cref="CoreSystem"/>
|
||||
/// </summary>
|
||||
/// <param name="system"><see cref="CoreSystem"/> you're looking for</param>
|
||||
/// <returns><see cref="SystemInfo"/></returns>
|
||||
public static SystemInfo FindByCoreSystem(CoreSystem system)
|
||||
{
|
||||
return _allSystemInfos.Find(s => s.System == system);
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Couldn't load XMLGame Asset \"" + filename + "\"");
|
||||
throw new Exception($"Couldn't load XMLGame Asset \"{filename}\"");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -98,7 +98,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
catch
|
||||
{
|
||||
throw new Exception("Couldn't load XMLGame LoadAsset \"" + filename + "\"");
|
||||
throw new Exception($"Couldn't load XMLGame LoadAsset \"{filename}\"");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
// ReSharper disable FieldCanBeMadeReadOnly.Global
|
||||
|
@ -341,8 +342,13 @@ namespace BizHawk.Client.Common
|
|||
|
||||
public int DispPrescale = 1;
|
||||
|
||||
// warning: we dont even want to deal with changing this at runtime. but we want it changed here for config purposes. so dont check this variable. check in GlobalWin or something like that.
|
||||
public EDispMethod DispMethod = EDispMethod.SlimDX9;
|
||||
/// <remarks>
|
||||
/// warning: we dont even want to deal with changing this at runtime. but we want it changed here for config purposes. so dont check this variable. check in GlobalWin or something like that.
|
||||
/// force DX for Windows and GDI+ for Unix when a new config is generated
|
||||
/// </remarks>
|
||||
public EDispMethod DispMethod = OSTailoredCode.CurrentOS == OSTailoredCode.DistinctOS.Windows
|
||||
? EDispMethod.SlimDX9
|
||||
: EDispMethod.GdiPlus;
|
||||
|
||||
public int DispChrome_FrameWindowed = 2;
|
||||
public bool DispChrome_StatusBarWindowed = true;
|
||||
|
@ -363,12 +369,16 @@ namespace BizHawk.Client.Common
|
|||
public float DispCustomUserARX = -1;
|
||||
public float DispCustomUserARY = -1;
|
||||
|
||||
//these default to 0 because by default we crop nothing
|
||||
public int DispCropLeft = 0;
|
||||
public int DispCropTop = 0;
|
||||
public int DispCropRight = 0;
|
||||
public int DispCropBottom = 0;
|
||||
|
||||
// Sound options
|
||||
#if WINDOWS
|
||||
public ESoundOutputMethod SoundOutputMethod = ESoundOutputMethod.DirectSound;
|
||||
#else
|
||||
public ESoundOutputMethod SoundOutputMethod = ESoundOutputMethod.OpenAL;
|
||||
#endif
|
||||
public ESoundOutputMethod SoundOutputMethod = OSTailoredCode.CurrentOS == OSTailoredCode.DistinctOS.Windows
|
||||
? ESoundOutputMethod.DirectSound
|
||||
: ESoundOutputMethod.OpenAL; // force OpenAL for Unix when config is generated
|
||||
public bool SoundEnabled = true;
|
||||
public bool SoundEnabledNormal = true;
|
||||
public bool SoundEnabledRWFF = true;
|
||||
|
@ -554,6 +564,7 @@ namespace BizHawk.Client.Common
|
|||
// as this setting spans multiple cores and doesn't actually affect the behavior of any core,
|
||||
// it hasn't been absorbed into the new system
|
||||
public bool GB_AsSGB = false;
|
||||
public bool UseSubNESHawk = false;
|
||||
public bool NES_InQuickNES = true;
|
||||
public bool SNES_InSnes9x = true;
|
||||
public bool GBA_UsemGBA = true;
|
||||
|
|
|
@ -73,8 +73,8 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
|
||||
// we don't have anything for the system in question. add a set of stock paths
|
||||
var systempath = PathManager.RemoveInvalidFileSystemChars(system) + "_INTERIM";
|
||||
var systemdisp = system + " (INTERIM)";
|
||||
var systempath = $"{PathManager.RemoveInvalidFileSystemChars(system)}_INTERIM";
|
||||
var systemdisp = $"{system} (INTERIM)";
|
||||
|
||||
Paths.AddRange(new[]
|
||||
{
|
||||
|
@ -382,6 +382,12 @@ namespace BizHawk.Client.Common
|
|||
new PathEntry { System = "PCFX", SystemDisplayName = "PCFX", Type = "Save RAM", Path = Path.Combine(".", "SaveRAM"), Ordinal = 3 },
|
||||
new PathEntry { System = "PCFX", SystemDisplayName = "PCFX", Type = "Screenshots", Path = Path.Combine(".", "Screenshots"), Ordinal = 4 },
|
||||
new PathEntry { System = "PCFX", SystemDisplayName = "PCFX", Type = "Cheats", Path = Path.Combine(".", "Cheats"), Ordinal = 5 },
|
||||
|
||||
new PathEntry { System = "ChannelF", SystemDisplayName = "Fairchild Channel F", Type = "Base", Path = Path.Combine(".", "ZXSpectrum"), Ordinal = 0 },
|
||||
new PathEntry { System = "ChannelF", SystemDisplayName = "Fairchild Channel F", Type = "ROM", Path = ".", Ordinal = 1 },
|
||||
new PathEntry { System = "ChannelF", SystemDisplayName = "Fairchild Channel F", Type = "Savestates", Path = Path.Combine(".", "State"), Ordinal = 2 },
|
||||
new PathEntry { System = "ChannelF", SystemDisplayName = "Fairchild Channel F", Type = "Screenshots", Path = Path.Combine(".", "Screenshots"), Ordinal = 4 },
|
||||
new PathEntry { System = "ChannelF", SystemDisplayName = "Fairchild Channel F", Type = "Cheats", Path = Path.Combine(".", "Cheats"), Ordinal = 5 },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ namespace BizHawk.Client.Common
|
|||
return new Point(_wndx.Value, _wndy.Value);
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("TopLeft can not be used when one of the coordinates is null");
|
||||
throw new InvalidOperationException($"{nameof(TopLeft)} can not be used when one of the coordinates is null");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
|
||||
using DoublePair = System.Tuple<double, double>;
|
||||
|
||||
namespace BizHawk.Client.Common
|
||||
{
|
||||
public static class PolarRectConversion
|
||||
{
|
||||
/// <param name="θ">angle in degrees</param>
|
||||
/// <returns>rectangular (Cartesian) coordinates (x, y)</returns>
|
||||
public static DoublePair PolarDegToRect(double r, double θ) => PolarRadToRect(r, θ * Math.PI / 180);
|
||||
|
||||
/// <param name="θ">angle in radians</param>
|
||||
/// <returns>rectangular (Cartesian) coordinates (x, y)</returns>
|
||||
public static DoublePair PolarRadToRect(double r, double θ) => new DoublePair(r * Math.Cos(θ), r * Math.Sin(θ));
|
||||
|
||||
/// <returns>polar coordinates (r, θ) where θ is in degrees</returns>
|
||||
public static DoublePair RectToPolarDeg(double x, double y) => new DoublePair(Math.Sqrt(x * x + y * y), Math.Atan2(y, x) * 180 / Math.PI);
|
||||
}
|
||||
}
|
|
@ -32,7 +32,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
|
||||
prefix = button.GetPrecedingString("Down");
|
||||
string other = prefix + "Up";
|
||||
string other = $"{prefix}Up";
|
||||
if (Source.IsPressed(other))
|
||||
{
|
||||
if (_unpresses.Contains(button))
|
||||
|
@ -61,7 +61,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
|
||||
prefix = button.GetPrecedingString("Up");
|
||||
string other = prefix + "Down";
|
||||
string other = $"{prefix}Down";
|
||||
if (Source.IsPressed(other))
|
||||
{
|
||||
if (_unpresses.Contains(button))
|
||||
|
@ -90,7 +90,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
|
||||
prefix = button.GetPrecedingString("Right");
|
||||
string other = prefix + "Left";
|
||||
string other = $"{prefix}Left";
|
||||
if (Source.IsPressed(other))
|
||||
{
|
||||
if (_unpresses.Contains(button))
|
||||
|
@ -119,7 +119,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
|
||||
prefix = button.GetPrecedingString("Left");
|
||||
string other = prefix + "Right";
|
||||
string other = $"{prefix}Right";
|
||||
if (Source.IsPressed(other))
|
||||
{
|
||||
if (_unpresses.Contains(button))
|
||||
|
|
|
@ -93,7 +93,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
catch (NotImplementedException)
|
||||
{
|
||||
Log($"Error: {Emulator.Attributes().CoreName} does not yet implement disassemble()");
|
||||
Log($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDisassemblable.Disassemble)}()");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
catch (NotImplementedException)
|
||||
{
|
||||
Log($"Error: {Emulator.Attributes().CoreName} does not yet implement getregister()");
|
||||
Log($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.GetCpuFlagsAndRegisters)}()");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
catch (NotImplementedException)
|
||||
{
|
||||
Log($"Error: {Emulator.Attributes().CoreName} does not yet implement getregisters()");
|
||||
Log($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.GetCpuFlagsAndRegisters)}()");
|
||||
}
|
||||
|
||||
return table;
|
||||
|
@ -163,7 +163,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
catch (NotImplementedException)
|
||||
{
|
||||
Log($"Error: {Emulator.Attributes().CoreName} does not yet implement setregister()");
|
||||
Log($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.SetCpuRegister)}()");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -182,7 +182,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
catch (NotImplementedException)
|
||||
{
|
||||
Log($"Error: {Emulator.Attributes().CoreName} does not yet implement totalexecutedcycles()");
|
||||
Log($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.TotalExecutedCycles)}()");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -204,7 +204,7 @@ namespace BizHawk.Client.Common
|
|||
return InputPollableCore.IsLagFrame;
|
||||
}
|
||||
|
||||
Log($"Can not get lag information, {Emulator.Attributes().CoreName} does not implement IInputPollable");
|
||||
Log($"Can not get lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -218,7 +218,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
else
|
||||
{
|
||||
Log($"Can not set lag information, {Emulator.Attributes().CoreName} does not implement IInputPollable");
|
||||
Log($"Can not set lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -231,7 +231,7 @@ namespace BizHawk.Client.Common
|
|||
return InputPollableCore.LagCount;
|
||||
}
|
||||
|
||||
Log($"Can not get lag information, {Emulator.Attributes().CoreName} does not implement IInputPollable");
|
||||
Log($"Can not get lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -245,7 +245,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
else
|
||||
{
|
||||
Log($"Can not set lag information, {Emulator.Attributes().CoreName} does not implement IInputPollable");
|
||||
Log($"Can not set lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -62,10 +62,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log(
|
||||
"error running function attached by lua function event.onsavestate" +
|
||||
"\nError message: " +
|
||||
e.Message);
|
||||
Log($"error running function attached by lua function event.onsavestate\nError message: {e.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -84,10 +81,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log(
|
||||
"error running function attached by lua function event.onloadstate" +
|
||||
"\nError message: " +
|
||||
e.Message);
|
||||
Log($"error running function attached by lua function event.onloadstate\nError message: {e.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,10 +100,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log(
|
||||
"error running function attached by lua function event.onframestart" +
|
||||
"\nError message: " +
|
||||
e.Message);
|
||||
Log($"error running function attached by lua function event.onframestart\nError message: {e.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -128,10 +119,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log(
|
||||
"error running function attached by lua function event.onframeend" +
|
||||
"\nError message: " +
|
||||
e.Message);
|
||||
Log($"error running function attached by lua function event.onframeend\nError message: {e.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -243,7 +231,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
|
||||
DebuggableCore.MemoryCallbacks.Add(
|
||||
new MemoryCallback(domain, MemoryCallbackType.Execute, "Lua Hook", nlf.Callback, address, null));
|
||||
new MemoryCallback(domain, MemoryCallbackType.Execute, "Lua Hook", nlf.MemCallback, address, null));
|
||||
return nlf.Guid.ToString();
|
||||
}
|
||||
}
|
||||
|
@ -282,7 +270,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
|
||||
DebuggableCore.MemoryCallbacks.Add(
|
||||
new MemoryCallback(domain, MemoryCallbackType.Read, "Lua Hook", nlf.Callback, address, null));
|
||||
new MemoryCallback(domain, MemoryCallbackType.Read, "Lua Hook", nlf.MemCallback, address, null));
|
||||
return nlf.Guid.ToString();
|
||||
}
|
||||
}
|
||||
|
@ -321,7 +309,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
|
||||
DebuggableCore.MemoryCallbacks.Add(
|
||||
new MemoryCallback(domain, MemoryCallbackType.Write, "Lua Hook", nlf.Callback, address, null));
|
||||
new MemoryCallback(domain, MemoryCallbackType.Write, "Lua Hook", nlf.MemCallback, address, null));
|
||||
return nlf.Guid.ToString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,9 +25,9 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
buttons[button] = adaptor.IsPressed(button);
|
||||
}
|
||||
else if (button.Length >= 3 && button.Substring(0, 2) == "P" + controller)
|
||||
else if (button.Length >= 3 && button.Substring(0, 2) == $"P{controller}")
|
||||
{
|
||||
buttons[button.Substring(3)] = adaptor.IsPressed("P" + controller + " " + button.Substring(3));
|
||||
buttons[button.Substring(3)] = adaptor.IsPressed($"P{controller} {button.Substring(3)}");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,9 +37,9 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
buttons[button] = adaptor.GetFloat(button);
|
||||
}
|
||||
else if (button.Length >= 3 && button.Substring(0, 2) == "P" + controller)
|
||||
else if (button.Length >= 3 && button.Substring(0, 2) == $"P{controller}")
|
||||
{
|
||||
buttons[button.Substring(3)] = adaptor.GetFloat("P" + controller + " " + button.Substring(3));
|
||||
buttons[button.Substring(3)] = adaptor.GetFloat($"P{controller} {button.Substring(3)}");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Log("invalid mnemonic string: " + inputLogEntry);
|
||||
Log($"invalid mnemonic string: {inputLogEntry}");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,7 +125,7 @@ namespace BizHawk.Client.Common
|
|||
var toPress = button.ToString();
|
||||
if (controller.HasValue)
|
||||
{
|
||||
toPress = "P" + controller + " " + button;
|
||||
toPress = $"P{controller} {button}";
|
||||
}
|
||||
|
||||
if (!invert)
|
||||
|
@ -180,7 +180,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
else
|
||||
{
|
||||
Global.StickyXORAdapter.SetFloat("P" + controller + " " + name, theValue);
|
||||
Global.StickyXORAdapter.SetFloat($"P{controller} {name}", theValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,7 +149,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
if (!string.IsNullOrEmpty(filename))
|
||||
{
|
||||
filename += "." + Global.MovieSession.Movie.PreferredExtension;
|
||||
filename += $".{Global.MovieSession.Movie.PreferredExtension}";
|
||||
var test = new FileInfo(filename);
|
||||
if (test.Exists)
|
||||
{
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data.SQLite;
|
||||
using NLua;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BizHawk.Client.Common
|
||||
{
|
||||
|
@ -106,7 +105,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
var table = Lua.NewTable();
|
||||
m_dbConnection.Open();
|
||||
string sql = "PRAGMA read_uncommitted =1;" + query;
|
||||
string sql = $"PRAGMA read_uncommitted =1;{query}";
|
||||
SQLiteCommand command = new SQLiteCommand(sql, m_dbConnection);
|
||||
SQLiteDataReader reader = command.ExecuteReader();
|
||||
bool rows = reader.HasRows;
|
||||
|
@ -120,7 +119,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
for (int i = 0; i < reader.FieldCount; ++i)
|
||||
{
|
||||
table[columns[i] + " " + rowCount.ToString()] = reader.GetValue(i);
|
||||
table[$"{columns[i]} {rowCount}"] = reader.GetValue(i);
|
||||
}
|
||||
rowCount += 1;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace BizHawk.Client.Common
|
|||
var hex = $"{num:X}";
|
||||
if (hex.Length == 1)
|
||||
{
|
||||
hex = "0" + hex;
|
||||
hex = $"0{hex}";
|
||||
}
|
||||
|
||||
return hex;
|
||||
|
@ -46,7 +46,7 @@ namespace BizHawk.Client.Common
|
|||
var octal = Convert.ToString(num, 8);
|
||||
if (octal.Length == 1)
|
||||
{
|
||||
octal = "0" + octal;
|
||||
octal = $"0{octal}";
|
||||
}
|
||||
|
||||
return octal;
|
||||
|
|
|
@ -26,10 +26,10 @@ __Types and notation__
|
|||
* ? (question mark)
|
||||
** A question mark next to a value indicates that it is a Nullable type (only applies to types that are not normally nullable)
|
||||
* [[]] (brackets)
|
||||
** Brackets around a parameter indicate that the parameter is optional. optional parameters have an equals sign followed by the value that will be used if no value is supplied.
|
||||
** Brackets around a parameter indicate that the parameter is optional. Optional parameters have an equals sign followed by the value that will be used if no value is supplied.
|
||||
** Brackets after a parameter type indicate it is an array
|
||||
* null
|
||||
** null is equivalent to the lua nil
|
||||
** null is equivalent to the lua nil. Lua doesn't support named arguments, it checks the arguments by position. So if you're sending an optional argument that goes ''after'' other optional arguments you don't want to send, replace those with lua nil.
|
||||
* Color
|
||||
** This is a .NET System.Drawing.Color struct. The value passed from lua is any value acceptable in the Color constructor. This means either a string with the color name such as ""red"", or a 0xAARRGGBB integer value. Unless specified, this is not a nullable value
|
||||
* object
|
||||
|
@ -102,7 +102,7 @@ __Types and notation__
|
|||
{
|
||||
var completion = new SublimeCompletions.Completion
|
||||
{
|
||||
Trigger = f.Library + "." + f.Name
|
||||
Trigger = $"{f.Library}.{f.Name}"
|
||||
};
|
||||
|
||||
var sb = new StringBuilder();
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
if (Global.Emulator.MemoryCallbacksAvailable())
|
||||
{
|
||||
Global.Emulator.AsDebuggable().MemoryCallbacks.Remove(function.Callback);
|
||||
Global.Emulator.AsDebuggable().MemoryCallbacks.Remove(function.MemCallback);
|
||||
}
|
||||
|
||||
return base.Remove(function);
|
||||
|
@ -40,7 +40,7 @@ namespace BizHawk.Client.Common
|
|||
if (Global.Emulator.MemoryCallbacksAvailable())
|
||||
{
|
||||
var memoryCallbacks = Global.Emulator.AsDebuggable().MemoryCallbacks;
|
||||
memoryCallbacks.RemoveAll(this.Select(w => w.Callback));
|
||||
memoryCallbacks.RemoveAll(this.Select(w => w.MemCallback));
|
||||
}
|
||||
|
||||
Clear();
|
||||
|
|
|
@ -101,7 +101,7 @@ namespace BizHawk.Client.Common
|
|||
foreach (var method in methods)
|
||||
{
|
||||
var luaMethodAttr = (LuaMethodAttribute)method.GetCustomAttributes(luaAttr, false).First();
|
||||
var luaName = Name + "." + luaMethodAttr.Name;
|
||||
var luaName = $"{Name}.{luaMethodAttr.Name}";
|
||||
Lua.RegisterFunction(luaName, this, method);
|
||||
|
||||
docs?.Add(new LibraryFunction(Name, callingLibrary.Description(), method));
|
||||
|
|
|
@ -67,8 +67,7 @@ namespace BizHawk.Client.Common
|
|||
return d.PeekByte(addr);
|
||||
}
|
||||
|
||||
Log("Warning: attempted read of " + addr +
|
||||
" outside the memory size of " + d.Size);
|
||||
Log($"Warning: attempted read of {addr} outside the memory size of {d.Size}");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -83,8 +82,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
else
|
||||
{
|
||||
Log("Warning: attempted write to " + addr +
|
||||
" outside the memory size of " + d.Size);
|
||||
Log($"Warning: attempted write to {addr} outside the memory size of {d.Size}");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -188,8 +186,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
else
|
||||
{
|
||||
Log("Warning: Attempted read " + lastAddr + " outside memory domain size of " +
|
||||
d.Size + " in readbyterange()");
|
||||
Log($"Warning: Attempted read {lastAddr} outside memory domain size of {d.Size} in readbyterange()");
|
||||
}
|
||||
|
||||
return table;
|
||||
|
@ -209,8 +206,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
else
|
||||
{
|
||||
Log("Warning: Attempted write " + addr + " outside memory domain size of " +
|
||||
d.Size + " in writebyterange()");
|
||||
Log($"Warning: Attempted write {addr} outside memory domain size of {d.Size} in writebyterange()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -230,8 +226,7 @@ namespace BizHawk.Client.Common
|
|||
return BitConverter.ToSingle(bytes, 0);
|
||||
}
|
||||
|
||||
Log("Warning: Attempted read " + addr +
|
||||
" outside memory size of " + d.Size);
|
||||
Log($"Warning: Attempted read {addr} outside memory size of {d.Size}");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -250,8 +245,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
else
|
||||
{
|
||||
Log("Warning: Attempted write " + addr +
|
||||
" outside memory size of " + d.Size);
|
||||
Log($"Warning: Attempted write {addr} outside memory size of {d.Size}");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using BizHawk.Common;
|
||||
|
||||
using NLua;
|
||||
|
||||
// TODO - evaluate for re-entrancy problems
|
||||
|
@ -18,16 +21,14 @@ namespace BizHawk.Client.Common
|
|||
|
||||
private string _currentDirectory;
|
||||
|
||||
#if WINDOWS
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
static extern bool SetCurrentDirectoryW(byte* lpPathName);
|
||||
[DllImport("kernel32.dll", SetLastError=true)]
|
||||
static extern uint GetCurrentDirectoryW(uint nBufferLength, byte* pBuffer);
|
||||
#endif
|
||||
|
||||
private bool CoolSetCurrentDirectory(string path, string currDirSpeedHack = null)
|
||||
{
|
||||
string target = _currentDirectory + "\\";
|
||||
string target = $"{_currentDirectory}\\";
|
||||
|
||||
// first we'll bypass it with a general hack: dont do any setting if the value's already there (even at the OS level, setting the directory can be slow)
|
||||
// yeah I know, not the smoothest move to compare strings here, in case path normalization is happening at some point
|
||||
|
@ -42,40 +43,43 @@ namespace BizHawk.Client.Common
|
|||
return true;
|
||||
}
|
||||
|
||||
// WARNING: setting the current directory is SLOW!!! security checks for some reason.
|
||||
// so we're bypassing it with windows hacks
|
||||
#if WINDOWS
|
||||
fixed (byte* pstr = &System.Text.Encoding.Unicode.GetBytes(target + "\0")[0])
|
||||
if (OSTailoredCode.CurrentOS == OSTailoredCode.DistinctOS.Windows)
|
||||
{
|
||||
// WARNING: setting the current directory is SLOW!!! security checks for some reason.
|
||||
// so we're bypassing it with windows hacks
|
||||
fixed (byte* pstr = &System.Text.Encoding.Unicode.GetBytes($"{target}\0")[0])
|
||||
return SetCurrentDirectoryW(pstr);
|
||||
#else
|
||||
if (System.IO.Directory.Exists(CurrentDirectory)) // race condition for great justice
|
||||
{
|
||||
Environment.CurrentDirectory = CurrentDirectory; // thats right, you can't set a directory as current that doesnt exist because .net's got to do SENSELESS SLOW-ASS SECURITY CHECKS on it and it can't do that on a NONEXISTENT DIRECTORY
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if (System.IO.Directory.Exists(_currentDirectory)) // race condition for great justice
|
||||
{
|
||||
Environment.CurrentDirectory = _currentDirectory; // thats right, you can't set a directory as current that doesnt exist because .net's got to do SENSELESS SLOW-ASS SECURITY CHECKS on it and it can't do that on a NONEXISTENT DIRECTORY
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string CoolGetCurrentDirectory()
|
||||
{
|
||||
// GUESS WHAT!
|
||||
// .NET DOES A SECURITY CHECK ON THE DIRECTORY WE JUST RETRIEVED
|
||||
// AS IF ASKING FOR THE CURRENT DIRECTORY IS EQUIVALENT TO TRYING TO ACCESS IT
|
||||
// SCREW YOU
|
||||
#if WINDOWS
|
||||
if (OSTailoredCode.CurrentOS == OSTailoredCode.DistinctOS.Windows)
|
||||
{
|
||||
// GUESS WHAT!
|
||||
// .NET DOES A SECURITY CHECK ON THE DIRECTORY WE JUST RETRIEVED
|
||||
// AS IF ASKING FOR THE CURRENT DIRECTORY IS EQUIVALENT TO TRYING TO ACCESS IT
|
||||
// SCREW YOU
|
||||
var buf = new byte[32768];
|
||||
fixed(byte* pBuf = &buf[0])
|
||||
{
|
||||
uint ret = GetCurrentDirectoryW(32767, pBuf);
|
||||
return System.Text.Encoding.Unicode.GetString(buf, 0, (int)ret*2);
|
||||
}
|
||||
#else
|
||||
fixed (byte* pBuf = &buf[0])
|
||||
return System.Text.Encoding.Unicode.GetString(buf, 0, 2 * (int) GetCurrentDirectoryW(32767, pBuf));
|
||||
}
|
||||
else
|
||||
{
|
||||
return Environment.CurrentDirectory;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private void Sandbox(Action callback, Action exceptionCallback)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
using System;
|
||||
using NLua;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Client.Common
|
||||
{
|
||||
public class NamedLuaFunction
|
||||
|
@ -23,13 +25,14 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logCallback(
|
||||
"error running function attached by the event " +
|
||||
Event +
|
||||
"\nError message: " +
|
||||
ex.Message);
|
||||
logCallback($"error running function attached by the event {Event}\nError message: {ex.Message}");
|
||||
}
|
||||
};
|
||||
|
||||
MemCallback = delegate
|
||||
{
|
||||
Callback();
|
||||
};
|
||||
}
|
||||
|
||||
public Guid Guid { get; private set; }
|
||||
|
@ -42,6 +45,8 @@ namespace BizHawk.Client.Common
|
|||
|
||||
public Action Callback { get; }
|
||||
|
||||
public MemoryCallbackDelegate MemCallback { get; }
|
||||
|
||||
public void Call(string name = null)
|
||||
{
|
||||
LuaSandbox.Sandbox(Lua, () =>
|
||||
|
|
|
@ -163,7 +163,7 @@ namespace BizHawk.Client.Common
|
|||
Movie.SwitchToRecord();
|
||||
break;
|
||||
case MovieEndAction.Pause:
|
||||
Movie.Stop();
|
||||
Movie.FinishedMode();
|
||||
PauseCallback();
|
||||
break;
|
||||
default:
|
||||
|
@ -201,7 +201,7 @@ namespace BizHawk.Client.Common
|
|||
var result = Movie.Stop(saveChanges);
|
||||
if (result)
|
||||
{
|
||||
Output(Path.GetFileName(Movie.Filename) + " written to disk.");
|
||||
Output($"{Path.GetFileName(Movie.Filename)} written to disk.");
|
||||
}
|
||||
|
||||
Output(message);
|
||||
|
@ -225,7 +225,7 @@ namespace BizHawk.Client.Common
|
|||
if (Movie.IsPlaying)
|
||||
{
|
||||
Movie.ClearFrame(Global.Emulator.Frame);
|
||||
Output("Scrubbed input at frame " + Global.Emulator.Frame);
|
||||
Output($"Scrubbed input at frame {Global.Emulator.Frame}");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace BizHawk.Client.Common
|
|||
return "Recording None";
|
||||
}
|
||||
|
||||
return "Recording Player " + CurrentPlayer;
|
||||
return $"Recording Player {CurrentPlayer}";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,19 +59,9 @@ namespace BizHawk.Client.Common
|
|||
int startTime = (int)(start * 1000 / fps);
|
||||
int endTime = (int)(end * 1000 / fps);
|
||||
|
||||
var startString = string.Format(
|
||||
"{0:d2}:{1:d2}:{2:d2},{3:d3}",
|
||||
startTime / 3600000,
|
||||
(startTime / 60000) % 60,
|
||||
(startTime / 1000) % 60,
|
||||
startTime % 1000);
|
||||
var startString = $"{startTime / 3600000:d2}:{(startTime / 60000) % 60:d2}:{(startTime / 1000) % 60:d2},{startTime % 1000:d3}";
|
||||
|
||||
var endString = string.Format(
|
||||
"{0:d2}:{1:d2}:{2:d2},{3:d3}",
|
||||
endTime / 3600000,
|
||||
(endTime / 60000) % 60,
|
||||
(endTime / 1000) % 60,
|
||||
endTime % 1000);
|
||||
var endString = $"{endTime / 3600000:d2}:{(endTime / 60000) % 60:d2}:{(endTime / 1000) % 60:d2},{endTime % 1000:d3}";
|
||||
|
||||
sb.Append(startString);
|
||||
sb.Append(" --> ");
|
||||
|
|
|
@ -103,7 +103,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
if (i > 0 && lastframe == subs[i].Frame)
|
||||
{
|
||||
subs[i].Message = subs[i - 1].Message + " " + subs[i].Message;
|
||||
subs[i].Message = $"{subs[i - 1].Message} {subs[i].Message}";
|
||||
subs.Remove(subs[i - 1]);
|
||||
i--;
|
||||
}
|
||||
|
|
|
@ -144,10 +144,10 @@ namespace BizHawk.Client.Common
|
|||
_myBoolButtons[button] = Global.AutofireStickyXORAdapter.IsSticky(button);
|
||||
}
|
||||
|
||||
// float controls don't have sticky logic. but old values remain in MovieOutputHardpoint if we don't update this here
|
||||
foreach (var name in Definition.FloatControls)
|
||||
// float controls don't have sticky logic, so latch default value
|
||||
for (int i = 0; i < Definition.FloatControls.Count; i++)
|
||||
{
|
||||
_myFloatControls[name] = Global.AutofireStickyXORAdapter.GetFloat(name);
|
||||
_myFloatControls[Definition.FloatControls[i]] = Definition.FloatRanges[i].Mid;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -81,6 +81,8 @@ namespace BizHawk.Client.Common
|
|||
["Button"] = 'B',
|
||||
["Button 1"] = '1',
|
||||
["Button 2"] = '2',
|
||||
["Button 3"] = '3',
|
||||
["Button 4"] = '4',
|
||||
["B1"] = '1',
|
||||
["B2"] = '2',
|
||||
|
||||
|
|
|
@ -93,11 +93,17 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
if (value)
|
||||
{
|
||||
Header.Add(HeaderKeys.STARTSFROMSAVERAM, "True");
|
||||
if (!Header.ContainsKey(HeaderKeys.STARTSFROMSAVERAM))
|
||||
{
|
||||
Header.Add(HeaderKeys.STARTSFROMSAVERAM, "True");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Header.Remove(HeaderKeys.STARTSFROMSAVERAM);
|
||||
if (Header.ContainsKey(HeaderKeys.STARTSFROMSAVERAM))
|
||||
{
|
||||
Header.Remove(HeaderKeys.STARTSFROMSAVERAM);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -166,6 +166,12 @@ namespace BizHawk.Client.Common
|
|||
|
||||
protected virtual void Write(string fn, bool backup = false)
|
||||
{
|
||||
if (Global.Emulator is BizHawk.Emulation.Cores.Nintendo.SubNESHawk.SubNESHawk)
|
||||
{
|
||||
var _subnes = (BizHawk.Emulation.Cores.Nintendo.SubNESHawk.SubNESHawk)Global.Emulator;
|
||||
Header["VBlankCount"] = _subnes.VBL_CNT.ToString();
|
||||
}
|
||||
|
||||
var file = new FileInfo(fn);
|
||||
if (!file.Directory.Exists)
|
||||
{
|
||||
|
|
|
@ -250,10 +250,7 @@ namespace BizHawk.Client.Common
|
|||
return true;
|
||||
}
|
||||
|
||||
errorMessage = "The savestate is from frame "
|
||||
+ newLog.Count
|
||||
+ " which is greater than the current movie length of "
|
||||
+ Log.Count;
|
||||
errorMessage = $"The savestate is from frame {newLog.Count} which is greater than the current movie length of {Log.Count}";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -262,9 +259,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
if (Log[i] != newLog[i])
|
||||
{
|
||||
errorMessage = "The savestate input does not match the movie input at frame "
|
||||
+ (i + 1)
|
||||
+ ".";
|
||||
errorMessage = $"The savestate input does not match the movie input at frame {(i + 1)}.";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -253,7 +253,7 @@ namespace BizHawk.Client.Common
|
|||
string prefix = "";
|
||||
if (ControlType != "Gameboy Controller" && ControlType != "TI83 Controller")
|
||||
{
|
||||
prefix = "P" + player + " ";
|
||||
prefix = $"P{player} ";
|
||||
}
|
||||
|
||||
foreach (string button in BkmMnemonicConstants.Buttons[ControlType].Keys)
|
||||
|
@ -352,7 +352,7 @@ namespace BizHawk.Client.Common
|
|||
int start = 3;
|
||||
foreach (string button in BkmMnemonicConstants.Buttons[ControlType].Keys)
|
||||
{
|
||||
Force("P" + player + " " + button, c[srcindex + start++]);
|
||||
Force($"P{player} {button}", c[srcindex + start++]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -393,7 +393,7 @@ namespace BizHawk.Client.Common
|
|||
int start = 3;
|
||||
foreach (string button in BkmMnemonicConstants.Buttons["GPGX 3-Button Controller"].Keys)
|
||||
{
|
||||
Force("P" + player + " " + button, c[srcindex + start++]);
|
||||
Force($"P{player} {button}", c[srcindex + start++]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -429,7 +429,7 @@ namespace BizHawk.Client.Common
|
|||
int start = 3;
|
||||
foreach (var button in BkmMnemonicConstants.Buttons[ControlType].Keys)
|
||||
{
|
||||
Force("P" + player + " " + button, c[srcindex + start++]);
|
||||
Force($"P{player} {button}", c[srcindex + start++]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -497,12 +497,12 @@ namespace BizHawk.Client.Common
|
|||
int start = 3;
|
||||
foreach (string button in BkmMnemonicConstants.Buttons[ControlType].Keys)
|
||||
{
|
||||
Force("P" + player + " " + button, c[srcindex + start++]);
|
||||
Force($"P{player} {button}", c[srcindex + start++]);
|
||||
}
|
||||
|
||||
foreach (string name in BkmMnemonicConstants.Analogs[ControlType].Keys)
|
||||
{
|
||||
Force("P" + player + " " + name, int.Parse(mnemonic.Substring(srcindex + start, 4)));
|
||||
Force($"P{player} {name}", int.Parse(mnemonic.Substring(srcindex + start, 4)));
|
||||
start += 5;
|
||||
}
|
||||
}
|
||||
|
@ -539,7 +539,7 @@ namespace BizHawk.Client.Common
|
|||
int start = 3;
|
||||
foreach (string button in BkmMnemonicConstants.Buttons[ControlType].Keys)
|
||||
{
|
||||
Force("P" + player + " " + button, c[srcindex + start++]);
|
||||
Force($"P{player} {button}", c[srcindex + start++]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -585,7 +585,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
foreach (string button in BkmMnemonicConstants.Buttons[ControlType].Keys)
|
||||
{
|
||||
Force("P" + player + " " + button, c[srcindex + start++]);
|
||||
Force($"P{player} {button}", c[srcindex + start++]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -635,7 +635,7 @@ namespace BizHawk.Client.Common
|
|||
int start = 1;
|
||||
foreach (var button in BkmMnemonicConstants.Buttons[ControlType].Keys)
|
||||
{
|
||||
Force("P" + player + " " + button, c[srcindex + start++]);
|
||||
Force($"P{player} {button}", c[srcindex + start++]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -165,7 +165,7 @@ namespace BizHawk.Client.Common
|
|||
var prefix = "";
|
||||
if (_controlType != "Gameboy Controller" && _controlType != "TI83 Controller")
|
||||
{
|
||||
prefix = "P" + player + " ";
|
||||
prefix = $"P{player} ";
|
||||
}
|
||||
|
||||
foreach (var button in BkmMnemonicConstants.Buttons[_controlType].Keys)
|
||||
|
@ -313,7 +313,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
foreach (var button in BkmMnemonicConstants.Buttons[_controlType].Keys)
|
||||
{
|
||||
input.Append(IsBasePressed("P" + player + " " + button) ? BkmMnemonicConstants.Buttons[_controlType][button] : ".");
|
||||
input.Append(IsBasePressed($"P{player} {button}") ? BkmMnemonicConstants.Buttons[_controlType][button] : ".");
|
||||
}
|
||||
|
||||
input.Append("|");
|
||||
|
@ -330,7 +330,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
foreach (var button in BkmMnemonicConstants.Buttons[_controlType].Keys)
|
||||
{
|
||||
input.Append(IsBasePressed("P" + player + " " + button) ? BkmMnemonicConstants.Buttons[_controlType][button] : ".");
|
||||
input.Append(IsBasePressed($"P{player} {button}") ? BkmMnemonicConstants.Buttons[_controlType][button] : ".");
|
||||
}
|
||||
|
||||
input.Append('|');
|
||||
|
@ -398,7 +398,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
foreach (var button in BkmMnemonicConstants.Buttons[_controlType].Keys)
|
||||
{
|
||||
input.Append(IsBasePressed("P" + player + " " + button) ? BkmMnemonicConstants.Buttons[_controlType][button] : ".");
|
||||
input.Append(IsBasePressed($"P{player} {button}") ? BkmMnemonicConstants.Buttons[_controlType][button] : ".");
|
||||
}
|
||||
|
||||
input.Append('|');
|
||||
|
@ -448,7 +448,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
foreach (var button in BkmMnemonicConstants.Buttons[_controlType].Keys)
|
||||
{
|
||||
input.Append(IsBasePressed("P" + player + " " + button) ? BkmMnemonicConstants.Buttons[_controlType][button] : ".");
|
||||
input.Append(IsBasePressed($"P{player} {button}") ? BkmMnemonicConstants.Buttons[_controlType][button] : ".");
|
||||
}
|
||||
|
||||
if (BkmMnemonicConstants.Analogs[_controlType].Keys.Count > 0)
|
||||
|
@ -460,37 +460,37 @@ namespace BizHawk.Client.Common
|
|||
// Nasty hackery
|
||||
if (name == "Y Axis")
|
||||
{
|
||||
if (IsBasePressed("P" + player + " A Up"))
|
||||
if (IsBasePressed($"P{player} A Up"))
|
||||
{
|
||||
val = 127;
|
||||
}
|
||||
else if (IsBasePressed("P" + player + " A Down"))
|
||||
else if (IsBasePressed($"P{player} A Down"))
|
||||
{
|
||||
val = -127;
|
||||
}
|
||||
else
|
||||
{
|
||||
val = (int)GetBaseFloat("P" + player + " " + name);
|
||||
val = (int)GetBaseFloat($"P{player} {name}");
|
||||
}
|
||||
}
|
||||
else if (name == "X Axis")
|
||||
{
|
||||
if (IsBasePressed("P" + player + " A Left"))
|
||||
if (IsBasePressed($"P{player} A Left"))
|
||||
{
|
||||
val = -127;
|
||||
}
|
||||
else if (IsBasePressed("P" + player + " A Right"))
|
||||
else if (IsBasePressed($"P{player} A Right"))
|
||||
{
|
||||
val = 127;
|
||||
}
|
||||
else
|
||||
{
|
||||
val = (int)GetBaseFloat("P" + player + " " + name);
|
||||
val = (int)GetBaseFloat($"P{player} {name}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
val = (int)GetBaseFloat("P" + player + " " + name);
|
||||
val = (int)GetBaseFloat($"P{player} {name}");
|
||||
}
|
||||
|
||||
if (val >= 0)
|
||||
|
@ -532,7 +532,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
foreach (var button in BkmMnemonicConstants.Buttons[_controlType].Keys)
|
||||
{
|
||||
input.Append(IsBasePressed("P" + player + " " + button) ? BkmMnemonicConstants.Buttons[_controlType][button] : ".");
|
||||
input.Append(IsBasePressed($"P{player} {button}") ? BkmMnemonicConstants.Buttons[_controlType][button] : ".");
|
||||
}
|
||||
|
||||
input.Append('|');
|
||||
|
@ -563,7 +563,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
foreach (var button in BkmMnemonicConstants.Buttons[_controlType].Keys)
|
||||
{
|
||||
input.Append(IsBasePressed("P" + player + " " + button) ? BkmMnemonicConstants.Buttons[_controlType][button] : ".");
|
||||
input.Append(IsBasePressed($"P{player} {button}") ? BkmMnemonicConstants.Buttons[_controlType][button] : ".");
|
||||
}
|
||||
|
||||
input.Append("|");
|
||||
|
@ -595,7 +595,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
foreach (var button in BkmMnemonicConstants.Buttons[_controlType].Keys)
|
||||
{
|
||||
input.Append(IsBasePressed("P" + player + " " + button) ? BkmMnemonicConstants.Buttons[_controlType][button] : ".");
|
||||
input.Append(IsBasePressed($"P{player} {button}") ? BkmMnemonicConstants.Buttons[_controlType][button] : ".");
|
||||
}
|
||||
|
||||
input.Append("|");
|
||||
|
|
|
@ -265,7 +265,7 @@ namespace BizHawk.Client.Common
|
|||
// TODO: clean this up
|
||||
if (_loopOffset.HasValue)
|
||||
{
|
||||
sw.WriteLine("LoopOffset " + _loopOffset);
|
||||
sw.WriteLine($"LoopOffset {_loopOffset}");
|
||||
}
|
||||
|
||||
foreach (var input in _log)
|
||||
|
|
|
@ -254,10 +254,7 @@ namespace BizHawk.Client.Common
|
|||
return true;
|
||||
}
|
||||
|
||||
errorMessage = "The savestate is from frame "
|
||||
+ log.Count
|
||||
+ " which is greater than the current movie length of "
|
||||
+ _log.Count;
|
||||
errorMessage = $"The savestate is from frame {log.Count} which is greater than the current movie length of {_log.Count}";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -266,9 +263,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
if (_log[i] != log[i])
|
||||
{
|
||||
errorMessage = "The savestate input does not match the movie input at frame "
|
||||
+ (i + 1)
|
||||
+ ".";
|
||||
errorMessage = $"The savestate input does not match the movie input at frame {(i + 1)}.";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Emulation.Cores.Nintendo.Gameboy;
|
||||
using BizHawk.Emulation.Cores.Nintendo.SubNESHawk;
|
||||
using BizHawk.Emulation.Cores.Sega.MasterSystem;
|
||||
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
||||
using BizHawk.Emulation.Cores.Consoles.Sega.gpgx;
|
||||
|
@ -15,7 +16,7 @@ namespace BizHawk.Client.Common.MovieConversionExtensions
|
|||
{
|
||||
public static TasMovie ToTasMovie(this IMovie old, bool copy = false)
|
||||
{
|
||||
string newFilename = old.Filename + "." + TasMovie.Extension;
|
||||
string newFilename = $"{old.Filename}.{TasMovie.Extension}";
|
||||
|
||||
if (File.Exists(newFilename))
|
||||
{
|
||||
|
@ -25,7 +26,7 @@ namespace BizHawk.Client.Common.MovieConversionExtensions
|
|||
{
|
||||
if (File.Exists(newFilename))
|
||||
{
|
||||
newFilename = old.Filename + " (" + fileNum + ")" + "." + TasMovie.Extension;
|
||||
newFilename = $"{old.Filename} ({fileNum}).{TasMovie.Extension}";
|
||||
fileNum++;
|
||||
}
|
||||
else
|
||||
|
@ -125,7 +126,17 @@ namespace BizHawk.Client.Common.MovieConversionExtensions
|
|||
|
||||
public static TasMovie ConvertToSavestateAnchoredMovie(this TasMovie old, int frame, byte[] savestate)
|
||||
{
|
||||
string newFilename = old.Filename + "." + TasMovie.Extension;
|
||||
string newFilename = old.Filename;
|
||||
|
||||
if (old.Filename.Contains("tasproj"))
|
||||
{
|
||||
newFilename = newFilename.Remove(newFilename.Length - 7, 7);
|
||||
newFilename = $"{newFilename}nfn.{TasMovie.Extension}";
|
||||
}
|
||||
else
|
||||
{
|
||||
newFilename = $"{old.Filename}.{TasMovie.Extension}";
|
||||
}
|
||||
|
||||
if (File.Exists(newFilename))
|
||||
{
|
||||
|
@ -135,7 +146,7 @@ namespace BizHawk.Client.Common.MovieConversionExtensions
|
|||
{
|
||||
if (File.Exists(newFilename))
|
||||
{
|
||||
newFilename = old.Filename + " (" + fileNum + ")" + "." + TasMovie.Extension;
|
||||
newFilename = $"{old.Filename} ({fileNum}).{TasMovie.Extension}";
|
||||
fileNum++;
|
||||
}
|
||||
else
|
||||
|
@ -200,7 +211,17 @@ namespace BizHawk.Client.Common.MovieConversionExtensions
|
|||
|
||||
public static TasMovie ConvertToSaveRamAnchoredMovie(this TasMovie old, byte[] saveRam)
|
||||
{
|
||||
string newFilename = old.Filename + "." + TasMovie.Extension;
|
||||
string newFilename = old.Filename;
|
||||
|
||||
if (old.Filename.Contains("tasproj"))
|
||||
{
|
||||
newFilename = newFilename.Remove(newFilename.Length - 7, 7);
|
||||
newFilename = $"{newFilename}nfsr.{TasMovie.Extension}";
|
||||
}
|
||||
else
|
||||
{
|
||||
newFilename = $"{old.Filename}.{TasMovie.Extension}";
|
||||
}
|
||||
|
||||
if (File.Exists(newFilename))
|
||||
{
|
||||
|
@ -210,7 +231,7 @@ namespace BizHawk.Client.Common.MovieConversionExtensions
|
|||
{
|
||||
if (File.Exists(newFilename))
|
||||
{
|
||||
newFilename = old.Filename + " (" + fileNum + ")" + "." + TasMovie.Extension;
|
||||
newFilename = $"{old.Filename} ({fileNum}).{TasMovie.Extension}";
|
||||
fileNum++;
|
||||
}
|
||||
else
|
||||
|
@ -302,7 +323,7 @@ namespace BizHawk.Client.Common.MovieConversionExtensions
|
|||
{
|
||||
foreach (var firmware in Global.FirmwareManager.RecentlyServed)
|
||||
{
|
||||
var key = firmware.SystemId + "_Firmware_" + firmware.FirmwareId;
|
||||
var key = $"{firmware.SystemId}_Firmware_{firmware.FirmwareId}";
|
||||
|
||||
if (!movie.HeaderEntries.ContainsKey(key))
|
||||
{
|
||||
|
@ -336,6 +357,11 @@ namespace BizHawk.Client.Common.MovieConversionExtensions
|
|||
movie.HeaderEntries.Add("Is32X", "1");
|
||||
}
|
||||
|
||||
if (Global.Emulator is SubNESHawk)
|
||||
{
|
||||
movie.HeaderEntries.Add("VBlankCount", "0");
|
||||
}
|
||||
|
||||
movie.Core = ((CoreAttribute)Attribute
|
||||
.GetCustomAttribute(Global.Emulator.GetType(), typeof(CoreAttribute)))
|
||||
.CoreName;
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
else
|
||||
{
|
||||
Result.Movie.Comments.Add(Movieorigin + " .fm2 version 3");
|
||||
Result.Movie.Comments.Add($"{Movieorigin} .fm2 version 3");
|
||||
}
|
||||
}
|
||||
else if (line.ToLower().StartsWith("romfilename"))
|
||||
|
@ -139,7 +139,7 @@ namespace BizHawk.Client.Common
|
|||
string length = line.Substring(first + 1, second - first - 1);
|
||||
string message = line.Substring(second + 1).Trim();
|
||||
|
||||
return "subtitle " + frame + " 0 0 " + length + " FFFFFFFF " + message;
|
||||
return $"subtitle {frame} 0 0 {length} FFFFFFFF {message}";
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace BizHawk.Client.Common
|
|||
return Result;
|
||||
}
|
||||
|
||||
var newFileName = SourceFile.FullName + "." + Bk2Movie.Extension;
|
||||
var newFileName = $"{SourceFile.FullName}.{Bk2Movie.Extension}";
|
||||
Result.Movie = new Bk2Movie(newFileName);
|
||||
|
||||
RunImport();
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
else
|
||||
{
|
||||
messageCallback(Path.GetFileName(fn) + " imported as " + m.Filename);
|
||||
messageCallback($"{Path.GetFileName(fn)} imported as {m.Filename}");
|
||||
}
|
||||
|
||||
if (!Directory.Exists(d))
|
||||
|
@ -83,7 +83,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
if (importerType == default(Type))
|
||||
{
|
||||
errorMsg = "No importer found for file type " + ext;
|
||||
errorMsg = $"No importer found for file type {ext}";
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -205,7 +205,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
if (m != null)
|
||||
{
|
||||
m.Filename += "." + BkmMovie.Extension;
|
||||
m.Filename += $".{BkmMovie.Extension}";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -230,7 +230,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
"BKM", "FCM", "FM2", "FMV", "GMV", "MCM", "MC2", "MMV", "NMV", "LSMV", "SMV", "VBM", "VMV", "YMV", "ZMV"
|
||||
};
|
||||
return extensions.Any(ext => extension.ToUpper() == "." + ext);
|
||||
return extensions.Any(ext => extension.ToUpper() == $".{ext}");
|
||||
}
|
||||
|
||||
// Reduce all whitespace to single spaces.
|
||||
|
@ -261,7 +261,7 @@ namespace BizHawk.Client.Common
|
|||
for (int section = 2; section < sections.Length - 1; section++)
|
||||
{
|
||||
int player = section - 1; // We start with 1
|
||||
string prefix = "P" + player + " "; // "P1"
|
||||
string prefix = $"P{player} "; // "P1"
|
||||
|
||||
for (int button = 0; button < buttons.Length; button++)
|
||||
{
|
||||
|
@ -344,7 +344,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
if (warningMsg != "")
|
||||
{
|
||||
warningMsg = "Unable to import " + warningMsg + " command on line " + lineNum + ".";
|
||||
warningMsg = $"Unable to import {warningMsg} command on line {lineNum}.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -397,7 +397,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
// The player number is one less than the section number for the reasons explained above.
|
||||
int player = section + playerOffset;
|
||||
string prefix = "P" + player + " ";
|
||||
string prefix = $"P{player} ";
|
||||
|
||||
// Gameboy doesn't currently have a prefix saying which player the input is for.
|
||||
if (controllers.Definition.Name == "Gameboy Controller")
|
||||
|
@ -450,7 +450,7 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
|
||||
string message = line.Substring(second + 1).Trim();
|
||||
m.Subtitles.AddFromString("subtitle " + frame + " 0 0 " + length + " FFFFFFFF " + message);
|
||||
m.Subtitles.AddFromString($"subtitle {frame} 0 0 {length} FFFFFFFF {message}");
|
||||
}
|
||||
|
||||
return m;
|
||||
|
@ -507,14 +507,12 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
else if (line.ToLower().StartsWith("emuversion"))
|
||||
{
|
||||
m.Comments.Add(
|
||||
EMULATIONORIGIN + " " + emulator + " version " + ParseHeader(line, "emuVersion"));
|
||||
m.Comments.Add($"{EMULATIONORIGIN} {emulator} version {ParseHeader(line, "emuVersion")}");
|
||||
}
|
||||
else if (line.ToLower().StartsWith("version"))
|
||||
{
|
||||
string version = ParseHeader(line, "version");
|
||||
m.Comments.Add(
|
||||
MOVIEORIGIN + " " + Path.GetExtension(path) + " version " + version);
|
||||
m.Comments.Add($"{MOVIEORIGIN} {Path.GetExtension(path)} version {version}");
|
||||
if (Path.GetExtension(path).ToUpper() == ".FM2" && version != "3")
|
||||
{
|
||||
errorMsg = ".FM2 movie version must always be 3.";
|
||||
|
@ -683,7 +681,7 @@ namespace BizHawk.Client.Common
|
|||
return null;
|
||||
}
|
||||
|
||||
m.Comments.Add(MOVIEORIGIN + " .FCM version " + version);
|
||||
m.Comments.Add($"{MOVIEORIGIN} .FCM version {version}");
|
||||
|
||||
// 008 1-byte flags
|
||||
byte flags = r.ReadByte();
|
||||
|
@ -715,7 +713,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
// other: reserved, set to 0
|
||||
bool syncHack = ((flags >> 4) & 0x1) != 0;
|
||||
m.Comments.Add(SYNCHACK + " " + syncHack);
|
||||
m.Comments.Add($"{SYNCHACK} {syncHack}");
|
||||
|
||||
// 009 1-byte flags: reserved, set to 0
|
||||
r.ReadByte();
|
||||
|
@ -749,7 +747,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
// 030 4-byte little-endian unsigned int: version of the emulator used
|
||||
uint emuVersion = r.ReadUInt32();
|
||||
m.Comments.Add(EMULATIONORIGIN + " FCEU " + emuVersion);
|
||||
m.Comments.Add($"{EMULATIONORIGIN} FCEU {emuVersion}");
|
||||
|
||||
// 034 name of the ROM used - UTF8 encoded nul-terminated string.
|
||||
List<byte> gameBytes = new List<byte>();
|
||||
|
@ -870,7 +868,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
if (warningMsg != "")
|
||||
{
|
||||
warningMsg = "Unable to import " + warningMsg + " command at frame " + frame + ".";
|
||||
warningMsg = $"Unable to import {warningMsg} command at frame {frame}.";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -917,7 +915,7 @@ namespace BizHawk.Client.Common
|
|||
The controller update toggles the affected input. Controller update data is emitted to the movie file
|
||||
only when the state of the controller changes.
|
||||
*/
|
||||
controllers["P" + player + " " + buttons[button]] = !controllers["P" + player + " " + buttons[button]];
|
||||
controllers[$"P{player} {buttons[button]}"] = !controllers[$"P{player} {buttons[button]}"];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1012,12 +1010,12 @@ namespace BizHawk.Client.Common
|
|||
|
||||
// 010 64-byte zero-terminated emulator identifier string
|
||||
string emuVersion = NullTerminated(r.ReadStringFixedAscii(64));
|
||||
m.Comments.Add(EMULATIONORIGIN + " Famtasia version " + emuVersion);
|
||||
m.Comments.Add(MOVIEORIGIN + " .FMV");
|
||||
m.Comments.Add($"{EMULATIONORIGIN} Famtasia version {emuVersion}");
|
||||
m.Comments.Add($"{MOVIEORIGIN} .FMV");
|
||||
|
||||
// 050 64-byte zero-terminated movie title string
|
||||
string description = NullTerminated(r.ReadStringFixedAscii(64));
|
||||
m.Comments.Add(COMMENT + " " + description);
|
||||
m.Comments.Add($"{COMMENT} {description}");
|
||||
if (!controller1 && !controller2 && !fds)
|
||||
{
|
||||
warningMsg = "No input recorded.";
|
||||
|
@ -1080,7 +1078,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
for (int button = 0; button < buttons.Length; button++)
|
||||
{
|
||||
controllers["P" + player + " " + buttons[button]] = ((controllerState >> button) & 0x1) != 0;
|
||||
controllers[$"P{player} {buttons[button]}"] = ((controllerState >> button) & 0x1) != 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1119,8 +1117,8 @@ namespace BizHawk.Client.Common
|
|||
|
||||
// 00F ASCII-encoded GMV file format version. The most recent is 'A'. (?)
|
||||
string version = r.ReadStringFixedAscii(1);
|
||||
m.Comments.Add(MOVIEORIGIN + " .GMV version " + version);
|
||||
m.Comments.Add(EMULATIONORIGIN + " Gens");
|
||||
m.Comments.Add($"{MOVIEORIGIN} .GMV version {version}");
|
||||
m.Comments.Add($"{EMULATIONORIGIN} Gens");
|
||||
|
||||
// 010 4-byte little-endian unsigned int: rerecord count
|
||||
uint rerecordCount = r.ReadUInt32();
|
||||
|
@ -1169,7 +1167,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
// 018 40-byte zero-terminated ASCII movie name string
|
||||
string description = NullTerminated(r.ReadStringFixedAscii(40));
|
||||
m.Comments.Add(COMMENT + " " + description);
|
||||
m.Comments.Add($"{COMMENT} {description}");
|
||||
|
||||
/*
|
||||
040 frame data
|
||||
|
@ -1213,7 +1211,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
for (int button = 0; button < buttons.Length; button++)
|
||||
{
|
||||
controllers["P" + player + " " + buttons[button]] = ((controllerState >> button) & 0x1) == 0;
|
||||
controllers[$"P{player} {buttons[button]}"] = ((controllerState >> button) & 0x1) == 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1222,12 +1220,12 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
if (player1Config == "6")
|
||||
{
|
||||
controllers["P1 " + other[button]] = ((controllerState >> button) & 0x1) == 0;
|
||||
controllers[$"P1 {other[button]}"] = ((controllerState >> button) & 0x1) == 0;
|
||||
}
|
||||
|
||||
if (player2Config == "6")
|
||||
{
|
||||
controllers["P2 " + other[button]] = ((controllerState >> (button + 4)) & 0x1) == 0;
|
||||
controllers[$"P2 {other[button]}"] = ((controllerState >> (button + 4)) & 0x1) == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1275,7 +1273,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
if (authorLast != "")
|
||||
{
|
||||
authorList += authorLast + ", ";
|
||||
authorList += $"{authorLast}, ";
|
||||
}
|
||||
|
||||
authorLast = author;
|
||||
|
@ -1301,7 +1299,7 @@ namespace BizHawk.Client.Common
|
|||
hf.BindArchiveMember(item.Index);
|
||||
var stream = hf.GetStream();
|
||||
string coreversion = Encoding.UTF8.GetString(stream.ReadAllBytes()).Trim();
|
||||
m.Comments.Add(COREORIGIN + " " + coreversion);
|
||||
m.Comments.Add($"{COREORIGIN} {coreversion}");
|
||||
hf.Unbind();
|
||||
}
|
||||
else if (item.Name == "gamename")
|
||||
|
@ -1446,7 +1444,7 @@ namespace BizHawk.Client.Common
|
|||
string rom = Encoding.UTF8.GetString(stream.ReadAllBytes()).Trim();
|
||||
int pos = item.Name.LastIndexOf(".sha256");
|
||||
string name = item.Name.Substring(0, pos);
|
||||
m.Header[SHA256 + "_" + name] = rom;
|
||||
m.Header[$"{SHA256}_{name}"] = rom;
|
||||
hf.Unbind();
|
||||
}
|
||||
else if (item.Name == "savestate")
|
||||
|
@ -1491,7 +1489,7 @@ namespace BizHawk.Client.Common
|
|||
hf.BindArchiveMember(item.Index);
|
||||
var stream = hf.GetStream();
|
||||
string systemid = Encoding.UTF8.GetString(stream.ReadAllBytes()).Trim();
|
||||
m.Comments.Add(EMULATIONORIGIN + " " + systemid);
|
||||
m.Comments.Add($"{EMULATIONORIGIN} {systemid}");
|
||||
hf.Unbind();
|
||||
}
|
||||
}
|
||||
|
@ -1528,11 +1526,11 @@ namespace BizHawk.Client.Common
|
|||
|
||||
// 008 uint32 Mednafen Version (Current is 0A 08)
|
||||
uint emuVersion = r.ReadUInt32();
|
||||
m.Comments.Add(EMULATIONORIGIN + " Mednafen " + emuVersion);
|
||||
m.Comments.Add($"{EMULATIONORIGIN} Mednafen {emuVersion}");
|
||||
|
||||
// 00C uint32 Movie Format Version (Current is 01)
|
||||
uint version = r.ReadUInt32();
|
||||
m.Comments.Add(MOVIEORIGIN + " .MCM version " + version);
|
||||
m.Comments.Add($"{MOVIEORIGIN} .MCM version {version}");
|
||||
|
||||
// 010 32-byte MD5 of the ROM used
|
||||
byte[] md5 = r.ReadBytes(16);
|
||||
|
@ -1580,7 +1578,7 @@ namespace BizHawk.Client.Common
|
|||
};
|
||||
if (!platforms.ContainsKey(platform))
|
||||
{
|
||||
errorMsg = "Platform " + platform + " not supported.";
|
||||
errorMsg = $"Platform {platform} not supported.";
|
||||
r.Close();
|
||||
fs.Close();
|
||||
return null;
|
||||
|
@ -1601,7 +1599,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
// TODO: Verify if NTSC/"PAL" mode used for the movie can be detected or not.
|
||||
// 100 variable Input data
|
||||
SimpleController controllers = new SimpleController { Definition = new ControllerDefinition { Name = name + " Controller" } };
|
||||
SimpleController controllers = new SimpleController { Definition = new ControllerDefinition { Name = $"{name} Controller" } };
|
||||
int bytes = 256;
|
||||
|
||||
// The input stream consists of 1 byte for power-on and reset, and then X bytes per each input port per frame.
|
||||
|
@ -1632,7 +1630,7 @@ namespace BizHawk.Client.Common
|
|||
ushort controllerState = r.ReadByte();
|
||||
for (int button = 0; button < buttons.Length; button++)
|
||||
{
|
||||
string prefix = platform == "lynx" ? "" : "P" + player + " "; // hack
|
||||
string prefix = platform == "lynx" ? "" : $"P{player} "; // hack
|
||||
controllers[prefix + buttons[button]] = ((controllerState >> button) & 0x1) != 0;
|
||||
}
|
||||
}
|
||||
|
@ -1677,8 +1675,8 @@ namespace BizHawk.Client.Common
|
|||
|
||||
// 0004: 4-byte little endian unsigned int: dega version
|
||||
uint emuVersion = r.ReadUInt32();
|
||||
m.Comments.Add(EMULATIONORIGIN + " Dega version " + emuVersion);
|
||||
m.Comments.Add(MOVIEORIGIN + " .MMV");
|
||||
m.Comments.Add($"{EMULATIONORIGIN} Dega version {emuVersion}");
|
||||
m.Comments.Add($"{MOVIEORIGIN} .MMV");
|
||||
|
||||
// 0008: 4-byte little endian unsigned int: frame count
|
||||
uint frameCount = r.ReadUInt32();
|
||||
|
@ -1771,7 +1769,7 @@ namespace BizHawk.Client.Common
|
|||
byte controllerState = r.ReadByte();
|
||||
for (int button = 0; button < buttons.Length; button++)
|
||||
{
|
||||
controllers["P" + player + " " + buttons[button]] = ((controllerState >> button) & 0x1) != 0;
|
||||
controllers[$"P{player} {buttons[button]}"] = ((controllerState >> button) & 0x1) != 0;
|
||||
}
|
||||
|
||||
if (player == 1)
|
||||
|
@ -1810,8 +1808,8 @@ namespace BizHawk.Client.Common
|
|||
|
||||
// 004 4-byte version string (example "0960")
|
||||
string emuVersion = r.ReadStringFixedAscii(4);
|
||||
m.Comments.Add(EMULATIONORIGIN + " Nintendulator version " + emuVersion);
|
||||
m.Comments.Add(MOVIEORIGIN + " .NMV");
|
||||
m.Comments.Add($"{EMULATIONORIGIN} Nintendulator version {emuVersion}");
|
||||
m.Comments.Add($"{MOVIEORIGIN} .NMV");
|
||||
|
||||
// 008 4-byte file size, not including the 16-byte header
|
||||
r.ReadUInt32();
|
||||
|
@ -1918,7 +1916,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
if (warningMsg != "")
|
||||
{
|
||||
warningMsg = warningMsg + " is not properly supported.";
|
||||
warningMsg = $"{warningMsg} is not properly supported.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1945,7 +1943,7 @@ namespace BizHawk.Client.Common
|
|||
};
|
||||
if (expansion != 0 && warningMsg == "")
|
||||
{
|
||||
warningMsg = "Expansion port is not properly supported. This movie uses " + expansions[expansion] + ".";
|
||||
warningMsg = $"Expansion port is not properly supported. This movie uses {expansions[expansion]}.";
|
||||
}
|
||||
|
||||
// 003 1-byte number of bytes per frame, plus flags
|
||||
|
@ -1989,7 +1987,7 @@ namespace BizHawk.Client.Common
|
|||
00C (variable) null-terminated UTF-8 text, movie description (currently not implemented)
|
||||
*/
|
||||
string movieDescription = NullTerminated(r.ReadStringFixedAscii((int)r.ReadUInt32()));
|
||||
m.Comments.Add(COMMENT + " " + movieDescription);
|
||||
m.Comments.Add($"{COMMENT} {movieDescription}");
|
||||
|
||||
// ... 4-byte little-endian unsigned int: length of controller data in bytes
|
||||
uint length = r.ReadUInt32();
|
||||
|
@ -2027,7 +2025,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
for (int button = 0; button < buttons.Length; button++)
|
||||
{
|
||||
controllers["P" + player + " " + buttons[button]] = ((controllerState >> button) & 0x1) != 0;
|
||||
controllers[$"P{player} {buttons[button]}"] = ((controllerState >> button) & 0x1) != 0;
|
||||
}
|
||||
}
|
||||
else if (warningMsg == "")
|
||||
|
@ -2084,8 +2082,8 @@ namespace BizHawk.Client.Common
|
|||
return null;
|
||||
}
|
||||
|
||||
m.Comments.Add(EMULATIONORIGIN + " Snes9x version " + version);
|
||||
m.Comments.Add(MOVIEORIGIN + " .SMV");
|
||||
m.Comments.Add($"{EMULATIONORIGIN} Snes9x version {version}");
|
||||
m.Comments.Add($"{MOVIEORIGIN} .SMV");
|
||||
/*
|
||||
008 4-byte little-endian integer: movie "uid" - identifies the movie-savestate relationship, also used as the
|
||||
recording time in Unix epoch format
|
||||
|
@ -2302,7 +2300,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
if (peripheral != "" && warningMsg == "")
|
||||
{
|
||||
warningMsg = "Unable to import " + peripheral + ".";
|
||||
warningMsg = $"Unable to import {peripheral}.";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2311,13 +2309,13 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
for (int button = 0; button < buttons.Length; button++)
|
||||
{
|
||||
controllers["P" + player + " " + buttons[button]] =
|
||||
controllers[$"P{player} {buttons[button]}"] =
|
||||
((controllerState >> button) & 0x1) != 0;
|
||||
}
|
||||
}
|
||||
else if (warningMsg == "")
|
||||
{
|
||||
warningMsg = "Controller " + player + " not supported.";
|
||||
warningMsg = $"Controller {player} not supported.";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2475,7 +2473,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
if (isSGB)
|
||||
{
|
||||
m.Comments.Add(SUPERGAMEBOYMODE + " True");
|
||||
m.Comments.Add($"{SUPERGAMEBOYMODE} True");
|
||||
}
|
||||
|
||||
m.Header[HeaderKeys.PLATFORM] = platform;
|
||||
|
@ -2521,8 +2519,8 @@ namespace BizHawk.Client.Common
|
|||
|
||||
// 030 1-byte unsigned char: minor version/revision number of current VBM version, the latest is "1"
|
||||
byte minorVersion = r.ReadByte();
|
||||
m.Comments.Add(MOVIEORIGIN + " .VBM version " + majorVersion + "." + minorVersion);
|
||||
m.Comments.Add(EMULATIONORIGIN + " Visual Boy Advance");
|
||||
m.Comments.Add($"{MOVIEORIGIN} .VBM version {majorVersion}.{minorVersion}");
|
||||
m.Comments.Add($"{EMULATIONORIGIN} Visual Boy Advance");
|
||||
|
||||
// 031 1-byte unsigned char: the internal CRC of the ROM used while recording
|
||||
r.ReadByte();
|
||||
|
@ -2559,7 +2557,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
// The following 128 bytes are for a description of the movie. Both parts must be null-terminated.
|
||||
string movieDescription = NullTerminated(r.ReadStringFixedAscii(128));
|
||||
m.Comments.Add(COMMENT + " " + movieDescription);
|
||||
m.Comments.Add($"{COMMENT} {movieDescription}");
|
||||
r.BaseStream.Position = firstFrameOffset;
|
||||
SimpleController controllers = new SimpleController { Definition = new ControllerDefinition() };
|
||||
controllers.Definition.Name = platform != "GBA"
|
||||
|
@ -2615,7 +2613,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
if (((controllerState >> (button + 10)) & 0x1) != 0)
|
||||
{
|
||||
warningMsg = "Unable to import " + other[button] + " at frame " + frame + ".";
|
||||
warningMsg = $"Unable to import {other[button]} at frame {frame}.";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2660,12 +2658,12 @@ namespace BizHawk.Client.Common
|
|||
|
||||
// 00C 2-byte little-endian integer: movie version 0x0400
|
||||
ushort version = r.ReadUInt16();
|
||||
m.Comments.Add(MOVIEORIGIN + " .VMV version " + version);
|
||||
m.Comments.Add(EMULATIONORIGIN + " VirtuaNES");
|
||||
m.Comments.Add($"{MOVIEORIGIN} .VMV version {version}");
|
||||
m.Comments.Add($"{EMULATIONORIGIN} VirtuaNES");
|
||||
|
||||
// 00E 2-byte little-endian integer: record version
|
||||
ushort recordVersion = r.ReadUInt16();
|
||||
m.Comments.Add(COMMENT + " Record version " + recordVersion);
|
||||
m.Comments.Add($"{COMMENT} Record version {recordVersion}");
|
||||
|
||||
// 010 4-byte flags (control byte)
|
||||
uint flags = r.ReadUInt32();
|
||||
|
@ -2837,12 +2835,12 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
else
|
||||
{
|
||||
commandName = "NESCMD_EXCONTROLLER, " + (command & 0xFF00);
|
||||
commandName = $"NESCMD_EXCONTROLLER, {(command & 0xFF00)}";
|
||||
}
|
||||
|
||||
if (commandName != "" && warningMsg == "")
|
||||
{
|
||||
warningMsg = "Unable to run command \"" + commandName + "\".";
|
||||
warningMsg = $"Unable to run command \"{commandName}\".";
|
||||
}
|
||||
}
|
||||
else if (controllerState == 0xF3)
|
||||
|
@ -2852,7 +2850,7 @@ namespace BizHawk.Client.Common
|
|||
// TODO: Make a clearer warning message.
|
||||
if (warningMsg == "")
|
||||
{
|
||||
warningMsg = "Unable to run SetSyncExData(" + dwdata + ").";
|
||||
warningMsg = $"Unable to run SetSyncExData({dwdata}).";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2861,7 +2859,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
for (int button = 0; button < buttons.Length; button++)
|
||||
{
|
||||
controllers["P" + player + " " + buttons[button]] = ((controllerState >> button) & 0x1) != 0;
|
||||
controllers[$"P{player} {buttons[button]}"] = ((controllerState >> button) & 0x1) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2901,8 +2899,8 @@ namespace BizHawk.Client.Common
|
|||
|
||||
// 003 2-byte little-endian unsigned int: zsnes version number
|
||||
short version = r.ReadInt16();
|
||||
m.Comments.Add(EMULATIONORIGIN + " ZSNES version " + version);
|
||||
m.Comments.Add(MOVIEORIGIN + " .ZMV");
|
||||
m.Comments.Add($"{EMULATIONORIGIN} ZSNES version {version}");
|
||||
m.Comments.Add($"{MOVIEORIGIN} .ZMV");
|
||||
|
||||
// 005 4-byte little-endian integer: CRC32 of the ROM
|
||||
int crc32 = r.ReadInt32();
|
||||
|
@ -2973,7 +2971,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
if (peripheral != "")
|
||||
{
|
||||
warningMsg = "Unable to import " + peripheral + ".";
|
||||
warningMsg = $"Unable to import {peripheral}.";
|
||||
}
|
||||
|
||||
// 027 1-byte flags:
|
||||
|
@ -3182,14 +3180,14 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
for (int button = 0; button < buttons.Length; button++)
|
||||
{
|
||||
controllers["P" + player + " " + buttons[button]] =
|
||||
controllers[$"P{player} {buttons[button]}"] =
|
||||
((controllerState >> button) & 0x1) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (warningMsg == "")
|
||||
{
|
||||
warningMsg = "Controller " + player + " not supported.";
|
||||
warningMsg = $"Controller {player} not supported.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace BizHawk.Client.Common
|
|||
string magic = new string(br.ReadChars(4));
|
||||
if (magic != expectedMagic)
|
||||
{
|
||||
Result.Errors.Add("Not a " + expectedMagic + "file: invalid magic number in file header.");
|
||||
Result.Errors.Add($"Not a {expectedMagic}file: invalid magic number in file header.");
|
||||
return info;
|
||||
}
|
||||
|
||||
|
@ -221,7 +221,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
for (int button = 3; button < buttons.Length; button++)
|
||||
{
|
||||
controllers["P1 " + buttons[button]] = ((controllerState >> button) & 0x1) != 0;
|
||||
controllers[$"P1 {buttons[button]}"] = ((controllerState >> button) & 0x1) != 0;
|
||||
if (((controllerState >> button) & 0x1) != 0 && button > 15)
|
||||
{
|
||||
continue;
|
||||
|
@ -246,7 +246,7 @@ namespace BizHawk.Client.Common
|
|||
ushort controllerState = br.ReadUInt16();
|
||||
for (int button = 0; button < buttons.Length; button++)
|
||||
{
|
||||
controllers["P2 " + buttons[button]] = ((controllerState >> button) & 0x1) != 0;
|
||||
controllers[$"P2 {buttons[button]}"] = ((controllerState >> button) & 0x1) != 0;
|
||||
if (((controllerState >> button) & 0x1) != 0 && button > 15)
|
||||
{
|
||||
continue;
|
||||
|
@ -291,7 +291,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
if ((controlState & 0xFC) != 0)
|
||||
{
|
||||
Result.Warnings.Add("Ignored toggle hack flag on frame " + frame);
|
||||
Result.Warnings.Add($"Ignored toggle hack flag on frame {frame}");
|
||||
}
|
||||
|
||||
movie.AppendFrame(controllers);
|
||||
|
@ -336,7 +336,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
for (int button = 3; button < buttons.Length; button++)
|
||||
{
|
||||
controllers["P1 " + buttons[button]] = br.ReadChar() != '.';
|
||||
controllers[$"P1 {buttons[button]}"] = br.ReadChar() != '.';
|
||||
}
|
||||
|
||||
if (info.Player1Type == OctoshockDll.ePeripheralType.DualShock)
|
||||
|
@ -373,7 +373,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
for (int button = 3; button < buttons.Length; button++)
|
||||
{
|
||||
controllers["P2 " + buttons[button]] = br.ReadChar() != '.';
|
||||
controllers[$"P2 {buttons[button]}"] = br.ReadChar() != '.';
|
||||
}
|
||||
|
||||
if (info.Player2Type == OctoshockDll.ePeripheralType.DualShock)
|
||||
|
@ -423,7 +423,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
if ((controlState & 0xFC) != 0)
|
||||
{
|
||||
Result.Warnings.Add("Ignored toggle hack flag on frame " + frame);
|
||||
Result.Warnings.Add($"Ignored toggle hack flag on frame {frame}");
|
||||
}
|
||||
|
||||
// Each controller is terminated with a pipeline.
|
||||
|
|
|
@ -10,6 +10,11 @@ namespace BizHawk.Client.Common
|
|||
|
||||
void LatchFromSource(IController source);
|
||||
|
||||
/// <summary>
|
||||
/// Used by tastudio when it appends new frames in HandleMovieAfterFrameLoop() and ExtendMovieForEdit().
|
||||
/// For buttons it latches autohold state, for analogs it latches mid value.
|
||||
/// All real user input latched by LatchFromPhysical() is ignored.
|
||||
/// </summary>
|
||||
void LatchSticky();
|
||||
|
||||
void SetControllersAsMnemonic(string mnemonic);
|
||||
|
|
|
@ -156,6 +156,8 @@ namespace BizHawk.Client.Common
|
|||
backwardFrame = currentFrame;
|
||||
}
|
||||
}
|
||||
|
||||
int decayStatesLast = decayStates;
|
||||
|
||||
if (forwardFrame > -1 && backwardFrame > -1)
|
||||
{
|
||||
|
@ -192,10 +194,11 @@ namespace BizHawk.Client.Common
|
|||
decayStates--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// we're very sorry about failing to find states to remove, but we can't go beyond capacity, so remove at least something
|
||||
// this shouldn't happen, but if we don't do it here, nothing good will happen either
|
||||
if (decayStatesLast == decayStates)
|
||||
{
|
||||
if (_tsm.RemoveState(_tsm.GetStateFrameByIndex(1)))
|
||||
{
|
||||
// decrementing this if no state was removed is BAD
|
||||
|
|
|
@ -12,8 +12,8 @@ namespace BizHawk.Client.Common
|
|||
public int Frame { get; set; }
|
||||
public byte[] CoreData { get; set; }
|
||||
public IStringLog InputLog { get; set; }
|
||||
public BitmapBuffer CoreFrameBuffer { get; set; }
|
||||
public BitmapBuffer OSDFrameBuffer { get; set; }
|
||||
public TasLagLog LagLog { get; set; }
|
||||
public TasMovieChangeLog ChangeLog { get; set; }
|
||||
public DateTime TimeStamp { get; set; }
|
||||
public TasMovieMarkerList Markers { get; set; }
|
||||
|
@ -50,7 +50,7 @@ namespace BizHawk.Client.Common
|
|||
var ncore = new IndexedStateLump(BinaryStateLump.BranchCoreData);
|
||||
var ninput = new IndexedStateLump(BinaryStateLump.BranchInputLog);
|
||||
var nframebuffer = new IndexedStateLump(BinaryStateLump.BranchFrameBuffer);
|
||||
var nlaglog = new IndexedStateLump(BinaryStateLump.BranchLagLog);
|
||||
var ncoreframebuffer = new IndexedStateLump(BinaryStateLump.BranchCoreFrameBuffer);
|
||||
var nmarkers = new IndexedStateLump(BinaryStateLump.BranchMarkers);
|
||||
var nusertext = new IndexedStateLump(BinaryStateLump.BranchUserText);
|
||||
foreach (var b in this)
|
||||
|
@ -86,9 +86,10 @@ namespace BizHawk.Client.Common
|
|||
QuickBmpFile.Save(vp, s, b.OSDFrameBuffer.Width, b.OSDFrameBuffer.Height);
|
||||
});
|
||||
|
||||
bs.PutLump(nlaglog, delegate(BinaryWriter bw)
|
||||
bs.PutLump(ncoreframebuffer, delegate(Stream s)
|
||||
{
|
||||
b.LagLog.Save(bw);
|
||||
var vp = new BitmapBufferVideoProvider(b.CoreFrameBuffer);
|
||||
QuickBmpFile.Save(vp, s, b.CoreFrameBuffer.Width, b.CoreFrameBuffer.Height);
|
||||
});
|
||||
|
||||
bs.PutLump(nmarkers, delegate(TextWriter tw)
|
||||
|
@ -105,7 +106,7 @@ namespace BizHawk.Client.Common
|
|||
ncore.Increment();
|
||||
ninput.Increment();
|
||||
nframebuffer.Increment();
|
||||
nlaglog.Increment();
|
||||
ncoreframebuffer.Increment();
|
||||
nmarkers.Increment();
|
||||
nusertext.Increment();
|
||||
}
|
||||
|
@ -117,7 +118,7 @@ namespace BizHawk.Client.Common
|
|||
var ncore = new IndexedStateLump(BinaryStateLump.BranchCoreData);
|
||||
var ninput = new IndexedStateLump(BinaryStateLump.BranchInputLog);
|
||||
var nframebuffer = new IndexedStateLump(BinaryStateLump.BranchFrameBuffer);
|
||||
var nlaglog = new IndexedStateLump(BinaryStateLump.BranchLagLog);
|
||||
var ncoreframebuffer = new IndexedStateLump(BinaryStateLump.BranchCoreFrameBuffer);
|
||||
var nmarkers = new IndexedStateLump(BinaryStateLump.BranchMarkers);
|
||||
var nusertext = new IndexedStateLump(BinaryStateLump.BranchUserText);
|
||||
|
||||
|
@ -180,10 +181,11 @@ namespace BizHawk.Client.Common
|
|||
b.OSDFrameBuffer = new BitmapBuffer(vp.BufferWidth, vp.BufferHeight, vp.VideoBuffer);
|
||||
});
|
||||
|
||||
bl.GetLump(nlaglog, true, delegate(BinaryReader br)
|
||||
bl.GetLump(ncoreframebuffer, false, delegate(Stream s, long length)
|
||||
{
|
||||
b.LagLog = new TasLagLog();
|
||||
b.LagLog.Load(br);
|
||||
var vp = new QuickBmpFile.LoadedBMP();
|
||||
QuickBmpFile.Load(vp, s);
|
||||
b.CoreFrameBuffer = new BitmapBuffer(vp.BufferWidth, vp.BufferHeight, vp.VideoBuffer);
|
||||
});
|
||||
|
||||
b.Markers = new TasMovieMarkerList(movie);
|
||||
|
@ -217,7 +219,7 @@ namespace BizHawk.Client.Common
|
|||
ncore.Increment();
|
||||
ninput.Increment();
|
||||
nframebuffer.Increment();
|
||||
nlaglog.Increment();
|
||||
ncoreframebuffer.Increment();
|
||||
nmarkers.Increment();
|
||||
nusertext.Increment();
|
||||
}
|
||||
|
|
|
@ -1,34 +1,30 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
||||
|
||||
namespace BizHawk.Client.Common
|
||||
{
|
||||
public class TasLagLog
|
||||
{
|
||||
// TODO: Change this into a regular list.
|
||||
private List<bool> _lagLog = new List<bool>();
|
||||
private List<bool> _wasLag = new List<bool>();
|
||||
private Dictionary<int, bool> _lagLog = new Dictionary<int, bool>();
|
||||
private Dictionary<int, bool> _wasLag = new Dictionary<int, bool>();
|
||||
|
||||
public bool? this[int frame]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (frame < _lagLog.Count)
|
||||
bool lag;
|
||||
var result = _lagLog.TryGetValue(frame, out lag);
|
||||
if (result)
|
||||
{
|
||||
if (frame < 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return _lagLog[frame];
|
||||
return lag;
|
||||
}
|
||||
|
||||
if (frame == Global.Emulator.Frame && frame == _lagLog.Count)
|
||||
// TODO: don't do this here, the calling code should decide if showing the current emulator state is the right decision
|
||||
if (frame == Global.Emulator.Frame)
|
||||
{
|
||||
////LagLog[frame] = Global.Emulator.AsInputPollable().IsLagFrame; // Note: Side effects!
|
||||
return Global.Emulator.AsInputPollable().IsLagFrame;
|
||||
}
|
||||
|
||||
|
@ -39,192 +35,92 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
if (!value.HasValue)
|
||||
{
|
||||
_lagLog.RemoveAt(frame);
|
||||
RemoveLagEntry(frame);
|
||||
return;
|
||||
}
|
||||
|
||||
if (frame < 0)
|
||||
{
|
||||
return; // Nothing to do
|
||||
}
|
||||
|
||||
if (frame > _lagLog.Count)
|
||||
{
|
||||
System.Diagnostics.Debug.Print("Lag Log error. f" + frame + ", log: " + _lagLog.Count);
|
||||
return; // Can this break anything?
|
||||
}
|
||||
|
||||
bool wasValue;
|
||||
if (frame < _lagLog.Count)
|
||||
{
|
||||
wasValue = _lagLog[frame];
|
||||
}
|
||||
else if (frame == _wasLag.Count)
|
||||
{
|
||||
wasValue = value.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
wasValue = _wasLag[frame];
|
||||
}
|
||||
|
||||
if (frame == _wasLag.Count)
|
||||
{
|
||||
_wasLag.Add(wasValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
_wasLag[frame] = wasValue;
|
||||
}
|
||||
|
||||
if (frame != 0)
|
||||
{
|
||||
_wasLag[frame - 1] = _lagLog[frame - 1];
|
||||
}
|
||||
|
||||
if (frame >= _lagLog.Count)
|
||||
{
|
||||
_lagLog.Add(value.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
_lagLog[frame] = value.Value;
|
||||
}
|
||||
_lagLog[frame] = value.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_wasLag.Clear();
|
||||
_lagLog.Clear();
|
||||
}
|
||||
|
||||
public bool RemoveFrom(int frame)
|
||||
{
|
||||
if (_lagLog.Count > frame && frame >= 0)
|
||||
var frames = _lagLog.Keys.Where(k => k > frame).ToList();
|
||||
foreach (var f in frames)
|
||||
{
|
||||
_lagLog.RemoveRange(frame + 1, _lagLog.Count - frame - 1);
|
||||
return true;
|
||||
RemoveLagEntry(frame);
|
||||
}
|
||||
|
||||
return false;
|
||||
return frames.Any();
|
||||
}
|
||||
|
||||
public void RemoveHistoryAt(int frame)
|
||||
{
|
||||
_wasLag.RemoveAt(frame);
|
||||
_wasLag.Remove(frame);
|
||||
}
|
||||
|
||||
public void InsertHistoryAt(int frame, bool isLag)
|
||||
{
|
||||
// LagLog was invalidated when the frame was inserted
|
||||
if (frame <= _lagLog.Count)
|
||||
{
|
||||
_lagLog.Insert(frame, isLag);
|
||||
}
|
||||
|
||||
_wasLag.Insert(frame, isLag);
|
||||
_lagLog[frame] = isLag;
|
||||
_wasLag[frame] = isLag;
|
||||
}
|
||||
|
||||
public void Save(BinaryWriter bw)
|
||||
public void Save(TextWriter tw)
|
||||
{
|
||||
bw.Write((byte)1); // New saving format.
|
||||
bw.Write(_lagLog.Count);
|
||||
bw.Write(_wasLag.Count);
|
||||
for (int i = 0; i < _lagLog.Count; i++)
|
||||
{
|
||||
bw.Write(_lagLog[i]);
|
||||
bw.Write(_wasLag[i]);
|
||||
}
|
||||
|
||||
for (int i = _lagLog.Count; i < _wasLag.Count; i++)
|
||||
{
|
||||
bw.Write(_wasLag[i]);
|
||||
}
|
||||
tw.WriteLine(JsonConvert.SerializeObject(_lagLog));
|
||||
tw.WriteLine(JsonConvert.SerializeObject(_wasLag));
|
||||
}
|
||||
|
||||
public void Load(BinaryReader br)
|
||||
public void Load(TextReader tr)
|
||||
{
|
||||
_lagLog.Clear();
|
||||
_wasLag.Clear();
|
||||
////if (br.BaseStream.Length > 0)
|
||||
////{ BaseStream.Length does not return the expected value.
|
||||
int formatVersion = br.ReadByte();
|
||||
if (formatVersion == 0)
|
||||
{
|
||||
int length = (br.ReadByte() << 8) | formatVersion; // The first byte should be a part of length.
|
||||
length = (br.ReadInt16() << 16) | length;
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
br.ReadInt32();
|
||||
_lagLog.Add(br.ReadBoolean());
|
||||
_wasLag.Add(_lagLog.Last());
|
||||
}
|
||||
}
|
||||
else if (formatVersion == 1)
|
||||
{
|
||||
int length = br.ReadInt32();
|
||||
int lenWas = br.ReadInt32();
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
_lagLog.Add(br.ReadBoolean());
|
||||
_wasLag.Add(br.ReadBoolean());
|
||||
}
|
||||
|
||||
for (int i = length; i < lenWas; i++)
|
||||
{
|
||||
_wasLag.Add(br.ReadBoolean());
|
||||
}
|
||||
}
|
||||
////}
|
||||
// TODO: support legacy lag logs that were List<bool>
|
||||
_lagLog = JsonConvert.DeserializeObject<Dictionary<int, bool>>(tr.ReadLine());
|
||||
_wasLag = JsonConvert.DeserializeObject<Dictionary<int, bool>>(tr.ReadLine());
|
||||
}
|
||||
|
||||
public bool? History(int frame)
|
||||
{
|
||||
if (frame < _wasLag.Count)
|
||||
bool wasLag;
|
||||
var result = _wasLag.TryGetValue(frame, out wasLag);
|
||||
if (result)
|
||||
{
|
||||
if (frame < 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return _wasLag[frame];
|
||||
return wasLag;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public int LastValidFrame
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_lagLog.Count == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _lagLog.Count - 1;
|
||||
}
|
||||
}
|
||||
|
||||
public TasLagLog Clone()
|
||||
{
|
||||
return new TasLagLog
|
||||
{
|
||||
_lagLog = _lagLog.ToList(),
|
||||
_wasLag = _wasLag.ToList()
|
||||
};
|
||||
}
|
||||
|
||||
public void FromLagLog(TasLagLog log)
|
||||
{
|
||||
_lagLog = log._lagLog.ToList();
|
||||
_wasLag = log._wasLag.ToList();
|
||||
_lagLog = log._lagLog.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
|
||||
_wasLag = log._wasLag.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
|
||||
}
|
||||
|
||||
public void StartFromFrame(int index)
|
||||
{
|
||||
_lagLog.RemoveRange(0, index);
|
||||
_wasLag.RemoveRange(0, index);
|
||||
for (int i = 0; i < index; i++)
|
||||
{
|
||||
_lagLog.Remove(i);
|
||||
_wasLag.Remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveLagEntry(int frame)
|
||||
{
|
||||
bool lag;
|
||||
var result = _lagLog.TryGetValue(frame, out lag);
|
||||
if (result)
|
||||
{
|
||||
_wasLag[frame] = lag;
|
||||
}
|
||||
|
||||
_lagLog.Remove(frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
if (frame != 0)
|
||||
{
|
||||
ChangeLog.AddGeneralUndo(frame - 1, frame - 1, "Record Frame: " + frame);
|
||||
ChangeLog.AddGeneralUndo(frame - 1, frame - 1, $"Record Frame: {frame}");
|
||||
}
|
||||
|
||||
base.RecordFrame(frame, source);
|
||||
|
@ -35,7 +35,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
public override void Truncate(int frame)
|
||||
{
|
||||
bool endBatch = ChangeLog.BeginNewBatch("Truncate Movie: " + frame, true);
|
||||
bool endBatch = ChangeLog.BeginNewBatch($"Truncate Movie: {frame}", true);
|
||||
ChangeLog.AddGeneralUndo(frame, InputLogLength - 1);
|
||||
|
||||
if (frame < Log.Count - 1)
|
||||
|
@ -58,7 +58,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
public override void PokeFrame(int frame, IController source)
|
||||
{
|
||||
ChangeLog.AddGeneralUndo(frame, frame, "Set Frame At: " + frame);
|
||||
ChangeLog.AddGeneralUndo(frame, frame, $"Set Frame At: {frame}");
|
||||
|
||||
base.PokeFrame(frame, source);
|
||||
InvalidateAfter(frame);
|
||||
|
@ -68,7 +68,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
public void SetFrame(int frame, string source)
|
||||
{
|
||||
ChangeLog.AddGeneralUndo(frame, frame, "Set Frame At: " + frame);
|
||||
ChangeLog.AddGeneralUndo(frame, frame, $"Set Frame At: {frame}");
|
||||
|
||||
SetFrameAt(frame, source);
|
||||
InvalidateAfter(frame);
|
||||
|
@ -78,7 +78,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
public override void ClearFrame(int frame)
|
||||
{
|
||||
ChangeLog.AddGeneralUndo(frame, frame, "Clear Frame: " + frame);
|
||||
ChangeLog.AddGeneralUndo(frame, frame, $"Clear Frame: {frame}");
|
||||
|
||||
base.ClearFrame(frame);
|
||||
InvalidateAfter(frame);
|
||||
|
@ -88,7 +88,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
public void RemoveFrame(int frame)
|
||||
{
|
||||
bool endBatch = ChangeLog.BeginNewBatch("Remove Frame: " + frame, true);
|
||||
bool endBatch = ChangeLog.BeginNewBatch($"Remove Frame: {frame}", true);
|
||||
ChangeLog.AddGeneralUndo(frame, InputLogLength - 1);
|
||||
|
||||
Log.RemoveAt(frame);
|
||||
|
@ -181,7 +181,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
public void RemoveFrames(int removeStart, int removeUpTo, bool fromHistory = false)
|
||||
{
|
||||
bool endBatch = ChangeLog.BeginNewBatch("Remove Frames: " + removeStart + "-" + removeUpTo, true);
|
||||
bool endBatch = ChangeLog.BeginNewBatch($"Remove Frames: {removeStart}-{removeUpTo}", true);
|
||||
ChangeLog.AddGeneralUndo(removeStart, InputLogLength - 1);
|
||||
|
||||
for (int i = removeUpTo - 1; i >= removeStart; i--)
|
||||
|
@ -225,7 +225,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
public void InsertInput(int frame, string inputState)
|
||||
{
|
||||
bool endBatch = ChangeLog.BeginNewBatch("Insert Frame: " + frame, true);
|
||||
bool endBatch = ChangeLog.BeginNewBatch($"Insert Frame: {frame}", true);
|
||||
ChangeLog.AddGeneralUndo(frame, InputLogLength);
|
||||
|
||||
Log.Insert(frame, inputState);
|
||||
|
@ -258,7 +258,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
public void InsertInput(int frame, IEnumerable<string> inputLog)
|
||||
{
|
||||
bool endBatch = ChangeLog.BeginNewBatch("Insert Frame: " + frame, true);
|
||||
bool endBatch = ChangeLog.BeginNewBatch($"Insert Frame: {frame}", true);
|
||||
ChangeLog.AddGeneralUndo(frame, InputLogLength + inputLog.Count() - 1);
|
||||
|
||||
Log.InsertRange(frame, inputLog);
|
||||
|
@ -307,7 +307,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
public void CopyOverInput(int frame, IEnumerable<IController> inputStates)
|
||||
{
|
||||
ChangeLog.BeginNewBatch("Copy Over Input: " + frame);
|
||||
ChangeLog.BeginNewBatch($"Copy Over Input: {frame}");
|
||||
var lg = LogGeneratorInstance();
|
||||
var states = inputStates.ToList();
|
||||
|
||||
|
@ -316,7 +316,7 @@ namespace BizHawk.Client.Common
|
|||
ExtendMovieForEdit(states.Count + frame - Log.Count);
|
||||
}
|
||||
|
||||
ChangeLog.AddGeneralUndo(frame, frame + inputStates.Count() - 1, "Copy Over Input: " + frame);
|
||||
ChangeLog.AddGeneralUndo(frame, frame + inputStates.Count() - 1, $"Copy Over Input: {frame}");
|
||||
|
||||
for (int i = 0; i < states.Count; i++)
|
||||
{
|
||||
|
@ -338,7 +338,7 @@ namespace BizHawk.Client.Common
|
|||
|
||||
public void InsertEmptyFrame(int frame, int count = 1, bool fromHistory = false)
|
||||
{
|
||||
bool endBatch = ChangeLog.BeginNewBatch("Insert Empty Frame: " + frame, true);
|
||||
bool endBatch = ChangeLog.BeginNewBatch($"Insert Empty Frame: {frame}", true);
|
||||
ChangeLog.AddGeneralUndo(frame, InputLogLength + count - 1);
|
||||
|
||||
var lg = LogGeneratorInstance();
|
||||
|
@ -422,7 +422,7 @@ namespace BizHawk.Client.Common
|
|||
Changes = true;
|
||||
InvalidateAfter(frame);
|
||||
|
||||
ChangeLog.AddBoolToggle(frame, buttonName, !adapter.IsPressed(buttonName), "Toggle " + buttonName + ": " + frame);
|
||||
ChangeLog.AddBoolToggle(frame, buttonName, !adapter.IsPressed(buttonName), $"Toggle {buttonName}: {frame}");
|
||||
}
|
||||
|
||||
public void SetBoolState(int frame, string buttonName, bool val)
|
||||
|
@ -444,7 +444,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
InvalidateAfter(frame);
|
||||
Changes = true;
|
||||
ChangeLog.AddBoolToggle(frame, buttonName, old, "Set " + buttonName + "(" + (val ? "On" : "Off") + "): " + frame);
|
||||
ChangeLog.AddBoolToggle(frame, buttonName, old, $"Set {buttonName}({(val ? "On" : "Off")}): {frame}");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -455,7 +455,7 @@ namespace BizHawk.Client.Common
|
|||
ExtendMovieForEdit(frame + count - Log.Count);
|
||||
}
|
||||
|
||||
ChangeLog.AddGeneralUndo(frame, frame + count - 1, "Set " + buttonName + "(" + (val ? "On" : "Off") + "): " + frame + "-" + (frame + count - 1));
|
||||
ChangeLog.AddGeneralUndo(frame, frame + count - 1, $"Set {buttonName}({(val ? "On" : "Off")}): {frame}-{(frame + count - 1)}");
|
||||
|
||||
int changed = -1;
|
||||
for (int i = 0; i < count; i++)
|
||||
|
@ -502,7 +502,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
InvalidateAfter(frame);
|
||||
Changes = true;
|
||||
ChangeLog.AddFloatChange(frame, buttonName, old, val, "Set " + buttonName + "(" + val + "): " + frame);
|
||||
ChangeLog.AddFloatChange(frame, buttonName, old, val, $"Set {buttonName}({val}): {frame}");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -513,7 +513,7 @@ namespace BizHawk.Client.Common
|
|||
ExtendMovieForEdit(frame - Log.Count + 1);
|
||||
}
|
||||
|
||||
ChangeLog.AddGeneralUndo(frame, frame + count - 1, "Set " + buttonName + "(" + val + "): " + frame + "-" + (frame + count - 1));
|
||||
ChangeLog.AddGeneralUndo(frame, frame + count - 1, $"Set {buttonName}({val}): {frame}-{(frame + count - 1)}");
|
||||
|
||||
int changed = -1;
|
||||
for (int i = 0; i < count; i++)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue