diff --git a/mocha-common/compilers/yaml2mcl/Program.py b/mocha-common/compilers/yaml2mcl/Program.py index 683a056..ad3e153 100644 --- a/mocha-common/compilers/yaml2mcl/Program.py +++ b/mocha-common/compilers/yaml2mcl/Program.py @@ -90,7 +90,7 @@ class Yaml2Mcl: exportEntitiesFileName = "entities.cs" print("export entities to file: '" + exportEntitiesFileName + "'") - manager.save_entities_to_file(exportEntitiesFileName) + manager.save_entities_to_file(exportEntitiesFileName, outputFileName) return True diff --git a/mocha-common/compilers/yaml2mcl/mocha/library/manager/MemoryLibraryManager.py b/mocha-common/compilers/yaml2mcl/mocha/library/manager/MemoryLibraryManager.py index b592ffc..6a485e5 100644 --- a/mocha-common/compilers/yaml2mcl/mocha/library/manager/MemoryLibraryManager.py +++ b/mocha-common/compilers/yaml2mcl/mocha/library/manager/MemoryLibraryManager.py @@ -114,79 +114,18 @@ class MemoryLibraryManager (MochaLibraryManager): guids = guid_db.to_list() + + from .sectionfile import SectionFile, Section, GuidSection, InstancesSection, AttributesSection, RelationshipsSection, StringTableSection, ResourcesSection + f = SectionFile("MCX!", 2.0, 15) + f.open(self.filename) - f = open(self.filename, "wb") - f.write("MCX!".encode('utf-8')) + f.sections.append(GuidSection("GUIDTable", guids)) + f.sections.append(InstancesSection("Instances", insts)) + f.sections.append(AttributesSection("Attributes", atts)) + f.sections.append(RelationshipsSection("Relationships", rels)) + f.sections.append(StringTableSection("StringTable", strs_db)) + f.sections.append(ResourcesSection("Resources", rsrc_db)) - # version - import struct - ba = bytearray(struct.pack("f", 2.0)) - f.write(ba) - - section_count = 6 - # section count - f.write(int.to_bytes(section_count, 4, 'little')) - - # sections = [ (offset, length) ] - sections = [ ("GUIDTable", guids, 16), ("Instances", insts, 16), ("Attributes", atts, 12), ("Relationships", rels, 12), ("StringTable", strs_db, None), ("Resources", rsrc_db, None) ] - offset = 12 + (section_count * 32) - - lastLength = 0 - for (name, sect, item_len) in sections: - offset += lastLength - length = 0 - - if item_len is None: - if sect == strs_db: - for itm in sect: - # FIXME: hard code for z-strings - length += len(itm) + 1 - elif sect == rsrc_db: - for itm in sect: - length += len(itm) - else: - length = item_len * len(sect) - - f.write(str(name).ljust(16, '\0').encode("utf-8")) - f.write(int.to_bytes(offset, 4, 'little')) - f.write(int.to_bytes(length, 4, 'little')) - f.write(int.to_bytes(len(sect), 4, 'little')) - f.write(int.to_bytes(0, 4, 'little')) # reserved or padding - - lastLength = length - - # guids - for guid in guids: - f.write(guid.to_bytes()) - - # instances - for (gi, cgi, ckey, ikey) in insts: - f.write(int.to_bytes(cgi, 4, 'little')) - f.write(int.to_bytes(gi, 4, 'little')) - f.write(int.to_bytes(ckey, 4, 'little')) - f.write(int.to_bytes(ikey, 4, 'little')) - - # attributes - for (srci, atti, vali, edate) in atts: - f.write(int.to_bytes(srci, 4, 'little')) - f.write(int.to_bytes(atti, 4, 'little')) - f.write(int.to_bytes(vali, 4, 'little')) - - # relationships - for (srci, reli, tgti, edate) in rels: - f.write(int.to_bytes(srci, 4, 'little')) - f.write(int.to_bytes(reli, 4, 'little')) - f.write(int.to_bytes(tgti, 4, 'little')) - - # string table - for strz in strs_db: - f.write(strz.encode("utf-8")) - f.write(int.to_bytes(0, 1, 'little')) - - # resource table - for rsrc in rsrc_db: - f.write(rsrc) - - f.close() + f.save() print ("processed " + str(len(self.instance_ops)) + " instances, " + str(len(self.attribute_ops)) + " attributes, and " + str(len(self.relationship_ops)) + " relationships") \ No newline at end of file diff --git a/mocha-common/compilers/yaml2mcl/mocha/library/manager/sectionfile/Section.py b/mocha-common/compilers/yaml2mcl/mocha/library/manager/sectionfile/Section.py new file mode 100644 index 0000000..2d503db --- /dev/null +++ b/mocha-common/compilers/yaml2mcl/mocha/library/manager/sectionfile/Section.py @@ -0,0 +1,108 @@ +# Copyright (C) 2024 Michael Becker +# +# This file is part of yaml2mcl. +# +# yaml2mcl is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# yaml2mcl is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with yaml2mcl. If not, see . + +class Section: + + def __init__(self, name : str, data, count : int): + self.name = name + self.data = data + self.count = count + + def get_length(self): + return self.count * len(self.data) + + def write_data(self, f): + pass + +class GuidSection (Section): + def __init__(self, name : str, data : list): + + Section.__init__(self, name, data, 16) + + def write_data(self, f): + for guid in self.data: + f.write(guid.to_bytes()) + +class InstancesSection (Section): + def __init__(self, name : str, data : list): + + Section.__init__(self, name, data, 16) + + def write_data(self, f): + + for (gi, cgi, ckey, ikey) in self.data: + f.write(int.to_bytes(cgi, 4, 'little')) + f.write(int.to_bytes(gi, 4, 'little')) + f.write(int.to_bytes(ckey, 4, 'little')) + f.write(int.to_bytes(ikey, 4, 'little')) + +class AttributesSection (Section): + def __init__(self, name : str, data : list): + + Section.__init__(self, name, data, 12) + + def write_data(self, f): + + for (srci, atti, vali, edate) in self.data: + f.write(int.to_bytes(srci, 4, 'little')) + f.write(int.to_bytes(atti, 4, 'little')) + f.write(int.to_bytes(vali, 4, 'little')) + +class RelationshipsSection (Section): + def __init__(self, name : str, data : list): + + Section.__init__(self, name, data, 12) + + def write_data(self, f): + + for (srci, reli, tgti, edate) in self.data: + f.write(int.to_bytes(srci, 4, 'little')) + f.write(int.to_bytes(reli, 4, 'little')) + f.write(int.to_bytes(tgti, 4, 'little')) + +class StringTableSection (Section): + + def __init__(self, name : str, data : list): + + Section.__init__(self, name, data, 0) + + def get_length(self): + length = 0 + for item in self.data: + length += len(item) + 1 + return length + + def write_data(self, f): + for item in self.data: + f.write(item.encode("utf-8")) + f.write(int.to_bytes(0, 1, 'little')) + +class ResourcesSection (Section): + + def __init__(self, name : str, data : list): + + Section.__init__(self, name, data, 0) + + def get_length(self): + length = 0 + for item in self.data: + length += len(item) + return length + + def write_data(self, f): + for rsrc in self.data: + f.write(rsrc) \ No newline at end of file diff --git a/mocha-common/compilers/yaml2mcl/mocha/library/manager/sectionfile/SectionFile.py b/mocha-common/compilers/yaml2mcl/mocha/library/manager/sectionfile/SectionFile.py new file mode 100644 index 0000000..ff0801a --- /dev/null +++ b/mocha-common/compilers/yaml2mcl/mocha/library/manager/sectionfile/SectionFile.py @@ -0,0 +1,68 @@ +# Copyright (C) 2024 Michael Becker +# +# This file is part of yaml2mcl. +# +# yaml2mcl is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# yaml2mcl is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with yaml2mcl. If not, see . + +from .Section import Section + +class SectionFile: + + def __init__(self, signature : str = None, version : float = 1.0, flags : int = 0): + self.signature = signature + self.sections = [ ] + self.version = version + self.flags = flags + + def add_section(self, section : Section): + self.sections.append(section) + + def open(self, filename : str): + + self.filename = filename + + def save(self): + + f = open(self.filename, 'wb') + + if self.signature is not None: + f.write(self.signature.encode('utf-8')) + + import struct + ba = bytearray(struct.pack("f", self.version)) + f.write(ba) + f.write(int.to_bytes(self.flags, 4, 'little')) + + section_count = len(self.sections) + f.write(int.to_bytes(section_count, 4, 'little')) + + offset = 16 + (section_count * 32) + lastLength = 0 + for sect in self.sections: + offset += lastLength + length = sect.get_length() + + f.write(str(sect.name).ljust(16, '\0').encode("utf-8")) + f.write(int.to_bytes(offset, 4, 'little')) + f.write(int.to_bytes(length, 4, 'little')) + f.write(int.to_bytes(len(sect.data), 4, 'little')) + f.write(int.to_bytes(0, 4, 'little')) # reserved or padding + + lastLength = length + + for sect in self.sections: + sect.write_data(f) + + f.close() + diff --git a/mocha-common/compilers/yaml2mcl/mocha/library/manager/sectionfile/__init__.py b/mocha-common/compilers/yaml2mcl/mocha/library/manager/sectionfile/__init__.py new file mode 100644 index 0000000..c9291d8 --- /dev/null +++ b/mocha-common/compilers/yaml2mcl/mocha/library/manager/sectionfile/__init__.py @@ -0,0 +1,16 @@ +# Copyright 2024 Michael Becker +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from .SectionFile import SectionFile +from .Section import Section, GuidSection, InstancesSection, AttributesSection, RelationshipsSection, StringTableSection, ResourcesSection \ No newline at end of file