Jump to content

Recommended Posts

Posted (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 by FalcoGer
  • Like 1
  • 6 months later...
Posted

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. 

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...