260 lines
9.1 KiB
C#
260 lines
9.1 KiB
C#
using System;
|
|
using System.ComponentModel;
|
|
using System.Linq;
|
|
|
|
using NLua;
|
|
|
|
using BizHawk.Emulation.Common;
|
|
using BizHawk.Emulation.Cores.Nintendo.NES;
|
|
using BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES;
|
|
|
|
// ReSharper disable UnusedMember.Global
|
|
// ReSharper disable UnusedAutoPropertyAccessor.Local
|
|
namespace BizHawk.Client.Common
|
|
{
|
|
[Description("Functions related specifically to Nes Cores")]
|
|
public sealed class NesLuaLibrary : DelegatingLuaLibrary
|
|
{
|
|
// TODO:
|
|
// perhaps with the new core config system, one could
|
|
// automatically bring out all of the settings to a lua table, with names. that
|
|
// would be completely arbitrary and would remove the whole requirement for this mess
|
|
[OptionalService]
|
|
private IMemoryDomains MemoryDomains { get; set; }
|
|
|
|
public NesLuaLibrary(Lua lua)
|
|
: base(lua) { }
|
|
|
|
public NesLuaLibrary(Lua lua, Action<string> logOutputCallback)
|
|
: base(lua, logOutputCallback) { }
|
|
|
|
public override string Name => "nes";
|
|
|
|
private bool NESAvailable => APIs.Emu.GetSystemId() == "NES";
|
|
|
|
private object Settings
|
|
{
|
|
get => APIs.Emu.GetSettings();
|
|
set => APIs.Emu.PutSettings(value);
|
|
}
|
|
|
|
[LuaMethodExample("nes.addgamegenie( \"GXXZZLVI\" );")]
|
|
[LuaMethod("addgamegenie", "Adds the specified game genie code. If an NES game is not currently loaded or the code is not a valid game genie code, this will have no effect")]
|
|
public void AddGameGenie(string code)
|
|
{
|
|
if (NESAvailable && MemoryDomains != null)
|
|
{
|
|
var decoder = new NESGameGenieDecoder(code);
|
|
var watch = Watch.GenerateWatch(
|
|
MemoryDomains["System Bus"],
|
|
decoder.Address,
|
|
WatchSize.Byte,
|
|
DisplayType.Hex,
|
|
false,
|
|
code);
|
|
|
|
Global.CheatList.Add(new Cheat(
|
|
watch,
|
|
decoder.Value,
|
|
decoder.Compare));
|
|
}
|
|
}
|
|
|
|
/// <exception cref="InvalidOperationException">loaded core is not NESHawk or QuickNes</exception>
|
|
[LuaMethodExample("if ( nes.getallowmorethaneightsprites( ) ) then\r\n\tconsole.log( \"Gets the NES setting 'Allow more than 8 sprites per scanline' value\" );\r\nend;")]
|
|
[LuaMethod("getallowmorethaneightsprites", "Gets the NES setting 'Allow more than 8 sprites per scanline' value")]
|
|
public bool GetAllowMoreThanEightSprites() => Settings switch
|
|
{
|
|
NES.NESSettings nhs => nhs.AllowMoreThanEightSprites,
|
|
QuickNES.QuickNESSettings qns => qns.NumSprites != 8,
|
|
_ => throw new InvalidOperationException()
|
|
};
|
|
|
|
/// <exception cref="InvalidOperationException">loaded core is not NESHawk or QuickNes</exception>
|
|
[LuaMethodExample("local innesget = nes.getbottomscanline( false );")]
|
|
[LuaMethod("getbottomscanline", "Gets the current value for the bottom scanline value")]
|
|
public int GetBottomScanline(bool pal = false) => Settings switch
|
|
{
|
|
NES.NESSettings nhs => pal ? nhs.PAL_BottomLine : nhs.NTSC_BottomLine,
|
|
QuickNES.QuickNESSettings qns => qns.ClipTopAndBottom ? 231 : 239,
|
|
_ => throw new InvalidOperationException()
|
|
};
|
|
|
|
/// <exception cref="InvalidOperationException">loaded core is not NESHawk or QuickNes</exception>
|
|
[LuaMethodExample("if ( nes.getclipleftandright( ) ) then\r\n\tconsole.log( \"Gets the current value for the Clip Left and Right sides option\" );\r\nend;")]
|
|
[LuaMethod("getclipleftandright", "Gets the current value for the Clip Left and Right sides option")]
|
|
public bool GetClipLeftAndRight() => Settings switch
|
|
{
|
|
NES.NESSettings nhs => nhs.ClipLeftAndRight,
|
|
QuickNES.QuickNESSettings qns => qns.ClipLeftAndRight,
|
|
_ => throw new InvalidOperationException()
|
|
};
|
|
|
|
/// <exception cref="InvalidOperationException">loaded core is not NESHawk or QuickNes</exception>
|
|
[LuaMethodExample("if ( nes.getdispbackground( ) ) then\r\n\tconsole.log( \"Indicates whether or not the bg layer is being displayed\" );\r\nend;")]
|
|
[LuaMethod("getdispbackground", "Indicates whether or not the bg layer is being displayed")]
|
|
public bool GetDisplayBackground() => Settings switch
|
|
{
|
|
NES.NESSettings nhs => nhs.DispBackground,
|
|
QuickNES.QuickNESSettings _ => true,
|
|
_ => throw new InvalidOperationException()
|
|
};
|
|
|
|
/// <exception cref="InvalidOperationException">loaded core is not NESHawk or QuickNes</exception>
|
|
[LuaMethodExample("if ( nes.getdispsprites( ) ) then\r\n\tconsole.log( \"Indicates whether or not sprites are being displayed\" );\r\nend;")]
|
|
[LuaMethod("getdispsprites", "Indicates whether or not sprites are being displayed")]
|
|
public bool GetDisplaySprites() => Settings switch
|
|
{
|
|
NES.NESSettings nhs => nhs.DispSprites,
|
|
QuickNES.QuickNESSettings qns => qns.NumSprites > 0,
|
|
_ => throw new InvalidOperationException()
|
|
};
|
|
|
|
/// <exception cref="InvalidOperationException">loaded core is not NESHawk or QuickNes</exception>
|
|
[LuaMethodExample("local innesget = nes.gettopscanline(false);")]
|
|
[LuaMethod("gettopscanline", "Gets the current value for the top scanline value")]
|
|
public int GetTopScanline(bool pal = false) => Settings switch
|
|
{
|
|
NES.NESSettings nhs => pal ? nhs.PAL_TopLine : nhs.NTSC_TopLine,
|
|
QuickNES.QuickNESSettings qns => qns.ClipTopAndBottom ? 8 : 0,
|
|
_ => throw new InvalidOperationException()
|
|
};
|
|
|
|
[LuaMethodExample("nes.removegamegenie( \"GXXZZLVI\" );")]
|
|
[LuaMethod("removegamegenie", "Removes the specified game genie code. If an NES game is not currently loaded or the code is not a valid game genie code, this will have no effect")]
|
|
public void RemoveGameGenie(string code)
|
|
{
|
|
if (NESAvailable)
|
|
{
|
|
var decoder = new NESGameGenieDecoder(code);
|
|
Global.CheatList.RemoveRange(
|
|
Global.CheatList.Where(c => c.Address == decoder.Address));
|
|
}
|
|
}
|
|
|
|
/// <exception cref="InvalidOperationException">loaded core is not NESHawk or QuickNes</exception>
|
|
[LuaMethodExample("nes.setallowmorethaneightsprites( true );")]
|
|
[LuaMethod("setallowmorethaneightsprites", "Sets the NES setting 'Allow more than 8 sprites per scanline'")]
|
|
public void SetAllowMoreThanEightSprites(bool allow)
|
|
{
|
|
switch (Settings)
|
|
{
|
|
case NES.NESSettings nhs:
|
|
nhs.AllowMoreThanEightSprites = allow;
|
|
Settings = nhs;
|
|
break;
|
|
case QuickNES.QuickNESSettings qns:
|
|
qns.NumSprites = allow ? 64 : 8;
|
|
Settings = qns;
|
|
break;
|
|
default:
|
|
throw new InvalidOperationException();
|
|
}
|
|
}
|
|
|
|
/// <exception cref="InvalidOperationException">loaded core is not NESHawk or QuickNes</exception>
|
|
[LuaMethodExample("nes.setclipleftandright( true );")]
|
|
[LuaMethod("setclipleftandright", "Sets the Clip Left and Right sides option")]
|
|
public void SetClipLeftAndRight(bool leftandright)
|
|
{
|
|
switch (Settings)
|
|
{
|
|
case NES.NESSettings nhs:
|
|
nhs.ClipLeftAndRight = leftandright;
|
|
Settings = nhs;
|
|
break;
|
|
case QuickNES.QuickNESSettings qns:
|
|
qns.ClipLeftAndRight = leftandright;
|
|
Settings = qns;
|
|
break;
|
|
default:
|
|
throw new InvalidOperationException();
|
|
}
|
|
}
|
|
|
|
/// <exception cref="InvalidOperationException">loaded core is not NESHawk or QuickNes</exception>
|
|
[LuaMethodExample("nes.setdispbackground( true );")]
|
|
[LuaMethod("setdispbackground", "Sets whether or not the background layer will be displayed")]
|
|
public void SetDisplayBackground(bool show)
|
|
{
|
|
switch (Settings)
|
|
{
|
|
case NES.NESSettings nhs:
|
|
nhs.DispBackground = show;
|
|
Settings = nhs;
|
|
break;
|
|
case QuickNES.QuickNESSettings _:
|
|
return;
|
|
default:
|
|
throw new InvalidOperationException();
|
|
}
|
|
}
|
|
|
|
/// <exception cref="InvalidOperationException">loaded core is not NESHawk or QuickNes</exception>
|
|
[LuaMethodExample("nes.setdispsprites( true );")]
|
|
[LuaMethod("setdispsprites", "Sets whether or not sprites will be displayed")]
|
|
public void SetDisplaySprites(bool show)
|
|
{
|
|
switch (Settings)
|
|
{
|
|
case NES.NESSettings nhs:
|
|
nhs.DispSprites = show;
|
|
Settings = nhs;
|
|
break;
|
|
case QuickNES.QuickNESSettings qns:
|
|
qns.NumSprites = show ? 8 : 0;
|
|
Settings = qns;
|
|
break;
|
|
default:
|
|
throw new InvalidOperationException();
|
|
}
|
|
}
|
|
|
|
/// <exception cref="InvalidOperationException">loaded core is not NESHawk or QuickNes</exception>
|
|
[LuaMethodExample("nes.setscanlines( 10, 20, false );")]
|
|
[LuaMethod("setscanlines", "sets the top and bottom scanlines to be drawn (same values as in the graphics options dialog). Top must be in the range of 0 to 127, bottom must be between 128 and 239. Not supported in the Quick Nes core")]
|
|
public void SetScanlines(int top, int bottom, bool pal = false)
|
|
{
|
|
switch (Settings)
|
|
{
|
|
case NES.NESSettings nhs:
|
|
if (top > 127)
|
|
{
|
|
top = 127;
|
|
}
|
|
else if (top < 0)
|
|
{
|
|
top = 0;
|
|
}
|
|
|
|
if (bottom > 239)
|
|
{
|
|
bottom = 239;
|
|
}
|
|
else if (bottom < 128)
|
|
{
|
|
bottom = 128;
|
|
}
|
|
|
|
if (pal)
|
|
{
|
|
nhs.PAL_TopLine = top;
|
|
nhs.PAL_BottomLine = bottom;
|
|
}
|
|
else
|
|
{
|
|
nhs.NTSC_TopLine = top;
|
|
nhs.NTSC_BottomLine = bottom;
|
|
}
|
|
|
|
Settings = nhs;
|
|
break;
|
|
case QuickNES.QuickNESSettings _:
|
|
return;
|
|
default:
|
|
throw new InvalidOperationException();
|
|
}
|
|
}
|
|
}
|
|
}
|