2017-08-30 18:31:27 -04:00
# include "stdafx.h"
# include "LuaApi.h"
# include "../Utilities/HexUtilities.h"
2017-10-07 15:16:14 -04:00
# include "../Utilities/FolderUtilities.h"
2017-08-30 18:31:27 -04:00
# include "../Lua/lua.hpp"
# include "LuaCallHelper.h"
# include "Debugger.h"
# include "MemoryDumper.h"
# include "MessageManager.h"
# include "ScriptingContext.h"
# include "DebugHud.h"
# include "VideoDecoder.h"
# include "RewindManager.h"
# include "SaveStateManager.h"
# include "Console.h"
# include "IKeyManager.h"
# include "ControlManager.h"
# include "StandardController.h"
# include "PPU.h"
# include "CheatManager.h"
2017-11-19 23:08:23 -05:00
# include "KeyManager.h"
2018-03-30 19:54:47 -04:00
# include "MemoryAccessCounter.h"
2018-07-07 14:52:51 -04:00
# include "RomData.h"
2018-12-27 13:48:39 -05:00
# include "LabelManager.h"
2017-08-30 18:31:27 -04:00
# define lua_pushintvalue(name, value) lua_pushliteral(lua, #name); lua_pushinteger(lua, (int)value); lua_settable(lua, -3);
2019-05-22 20:35:50 -04:00
# define lua_pushint64value(name, value) lua_pushliteral(lua, #name); lua_pushinteger(lua, (int64_t)value); lua_settable(lua, -3);
2017-12-20 22:11:36 -05:00
# define lua_pushdoublevalue(name, value) lua_pushliteral(lua, #name); lua_pushnumber(lua, (double)value); lua_settable(lua, -3);
2017-08-30 18:31:27 -04:00
# define lua_pushboolvalue(name, value) lua_pushliteral(lua, #name); lua_pushboolean(lua, (int)value); lua_settable(lua, -3);
2017-12-20 22:11:36 -05:00
# define lua_pushstringvalue(name, value) lua_pushliteral(lua, #name); lua_pushstring(lua, value.c_str()); lua_settable(lua, -3);
2017-08-30 18:31:27 -04:00
# define lua_starttable(name) lua_pushliteral(lua, name); lua_newtable(lua);
# define lua_endtable() lua_settable(lua, -3);
# define lua_readint(name, dest) lua_getfield(lua, -1, #name); dest = l.ReadInteger();
# define lua_readbool(name, dest) lua_getfield(lua, -1, #name); dest = l.ReadBool();
# define error(text) luaL_error(lua, text); return 0;
# define errorCond(cond, text) if(cond) { luaL_error(lua, text); return 0; }
# define checkparams() if(!l.CheckParamCount()) { return 0; }
# define checkminparams(x) if(!l.CheckParamCount(x)) { return 0; }
2020-04-21 20:04:04 -04:00
# define checkinitdone() if(!_context->CheckInitDone()) { error("This function cannot be called outside a callback"); return 0; }
2017-10-07 19:48:45 -04:00
# define checksavestateconditions() if(!_context->CheckInStartFrameEvent() && !_context->CheckInExecOpEvent()) { error("This function must be called inside a StartFrame event callback or a CpuExec memory operation callback"); return 0; }
2017-08-30 18:31:27 -04:00
enum class ExecuteCountType
{
CpuCycles = 0 ,
PpuCycles = 1 ,
CpuInstructions = 2
} ;
Debugger * LuaApi : : _debugger = nullptr ;
2018-07-02 16:39:24 -04:00
Console * LuaApi : : _console = nullptr ;
2017-08-30 18:31:27 -04:00
MemoryDumper * LuaApi : : _memoryDumper = nullptr ;
ScriptingContext * LuaApi : : _context = nullptr ;
2018-07-02 16:39:24 -04:00
void LuaApi : : SetContext ( ScriptingContext * context )
2017-08-30 18:31:27 -04:00
{
_context = context ;
2018-07-02 16:39:24 -04:00
_debugger = _context - > GetDebugger ( ) ;
_memoryDumper = _debugger - > GetMemoryDumper ( ) . get ( ) ;
_console = _debugger - > GetConsole ( ) ;
2017-08-30 18:31:27 -04:00
}
int LuaApi : : GetLibrary ( lua_State * lua )
{
static const luaL_Reg apilib [ ] = {
{ " read " , LuaApi : : ReadMemory } ,
{ " write " , LuaApi : : WriteMemory } ,
{ " readWord " , LuaApi : : ReadMemoryWord } ,
{ " writeWord " , LuaApi : : WriteMemoryWord } ,
2018-07-29 12:08:28 -04:00
{ " getPrgRomOffset " , LuaApi : : GetPrgRomOffset } ,
{ " getChrRomOffset " , LuaApi : : GetChrRomOffset } ,
2017-08-30 18:31:27 -04:00
{ " revertPrgChrChanges " , LuaApi : : RevertPrgChrChanges } ,
{ " addMemoryCallback " , LuaApi : : RegisterMemoryCallback } ,
{ " removeMemoryCallback " , LuaApi : : UnregisterMemoryCallback } ,
{ " addEventCallback " , LuaApi : : RegisterEventCallback } ,
{ " removeEventCallback " , LuaApi : : UnregisterEventCallback } ,
{ " drawString " , LuaApi : : DrawString } ,
{ " drawPixel " , LuaApi : : DrawPixel } ,
{ " drawLine " , LuaApi : : DrawLine } ,
{ " drawRectangle " , LuaApi : : DrawRectangle } ,
{ " clearScreen " , LuaApi : : ClearScreen } ,
2018-03-10 15:44:38 -05:00
{ " getScreenBuffer " , LuaApi : : GetScreenBuffer } ,
{ " setScreenBuffer " , LuaApi : : SetScreenBuffer } ,
2017-08-30 18:31:27 -04:00
{ " getPixel " , LuaApi : : GetPixel } ,
{ " getMouseState " , LuaApi : : GetMouseState } ,
{ " log " , LuaApi : : Log } ,
{ " displayMessage " , LuaApi : : DisplayMessage } ,
{ " reset " , LuaApi : : Reset } ,
2018-04-14 21:53:52 -04:00
{ " stop " , LuaApi : : Stop } ,
2017-08-30 18:31:27 -04:00
{ " breakExecution " , LuaApi : : Break } ,
2021-11-13 12:21:49 -06:00
{ " stepOver " , LuaApi : : StepOver } ,
{ " stepOut " , LuaApi : : StepOut } ,
2017-08-30 18:31:27 -04:00
{ " resume " , LuaApi : : Resume } ,
{ " execute " , LuaApi : : Execute } ,
{ " rewind " , LuaApi : : Rewind } ,
{ " takeScreenshot " , LuaApi : : TakeScreenshot } ,
{ " saveSavestate " , LuaApi : : SaveSavestate } ,
{ " loadSavestate " , LuaApi : : LoadSavestate } ,
2017-10-05 19:44:37 -04:00
{ " saveSavestateAsync " , LuaApi : : SaveSavestateAsync } ,
{ " loadSavestateAsync " , LuaApi : : LoadSavestateAsync } ,
{ " getSavestateData " , LuaApi : : GetSavestateData } ,
{ " clearSavestateData " , LuaApi : : ClearSavestateData } ,
{ " isKeyPressed " , LuaApi : : IsKeyPressed } ,
2017-08-30 18:31:27 -04:00
{ " getInput " , LuaApi : : GetInput } ,
{ " setInput " , LuaApi : : SetInput } ,
{ " addCheat " , LuaApi : : AddCheat } ,
{ " clearCheats " , LuaApi : : ClearCheats } ,
2018-03-30 19:54:47 -04:00
{ " getAccessCounters " , LuaApi : : GetAccessCounters } ,
{ " resetAccessCounters " , LuaApi : : ResetAccessCounters } ,
2017-08-30 18:31:27 -04:00
{ " setState " , LuaApi : : SetState } ,
{ " getState " , LuaApi : : GetState } ,
2017-10-07 15:16:14 -04:00
{ " getScriptDataFolder " , LuaApi : : GetScriptDataFolder } ,
2017-12-20 22:11:36 -05:00
{ " getRomInfo " , LuaApi : : GetRomInfo } ,
{ " getLogWindowLog " , LuaApi : : GetLogWindowLog } ,
2018-12-27 13:48:39 -05:00
{ " getLabelAddress " , LuaApi : : GetLabelAddress } ,
2017-08-30 18:31:27 -04:00
{ NULL , NULL }
} ;
luaL_newlib ( lua , apilib ) ;
//Expose DebugMemoryType enum as "memory.type"
lua_pushliteral ( lua , " memType " ) ;
lua_newtable ( lua ) ;
lua_pushintvalue ( cpu , DebugMemoryType : : CpuMemory ) ;
lua_pushintvalue ( ppu , DebugMemoryType : : PpuMemory ) ;
lua_pushintvalue ( palette , DebugMemoryType : : PaletteMemory ) ;
lua_pushintvalue ( oam , DebugMemoryType : : SpriteMemory ) ;
lua_pushintvalue ( secondaryOam , DebugMemoryType : : SecondarySpriteMemory ) ;
lua_pushintvalue ( prgRom , DebugMemoryType : : PrgRom ) ;
lua_pushintvalue ( chrRom , DebugMemoryType : : ChrRom ) ;
lua_pushintvalue ( chrRam , DebugMemoryType : : ChrRam ) ;
lua_pushintvalue ( workRam , DebugMemoryType : : WorkRam ) ;
lua_pushintvalue ( saveRam , DebugMemoryType : : SaveRam ) ;
2017-10-07 13:31:28 -04:00
lua_pushintvalue ( cpuDebug , DebugMemoryType : : CpuMemory | 0x100 ) ;
lua_pushintvalue ( ppuDebug , DebugMemoryType : : PpuMemory | 0x100 ) ;
2017-08-30 18:31:27 -04:00
lua_settable ( lua , - 3 ) ;
lua_pushliteral ( lua , " memCallbackType " ) ;
lua_newtable ( lua ) ;
lua_pushintvalue ( cpuRead , CallbackType : : CpuRead ) ;
lua_pushintvalue ( cpuWrite , CallbackType : : CpuWrite ) ;
lua_pushintvalue ( cpuExec , CallbackType : : CpuExec ) ;
lua_pushintvalue ( ppuRead , CallbackType : : PpuRead ) ;
lua_pushintvalue ( ppuWrite , CallbackType : : PpuWrite ) ;
lua_settable ( lua , - 3 ) ;
2018-03-30 19:54:47 -04:00
lua_pushliteral ( lua , " counterMemType " ) ;
lua_newtable ( lua ) ;
lua_pushintvalue ( nesRam , AddressType : : InternalRam ) ;
lua_pushintvalue ( prgRom , AddressType : : PrgRom ) ;
lua_pushintvalue ( workRam , AddressType : : WorkRam ) ;
lua_pushintvalue ( saveRam , AddressType : : SaveRam ) ;
lua_settable ( lua , - 3 ) ;
lua_pushliteral ( lua , " counterOpType " ) ;
lua_newtable ( lua ) ;
lua_pushintvalue ( read , MemoryOperationType : : Read ) ;
lua_pushintvalue ( write , MemoryOperationType : : Write ) ;
lua_pushintvalue ( exec , MemoryOperationType : : ExecOpCode ) ;
lua_settable ( lua , - 3 ) ;
2017-09-01 14:57:02 -04:00
lua_pushliteral ( lua , " eventType " ) ;
2017-08-30 18:31:27 -04:00
lua_newtable ( lua ) ;
lua_pushintvalue ( reset , EventType : : Reset ) ;
lua_pushintvalue ( nmi , EventType : : Nmi ) ;
lua_pushintvalue ( irq , EventType : : Irq ) ;
lua_pushintvalue ( startFrame , EventType : : StartFrame ) ;
lua_pushintvalue ( endFrame , EventType : : EndFrame ) ;
lua_pushintvalue ( codeBreak , EventType : : CodeBreak ) ;
2017-10-07 19:48:45 -04:00
lua_pushintvalue ( stateLoaded , EventType : : StateLoaded ) ;
lua_pushintvalue ( stateSaved , EventType : : StateSaved ) ;
2017-11-19 23:08:23 -05:00
lua_pushintvalue ( inputPolled , EventType : : InputPolled ) ;
2018-04-04 23:35:41 -04:00
lua_pushintvalue ( scriptEnded , EventType : : ScriptEnded ) ;
2021-10-26 13:15:08 -05:00
lua_pushintvalue ( whilePaused , EventType : : WhilePaused ) ;
2017-08-30 18:31:27 -04:00
lua_settable ( lua , - 3 ) ;
2017-09-01 14:57:02 -04:00
lua_pushliteral ( lua , " executeCountType " ) ;
lua_newtable ( lua ) ;
lua_pushintvalue ( cpuCycles , ExecuteCountType : : CpuCycles ) ;
lua_pushintvalue ( cpuInstructions , ExecuteCountType : : CpuInstructions ) ;
lua_pushintvalue ( ppuCycles , ExecuteCountType : : PpuCycles ) ;
lua_settable ( lua , - 3 ) ;
2017-08-30 18:31:27 -04:00
return 1 ;
}
2018-12-27 13:48:39 -05:00
int LuaApi : : GetLabelAddress ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
string label = l . ReadString ( ) ;
2018-12-31 15:05:29 -05:00
checkparams ( ) ;
2018-12-27 13:48:39 -05:00
errorCond ( label . length ( ) = = 0 , " label cannot be empty " ) ;
std : : shared_ptr < LabelManager > lblMan = _debugger - > GetLabelManager ( ) ;
int32_t value = lblMan - > GetLabelRelativeAddress ( label ) ;
2019-01-19 14:59:18 -05:00
if ( value = = - 2 ) {
//Check to see if the label is a multi-byte label instead
string mbLabel = label + " +0 " ;
value = lblMan - > GetLabelRelativeAddress ( mbLabel ) ;
}
errorCond ( value = = - 1 , " label out of scope (not mapped to CPU memory) " ) ;
errorCond ( value < = - 2 , " label not found " ) ;
2018-12-27 13:48:39 -05:00
l . Return ( value ) ;
return l . ReturnCount ( ) ;
}
2017-08-30 18:31:27 -04:00
int LuaApi : : ReadMemory ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
2017-10-03 19:10:23 -04:00
l . ForceParamCount ( 3 ) ;
bool returnSignedValue = l . ReadBool ( ) ;
2017-10-07 13:31:28 -04:00
int type = l . ReadInteger ( ) ;
bool disableSideEffects = ( type & 0x100 ) = = 0x100 ;
DebugMemoryType memType = ( DebugMemoryType ) ( type & 0xFF ) ;
2017-08-30 18:31:27 -04:00
int address = l . ReadInteger ( ) ;
2017-10-03 19:10:23 -04:00
checkminparams ( 2 ) ;
2017-08-30 18:31:27 -04:00
errorCond ( address < 0 , " address must be >= 0 " ) ;
2017-10-07 13:31:28 -04:00
uint8_t value = _memoryDumper - > GetMemoryValue ( memType , address , disableSideEffects ) ;
2017-10-03 19:10:23 -04:00
l . Return ( returnSignedValue ? ( int8_t ) value : value ) ;
2017-08-30 18:31:27 -04:00
return l . ReturnCount ( ) ;
}
int LuaApi : : WriteMemory ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
2017-10-07 13:31:28 -04:00
int type = l . ReadInteger ( ) ;
bool disableSideEffects = ( type & 0x100 ) = = 0x100 ;
DebugMemoryType memType = ( DebugMemoryType ) ( type & 0xFF ) ;
2017-08-30 18:31:27 -04:00
int value = l . ReadInteger ( ) ;
int address = l . ReadInteger ( ) ;
checkparams ( ) ;
errorCond ( value > 255 | | value < - 128 , " value out of range " ) ;
errorCond ( address < 0 , " address must be >= 0 " ) ;
2017-10-07 13:31:28 -04:00
_memoryDumper - > SetMemoryValue ( memType , address , value , false , disableSideEffects ) ;
2017-08-30 18:31:27 -04:00
return l . ReturnCount ( ) ;
}
int LuaApi : : ReadMemoryWord ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
2017-10-03 19:10:23 -04:00
l . ForceParamCount ( 3 ) ;
bool returnSignedValue = l . ReadBool ( ) ;
2017-10-07 13:31:28 -04:00
int type = l . ReadInteger ( ) ;
bool disableSideEffects = ( type & 0x100 ) = = 0x100 ;
DebugMemoryType memType = ( DebugMemoryType ) ( type & 0xFF ) ;
2017-08-30 18:31:27 -04:00
int address = l . ReadInteger ( ) ;
2017-10-03 19:10:23 -04:00
checkminparams ( 2 ) ;
2017-08-30 18:31:27 -04:00
errorCond ( address < 0 , " address must be >= 0 " ) ;
2017-10-07 13:31:28 -04:00
uint16_t value = _memoryDumper - > GetMemoryValueWord ( memType , address , disableSideEffects ) ;
2017-10-03 19:10:23 -04:00
l . Return ( returnSignedValue ? ( int16_t ) value : value ) ;
2017-08-30 18:31:27 -04:00
return l . ReturnCount ( ) ;
}
int LuaApi : : WriteMemoryWord ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
2017-10-07 13:31:28 -04:00
int type = l . ReadInteger ( ) ;
bool disableSideEffects = ( type & 0x100 ) = = 0x100 ;
DebugMemoryType memType = ( DebugMemoryType ) ( type & 0xFF ) ;
2017-08-30 18:31:27 -04:00
int value = l . ReadInteger ( ) ;
int address = l . ReadInteger ( ) ;
checkparams ( ) ;
errorCond ( value > 65535 | | value < - 32768 , " value out of range " ) ;
errorCond ( address < 0 , " address must be >= 0 " ) ;
2017-10-07 13:31:28 -04:00
_memoryDumper - > SetMemoryValueWord ( memType , address , value , false , disableSideEffects ) ;
2017-08-30 18:31:27 -04:00
return l . ReturnCount ( ) ;
}
2018-07-29 12:08:28 -04:00
int LuaApi : : GetPrgRomOffset ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
int address = l . ReadInteger ( ) ;
checkminparams ( 1 ) ;
errorCond ( address < 0 | | address > 0xFFFF , " address must be between 0 and $FFFF " ) ;
int32_t prgRomOffset = _debugger - > GetAbsoluteAddress ( ( uint32_t ) address ) ;
l . Return ( prgRomOffset ) ;
return l . ReturnCount ( ) ;
}
int LuaApi : : GetChrRomOffset ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
int address = l . ReadInteger ( ) ;
checkminparams ( 1 ) ;
errorCond ( address < 0 | | address > 0x3FFF , " address must be between 0 and $3FFF " ) ;
int32_t chrRomOffset = _debugger - > GetAbsoluteChrAddress ( ( uint32_t ) address ) ;
l . Return ( chrRomOffset ) ;
return l . ReturnCount ( ) ;
}
2017-08-30 18:31:27 -04:00
int LuaApi : : RevertPrgChrChanges ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
checkparams ( ) ;
_debugger - > RevertPrgChrChanges ( ) ;
return l . ReturnCount ( ) ;
}
int LuaApi : : RegisterMemoryCallback ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
2018-06-06 19:31:01 -04:00
l . ForceParamCount ( 4 ) ;
int32_t endAddr = l . ReadInteger ( - 1 ) ;
int32_t startAddr = l . ReadInteger ( ) ;
2017-08-30 18:31:27 -04:00
CallbackType type = ( CallbackType ) l . ReadInteger ( ) ;
int reference = l . GetReference ( ) ;
2018-06-06 19:31:01 -04:00
checkminparams ( 3 ) ;
if ( endAddr = = - 1 ) {
endAddr = startAddr ;
}
2017-08-30 18:31:27 -04:00
errorCond ( startAddr > endAddr , " start address must be <= end address " ) ;
errorCond ( type < CallbackType : : CpuRead | | type > CallbackType : : PpuWrite , " the specified type is invalid " ) ;
errorCond ( reference = = LUA_NOREF , " the specified function could not be found " ) ;
_context - > RegisterMemoryCallback ( type , startAddr , endAddr , reference ) ;
_context - > Log ( " Registered memory callback from $ " + HexUtilities : : ToHex ( ( uint32_t ) startAddr ) + " to $ " + HexUtilities : : ToHex ( ( uint32_t ) endAddr ) ) ;
l . Return ( reference ) ;
return l . ReturnCount ( ) ;
}
int LuaApi : : UnregisterMemoryCallback ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
2018-06-06 19:31:01 -04:00
l . ForceParamCount ( 4 ) ;
2018-06-14 18:36:31 -04:00
int endAddr = l . ReadInteger ( - 1 ) ;
2017-08-30 18:31:27 -04:00
int startAddr = l . ReadInteger ( ) ;
CallbackType type = ( CallbackType ) l . ReadInteger ( ) ;
int reference = l . ReadInteger ( ) ;
2018-06-06 19:31:01 -04:00
checkminparams ( 3 ) ;
if ( endAddr = = - 1 ) {
endAddr = startAddr ;
}
2017-08-30 18:31:27 -04:00
errorCond ( startAddr > endAddr , " start address must be <= end address " ) ;
errorCond ( type < CallbackType : : CpuRead | | type > CallbackType : : PpuWrite , " the specified type is invalid " ) ;
errorCond ( reference = = LUA_NOREF , " function reference is invalid " ) ;
_context - > UnregisterMemoryCallback ( type , startAddr , endAddr , reference ) ;
return l . ReturnCount ( ) ;
}
int LuaApi : : RegisterEventCallback ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
EventType type = ( EventType ) l . ReadInteger ( ) ;
int reference = l . GetReference ( ) ;
checkparams ( ) ;
2017-11-19 23:08:23 -05:00
errorCond ( type < EventType : : Reset | | type > = EventType : : EventTypeSize , " the specified type is invalid " ) ;
2017-08-30 18:31:27 -04:00
errorCond ( reference = = LUA_NOREF , " the specified function could not be found " ) ;
_context - > RegisterEventCallback ( type , reference ) ;
2017-09-01 14:57:02 -04:00
l . Return ( reference ) ;
2017-08-30 18:31:27 -04:00
return l . ReturnCount ( ) ;
}
int LuaApi : : UnregisterEventCallback ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
EventType type = ( EventType ) l . ReadInteger ( ) ;
int reference = l . ReadInteger ( ) ;
checkparams ( ) ;
2017-11-19 23:08:23 -05:00
errorCond ( type < EventType : : Reset | | type > = EventType : : EventTypeSize , " the specified type is invalid " ) ;
2017-08-30 18:31:27 -04:00
errorCond ( reference = = LUA_NOREF , " function reference is invalid " ) ;
_context - > UnregisterEventCallback ( type , reference ) ;
return l . ReturnCount ( ) ;
}
int LuaApi : : DrawString ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
2018-07-26 19:32:41 -04:00
l . ForceParamCount ( 7 ) ;
int displayDelay = l . ReadInteger ( 0 ) ;
2017-08-30 18:31:27 -04:00
int frameCount = l . ReadInteger ( 1 ) ;
int backColor = l . ReadInteger ( 0 ) ;
2017-11-19 23:08:23 -05:00
int color = l . ReadInteger ( 0xFFFFFF ) ;
2017-08-30 18:31:27 -04:00
string text = l . ReadString ( ) ;
int y = l . ReadInteger ( ) ;
int x = l . ReadInteger ( ) ;
checkminparams ( 3 ) ;
2018-07-26 19:32:41 -04:00
int startFrame = _console - > GetFrameCount ( ) + displayDelay ;
2018-07-02 16:39:24 -04:00
_console - > GetDebugHud ( ) - > DrawString ( x , y , text , color , backColor , frameCount , startFrame ) ;
2017-08-30 18:31:27 -04:00
return l . ReturnCount ( ) ;
}
int LuaApi : : DrawLine ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
2018-07-26 19:32:41 -04:00
l . ForceParamCount ( 7 ) ;
int displayDelay = l . ReadInteger ( 0 ) ;
2017-08-30 18:31:27 -04:00
int frameCount = l . ReadInteger ( 1 ) ;
2017-11-19 23:08:23 -05:00
int color = l . ReadInteger ( 0xFFFFFF ) ;
2017-08-30 18:31:27 -04:00
int y2 = l . ReadInteger ( ) ;
int x2 = l . ReadInteger ( ) ;
int y = l . ReadInteger ( ) ;
int x = l . ReadInteger ( ) ;
checkminparams ( 4 ) ;
2018-07-26 19:32:41 -04:00
int startFrame = _console - > GetFrameCount ( ) + displayDelay ;
2018-07-02 16:39:24 -04:00
_console - > GetDebugHud ( ) - > DrawLine ( x , y , x2 , y2 , color , frameCount , startFrame ) ;
2017-08-30 18:31:27 -04:00
return l . ReturnCount ( ) ;
}
int LuaApi : : DrawPixel ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
2018-07-26 19:32:41 -04:00
l . ForceParamCount ( 5 ) ;
int displayDelay = l . ReadInteger ( 0 ) ;
2017-08-30 18:31:27 -04:00
int frameCount = l . ReadInteger ( 1 ) ;
int color = l . ReadInteger ( ) ;
int y = l . ReadInteger ( ) ;
int x = l . ReadInteger ( ) ;
checkminparams ( 3 ) ;
2018-07-26 19:32:41 -04:00
int startFrame = _console - > GetFrameCount ( ) + displayDelay ;
2018-07-02 16:39:24 -04:00
_console - > GetDebugHud ( ) - > DrawPixel ( x , y , color , frameCount , startFrame ) ;
2017-08-30 18:31:27 -04:00
return l . ReturnCount ( ) ;
}
int LuaApi : : DrawRectangle ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
2018-07-26 19:32:41 -04:00
l . ForceParamCount ( 8 ) ;
int displayDelay = l . ReadInteger ( 0 ) ;
2017-08-30 18:31:27 -04:00
int frameCount = l . ReadInteger ( 1 ) ;
bool fill = l . ReadBool ( false ) ;
2017-11-19 23:08:23 -05:00
int color = l . ReadInteger ( 0xFFFFFF ) ;
2017-08-30 18:31:27 -04:00
int height = l . ReadInteger ( ) ;
int width = l . ReadInteger ( ) ;
int y = l . ReadInteger ( ) ;
int x = l . ReadInteger ( ) ;
checkminparams ( 4 ) ;
2018-07-26 19:32:41 -04:00
int startFrame = _console - > GetFrameCount ( ) + displayDelay ;
2018-07-02 16:39:24 -04:00
_console - > GetDebugHud ( ) - > DrawRectangle ( x , y , width , height , color , fill , frameCount , startFrame ) ;
2017-08-30 18:31:27 -04:00
return l . ReturnCount ( ) ;
}
int LuaApi : : ClearScreen ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
checkparams ( ) ;
2018-07-01 15:21:05 -04:00
2018-07-02 16:39:24 -04:00
_console - > GetDebugHud ( ) - > ClearScreen ( ) ;
2017-08-30 18:31:27 -04:00
return l . ReturnCount ( ) ;
}
2018-03-10 15:44:38 -05:00
int LuaApi : : GetScreenBuffer ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
2018-07-13 22:19:26 -04:00
uint32_t * palette = _console - > GetSettings ( ) - > GetRgbPalette ( ) ;
2018-03-10 15:44:38 -05:00
lua_newtable ( lua ) ;
for ( int y = 0 ; y < PPU : : ScreenHeight ; y + + ) {
for ( int x = 0 ; x < PPU : : ScreenWidth ; x + + ) {
2018-07-01 15:21:05 -04:00
lua_pushinteger ( lua , palette [ _debugger - > GetScreenPixel ( x , y ) & 0x3F ] & 0xFFFFFF ) ;
2018-03-10 15:44:38 -05:00
lua_rawseti ( lua , - 2 , ( y < < 8 ) + x ) ;
}
}
return 1 ;
}
int LuaApi : : SetScreenBuffer ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
uint32_t pixels [ PPU : : PixelCount ] = { } ;
luaL_checktype ( lua , 1 , LUA_TTABLE ) ;
for ( int i = 0 ; i < PPU : : PixelCount ; i + + ) {
lua_rawgeti ( lua , 1 , i ) ;
pixels [ i ] = l . ReadInteger ( ) ^ 0xFF000000 ;
}
2018-07-02 16:39:24 -04:00
int startFrame = _console - > GetFrameCount ( ) ;
_console - > GetDebugHud ( ) - > DrawScreenBuffer ( pixels , startFrame ) ;
2018-03-10 15:44:38 -05:00
return l . ReturnCount ( ) ;
}
2017-08-30 18:31:27 -04:00
int LuaApi : : GetPixel ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
int y = l . ReadInteger ( ) ;
int x = l . ReadInteger ( ) ;
checkparams ( ) ;
errorCond ( x < 0 | | x > 255 | | y < 0 | | y > 239 , " invalid x,y coordinates (must be between 0-255, 0-239) " ) ;
//Ignores intensify & grayscale bits
2018-07-13 22:19:26 -04:00
l . Return ( _console - > GetSettings ( ) - > GetRgbPalette ( ) [ _debugger - > GetScreenPixel ( x , y ) & 0x3F ] & 0xFFFFFF ) ;
2017-08-30 18:31:27 -04:00
return l . ReturnCount ( ) ;
}
int LuaApi : : GetMouseState ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
2017-11-19 23:08:23 -05:00
MousePosition pos = KeyManager : : GetMousePosition ( ) ;
2017-08-30 18:31:27 -04:00
checkparams ( ) ;
lua_newtable ( lua ) ;
lua_pushintvalue ( x , pos . X ) ;
lua_pushintvalue ( y , pos . Y ) ;
2017-11-19 23:08:23 -05:00
lua_pushboolvalue ( left , KeyManager : : IsMouseButtonPressed ( MouseButton : : LeftButton ) ) ;
lua_pushboolvalue ( middle , KeyManager : : IsMouseButtonPressed ( MouseButton : : MiddleButton ) ) ;
lua_pushboolvalue ( right , KeyManager : : IsMouseButtonPressed ( MouseButton : : RightButton ) ) ;
2017-08-30 18:31:27 -04:00
return 1 ;
}
int LuaApi : : Log ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
string text = l . ReadString ( ) ;
checkparams ( ) ;
_context - > Log ( text ) ;
return l . ReturnCount ( ) ;
}
int LuaApi : : DisplayMessage ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
string text = l . ReadString ( ) ;
string category = l . ReadString ( ) ;
checkparams ( ) ;
MessageManager : : DisplayMessage ( category , text ) ;
return l . ReturnCount ( ) ;
}
int LuaApi : : Reset ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
checkparams ( ) ;
2020-04-21 20:04:04 -04:00
checkinitdone ( ) ;
2018-07-02 16:39:24 -04:00
_console - > Reset ( true ) ;
2017-08-30 18:31:27 -04:00
return l . ReturnCount ( ) ;
}
2018-04-14 21:53:52 -04:00
int LuaApi : : Stop ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
int32_t stopCode = l . ReadInteger ( 0 ) ;
checkminparams ( 0 ) ;
2020-04-21 20:04:04 -04:00
checkinitdone ( ) ;
2018-07-02 16:39:24 -04:00
_console - > Stop ( stopCode ) ;
2018-04-14 21:53:52 -04:00
return l . ReturnCount ( ) ;
}
2017-08-30 18:31:27 -04:00
int LuaApi : : Break ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
checkparams ( ) ;
2020-04-21 20:04:04 -04:00
checkinitdone ( ) ;
2017-08-30 18:31:27 -04:00
_debugger - > Step ( 1 ) ;
return l . ReturnCount ( ) ;
}
int LuaApi : : Resume ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
checkparams ( ) ;
2020-04-21 20:04:04 -04:00
checkinitdone ( ) ;
2017-08-30 18:31:27 -04:00
_debugger - > Run ( ) ;
return l . ReturnCount ( ) ;
}
int LuaApi : : Execute ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
ExecuteCountType type = ( ExecuteCountType ) l . ReadInteger ( ) ;
int count = l . ReadInteger ( ) ;
checkparams ( ) ;
2020-04-21 20:04:04 -04:00
checkinitdone ( ) ;
2017-08-30 18:31:27 -04:00
errorCond ( count < = 0 , " count must be >= 1 " ) ;
errorCond ( type < ExecuteCountType : : CpuCycles | | type > ExecuteCountType : : CpuInstructions , " type is invalid " ) ;
switch ( type ) {
case ExecuteCountType : : CpuCycles : _debugger - > StepCycles ( count ) ; break ;
case ExecuteCountType : : PpuCycles : _debugger - > PpuStep ( count ) ; break ;
case ExecuteCountType : : CpuInstructions : _debugger - > Step ( count ) ; break ;
}
return l . ReturnCount ( ) ;
}
2021-11-13 12:21:49 -06:00
int LuaApi : : StepOut ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
checkparams ( ) ;
checkinitdone ( ) ;
_debugger - > StepOut ( ) ;
return l . ReturnCount ( ) ;
}
int LuaApi : : StepOver ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
checkparams ( ) ;
checkinitdone ( ) ;
_debugger - > StepOver ( ) ;
return l . ReturnCount ( ) ;
}
2017-08-30 18:31:27 -04:00
int LuaApi : : Rewind ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
int seconds = l . ReadInteger ( ) ;
checkparams ( ) ;
2017-10-07 19:48:45 -04:00
checksavestateconditions ( ) ;
2017-08-30 18:31:27 -04:00
errorCond ( seconds < = 0 , " seconds must be >= 1 " ) ;
2018-07-02 16:39:24 -04:00
_console - > GetRewindManager ( ) - > RewindSeconds ( seconds ) ;
2017-08-30 18:31:27 -04:00
return l . ReturnCount ( ) ;
}
int LuaApi : : TakeScreenshot ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
checkparams ( ) ;
stringstream ss ;
2018-07-02 16:39:24 -04:00
_console - > GetVideoDecoder ( ) - > TakeScreenshot ( ss ) ;
2017-08-30 18:31:27 -04:00
l . Return ( ss . str ( ) ) ;
return l . ReturnCount ( ) ;
}
int LuaApi : : SaveSavestate ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
2017-10-07 19:48:45 -04:00
checksavestateconditions ( ) ;
2017-08-30 18:31:27 -04:00
stringstream ss ;
2018-07-02 16:39:24 -04:00
_console - > GetSaveStateManager ( ) - > SaveState ( ss ) ;
2017-08-30 18:31:27 -04:00
l . Return ( ss . str ( ) ) ;
return l . ReturnCount ( ) ;
}
int LuaApi : : LoadSavestate ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
string savestate = l . ReadString ( ) ;
checkparams ( ) ;
2017-10-07 19:48:45 -04:00
checksavestateconditions ( ) ;
l . Return ( _context - > LoadState ( savestate ) ) ;
2017-08-30 18:31:27 -04:00
return l . ReturnCount ( ) ;
}
2017-10-05 19:44:37 -04:00
int LuaApi : : SaveSavestateAsync ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
int32_t slot = l . ReadInteger ( ) ;
checkparams ( ) ;
errorCond ( slot < 0 , " Slot must be >= 0 " ) ;
_context - > RequestSaveState ( slot ) ;
return l . ReturnCount ( ) ;
}
int LuaApi : : LoadSavestateAsync ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
int32_t slot = l . ReadInteger ( ) ;
checkparams ( ) ;
errorCond ( slot < 0 , " Slot must be >= 0 " ) ;
2017-10-07 19:48:45 -04:00
l . Return ( _context - > RequestLoadState ( slot ) ) ;
2017-10-05 19:44:37 -04:00
return l . ReturnCount ( ) ;
}
int LuaApi : : GetSavestateData ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
int32_t slot = l . ReadInteger ( ) ;
checkparams ( ) ;
errorCond ( slot < 0 , " Slot must be >= 0 " ) ;
l . Return ( _context - > GetSavestateData ( slot ) ) ;
return l . ReturnCount ( ) ;
}
int LuaApi : : ClearSavestateData ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
int32_t slot = l . ReadInteger ( ) ;
checkparams ( ) ;
errorCond ( slot < 0 , " Slot must be >= 0 " ) ;
_context - > ClearSavestateData ( slot ) ;
return l . ReturnCount ( ) ;
}
int LuaApi : : IsKeyPressed ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
string keyName = l . ReadString ( ) ;
checkparams ( ) ;
2017-11-19 23:08:23 -05:00
uint32_t keyCode = KeyManager : : GetKeyCode ( keyName ) ;
2017-10-05 19:44:37 -04:00
errorCond ( keyCode = = 0 , " Invalid key name " ) ;
2017-11-19 23:08:23 -05:00
l . Return ( KeyManager : : IsKeyPressed ( keyCode ) ) ;
2017-10-05 19:44:37 -04:00
return l . ReturnCount ( ) ;
}
2017-08-30 18:31:27 -04:00
int LuaApi : : GetInput ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
int port = l . ReadInteger ( ) ;
checkparams ( ) ;
errorCond ( port < 0 | | port > 3 , " Invalid port number - must be between 0 to 3 " ) ;
2018-07-02 16:39:24 -04:00
shared_ptr < StandardController > controller = std : : dynamic_pointer_cast < StandardController > ( _console - > GetControlManager ( ) - > GetControlDevice ( port ) ) ;
2017-08-30 18:31:27 -04:00
errorCond ( controller = = nullptr , " Input port must be connected to a standard controller " ) ;
lua_newtable ( lua ) ;
2017-11-19 23:08:23 -05:00
lua_pushboolvalue ( a , controller - > IsPressed ( StandardController : : Buttons : : A ) ) ;
lua_pushboolvalue ( b , controller - > IsPressed ( StandardController : : Buttons : : B ) ) ;
lua_pushboolvalue ( start , controller - > IsPressed ( StandardController : : Buttons : : Start ) ) ;
lua_pushboolvalue ( select , controller - > IsPressed ( StandardController : : Buttons : : Select ) ) ;
lua_pushboolvalue ( up , controller - > IsPressed ( StandardController : : Buttons : : Up ) ) ;
lua_pushboolvalue ( down , controller - > IsPressed ( StandardController : : Buttons : : Down ) ) ;
lua_pushboolvalue ( left , controller - > IsPressed ( StandardController : : Buttons : : Left ) ) ;
lua_pushboolvalue ( right , controller - > IsPressed ( StandardController : : Buttons : : Right ) ) ;
2017-08-30 18:31:27 -04:00
return 1 ;
}
int LuaApi : : SetInput ( lua_State * lua )
{
2017-11-19 23:08:23 -05:00
LuaCallHelper l ( lua ) ;
lua_settop ( lua , 3 ) ;
bool allowUserInput = l . ReadBool ( ) ;
2017-08-30 18:31:27 -04:00
luaL_checktype ( lua , 2 , LUA_TTABLE ) ;
lua_getfield ( lua , 2 , " a " ) ;
lua_getfield ( lua , 2 , " b " ) ;
lua_getfield ( lua , 2 , " start " ) ;
lua_getfield ( lua , 2 , " select " ) ;
lua_getfield ( lua , 2 , " up " ) ;
lua_getfield ( lua , 2 , " down " ) ;
lua_getfield ( lua , 2 , " left " ) ;
lua_getfield ( lua , 2 , " right " ) ;
2017-11-19 23:08:23 -05:00
Nullable < bool > right = l . ReadOptionalBool ( ) ;
Nullable < bool > left = l . ReadOptionalBool ( ) ;
Nullable < bool > down = l . ReadOptionalBool ( ) ;
Nullable < bool > up = l . ReadOptionalBool ( ) ;
Nullable < bool > select = l . ReadOptionalBool ( ) ;
Nullable < bool > start = l . ReadOptionalBool ( ) ;
Nullable < bool > b = l . ReadOptionalBool ( ) ;
Nullable < bool > a = l . ReadOptionalBool ( ) ;
2017-08-30 18:31:27 -04:00
lua_pop ( lua , 1 ) ;
int port = l . ReadInteger ( ) ;
errorCond ( port < 0 | | port > 3 , " Invalid port number - must be between 0 to 3 " ) ;
2018-07-02 16:39:24 -04:00
shared_ptr < StandardController > controller = std : : dynamic_pointer_cast < StandardController > ( _console - > GetControlManager ( ) - > GetControlDevice ( port ) ) ;
2017-11-19 23:08:23 -05:00
errorCond ( controller = = nullptr , " Input port must be connected to a standard controller " ) ;
if ( right . HasValue | | ! allowUserInput ) controller - > SetBitValue ( StandardController : : Buttons : : Right , right . Value ) ;
if ( left . HasValue | | ! allowUserInput ) controller - > SetBitValue ( StandardController : : Buttons : : Left , left . Value ) ;
if ( down . HasValue | | ! allowUserInput ) controller - > SetBitValue ( StandardController : : Buttons : : Down , down . Value ) ;
if ( up . HasValue | | ! allowUserInput ) controller - > SetBitValue ( StandardController : : Buttons : : Up , up . Value ) ;
if ( select . HasValue | | ! allowUserInput ) controller - > SetBitValue ( StandardController : : Buttons : : Select , select . Value ) ;
if ( start . HasValue | | ! allowUserInput ) controller - > SetBitValue ( StandardController : : Buttons : : Start , start . Value ) ;
if ( b . HasValue | | ! allowUserInput ) controller - > SetBitValue ( StandardController : : Buttons : : B , b . Value ) ;
if ( a . HasValue | | ! allowUserInput ) controller - > SetBitValue ( StandardController : : Buttons : : A , a . Value ) ;
2017-08-30 18:31:27 -04:00
return l . ReturnCount ( ) ;
}
int LuaApi : : AddCheat ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
string gamegenieCode = l . ReadString ( ) ;
checkparams ( ) ;
errorCond ( gamegenieCode . length ( ) ! = 6 & & gamegenieCode . length ( ) ! = 8 , " Game genie code must be 6 or 8 characters long " ) ;
errorCond ( gamegenieCode . find_first_not_of ( " APZLGITYEOXUKSVN " , 0 ) ! = string : : npos , " Game genie code may only contain these characters: AEGIKLNOPSTUVXYZ " ) ;
2018-07-02 16:39:24 -04:00
_console - > GetCheatManager ( ) - > AddGameGenieCode ( gamegenieCode ) ;
2017-08-30 18:31:27 -04:00
return l . ReturnCount ( ) ;
}
int LuaApi : : ClearCheats ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
checkparams ( ) ;
2018-07-02 16:39:24 -04:00
_console - > GetCheatManager ( ) - > ClearCodes ( ) ;
2017-08-30 18:31:27 -04:00
return l . ReturnCount ( ) ;
}
2018-03-30 19:54:47 -04:00
int LuaApi : : GetAccessCounters ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
l . ForceParamCount ( 2 ) ;
MemoryOperationType operationType = ( MemoryOperationType ) l . ReadInteger ( ) ;
AddressType memoryType = ( AddressType ) l . ReadInteger ( ) ;
errorCond ( operationType > = MemoryOperationType : : ExecOperand , " Invalid operation type " ) ;
errorCond ( memoryType > = AddressType : : Register , " Invalid memory type " ) ;
checkparams ( ) ;
2019-01-13 18:32:27 -05:00
DebugMemoryType debugMemoryType ;
2018-03-30 19:54:47 -04:00
uint32_t size = 0 ;
switch ( memoryType ) {
2019-01-26 16:49:26 -05:00
default :
2018-06-25 15:56:05 -04:00
case AddressType : : Register : error ( " Invalid memory type " ) ; break ;
2019-01-26 16:49:26 -05:00
2019-01-13 18:32:27 -05:00
case AddressType : : InternalRam :
debugMemoryType = DebugMemoryType : : InternalRam ;
2020-02-14 21:40:50 -05:00
size = 0x800 ;
2019-01-13 18:32:27 -05:00
break ;
case AddressType : : PrgRom :
debugMemoryType = DebugMemoryType : : PrgRom ;
size = _memoryDumper - > GetMemorySize ( DebugMemoryType : : PrgRom ) ;
break ;
case AddressType : : WorkRam :
debugMemoryType = DebugMemoryType : : WorkRam ;
size = _memoryDumper - > GetMemorySize ( DebugMemoryType : : WorkRam ) ;
break ;
case AddressType : : SaveRam :
debugMemoryType = DebugMemoryType : : SaveRam ;
size = _memoryDumper - > GetMemorySize ( DebugMemoryType : : SaveRam ) ;
break ;
2018-03-30 19:54:47 -04:00
}
2020-02-14 21:40:50 -05:00
vector < AddressCounters > counts ;
counts . resize ( size , { } ) ;
_debugger - > GetMemoryAccessCounter ( ) - > GetAccessCounts ( 0 , size , debugMemoryType , counts . data ( ) ) ;
2018-03-30 19:54:47 -04:00
lua_newtable ( lua ) ;
2020-02-14 21:40:50 -05:00
switch ( operationType ) {
case MemoryOperationType : : Read :
for ( uint32_t i = 0 ; i < size ; i + + ) {
lua_pushinteger ( lua , counts [ i ] . ReadCount ) ;
lua_rawseti ( lua , - 2 , i ) ;
}
break ;
case MemoryOperationType : : Write :
for ( uint32_t i = 0 ; i < size ; i + + ) {
lua_pushinteger ( lua , counts [ i ] . WriteCount ) ;
lua_rawseti ( lua , - 2 , i ) ;
}
break ;
case MemoryOperationType : : ExecOpCode :
for ( uint32_t i = 0 ; i < size ; i + + ) {
lua_pushinteger ( lua , counts [ i ] . ExecCount ) ;
lua_rawseti ( lua , - 2 , i ) ;
}
break ;
2021-10-19 21:40:41 -04:00
default :
break ;
2018-03-30 19:54:47 -04:00
}
return 1 ;
}
int LuaApi : : ResetAccessCounters ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
checkparams ( ) ;
_debugger - > GetMemoryAccessCounter ( ) - > ResetCounts ( ) ;
return l . ReturnCount ( ) ;
}
2017-10-07 15:16:14 -04:00
int LuaApi : : GetScriptDataFolder ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
checkparams ( ) ;
string baseFolder = FolderUtilities : : CombinePath ( FolderUtilities : : GetHomeFolder ( ) , " LuaScriptData " ) ;
FolderUtilities : : CreateFolder ( baseFolder ) ;
string scriptFolder = FolderUtilities : : CombinePath ( baseFolder , FolderUtilities : : GetFilename ( _context - > GetScriptName ( ) , false ) ) ;
FolderUtilities : : CreateFolder ( scriptFolder ) ;
l . Return ( scriptFolder ) ;
return l . ReturnCount ( ) ;
}
2017-12-20 22:11:36 -05:00
int LuaApi : : GetRomInfo ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
checkparams ( ) ;
2018-07-07 14:52:51 -04:00
RomInfo romInfo = _console - > GetRomInfo ( ) ;
2018-07-02 16:39:24 -04:00
string romPath = _console - > GetRomPath ( ) ;
2018-03-20 22:05:38 -04:00
2017-12-20 22:11:36 -05:00
lua_newtable ( lua ) ;
2018-07-07 14:52:51 -04:00
lua_pushstringvalue ( name , romInfo . RomName ) ;
2018-07-01 15:21:05 -04:00
lua_pushstringvalue ( path , romPath ) ;
2017-12-20 22:11:36 -05:00
2018-07-07 14:52:51 -04:00
lua_pushintvalue ( fileCrc32Hash , romInfo . Hash . Crc32 ) ;
lua_pushstringvalue ( fileSha1Hash , romInfo . Hash . Sha1 ) ;
lua_pushintvalue ( prgChrCrc32Hash , romInfo . Hash . PrgCrc32 ) ;
lua_pushstringvalue ( prgChrMd5Hash , romInfo . Hash . PrgChrMd5 ) ;
lua_pushintvalue ( format , romInfo . Format ) ;
lua_pushboolvalue ( isChrRam , romInfo . HasChrRam ) ;
2017-12-20 22:11:36 -05:00
return 1 ;
}
int LuaApi : : GetLogWindowLog ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
checkparams ( ) ;
l . Return ( MessageManager : : GetLog ( ) ) ;
return l . ReturnCount ( ) ;
}
2017-08-30 18:31:27 -04:00
int LuaApi : : SetState ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
lua_settop ( lua , 1 ) ;
luaL_checktype ( lua , - 1 , LUA_TTABLE ) ;
DebugState state ;
lua_getfield ( lua , - 1 , " cpu " ) ;
luaL_checktype ( lua , - 1 , LUA_TTABLE ) ;
lua_readint ( a , state . CPU . A ) ;
lua_readint ( cycleCount , state . CPU . CycleCount ) ;
lua_readint ( irqFlag , state . CPU . IRQFlag ) ;
lua_readbool ( nmiFlag , state . CPU . NMIFlag ) ;
lua_readint ( pc , state . CPU . PC ) ;
lua_readint ( ps , state . CPU . PS ) ;
lua_readint ( sp , state . CPU . SP ) ;
lua_readint ( x , state . CPU . X ) ;
lua_readint ( y , state . CPU . Y ) ;
lua_pop ( lua , 1 ) ;
lua_getfield ( lua , - 1 , " ppu " ) ;
luaL_checktype ( lua , - 1 , LUA_TTABLE ) ;
lua_readint ( cycle , state . PPU . Cycle ) ;
lua_readint ( frameCount , state . PPU . FrameCount ) ;
lua_readint ( scanline , state . PPU . Scanline ) ;
lua_getfield ( lua , - 1 , " control " ) ;
luaL_checktype ( lua , - 1 , LUA_TTABLE ) ;
lua_readbool ( backgroundEnabled , state . PPU . ControlFlags . BackgroundEnabled ) ;
lua_readbool ( backgroundMask , state . PPU . ControlFlags . BackgroundMask ) ;
lua_readint ( backgroundPatternAddr , state . PPU . ControlFlags . BackgroundPatternAddr ) ;
lua_readbool ( grayscale , state . PPU . ControlFlags . Grayscale ) ;
lua_readbool ( intensifyBlue , state . PPU . ControlFlags . IntensifyBlue ) ;
lua_readbool ( intensifyGreen , state . PPU . ControlFlags . IntensifyGreen ) ;
lua_readbool ( intensifyRed , state . PPU . ControlFlags . IntensifyRed ) ;
lua_readbool ( largeSprites , state . PPU . ControlFlags . LargeSprites ) ;
lua_readbool ( spriteMask , state . PPU . ControlFlags . SpriteMask ) ;
lua_readint ( spritePatternAddr , state . PPU . ControlFlags . SpritePatternAddr ) ;
lua_readbool ( spritesEnabled , state . PPU . ControlFlags . SpritesEnabled ) ;
lua_readbool ( nmiOnVBlank , state . PPU . ControlFlags . VBlank ) ;
lua_readbool ( verticalWrite , state . PPU . ControlFlags . VerticalWrite ) ;
lua_pop ( lua , 1 ) ;
lua_getfield ( lua , - 1 , " status " ) ;
luaL_checktype ( lua , - 1 , LUA_TTABLE ) ;
lua_readbool ( sprite0Hit , state . PPU . StatusFlags . Sprite0Hit ) ;
lua_readbool ( spriteOverflow , state . PPU . StatusFlags . SpriteOverflow ) ;
lua_readbool ( verticalBlank , state . PPU . StatusFlags . VerticalBlank ) ;
lua_pop ( lua , 1 ) ;
lua_getfield ( lua , - 1 , " state " ) ;
luaL_checktype ( lua , - 1 , LUA_TTABLE ) ;
lua_readint ( control , state . PPU . State . Control ) ;
lua_readint ( highBitShift , state . PPU . State . HighBitShift ) ;
lua_readint ( lowBitShift , state . PPU . State . LowBitShift ) ;
lua_readint ( mask , state . PPU . State . Mask ) ;
lua_readint ( spriteRamAddr , state . PPU . State . SpriteRamAddr ) ;
lua_readint ( status , state . PPU . State . Status ) ;
lua_readint ( tmpVideoRamAddr , state . PPU . State . TmpVideoRamAddr ) ;
lua_readint ( videoRamAddr , state . PPU . State . VideoRamAddr ) ;
lua_readbool ( writeToggle , state . PPU . State . WriteToggle ) ;
lua_readint ( xScroll , state . PPU . State . XScroll ) ;
lua_pop ( lua , 1 ) ;
lua_pop ( lua , 1 ) ;
_debugger - > SetState ( state ) ;
return 0 ;
}
int LuaApi : : GetState ( lua_State * lua )
{
LuaCallHelper l ( lua ) ;
checkparams ( ) ;
DebugState state ;
_debugger - > GetState ( & state , true ) ;
lua_newtable ( lua ) ;
lua_pushintvalue ( region , state . Model ) ;
2018-07-01 15:21:05 -04:00
lua_pushintvalue ( clockRate , state . ClockRate ) ;
2017-08-30 18:31:27 -04:00
lua_starttable ( " cpu " ) ;
lua_pushintvalue ( a , state . CPU . A ) ;
2019-05-22 20:35:50 -04:00
lua_pushint64value ( cycleCount , state . CPU . CycleCount ) ;
2017-08-30 18:31:27 -04:00
lua_pushintvalue ( irqFlag , state . CPU . IRQFlag ) ;
lua_pushboolvalue ( nmiFlag , state . CPU . NMIFlag ) ;
lua_pushintvalue ( pc , state . CPU . PC ) ;
lua_pushintvalue ( status , state . CPU . PS ) ;
lua_pushintvalue ( sp , state . CPU . SP ) ;
lua_pushintvalue ( x , state . CPU . X ) ;
lua_pushintvalue ( y , state . CPU . Y ) ;
lua_endtable ( ) ;
lua_starttable ( " ppu " ) ;
lua_pushintvalue ( cycle , state . PPU . Cycle ) ;
lua_pushintvalue ( frameCount , state . PPU . FrameCount ) ;
lua_pushintvalue ( scanline , state . PPU . Scanline ) ;
lua_starttable ( " control " ) ;
lua_pushboolvalue ( backgroundEnabled , state . PPU . ControlFlags . BackgroundEnabled ) ;
lua_pushboolvalue ( backgroundMask , state . PPU . ControlFlags . BackgroundMask ) ;
lua_pushintvalue ( backgroundPatternAddr , state . PPU . ControlFlags . BackgroundPatternAddr ) ;
lua_pushboolvalue ( grayscale , state . PPU . ControlFlags . Grayscale ) ;
lua_pushboolvalue ( intensifyBlue , state . PPU . ControlFlags . IntensifyBlue ) ;
lua_pushboolvalue ( intensifyGreen , state . PPU . ControlFlags . IntensifyGreen ) ;
lua_pushboolvalue ( intensifyRed , state . PPU . ControlFlags . IntensifyRed ) ;
lua_pushboolvalue ( largeSprites , state . PPU . ControlFlags . LargeSprites ) ;
lua_pushboolvalue ( spriteMask , state . PPU . ControlFlags . SpriteMask ) ;
lua_pushintvalue ( spritePatternAddr , state . PPU . ControlFlags . SpritePatternAddr ) ;
lua_pushboolvalue ( spritesEnabled , state . PPU . ControlFlags . SpritesEnabled ) ;
lua_pushboolvalue ( nmiOnVBlank , state . PPU . ControlFlags . VBlank ) ;
lua_pushboolvalue ( verticalWrite , state . PPU . ControlFlags . VerticalWrite ) ;
lua_endtable ( ) ;
lua_starttable ( " status " ) ;
lua_pushboolvalue ( sprite0Hit , state . PPU . StatusFlags . Sprite0Hit ) ;
lua_pushboolvalue ( spriteOverflow , state . PPU . StatusFlags . SpriteOverflow ) ;
lua_pushboolvalue ( verticalBlank , state . PPU . StatusFlags . VerticalBlank ) ;
lua_endtable ( ) ;
lua_starttable ( " state " ) ;
lua_pushintvalue ( control , state . PPU . State . Control ) ;
lua_pushintvalue ( highBitShift , state . PPU . State . HighBitShift ) ;
lua_pushintvalue ( lowBitShift , state . PPU . State . LowBitShift ) ;
lua_pushintvalue ( mask , state . PPU . State . Mask ) ;
lua_pushintvalue ( spriteRamAddr , state . PPU . State . SpriteRamAddr ) ;
lua_pushintvalue ( status , state . PPU . State . Status ) ;
lua_pushintvalue ( tmpVideoRamAddr , state . PPU . State . TmpVideoRamAddr ) ;
lua_pushintvalue ( videoRamAddr , state . PPU . State . VideoRamAddr ) ;
lua_pushboolvalue ( writeToggle , state . PPU . State . WriteToggle ) ;
lua_pushintvalue ( xScroll , state . PPU . State . XScroll ) ;
lua_endtable ( ) ;
lua_endtable ( ) ; //end ppu
lua_starttable ( " cart " ) ;
lua_pushintvalue ( chrPageCount , state . Cartridge . ChrPageCount ) ;
lua_pushintvalue ( chrPageSize , state . Cartridge . ChrPageSize ) ;
lua_pushintvalue ( chrRamSize , state . Cartridge . ChrRamSize ) ;
lua_pushintvalue ( chrRomSize , state . Cartridge . ChrRomSize ) ;
lua_pushintvalue ( prgPageCount , state . Cartridge . PrgPageCount ) ;
lua_pushintvalue ( prgPageSize , state . Cartridge . PrgPageSize ) ;
lua_pushintvalue ( prgRomSize , state . Cartridge . PrgRomSize ) ;
lua_starttable ( " selectedPrgPages " ) ;
for ( int i = 0 , max = 0x8000 / state . Cartridge . PrgPageSize ; i < max ; i + + ) {
2018-08-19 13:53:20 -04:00
lua_pushinteger ( lua , i ) ;
lua_pushinteger ( lua , ( int32_t ) state . Cartridge . PrgMemoryOffset [ 0x80 + ( ( i * state . Cartridge . PrgPageSize ) > > 8 ) ] / state . Cartridge . PrgPageSize ) ;
2017-08-30 18:31:27 -04:00
lua_settable ( lua , - 3 ) ;
}
lua_endtable ( ) ;
lua_starttable ( " selectedChrPages " ) ;
for ( int i = 0 , max = 0x2000 / state . Cartridge . ChrPageSize ; i < max ; i + + ) {
2018-08-19 13:53:20 -04:00
lua_pushinteger ( lua , i ) ;
lua_pushinteger ( lua , ( int32_t ) state . Cartridge . ChrMemoryOffset [ ( i * state . Cartridge . ChrPageSize ) > > 8 ] / state . Cartridge . ChrPageSize ) ;
2017-08-30 18:31:27 -04:00
lua_settable ( lua , - 3 ) ;
}
lua_endtable ( ) ;
lua_endtable ( ) ;
lua_starttable ( " apu " ) ;
lua_starttable ( " square1 " ) ;
PushSquareState ( lua , state . APU . Square1 ) ;
lua_endtable ( ) ;
lua_starttable ( " square2 " ) ;
PushSquareState ( lua , state . APU . Square2 ) ;
lua_endtable ( ) ;
lua_starttable ( " triangle " ) ;
lua_pushboolvalue ( enabled , state . APU . Triangle . Enabled ) ;
2017-12-20 22:11:36 -05:00
lua_pushdoublevalue ( frequency , state . APU . Triangle . Frequency ) ;
2017-08-30 18:31:27 -04:00
PushLengthCounterState ( lua , state . APU . Triangle . LengthCounter ) ;
lua_pushintvalue ( outputVolume , state . APU . Triangle . OutputVolume ) ;
lua_pushintvalue ( period , state . APU . Triangle . Period ) ;
lua_pushintvalue ( sequencePosition , state . APU . Triangle . SequencePosition ) ;
lua_endtable ( ) ;
lua_starttable ( " noise " ) ;
lua_pushboolvalue ( enabled , state . APU . Noise . Enabled ) ;
2017-12-20 22:11:36 -05:00
lua_pushdoublevalue ( frequency , state . APU . Noise . Frequency ) ;
2017-08-30 18:31:27 -04:00
PushEnvelopeState ( lua , state . APU . Noise . Envelope ) ;
PushLengthCounterState ( lua , state . APU . Noise . LengthCounter ) ;
lua_pushboolvalue ( modeFlag , state . APU . Noise . ModeFlag ) ;
lua_pushintvalue ( outputVolume , state . APU . Noise . OutputVolume ) ;
lua_pushintvalue ( period , state . APU . Noise . Period ) ;
lua_pushintvalue ( shiftRegister , state . APU . Noise . ShiftRegister ) ;
lua_endtable ( ) ;
lua_starttable ( " dmc " ) ;
lua_pushintvalue ( bytesRemaining , state . APU . Dmc . BytesRemaining ) ;
2017-12-21 15:37:57 -05:00
lua_pushdoublevalue ( sampleRate , state . APU . Dmc . SampleRate ) ;
2017-08-30 18:31:27 -04:00
lua_pushboolvalue ( irqEnabled , state . APU . Dmc . IrqEnabled ) ;
lua_pushboolvalue ( loop , state . APU . Dmc . Loop ) ;
lua_pushintvalue ( outputVolume , state . APU . Dmc . OutputVolume ) ;
lua_pushintvalue ( period , state . APU . Dmc . Period ) ;
lua_pushintvalue ( sampleAddr , state . APU . Dmc . SampleAddr ) ;
lua_pushintvalue ( sampleLength , state . APU . Dmc . SampleLength ) ;
lua_endtable ( ) ;
lua_starttable ( " frameCounter " ) ;
lua_pushintvalue ( fiveStepMode , state . APU . FrameCounter . FiveStepMode ) ;
lua_pushboolvalue ( irqEnabled , state . APU . FrameCounter . IrqEnabled ) ;
lua_pushintvalue ( sequencePosition , state . APU . FrameCounter . SequencePosition ) ;
lua_endtable ( ) ;
lua_endtable ( ) ; //end apu
return 1 ;
}
void LuaApi : : PushSquareState ( lua_State * lua , ApuSquareState & state )
{
lua_pushintvalue ( duty , state . Duty ) ;
lua_pushintvalue ( dutyPosition , state . DutyPosition ) ;
2017-12-20 22:11:36 -05:00
lua_pushdoublevalue ( frequency , state . Frequency ) ;
2017-08-30 18:31:27 -04:00
lua_pushintvalue ( period , state . Period ) ;
lua_pushboolvalue ( sweepEnabled , state . SweepEnabled ) ;
lua_pushboolvalue ( sweepNegate , state . SweepNegate ) ;
lua_pushintvalue ( sweepPeriod , state . SweepPeriod ) ;
lua_pushintvalue ( sweepShift , state . SweepShift ) ;
lua_pushboolvalue ( enabled , state . Enabled ) ;
lua_pushintvalue ( outputVolume , state . OutputVolume ) ;
PushEnvelopeState ( lua , state . Envelope ) ;
PushLengthCounterState ( lua , state . LengthCounter ) ;
}
void LuaApi : : PushEnvelopeState ( lua_State * lua , ApuEnvelopeState & state )
{
lua_starttable ( " envelope " ) ;
lua_pushboolvalue ( startFlag , state . StartFlag ) ;
lua_pushboolvalue ( loop , state . Loop ) ;
lua_pushboolvalue ( constantVolume , state . ConstantVolume ) ;
lua_pushintvalue ( divider , state . Divider ) ;
lua_pushintvalue ( counter , state . Counter ) ;
lua_pushintvalue ( volume , state . Volume ) ;
lua_endtable ( ) ;
}
void LuaApi : : PushLengthCounterState ( lua_State * lua , ApuLengthCounterState & state )
{
lua_starttable ( " lengthCounter " ) ;
lua_pushboolvalue ( halt , state . Halt ) ;
lua_pushintvalue ( counter , state . Counter ) ;
lua_pushintvalue ( reloadValue , state . ReloadValue ) ;
lua_endtable ( ) ;
}