FalcoGer Posted September 13, 2023 Posted September 13, 2023 (edited) There is a lack of documentation for this feature. I want to export Displays (particularly the bottom and left MFD of the hornet, and the CDU of the A10C) to be read in by a C# program. Everything I could find on the whole thing was basically this -- you can export render targets via shared memory interface -- using next functions -- LoSetSharedTexture(name) -- register texture with name "name" to export -- LoRemoveSharedTexture(name) -- copy texture with name "name" to named shared memory area "name" -- LoUpdateSharedTexture(name) -- unregister texture -- texture exported like Windows BMP file -- -------------------------------- -- |BITMAPFILEHEADER | -- |BITMAPINFOHEADER | -- |bits | -- -------------------------------- -- sample textures : "mfd0" - full SHKVAL screen -- "mfd1" - ABRIS map screen -- "mfd2" - not used -- "mfd3" - not used -- "mirrors" - mirrors Along with a few forum posts complaining about the feature being broken/not working/not using the correct bitmap header layout from 10+ years ago. I tried this export script -- REF: https://wiki.hoggitworld.com/view/DCS_export -- REF: https://wiki.hoggitworld.com/view/DCS_Export_Script local LOG_MODNAME = "MFD_EXPORT_TEST" log.write(LOG_MODNAME, log.INFO, "Initializing...") --Version 3 package.path = package.path .. ";" .. lfs.currentdir() .. "/LuaSocket/?.lua" package.cpath = package.cpath .. ";" .. lfs.currentdir() .. "/LuaSocket/?.dll" package.path = package.path .. ";" .. lfs.currentdir() .. "/Scripts/?.lua" local upstreamLuaExportStart = LuaExportStart local upstreamLuaExportStop = LuaExportStop local upstreamLuaExportAfterNextFrame = LuaExportAfterNextFrame local upstreamLuaExportBeforeNextFrame = LuaExportBeforeNextFrame local textureName = "mfd0" function LuaExportStop() if upstreamLuaExportStop ~= nil then successful, err = pcall(upstreamLuaExportStop) if not successful then log.write(LOG_MODNAME, log.ERROR, "Error in upstream LuaExportStop function" .. tostring(err)) end end -- runs once when the mission is stopped LoRemoveSharedTexture(textureName) end function LuaExportStart() if upstreamLuaExportStart ~= nil then successful, err = pcall(upstreamLuaExportStart) if not successful then log.write(LOG_MODNAME, log.ERROR, "Error in upstream LuaExportStart function" .. tostring(err)) end end -- runs once when the mission is started LoSetSharedTexture(textureName) end function LuaExportBeforeNextFrame() if upstreamLuaExportBeforeNextFrame ~= nil then successful, err = pcall(upstreamLuaExportBeforeNextFrame) if not successful then log.write(LOG_MODNAME, log.ERROR, "Error in upstream LuaExportBeforeNextFrame function" .. tostring(err)) end end -- executed before the frame is rendered. -- put stuff into the frame here end function LuaExportAfterNextFrame() if upstreamLuaExportAfterNextFrame ~= nil then successful, err = pcall(upstreamLuaExportAfterNextFrame) if not successful then log.write(LOG_MODNAME, log.ERROR, "Error in upstream LuaExportAfterNextFrame function" .. tostring(err)) end end -- runs after a frame was rendered -- fetch data from the game here LoUpdateSharedTexture(textureName) end log.write(LOG_MODNAME, log.INFO, "Done") And I'm trying to read the texture using this C# code using System.IO.MemoryMappedFiles; using System.Runtime.InteropServices; namespace MFDExportTest { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void pictureBox1_Click(object sender, EventArgs e) { using (var mmf = MemoryMappedFile.OpenExisting("mfd0")) { var bitmapHeaderAccessor = mmf.CreateViewAccessor(0, 14); BitmapHeader header; bitmapHeaderAccessor.Read<BitmapHeader>(0, out header); // Bitmap bm = Bitmap.FromStream(); label1.Text = BitmapHeader.ToString(header); } } } [StructLayout(LayoutKind.Explicit)] struct BitmapHeader { [FieldOffset(0)] char Signature1; [FieldOffset(1)] char Signature2; [FieldOffset(2)] UInt32 FileSize; [FieldOffset(6)] UInt32 Reserved; [FieldOffset(10)] UInt32 PixelDataOffset; [FieldOffset(14)] UInt32 HeaderSize; [FieldOffset(18)] UInt32 ImageWidth; [FieldOffset(22)] UInt32 ImageHeight; [FieldOffset(26)] UInt16 Planes; [FieldOffset(28)] UInt16 BPP; [FieldOffset(30)] UInt32 Compression; [FieldOffset(34)] UInt32 ImageSize; [FieldOffset(38)] UInt32 XResolutionPxPerMeter; [FieldOffset(42)] UInt32 YResolutionPxPerMeter; [FieldOffset(46)] UInt32 ColorsInColorTable; [FieldOffset(50)] UInt32 ImportantColorCount; public static string ToString(BitmapHeader header) { return string.Format("Sig: \"{0}\"\n" + "FileSize: {1}\n" + "Pixel Data Offset: {2}\n" + "Header Size: {3}\n" + "Image Dims: {4} x {5}\n" + "Number of Planes: {6}\n", "BPP: {7}\n" + "Compression: {8}\n", "Image Size: {9}\n" + "Image Resolution [px/m]: {10} | {11}\n" + "Color Table: {12} [{13}]", header.Signature1 + header.Signature2, header.FileSize, header.PixelDataOffset, header.HeaderSize, header.ImageWidth, header.ImageHeight, header.Planes, header.BPP, header.Compression, header.ImageSize, header.XResolutionPxPerMeter, header.YResolutionPxPerMeter, header.ColorsInColorTable, header.ImportantColorCount ); } } } But an exception gets thrown when trying to open the memory mapped file with Quote System.IO.FileNotFoundException: 'Unable to find the specified file.' What am I doing wrong? How can I read the screen content? If there were some way to export the text from the A10 CDU screen that would also be really good. If there is another way to find out if the hornet has an option boxed on the MFD other than analyzing pixels, that would be amazing Edited September 13, 2023 by FalcoGer 1
Ozone42 Posted March 30, 2024 Posted March 30, 2024 I may be wrong, but my understanding is that these functions are deprecated and don’t work anymore. I have also tried to get it working and asked about it in the past.
Recommended Posts