+/*
+* parser.c -- part of ZilUtils/ZilAsm
+*
+* Copyright (C) 2020 Jason Self <j@jxself.org>
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License as
+* published by the Free Software Foundation, either version 3 of the
+* License, or (at your option) any later version.
+*
+* This program 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 Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>
+*
+* SPDX-License-Identifier: AGPL-3.0-or-later
+*/
+
+#include "include_all.h"
+
+CCompiler::CCompiler() :m_output_file(NULL)
+{
+}
+
+int
+CCompiler::assembly()
+{
+ FILE *file = fopen(m_output_file, "wb");
+ if (file)
+ {
+ program_header_reset(6);
+ int size = sizeof(program_header);
+
+ program_header.mode = 0;
+ program_header.release = 1; // game version
+
+ m_code_size = 0;
+ ZMemblock *zmem_code = zmem_init(65536);
+
+ unsigned current_address = 64;
+
+ if (parser.m_functions.size() > 0)
+ {
+ //unsigned function_table_size = parser.m_functions.size() * 2;
+ program_header.H_FUNCTIONS_OFFSET = current_address >> 3;
+ //current_address += function_table_size;
+ }
+ else
+ program_header.H_FUNCTIONS_OFFSET = 0;
+
+ int code_start_offset = current_address;
+
+ if (parser.m_start_function_name == "")
+ program_header.startPC = code_start_offset >> 2;
+ else
+ program_header.startPC = parser.m_functions.find(parser.m_start_function_name)->second.address >> 2;
+
+ // write instructions' codes
+ m_code_size = parser.output_codes(zmem_code);
+
+ if (m_code_size & 7)
+ {
+ const int additional_mem = 8 - (m_code_size & 7);
+ for (int i = 0; i < additional_mem; ++i)
+ zmem_putbyte(zmem_code, 0);
+ m_code_size += additional_mem;
+ }
+
+ program_header.dynamic_size = 8;
+
+ //Program_header.h_file_size = 33; //sizeof(Program_header) + zmb->used_size;
+
+ //m_code_size = 8;
+
+ Word stringTableOffset = m_code_size;
+ program_header.H_STRINGS_OFFSET = (64 + stringTableOffset) >> 3;
+
+ int stringTableSize = 64;
+ program_header.h_file_size =
+ (code_start_offset + m_code_size + stringTableSize) >> 3;
+ ZMemblock *zmb = zmem_init(program_header.h_file_size * 8);
+
+ for (int i = 0; i < m_code_size; ++i)
+ zmem_putbyte(zmb, zmem_code->contents[i]);
+
+ zmem_destroy(zmem_code);
+
+ //zmem_putbyte(zmb, 0); // number of local variables
+ //zmem_putbyte(zmb, 141); // print addr command
+
+ //Word offset = 0;
+ //zmem_putbyte(zmb, (offset >> 8) & 255);
+ //zmem_putbyte(zmb, offset & 255);
+
+ //zmem_putbyte(zmb, 186); // quit command
+
+ // output zeros until string table begins
+ while (zmb->used_size < stringTableOffset)
+ zmem_putbyte(zmb, 0);
+ //
+ //// fill string table with one string
+ //add_string_to_string_table("Hello, World!", zmb);
+
+ outputToFile(&program_header, file);
+ //output_function_table(file);
+
+ fwrite(zmb->contents, zmb->allocated_size, 1, file);
+ fclose(file);
+ }
+
+ return OK;
+}
+
+
+char *
+CCompiler::get_output_file_name()
+{
+ return m_output_file;
+}
+
+
+void
+CCompiler::output_function_table(FILE *file)
+{
+ if (parser.m_functions.size())
+ {
+ for(map<string, Function>::iterator iter = parser.m_functions.begin(); iter != parser.m_functions.end(); ++iter)
+ {
+ Word w = (iter->second.address) >> 4;
+ fprintf ( file, "%c", (w >> 8) & 255);
+ fprintf(file, "%c", w & 255);
+ }
+
+ }
+}
\ No newline at end of file