Added ability to define multiple functions (without parameters) and
[zilutils.git] / zilasm / compiler.cpp
1 /*
2 * parser.c -- part of ZilUtils/ZilAsm
3 *
4 * Copyright (C) 2020 Jason Self <j@jxself.org>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as
8 * published by the Free Software Foundation, either version 3 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program.  If not, see <http://www.gnu.org/licenses/>
18 *
19 * SPDX-License-Identifier: AGPL-3.0-or-later
20 */
21
22 #include "include_all.h"
23
24 CCompiler::CCompiler() :m_output_file(NULL)
25 {
26 }
27
28 int
29 CCompiler::assembly()
30 {
31         FILE *file = fopen(m_output_file, "wb");
32         if (file)
33         {
34                 program_header_reset(6);
35                 int size = sizeof(program_header);
36
37                 program_header.mode = 0;
38                 program_header.release = 1;     // game version
39
40                 m_code_size = 0;
41                 ZMemblock *zmem_code = zmem_init(65536);
42
43                 unsigned current_address = 64;
44
45                 if (parser.m_functions.size() > 0)
46                 {
47                         //unsigned function_table_size = parser.m_functions.size() * 2;
48                         program_header.H_FUNCTIONS_OFFSET = current_address >> 3;
49                         //current_address += function_table_size;
50                 }
51                 else
52                         program_header.H_FUNCTIONS_OFFSET = 0;
53
54                 int code_start_offset = current_address;
55
56                 if (parser.m_start_function_name == "")
57                         program_header.startPC = code_start_offset >> 2;
58                 else
59                         program_header.startPC = parser.m_functions.find(parser.m_start_function_name)->second.address >> 2;
60
61                 // write instructions' codes
62                 m_code_size = parser.output_codes(zmem_code);
63
64                 if (m_code_size & 7)
65                 {
66                         const int additional_mem = 8 - (m_code_size & 7);
67                         for (int i = 0; i < additional_mem; ++i)
68                                 zmem_putbyte(zmem_code, 0);
69                         m_code_size += additional_mem;
70                 }
71
72                 program_header.dynamic_size = 8;
73
74                 //Program_header.h_file_size = 33;  //sizeof(Program_header) + zmb->used_size;
75
76                 //m_code_size = 8;
77
78                 Word stringTableOffset = m_code_size;
79                 program_header.H_STRINGS_OFFSET = (64 + stringTableOffset) >> 3;
80
81                 int stringTableSize = 64;
82                 program_header.h_file_size =
83                         (code_start_offset + m_code_size + stringTableSize) >> 3;
84                 ZMemblock *zmb = zmem_init(program_header.h_file_size * 8);
85
86                 for (int i = 0; i < m_code_size; ++i)
87                         zmem_putbyte(zmb, zmem_code->contents[i]);
88
89                 zmem_destroy(zmem_code);
90
91                 //zmem_putbyte(zmb, 0); // number of local variables
92                 //zmem_putbyte(zmb, 141); // print addr command
93
94                 //Word offset = 0;
95                 //zmem_putbyte(zmb, (offset >> 8) & 255);
96                 //zmem_putbyte(zmb, offset & 255);
97
98                 //zmem_putbyte(zmb, 186); // quit command
99
100                 // output zeros until string table begins
101                 while (zmb->used_size < stringTableOffset)
102                         zmem_putbyte(zmb, 0);
103                 //
104                 //// fill string table with one string
105                 //add_string_to_string_table("Hello, World!", zmb);
106
107                 outputToFile(&program_header, file);
108                 //output_function_table(file);
109
110                 fwrite(zmb->contents, zmb->allocated_size, 1, file);
111                 fclose(file);
112         }
113
114         return OK;
115 }
116
117
118 char *
119 CCompiler::get_output_file_name()
120 {
121         return m_output_file;
122 }
123
124
125 void 
126 CCompiler::output_function_table(FILE *file)
127 {
128         if (parser.m_functions.size())
129         {
130                 for(map<string, Function>::iterator iter = parser.m_functions.begin(); iter != parser.m_functions.end(); ++iter)
131                 {
132                         Word w = (iter->second.address) >> 4;
133                         fprintf ( file, "%c", (w >> 8) & 255);
134                         fprintf(file, "%c", w & 255);
135                 }
136
137         }
138 }