使用 Mupen64Plus Unmanaged C dll API 命令填充 C# 结构
Populate C# struct using Mupen64Plus Unmanaged C dll API command
我正在使用 Mupen64Plus 和包含的 m64p_test_rom.v64
文件。
我正在使用 C# 与用 C 编写的 mupen64plus.dll
API 通信。
问题
我正在尝试使用其 API 命令 M64CMD_ROM_GET_HEADER
从 m64p_test_rom.v64
获取 ROM Header,其中包含 Name
、Manufacturer ID
、Country code
。看起来该命令将数据存储在 struct
.
中
问题是当调用 API 命令填充 struct
时,变量保持为空,它不会用新值填充它。
API
我正在使用 BizHawk 的 C# API code 与 mupen64plus.dll
.
交谈
命令
Mupen64Plus v2.0 Core Front-End Wiki
CoreDoCommand(m64p_command 命令, int ParamInt, void *ParamPtr)
命令枚举类型,指定应执行哪个命令。
ParamInt:可用作命令输入的整数值。
ParamPtr:可用作命令输入的指针。
M64CMD_ROM_GET_HEADER
这将检索当前打开的 ROM 的 header 数据。必须打开 ROM 映像。
ParamInt:指向 rom_header 结构的指针 以接收数据 。
ParamPtr:rom_header 结构的字节大小。
ROM Header 结构
在我的 C#
项目中,我创建了一个新的 struct
以匹配 Mupen64Plus 的 C
源代码中的那个。我不确定我是否已将它从 C
正确转换为 C#
。
Mupen64Plus Cm64p_types.h
typedef struct
{
uint8_t init_PI_BSB_DOM1_LAT_REG; /* 0x00 */
uint8_t init_PI_BSB_DOM1_PGS_REG; /* 0x01 */
uint8_t init_PI_BSB_DOM1_PWD_REG; /* 0x02 */
uint8_t init_PI_BSB_DOM1_PGS_REG2; /* 0x03 */
uint32_t ClockRate; /* 0x04 */
uint32_t PC; /* 0x08 */
uint32_t Release; /* 0x0C */
uint32_t CRC1; /* 0x10 */
uint32_t CRC2; /* 0x14 */
uint32_t Unknown[2]; /* 0x18 */
uint8_t Name[20]; /* 0x20 */
uint32_t unknown; /* 0x34 */
uint32_t Manufacturer_ID; /* 0x38 */
uint16_t Cartridge_ID; /* 0x3C - Game serial number */
uint16_t Country_code; /* 0x3E */
} m64p_rom_header;
我的 C# 结构
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct m64p_rom_header
{
public byte init_PI_BSB_DOM1_LAT_REG; /* 0x00 */
public byte init_PI_BSB_DOM1_PGS_REG; /* 0x01 */
public byte init_PI_BSB_DOM1_PWD_REG; /* 0x02 */
public byte init_PI_BSB_DOM1_PGS_REG2; /* 0x03 */
public uint ClockRate; /* 0x04 */
public uint PC; /* 0x08 */
public uint Release; /* 0x0C */
public uint CRC1; /* 0x10 */
public uint CRC2; /* 0x14 */
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public uint[] Unknown; /* 0x18 */
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public byte[] Name; /* 0x20 */
public uint unknown; /* 0x34 */
public uint Manufacturer_ID; /* 0x38 */
public ushort Cartridge_ID; /* 0x3C - Game serial number */
public ushort Country_code; /* 0x3E */
};
非托管函数指针
我添加了一个新的委托声明,因此我可以使用 API 的 CoreDoCommand()
函数和 M64CMD_ROM_GET_HEADER
命令。
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate m64p_error CoreDoCommandStruct(m64p_command Command, m64p_rom_header ParamInt, ref int ParamPtr);
CoreDoCommandStruct m64pCoreDoCommandStruct;
ROM 获取Header
我正在尝试检索 ROM 的名称。
运行 API 命令 M64CMD_ROM_GET_HEADER
应该填充 m64p_rom_header
struct
.
Name
属性应该return为Mupen64Plus Demo by Marshallh (GPL)
。
我在 rom_header.Name
上收到错误 ArgumentNullException: Array cannot be null.
。
调用命令时ROM打开运行
public m64p_rom_header rom_header;
public String ROMGetHeader()
{
// Get size of ROM Header struct
int size = Marshal.SizeOf(typeof(m64p_rom_header)); // returns value of 20?
// API ROM Get Header Command
// Question: Populates all variables in the m64p_rom_header struct?
m64pCoreDoCommandStruct(m64p_command.M64CMD_ROM_GET_HEADER, rom_header, ref size);
// Return the byte Array and convert to String
return System.Text.Encoding.Default.GetString(rom_header.Name); // <-- Error: Array null
}
您 defined/passed 方法的参数顺序错误。委托的第二个参数是 int 类型,第三个参数是 void pointer in C并且应用于传递数据作为参考。
比如在你发送的link(BizHawk/mupen64pluseCoreApi.cs)中可以找到如下代码:
// Pass the rom to the core
result = m64pCoreDoCommandByteArray(m64p_command.M64CMD_ROM_OPEN, rom.Length, rom);
所以delegate的定义应该是这样的:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate m64p_error CoreDoCommandStruct(m64p_command Command, int ParamInt, ref m64p_rom_header ParamPtr);
CoreDoCommandStruct m64pCoreDoCommandStruct;
你的使用方式应该是这样的:
m64pCoreDoCommandStruct(m64p_command.M64CMD_ROM_GET_HEADER, size, ref rom_header);
我正在使用 Mupen64Plus 和包含的 m64p_test_rom.v64
文件。
我正在使用 C# 与用 C 编写的 mupen64plus.dll
API 通信。
问题
我正在尝试使用其 API 命令 M64CMD_ROM_GET_HEADER
从 m64p_test_rom.v64
获取 ROM Header,其中包含 Name
、Manufacturer ID
、Country code
。看起来该命令将数据存储在 struct
.
问题是当调用 API 命令填充 struct
时,变量保持为空,它不会用新值填充它。
API
我正在使用 BizHawk 的 C# API code 与 mupen64plus.dll
.
命令
Mupen64Plus v2.0 Core Front-End Wiki
CoreDoCommand(m64p_command 命令, int ParamInt, void *ParamPtr)
命令枚举类型,指定应执行哪个命令。
ParamInt:可用作命令输入的整数值。
ParamPtr:可用作命令输入的指针。M64CMD_ROM_GET_HEADER
这将检索当前打开的 ROM 的 header 数据。必须打开 ROM 映像。
ParamInt:指向 rom_header 结构的指针 以接收数据 。
ParamPtr:rom_header 结构的字节大小。
ROM Header 结构
在我的 C#
项目中,我创建了一个新的 struct
以匹配 Mupen64Plus 的 C
源代码中的那个。我不确定我是否已将它从 C
正确转换为 C#
。
Mupen64Plus Cm64p_types.h
typedef struct
{
uint8_t init_PI_BSB_DOM1_LAT_REG; /* 0x00 */
uint8_t init_PI_BSB_DOM1_PGS_REG; /* 0x01 */
uint8_t init_PI_BSB_DOM1_PWD_REG; /* 0x02 */
uint8_t init_PI_BSB_DOM1_PGS_REG2; /* 0x03 */
uint32_t ClockRate; /* 0x04 */
uint32_t PC; /* 0x08 */
uint32_t Release; /* 0x0C */
uint32_t CRC1; /* 0x10 */
uint32_t CRC2; /* 0x14 */
uint32_t Unknown[2]; /* 0x18 */
uint8_t Name[20]; /* 0x20 */
uint32_t unknown; /* 0x34 */
uint32_t Manufacturer_ID; /* 0x38 */
uint16_t Cartridge_ID; /* 0x3C - Game serial number */
uint16_t Country_code; /* 0x3E */
} m64p_rom_header;
我的 C# 结构
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct m64p_rom_header
{
public byte init_PI_BSB_DOM1_LAT_REG; /* 0x00 */
public byte init_PI_BSB_DOM1_PGS_REG; /* 0x01 */
public byte init_PI_BSB_DOM1_PWD_REG; /* 0x02 */
public byte init_PI_BSB_DOM1_PGS_REG2; /* 0x03 */
public uint ClockRate; /* 0x04 */
public uint PC; /* 0x08 */
public uint Release; /* 0x0C */
public uint CRC1; /* 0x10 */
public uint CRC2; /* 0x14 */
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public uint[] Unknown; /* 0x18 */
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public byte[] Name; /* 0x20 */
public uint unknown; /* 0x34 */
public uint Manufacturer_ID; /* 0x38 */
public ushort Cartridge_ID; /* 0x3C - Game serial number */
public ushort Country_code; /* 0x3E */
};
非托管函数指针
我添加了一个新的委托声明,因此我可以使用 API 的 CoreDoCommand()
函数和 M64CMD_ROM_GET_HEADER
命令。
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate m64p_error CoreDoCommandStruct(m64p_command Command, m64p_rom_header ParamInt, ref int ParamPtr);
CoreDoCommandStruct m64pCoreDoCommandStruct;
ROM 获取Header
我正在尝试检索 ROM 的名称。
运行 API 命令 M64CMD_ROM_GET_HEADER
应该填充 m64p_rom_header
struct
.
Name
属性应该return为Mupen64Plus Demo by Marshallh (GPL)
。
我在 rom_header.Name
上收到错误 ArgumentNullException: Array cannot be null.
。
调用命令时ROM打开运行
public m64p_rom_header rom_header;
public String ROMGetHeader()
{
// Get size of ROM Header struct
int size = Marshal.SizeOf(typeof(m64p_rom_header)); // returns value of 20?
// API ROM Get Header Command
// Question: Populates all variables in the m64p_rom_header struct?
m64pCoreDoCommandStruct(m64p_command.M64CMD_ROM_GET_HEADER, rom_header, ref size);
// Return the byte Array and convert to String
return System.Text.Encoding.Default.GetString(rom_header.Name); // <-- Error: Array null
}
您 defined/passed 方法的参数顺序错误。委托的第二个参数是 int 类型,第三个参数是 void pointer in C并且应用于传递数据作为参考。 比如在你发送的link(BizHawk/mupen64pluseCoreApi.cs)中可以找到如下代码:
// Pass the rom to the core
result = m64pCoreDoCommandByteArray(m64p_command.M64CMD_ROM_OPEN, rom.Length, rom);
所以delegate的定义应该是这样的:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate m64p_error CoreDoCommandStruct(m64p_command Command, int ParamInt, ref m64p_rom_header ParamPtr);
CoreDoCommandStruct m64pCoreDoCommandStruct;
你的使用方式应该是这样的:
m64pCoreDoCommandStruct(m64p_command.M64CMD_ROM_GET_HEADER, size, ref rom_header);