mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-10-07 14:28:12 +03:00
strings: store size together with text in memory
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
#include "ain.h"
|
||||
#include "little_endian.h"
|
||||
#include "instructions.h"
|
||||
#include "vm_string.h"
|
||||
|
||||
static const char *errtab[AIN_MAX_ERROR] = {
|
||||
[AIN_SUCCESS] = "Success",
|
||||
@@ -86,6 +87,24 @@ static char **read_strings(struct ain_reader *r, int count)
|
||||
return strings;
|
||||
}
|
||||
|
||||
static struct string *read_vm_string(struct ain_reader *r)
|
||||
{
|
||||
size_t len = strlen((char*)r->buf + r->index);
|
||||
struct string *s = make_string((char*)r->buf + r->index, len);
|
||||
s->literal = true;
|
||||
r->index += len + 1;
|
||||
return s;
|
||||
}
|
||||
|
||||
static struct string **read_vm_strings(struct ain_reader *r, int count)
|
||||
{
|
||||
struct string **strings = calloc(count, sizeof(struct string*));
|
||||
for (int i = 0; i < count; i++) {
|
||||
strings[i] = read_vm_string(r);
|
||||
}
|
||||
return strings;
|
||||
}
|
||||
|
||||
static struct ain_variable *read_variables(struct ain_reader *r, int count)
|
||||
{
|
||||
struct ain_variable *variables = calloc(count, sizeof(struct ain_variable));
|
||||
@@ -260,7 +279,7 @@ static bool read_tag(struct ain_reader *r, struct ain *ain)
|
||||
int32_t count = read_int32(r);
|
||||
ain->structures = read_structures(r, count);
|
||||
} else if (TAG_EQ("MSG0")) {
|
||||
ain->messages = read_strings(r, read_int32(r));
|
||||
ain->messages = read_vm_strings(r, read_int32(r));
|
||||
} else if (TAG_EQ("MAIN")) {
|
||||
ain->main = read_int32(r);
|
||||
} else if (TAG_EQ("MSGF")) {
|
||||
@@ -274,7 +293,7 @@ static bool read_tag(struct ain_reader *r, struct ain *ain)
|
||||
} else if (TAG_EQ("GVER")) {
|
||||
ain->game_version = read_int32(r);
|
||||
} else if (TAG_EQ("STR0")) {
|
||||
ain->strings = read_strings(r, read_int32(r));
|
||||
ain->strings = read_vm_strings(r, read_int32(r));
|
||||
} else if (TAG_EQ("FNAM")) {
|
||||
ain->filenames = read_strings(r, read_int32(r));
|
||||
} else if (TAG_EQ("OJMP")) {
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "vm_string.h"
|
||||
|
||||
struct ain;
|
||||
|
||||
enum ain_error {
|
||||
@@ -160,13 +162,13 @@ struct ain {
|
||||
struct ain_global *globals;
|
||||
struct ain_initval *global_initvals;
|
||||
struct ain_struct *structures;
|
||||
char **messages;
|
||||
struct string **messages;
|
||||
int32_t main;
|
||||
int32_t msgf;
|
||||
struct ain_library *libraries;
|
||||
struct ain_switch *switches;
|
||||
int32_t game_version;
|
||||
char **strings;
|
||||
struct string **strings;
|
||||
char **filenames;
|
||||
int32_t ojmp;
|
||||
struct ain_function_type *function_types;
|
||||
|
||||
@@ -18,45 +18,42 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "system4.h"
|
||||
#include "sys4_string.h"
|
||||
#include "vm_string.h"
|
||||
|
||||
struct string make_string(char *str, size_t len)
|
||||
struct string *make_string(const char *str, unsigned int len)
|
||||
{
|
||||
return (struct string) {
|
||||
.str = str,
|
||||
.len = len,
|
||||
.mutable = false
|
||||
};
|
||||
struct string *s = xmalloc(sizeof(struct string) + len + 1);
|
||||
s->size = len;
|
||||
s->literal = false;
|
||||
memcpy(s->text, str, len);
|
||||
s->text[len] = '\0';
|
||||
return s;
|
||||
}
|
||||
|
||||
void free_string(struct string *str)
|
||||
{
|
||||
if (str->mutable)
|
||||
free(str->str);
|
||||
if (!str->literal)
|
||||
free(str);
|
||||
}
|
||||
|
||||
void string_add(struct string *a, struct string *b)
|
||||
struct string *string_append(struct string *a, struct string *b)
|
||||
{
|
||||
if (a->mutable) {
|
||||
a->str = xrealloc(a->str, a->len + b->len + 1);
|
||||
if (!a->literal) {
|
||||
a = xrealloc(a, sizeof(struct string) + a->size + b->size + 1);
|
||||
} else {
|
||||
char *literal = a->str;
|
||||
a->str = xmalloc(a->len + b->len + 1);
|
||||
memcpy(a->str, literal, a->len + 1);
|
||||
struct string *tmp = xmalloc(sizeof(struct string) + a->size + b->size + 1);
|
||||
memcpy(tmp, a, sizeof(struct string) + a->size);
|
||||
a = tmp;
|
||||
}
|
||||
memcpy(a->str + a->len, b->str, b->len + 1);
|
||||
a->len = a->len + b->len;
|
||||
memcpy(a->text + a->size, b->text, b->size + 1);
|
||||
a->size = a->size + b->size;
|
||||
return a;
|
||||
}
|
||||
|
||||
struct string integer_to_string(int n)
|
||||
struct string *integer_to_string(int n)
|
||||
{
|
||||
char buf[513];
|
||||
int len = snprintf(buf, 512, "%d" ,n);
|
||||
buf[512] = '\0';
|
||||
|
||||
return (struct string) {
|
||||
.str = xstrdup(buf),
|
||||
.len = len,
|
||||
.mutable = true
|
||||
};
|
||||
return make_string(buf, len);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "system4.h"
|
||||
#include "sys4_string.h"
|
||||
#include "vm_string.h"
|
||||
#include "ain.h"
|
||||
#include "instructions.h"
|
||||
#include "little_endian.h"
|
||||
@@ -35,7 +35,7 @@ static int stack_ptr = 0;
|
||||
// Separate stack for strings
|
||||
// Not sure exactly how System40.exe handles strings.
|
||||
// Further testing required to ensure this approach doesn't break anything.
|
||||
static struct string string_stack[1024];
|
||||
static struct string *string_stack[1024];
|
||||
static int string_stack_ptr = 0;
|
||||
|
||||
//static struct frame *frame_stack[1024];
|
||||
@@ -93,16 +93,15 @@ static int32_t stack_pop_ref(void)
|
||||
|
||||
static void stack_push_string_literal(int32_t no)
|
||||
{
|
||||
// FIXME: should store string length when reading AIN
|
||||
string_stack[string_stack_ptr++] = make_string(ain->strings[no], strlen(ain->strings[no]));
|
||||
string_stack[string_stack_ptr++] = ain->strings[no];
|
||||
}
|
||||
|
||||
static void stack_push_string(struct string *str)
|
||||
{
|
||||
string_stack[string_stack_ptr++] = *str;
|
||||
string_stack[string_stack_ptr++] = str;
|
||||
}
|
||||
|
||||
static struct string stack_pop_string(void)
|
||||
static struct string *stack_pop_string(void)
|
||||
{
|
||||
string_stack_ptr--;
|
||||
return string_stack[string_stack_ptr];
|
||||
@@ -111,12 +110,12 @@ static struct string stack_pop_string(void)
|
||||
static void stack_toss_string(void)
|
||||
{
|
||||
string_stack_ptr--;
|
||||
free_string(&string_stack[string_stack_ptr]);
|
||||
free_string(string_stack[string_stack_ptr]);
|
||||
}
|
||||
|
||||
static struct string *stack_peek_string(void)
|
||||
{
|
||||
return &string_stack[string_stack_ptr-1];
|
||||
return string_stack[string_stack_ptr-1];
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -158,7 +157,7 @@ static void system_call(int32_t code)
|
||||
sys_exit(stack_pop());
|
||||
break;
|
||||
case 0x6: // system.Output(string szText)
|
||||
sys_message("%s", stack_peek_string()->str);
|
||||
sys_message("%s", stack_peek_string()->text);
|
||||
// XXX: caller S_POPs
|
||||
break;
|
||||
case 0x14: // system.Peek()
|
||||
@@ -174,7 +173,7 @@ static void system_call(int32_t code)
|
||||
static void execute_instruction(int16_t opcode)
|
||||
{
|
||||
int32_t index, a, b, v;
|
||||
struct string sa, sb;
|
||||
struct string *sa, *sb;
|
||||
const char *opcode_name = "UNKNOWN";
|
||||
switch (opcode) {
|
||||
//
|
||||
@@ -396,12 +395,11 @@ static void execute_instruction(int16_t opcode)
|
||||
case S_ADD:
|
||||
sb = stack_pop_string();
|
||||
sa = stack_pop_string();
|
||||
string_add(&sa, &sb);
|
||||
stack_push_string(&sa);
|
||||
sa = string_append(sa, sb);
|
||||
stack_push_string(sa);
|
||||
break;
|
||||
case I_STRING:
|
||||
sa = integer_to_string(stack_pop());
|
||||
stack_push_string(&sa);
|
||||
stack_push_string(integer_to_string(stack_pop()));
|
||||
break;
|
||||
// -- NOOPs ---
|
||||
case FUNC:
|
||||
|
||||
@@ -21,14 +21,14 @@
|
||||
#include <stddef.h>
|
||||
|
||||
struct string {
|
||||
char *str;
|
||||
size_t len;
|
||||
bool mutable;
|
||||
unsigned int size;
|
||||
bool literal;
|
||||
char text[];
|
||||
};
|
||||
|
||||
struct string make_string(char *str, size_t len);
|
||||
struct string *make_string(const char *str, unsigned int len);
|
||||
void free_string(struct string *str);
|
||||
void string_add(struct string *a, struct string *b);
|
||||
struct string integer_to_string(int n);
|
||||
struct string *string_append(struct string *a, struct string *b);
|
||||
struct string *integer_to_string(int n);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user