mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-10-02 20:08:03 +03:00
Initial CALLHLL and Math.dll implementation
HLL libraries are compiled into the executable rather than dynamically loaded as in early versions of System 4. These days AliceSoft does the same thing.
This commit is contained in:
@@ -448,8 +448,8 @@ static bool read_tag(struct ain_reader *r, struct ain *ain)
|
||||
} else if (TAG_EQ("MSGF")) {
|
||||
ain->msgf = read_int32(r);
|
||||
} else if (TAG_EQ("HLL0")) {
|
||||
int32_t count = read_int32(r);
|
||||
ain->libraries = read_libraries(r, count);
|
||||
ain->nr_libraries = read_int32(r);
|
||||
ain->libraries = read_libraries(r, ain->nr_libraries);
|
||||
} else if (TAG_EQ("SWI0")) {
|
||||
int32_t count = read_int32(r);
|
||||
ain->switches = read_switches(r, count);
|
||||
|
||||
@@ -149,6 +149,7 @@ struct ain_hll_argument {
|
||||
|
||||
struct ain_hll_function {
|
||||
char *name;
|
||||
void (*fun)(void);
|
||||
int32_t data_type;
|
||||
int32_t nr_arguments;
|
||||
struct ain_hll_argument *arguments;
|
||||
@@ -188,14 +189,15 @@ struct ain {
|
||||
uint8_t *code;
|
||||
size_t code_size;
|
||||
struct ain_function *functions;
|
||||
struct ain_global *globals;
|
||||
int32_t nr_globals;
|
||||
struct ain_initval *global_initvals;
|
||||
struct ain_global *globals;
|
||||
int32_t nr_initvals;
|
||||
struct ain_initval *global_initvals;
|
||||
struct ain_struct *structures;
|
||||
struct string **messages;
|
||||
int32_t main;
|
||||
int32_t msgf;
|
||||
int32_t nr_libraries;
|
||||
struct ain_library *libraries;
|
||||
struct ain_switch *switches;
|
||||
int32_t game_version;
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/* Copyright (C) 2019 Nunuhara Cabbage <nunuhara@haniwa.technology>
|
||||
*
|
||||
* Credit to SLC for reverse engineering AIN formats.
|
||||
*
|
||||
* This program 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 2 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SYSTEM4_HLL_H
|
||||
#define SYSTEM4_HLL_H
|
||||
|
||||
/*
|
||||
* DSL for implementing for implementing libraries.
|
||||
*/
|
||||
|
||||
#include "../vm.h"
|
||||
#include "../page.h"
|
||||
|
||||
#define hll_defun(fname) \
|
||||
static void _hllfun_ ## fname(void); \
|
||||
static struct hll_function _hllstruct_ ## fname = { \
|
||||
.name = #fname, \
|
||||
.fun = _hllfun_ ## fname \
|
||||
}; \
|
||||
static void _hllfun_ ## fname(void)
|
||||
|
||||
#define hll_unimplemented(fname) \
|
||||
hll_defun(fname) { \
|
||||
ERROR("Unimplemented HLL function: " #fname); \
|
||||
}
|
||||
|
||||
#define hll_export(fname) &_hllstruct_ ## fname
|
||||
|
||||
#define hll_deflib(lname, ...) \
|
||||
static struct hll_function *_lib_ ## lname[]; \
|
||||
struct library lib_ ## lname = { \
|
||||
.name = #lname, \
|
||||
.functions = _lib_ ## lname \
|
||||
}; \
|
||||
static struct hll_function *_lib_ ## lname[] =
|
||||
|
||||
#define hll_return(v) stack_push(vm_value_cast(v))
|
||||
|
||||
static inline union vm_value hll_arg(int n)
|
||||
{
|
||||
return stack[stack_ptr + n];
|
||||
}
|
||||
|
||||
#endif /* SYSTEM4_HLL_H */
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
/* Copyright (C) 2019 Nunuhara Cabbage <nunuhara@haniwa.technology>
|
||||
*
|
||||
* Credit to SLC for reverse engineering AIN formats.
|
||||
*
|
||||
* This program 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 2 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "../system4.h"
|
||||
#include "hll.h"
|
||||
|
||||
static inline float deg2rad(float deg)
|
||||
{
|
||||
return deg * (M_PI / 180.0);
|
||||
}
|
||||
|
||||
hll_defun(Cos) {
|
||||
hll_return(cosf(deg2rad(hll_arg(0).f)));
|
||||
}
|
||||
|
||||
hll_defun(Sin) {
|
||||
hll_return(sinf(deg2rad(hll_arg(0).f)));
|
||||
}
|
||||
|
||||
hll_defun(Sqrt) {
|
||||
hll_return(sqrtf(hll_arg(0).f));
|
||||
}
|
||||
|
||||
hll_defun(Atan) {
|
||||
hll_return(atanf(hll_arg(0).f));
|
||||
}
|
||||
|
||||
hll_defun(Atan2) {
|
||||
hll_return(atan2f(hll_arg(0).f, hll_arg(1).f));
|
||||
}
|
||||
|
||||
hll_defun(Abs) {
|
||||
hll_return(abs(hll_arg(0).i));
|
||||
}
|
||||
|
||||
hll_defun(AbsF) {
|
||||
hll_return(fabsf(hll_arg(0).f));
|
||||
}
|
||||
|
||||
hll_defun(Pow) {
|
||||
hll_return(powf(hll_arg(0).f, hll_arg(1).f));
|
||||
}
|
||||
|
||||
hll_defun(SetSeed) {
|
||||
srand(hll_arg(0).i);
|
||||
hll_return(0);
|
||||
}
|
||||
|
||||
hll_unimplemented(SetRandMode)
|
||||
|
||||
hll_defun(Rand) {
|
||||
hll_return(rand());
|
||||
}
|
||||
|
||||
// TODO
|
||||
hll_unimplemented(RandF)
|
||||
hll_unimplemented(RandTableInit)
|
||||
hll_unimplemented(RandTable)
|
||||
hll_unimplemented(RandTable2Init)
|
||||
hll_unimplemented(RandTable2)
|
||||
|
||||
hll_defun(Min) {
|
||||
int a = hll_arg(0).i, b = hll_arg(1).i;
|
||||
hll_return(a < b ? a : b);
|
||||
}
|
||||
|
||||
hll_defun(MinF) {
|
||||
float a = hll_arg(0).f, b = hll_arg(1).f;
|
||||
hll_return(a < b ? a : b);
|
||||
}
|
||||
|
||||
hll_defun(Max) {
|
||||
int a = hll_arg(0).i, b = hll_arg(1).i;
|
||||
hll_return(a > b ? a : b);
|
||||
}
|
||||
|
||||
hll_defun(MaxF) {
|
||||
float a = hll_arg(0).f, b = hll_arg(1).f;
|
||||
hll_return(a > b ? a : b);
|
||||
}
|
||||
|
||||
hll_defun(Swap) {
|
||||
int tmp = *hll_arg(0).iref;
|
||||
*hll_arg(0).iref = *hll_arg(1).iref;
|
||||
*hll_arg(1).iref = tmp;
|
||||
}
|
||||
|
||||
hll_defun(SwapF) {
|
||||
float tmp = *hll_arg(0).fref;
|
||||
*hll_arg(0).fref = *hll_arg(1).fref;
|
||||
*hll_arg(1).fref = tmp;
|
||||
}
|
||||
|
||||
hll_deflib(Math) {
|
||||
hll_export(Cos),
|
||||
hll_export(Sin),
|
||||
hll_export(Sqrt),
|
||||
hll_export(Atan),
|
||||
hll_export(Atan2),
|
||||
hll_export(Abs),
|
||||
hll_export(AbsF),
|
||||
hll_export(Pow),
|
||||
hll_export(SetSeed),
|
||||
hll_export(SetRandMode),
|
||||
hll_export(Rand),
|
||||
hll_export(RandF),
|
||||
hll_export(RandTableInit),
|
||||
hll_export(RandTable),
|
||||
hll_export(RandTable2Init),
|
||||
hll_export(RandTable2),
|
||||
hll_export(Min),
|
||||
hll_export(MinF),
|
||||
hll_export(Max),
|
||||
hll_export(MaxF),
|
||||
hll_export(Swap),
|
||||
hll_export(SwapF),
|
||||
NULL
|
||||
};
|
||||
+1
-1
@@ -136,7 +136,7 @@ const struct instruction instructions[NR_OPCODES] = {
|
||||
OP(C_REF, 0),
|
||||
OP(C_ASSIGN, 0),
|
||||
OP(MSG, 0), // TODO
|
||||
OP(CALLHLL, 0), // TODO
|
||||
OP(CALLHLL, 2, INSTR_INT, INSTR_INT),
|
||||
OP(PUSHSTRUCTPAGE, 0),
|
||||
JMP(CALLMETHOD, 1, INSTR_FUN),
|
||||
OP(SH_GLOBALREF, 1, INSTR_INT),
|
||||
|
||||
+5
-2
@@ -1,4 +1,7 @@
|
||||
project('system4', 'c', default_options : ['c_std=c11'])
|
||||
system4 = ['system4.c', 'ain.c', 'instructions.c', 'vm.c', 'string.c', 'page.c', 'utfsjis.c']
|
||||
system4 = ['system4.c', 'ain.c', 'instructions.c', 'vm.c', 'string.c', 'page.c', 'utfsjis.c', 'hll/math.c']
|
||||
|
||||
zdep = dependency('zlib')
|
||||
executable('system4', system4, dependencies: zdep)
|
||||
mdep = meson.get_compiler('c').find_library('m', required: false)
|
||||
|
||||
executable('system4', system4, dependencies: [mdep, zdep])
|
||||
|
||||
@@ -59,8 +59,19 @@ struct page {
|
||||
union vm_value values[];
|
||||
};
|
||||
|
||||
static inline union vm_value page_get(int pageno, int varno)
|
||||
{
|
||||
return heap[pageno].page->values[varno];
|
||||
}
|
||||
|
||||
static inline void page_set(int pageno, int varno, union vm_value v)
|
||||
{
|
||||
heap[pageno].page->values[varno] = v;
|
||||
}
|
||||
|
||||
// variables
|
||||
union vm_value variable_initval(enum ain_data_type type);
|
||||
void variable_fini(union vm_value v, enum ain_data_type type);
|
||||
enum ain_data_type variable_type(struct page *page, int varno, enum ain_data_type *struct_type);
|
||||
|
||||
// pages
|
||||
|
||||
+2
-1
@@ -1,4 +1,5 @@
|
||||
OBJ/
|
||||
Run/
|
||||
Source/System/Etc/DLL/Math.dll
|
||||
Source/System/System42/System40.exe
|
||||
Source/System/System42/DLL/Sys42VM.dll
|
||||
Source/System/System42/DLL/Sys42VM.dll
|
||||
|
||||
Executable
+12
@@ -0,0 +1,12 @@
|
||||
|
||||
SystemSource = {
|
||||
"HLL\Math.hll", "Math",
|
||||
}
|
||||
|
||||
CopyToRun = {
|
||||
"SACT_DLL.inc",
|
||||
}
|
||||
|
||||
CopyToDLL = {
|
||||
"DLL\Math.dll",
|
||||
}
|
||||
Executable
+50
@@ -0,0 +1,50 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
// Math.hll
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// 数学
|
||||
float Cos(float fDeg); // コサイン(角度)
|
||||
float Sin(float fDeg); // サイン(角度)
|
||||
|
||||
float Sqrt(float fValue); // 平方根
|
||||
|
||||
float Atan(float x); // アークタンジェント
|
||||
float Atan2(float y, float x); // アークタンジェント y/x
|
||||
|
||||
int Abs(int nValue); // 絶対値を得る
|
||||
float AbsF(float fValue); // 絶対値float
|
||||
|
||||
float Pow(float fBase, float fExponent); // fBaseのfExponet乗を返します
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// 乱数
|
||||
void SetSeed(int nSeed); // 乱数の種セット
|
||||
void SetRandMode(int nMode); // 乱数のモードをセット(0:標準(default) 1:正規分布 2:1/f分布)
|
||||
int Rand(void); // 0~0x7FFFFFFFの範囲で乱数生成
|
||||
float RandF(void); // 0~1の範囲で乱数生成
|
||||
|
||||
// テーブルを作成して、その中身をシャッフルすることで
|
||||
// ランダムを取り出す関数、使う前に、SetSeedは必要。
|
||||
void RandTableInit(int nNum, int nSize); // nSize個のランダムテーブルを作成、0~nSize-1 までの数値が入る
|
||||
int RandTable(int nNum); // テーブルの数値を取得 nNumはテーブル番号
|
||||
|
||||
// ランダムテーブル、VM内の配列を使う版 ※配列の要素数が、そのままテーブルの大きさになります。
|
||||
// pArrayはテーブル配列を指定(Allocはスクリプトで確保すること)
|
||||
void RandTable2Init(int nNum, array@int pArray);
|
||||
|
||||
// テーブルの数値を取得 nNumはテーブル番号
|
||||
int RandTable2(int nNum);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// その他
|
||||
int Min(int x, int y);
|
||||
float MinF(float x, float y);
|
||||
int Max(int x, int y);
|
||||
float MaxF(float x, float y);
|
||||
|
||||
void Swap(intp x, intp y); // 入れ替え
|
||||
void SwapF(floatp x, floatp y);
|
||||
|
||||
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
LoadDLL = {
|
||||
"Math.dll",
|
||||
}
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
Note
|
||||
----
|
||||
|
||||
I am not 100% sure about the legality of distributing System40.exe and related
|
||||
DLLs here, so I've left them out. They can be found in the System 4 SDK, which
|
||||
which you'll want to have anyways to compile these tests.
|
||||
|
||||
Once you've copied the files, this directory should contain the following:
|
||||
|
||||
Etc/DLL/Math.dll (not included)
|
||||
Etc/HLL/Math.hll
|
||||
Etc/Etc.inc
|
||||
Etc/SACT_DLL.inc
|
||||
System42/DLL/Sys42VM.dll (not included)
|
||||
System42/System40.exe (not included)
|
||||
System42/System40.ini
|
||||
System42/System42.inc
|
||||
System.inc
|
||||
@@ -1,3 +1,4 @@
|
||||
Source = {
|
||||
"System42\System42.inc",
|
||||
"Etc\Etc.inc",
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
Note
|
||||
----
|
||||
|
||||
I am not 100% sure about the legality of distributing System40.exe and
|
||||
Sys42VM.dll here, so I've left them out. They can be found in the System 4 SDK,
|
||||
which you'll want to have anyways to compile these tests.
|
||||
|
||||
Once you've copied the files, this directory should contain the following:
|
||||
|
||||
System40.exe
|
||||
System40.ini
|
||||
DLL\Sys42VM.dll
|
||||
@@ -26,6 +26,11 @@ SaveFolder = "SaveData"
|
||||
; DLLフォルダ設定
|
||||
DLL = "DLL"
|
||||
|
||||
; DLLファイル設定
|
||||
LoadDLL = {
|
||||
"SACT_DLL.inc",
|
||||
}
|
||||
|
||||
; スキップ名設定
|
||||
MsgSkipName = "既読スキップ"
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
CopyToRun = {
|
||||
"System40.exe",
|
||||
"System40.ini"
|
||||
"System40.ini",
|
||||
}
|
||||
|
||||
CopyToDLL = {
|
||||
|
||||
@@ -31,6 +31,17 @@ void test_equal(string msg, int actual, int expected)
|
||||
}
|
||||
}
|
||||
|
||||
void test_float(string msg, float actual, float expected)
|
||||
{
|
||||
float d = actual - expected;
|
||||
if (d > 0.001 || d < -0.001) {
|
||||
system.Output("FAIL: " + msg + " (expected " + string(expected) + "; got " + string(actual) + ")\n");
|
||||
tests_failed++;
|
||||
} else {
|
||||
tests_passed++;
|
||||
}
|
||||
}
|
||||
|
||||
void test_bool(string msg, bool actual, bool expected)
|
||||
{
|
||||
if (actual != expected) {
|
||||
@@ -73,6 +84,10 @@ int main(void)
|
||||
test_arrays();
|
||||
test_end("arrays");
|
||||
|
||||
test_start("Math.dll");
|
||||
test_math();
|
||||
test_end("Math.dll");
|
||||
|
||||
if (total_failed > 0) {
|
||||
system.Output(string(total_failed) + " tests failed.\n");
|
||||
} else {
|
||||
|
||||
Executable
+32
@@ -0,0 +1,32 @@
|
||||
// -*-mode: C; coding: sjis; -*-
|
||||
|
||||
void test_math(void)
|
||||
{
|
||||
int ia, ib;
|
||||
float fa, fb;
|
||||
test_float("Math.Cos(40)", Math.Cos(40), 0.766044);
|
||||
test_float("Math.Sin(40)", Math.Sin(40), 0.642788);
|
||||
test_float("Math.Atan(40)", Math.Atan(40), 1.545802);
|
||||
test_float("Math.Atan2(20, 40)", Math.Atan2(20, 40), 0.463648);
|
||||
test_float("Math.Pow(0.5, 1.5)", Math.Pow(0.5, 1.5), 0.353553);
|
||||
test_equal("Math.Abs(-3)", Math.Abs(-3), 3);
|
||||
test_float("Math.AbsF(-3.5)", Math.Abs(-3.5), 3.0); // XXX: why not 3.5?
|
||||
test_equal("Math.Min(1, 2)", Math.Min(1, 2), 1);
|
||||
test_equal("Math.Min(2, 1)", Math.Min(2, 1), 1);
|
||||
test_float("Math.MinF(1.0, 2.0)", Math.MinF(1.0, 2.0), 1.0);
|
||||
test_float("Math.MinF(2.0, 1.0)", Math.MinF(2.0, 1.0), 1.0);
|
||||
test_equal("Math.Max(1, 2)", Math.Max(1, 2), 2);
|
||||
test_equal("Math.Max(2, 1)", Math.Max(2, 1), 2);
|
||||
test_float("Math.MaxF(1.0, 2.0)", Math.MaxF(1.0, 2.0), 2.0);
|
||||
test_float("Math.MaxF(2.0, 1.0)", Math.MaxF(2.0, 1.0), 2.0);
|
||||
|
||||
ia = 1, ib = 2;
|
||||
Math.Swap(ia, ib);
|
||||
test_equal("Math.Swap(a, b), a", ia, 2);
|
||||
test_equal("Math.Swap(a, b), b", ib, 1);
|
||||
|
||||
fa = 1.0, fb = 2.0;
|
||||
Math.SwapF(fa, fb);
|
||||
test_float("Math.SwapF(a, b), a", fa, 2.0);
|
||||
test_float("Math.SwapF(a, b), b", fb, 1.0);
|
||||
}
|
||||
@@ -4,6 +4,7 @@ Source = {
|
||||
"arithmetic.jaf",
|
||||
"strings.jaf",
|
||||
"structs.jaf",
|
||||
"arrays.jaf"
|
||||
"arrays.jaf",
|
||||
"math.jaf"
|
||||
}
|
||||
|
||||
|
||||
@@ -305,6 +305,49 @@ void vm_call(int fno, int struct_page)
|
||||
instr_ptr = saved_ip;
|
||||
}
|
||||
|
||||
static void hll_call(int libno, int fno)
|
||||
{
|
||||
struct ain_hll_function *f = &ain->libraries[libno].functions[fno];
|
||||
if (!f->fun)
|
||||
EXECUTION_ERROR("Unimplemented HLL function: %s", f->name);
|
||||
|
||||
// convert non-heap ref types to pointers
|
||||
for (int i = f->nr_arguments - 1; i >= 0; i--) {
|
||||
switch(f->arguments[i].data_type) {
|
||||
case AIN_REF_INT:
|
||||
case AIN_REF_BOOL:
|
||||
case AIN_REF_FLOAT:
|
||||
stack_ptr -= 2;
|
||||
break;
|
||||
default:
|
||||
stack_ptr--;
|
||||
}
|
||||
}
|
||||
for (int i = 0, src = 0; i < f->nr_arguments; i++, src++) {
|
||||
int pageno, varno;
|
||||
switch (f->arguments[i].data_type) {
|
||||
case AIN_REF_INT:
|
||||
case AIN_REF_BOOL:
|
||||
pageno = stack[stack_ptr+src].i;
|
||||
varno = stack[stack_ptr+src+1].i;
|
||||
stack[stack_ptr+i].iref = &heap[pageno].page->values[varno].i;
|
||||
src++;
|
||||
break;
|
||||
case AIN_REF_FLOAT:
|
||||
pageno = stack[stack_ptr+src].i;
|
||||
varno = stack[stack_ptr+src+1].i;
|
||||
stack[stack_ptr+i].fref = &heap[pageno].page->values[varno].f;
|
||||
src++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
f->fun();
|
||||
for (int i = 0; i < f->nr_arguments; i++) {
|
||||
variable_fini(stack[stack_ptr + i], f->arguments[i].data_type);
|
||||
}
|
||||
}
|
||||
|
||||
static void function_return(void)
|
||||
{
|
||||
call_stack_ptr--;
|
||||
@@ -522,6 +565,9 @@ static void execute_instruction(int16_t opcode)
|
||||
case CALLMETHOD:
|
||||
method_call(get_argument(0), instr_ptr + instruction_width(CALLMETHOD));
|
||||
break;
|
||||
case CALLHLL:
|
||||
hll_call(get_argument(0), get_argument(1));
|
||||
break;
|
||||
case RETURN:
|
||||
function_return();
|
||||
break;
|
||||
@@ -1028,6 +1074,44 @@ static void vm_execute(void)
|
||||
}
|
||||
}
|
||||
|
||||
extern struct library lib_Math;
|
||||
|
||||
struct library *libraries[] = {
|
||||
&lib_Math,
|
||||
NULL
|
||||
};
|
||||
|
||||
static void link_library(struct ain_library *ainlib, struct library *lib)
|
||||
{
|
||||
for (int i = 0; i < ainlib->nr_functions; i++) {
|
||||
bool linked = false;
|
||||
for (int j = 0; lib->functions[j]; j++) {
|
||||
if (!strcmp(ainlib->functions[i].name, lib->functions[j]->name)) {
|
||||
ainlib->functions[i].fun = lib->functions[j]->fun;
|
||||
linked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!linked)
|
||||
WARNING("Unimplemented library function: %s", ainlib->functions[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
static void link_libraries(void)
|
||||
{
|
||||
for (int i = 0; i < ain->nr_libraries; i++) {
|
||||
bool linked = false;
|
||||
for (int j = 0; libraries[j]; j++) {
|
||||
if (!strcmp(ain->libraries[i].name, libraries[j]->name)) {
|
||||
link_library(&ain->libraries[i], libraries[j]);
|
||||
linked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!linked)
|
||||
WARNING("Unimplemented library: %s", ain->libraries[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
void vm_execute_ain(struct ain *program)
|
||||
{
|
||||
@@ -1077,6 +1161,7 @@ void vm_execute_ain(struct ain *program)
|
||||
}
|
||||
}
|
||||
|
||||
link_libraries();
|
||||
vm_call(ain->main, -1);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,9 @@ union vm_value {
|
||||
int32_t i;
|
||||
int64_t i64;
|
||||
float f;
|
||||
// HLL only
|
||||
int *iref;
|
||||
float *fref;
|
||||
};
|
||||
|
||||
enum vm_pointer_type {
|
||||
@@ -48,6 +51,16 @@ struct vm_pointer {
|
||||
};
|
||||
};
|
||||
|
||||
struct hll_function {
|
||||
char *name;
|
||||
void (*fun)(void);
|
||||
};
|
||||
|
||||
struct library {
|
||||
char *name;
|
||||
struct hll_function **functions;
|
||||
};
|
||||
|
||||
struct ain;
|
||||
|
||||
struct vm_pointer *heap;
|
||||
|
||||
Reference in New Issue
Block a user