From 9090f266cd6e115be5f60b91e929e1212967d420 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Thu, 2 Jan 2025 08:46:49 -0600 Subject: [PATCH] load class files from Java --- c/class_resolver.c | 7 +- c/execute.c | 1 + c/frame.c | 39 +++++++-- c/frame.h | 8 +- c/hash_table.c | 4 + c/main_dreamcast.c | 14 ++- c/main_hosted.c | 16 +++- c/malloc.c | 5 ++ c/malloc.h | 1 + c/native.c | 37 ++++++++ c/native.h | 2 + class_bytes.py | 24 ++++++ java/misc/Resource.java | 2 +- jvm/internal/Loader.java | 10 +++ p/TestLoader.java | 181 +++++++++++++++++++++++++++++++++++++++ 15 files changed, 330 insertions(+), 21 deletions(-) create mode 100644 class_bytes.py create mode 100644 jvm/internal/Loader.java create mode 100644 p/TestLoader.java diff --git a/c/class_resolver.c b/c/class_resolver.c index 723181d..c617203 100644 --- a/c/class_resolver.c +++ b/c/class_resolver.c @@ -112,6 +112,7 @@ static int32_t class_resolver_create_fields_hash_table(int class_hash_table_leng int fields_hash_table_length = hash_table_next_power_of_two(class_entry->class_file->fields_count * 2); uint32_t fields_hash_table_size = (sizeof (struct hash_table_entry)) * fields_hash_table_length; struct hash_table_entry * fields_hash_table = malloc_class_arena(fields_hash_table_size); + hash_table_init(fields_hash_table_length, fields_hash_table); int static_index = 0; @@ -159,6 +160,8 @@ static void class_resolver_create_methods_hash_table(struct class_entry * class_ int methods_hash_table_length = hash_table_next_power_of_two(class_file->methods_count * 2); uint32_t methods_hash_table_size = (sizeof (struct hash_table_entry)) * methods_hash_table_length; struct hash_table_entry * methods_hash_table = malloc_class_arena(methods_hash_table_size); + hash_table_init(methods_hash_table_length, methods_hash_table); + for (int i = 0; i < class_file->methods_count; i++) { u2 name_index = class_file->methods[i].name_index; struct constant * name_constant = &class_file->constant_pool[name_index - 1]; @@ -215,6 +218,8 @@ struct hash_table_entry * class_resolver_load_from_buffers(const uint8_t ** buff int class_hash_table_length = hash_table_next_power_of_two(hash_table_next_power_of_two(length * 2)); uint32_t class_hash_table_size = (sizeof (struct hash_table_entry)) * class_hash_table_length; struct hash_table_entry * class_hash_table = malloc_class_arena(class_hash_table_size); + hash_table_init(class_hash_table_length, class_hash_table); + uint32_t class_entry_size = (sizeof (struct class_entry)) * length; struct class_entry * class_entry = malloc_class_arena(class_entry_size); @@ -233,7 +238,7 @@ struct hash_table_entry * class_resolver_load_from_buffers(const uint8_t ** buff assert(class_name_constant->tag == CONSTANT_Utf8); debugf("hash table entry for class: "); print_utf8_string(class_name_constant); - debugf("\n"); + debugf(" %p\n", &class_entry[i]); hash_table_add(class_hash_table_length, class_hash_table, diff --git a/c/execute.c b/c/execute.c index 25a7b33..0237dc0 100644 --- a/c/execute.c +++ b/c/execute.c @@ -1274,6 +1274,7 @@ void op_invokevirtual(struct vm * vm, uint32_t index) int32_t * objectref = (int32_t *)operand_stack_peek_u32(vm->current_frame, nargs + 1); assert(objectref != nullptr); struct class_entry * class_entry = (struct class_entry *)objectref[0]; + debugf("class_entry: %p\n", class_entry); struct method_entry method_entry = class_resolver_lookup_method_from_interfacemethodref_index(vm->class_hash_table.length, diff --git a/c/frame.c b/c/frame.c index 7032cc1..1f976c1 100644 --- a/c/frame.c +++ b/c/frame.c @@ -304,7 +304,7 @@ void vm_native_method_call(struct vm * vm, struct class_entry * class_entry, str hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"getResource", method_name_constant->utf8.length); if (getresource) { assert(nargs == 1); - assert(return_type == '['); + assert(return_type == 'I'); uint32_t value = java_misc_resource_getresource_1(args); operand_stack_push_u32(vm->current_frame, value); return; @@ -333,6 +333,30 @@ void vm_native_method_call(struct vm * vm, struct class_entry * class_entry, str } } + int jvm_internal_loader_length = 19; + bool jvm_internal_loader = + class_name_constant->utf8.length == jvm_internal_loader_length && + hash_table_key_equal(class_name_constant->utf8.bytes, (const uint8_t *)"jvm/internal/Loader", class_name_constant->utf8.length); + if (jvm_internal_loader) { + if (method_name_constant->utf8.length == 4) { + if (hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"load", 4)) { + assert(nargs == 1); + assert(return_type == 'V'); + native_jvm_internal_loader_load(args); + return; + } + } + if (method_name_constant->utf8.length == 9) { + if (hash_table_key_equal(method_name_constant->utf8.bytes, (const uint8_t *)"getBuffer", 9)) { + assert(nargs == 0); + assert(return_type == 'I'); + uint32_t value = native_jvm_internal_loader_getbuffer(); + operand_stack_push_u32(vm->current_frame, value); + return; + } + } + } + assert(false); } @@ -533,10 +557,10 @@ void vm_execute(struct vm * vm) } } -void vm_start(int class_hash_table_length, - struct hash_table_entry * class_hash_table, - const uint8_t * main_class_name, - int main_class_name_length) +struct vm * vm_start(int class_hash_table_length, + struct hash_table_entry * class_hash_table, + const uint8_t * main_class_name, + int main_class_name_length) { struct class_entry * class_entry = class_resolver_lookup_class(class_hash_table_length, class_hash_table, @@ -559,7 +583,7 @@ void vm_start(int class_hash_table_length, method_descriptor_length); assert(method_info != nullptr); - struct vm vm; + static struct vm vm; vm.class_hash_table.entry = class_hash_table; vm.class_hash_table.length = class_hash_table_length; @@ -583,5 +607,6 @@ void vm_start(int class_hash_table_length, entry_frame->operand_stack_ix = 0; vm_static_method_call(&vm, class_entry, method_info); - vm_execute(&vm); + + return &vm; } diff --git a/c/frame.h b/c/frame.h index 111090d..89064dd 100644 --- a/c/frame.h +++ b/c/frame.h @@ -160,8 +160,8 @@ void vm_special_method_call(struct vm * vm, struct class_entry * class_entry, st void vm_static_method_call(struct vm * vm, struct class_entry * class_entry, struct method_info * method_info); void vm_method_return(struct vm * vm); void vm_execute(struct vm * vm); -void vm_start(int class_hash_table_length, - struct hash_table_entry * class_hash_table, - const uint8_t * main_class_name, - int main_class_name_length); +struct vm * vm_start(int class_hash_table_length, + struct hash_table_entry * class_hash_table, + const uint8_t * main_class_name, + int main_class_name_length); int descriptor_nargs(struct constant * descriptor_constant, uint8_t * return_type); diff --git a/c/hash_table.c b/c/hash_table.c index 3b8fa59..c211d00 100644 --- a/c/hash_table.c +++ b/c/hash_table.c @@ -64,6 +64,8 @@ void hash_table_add(int hash_table_length, if (e->key != nullptr) { // allocate e from overflow e->next = malloc_class_arena((sizeof (struct hash_table_entry))); + e->next->key = nullptr; + e->next->next = nullptr; e = e->next; } @@ -135,6 +137,8 @@ void hash_table_add2(int hash_table_length, if (e->key != nullptr) { // allocate e from overflow e->next = malloc_class_arena((sizeof (struct hash_table_entry))); + e->next->key = nullptr; + e->next->next = nullptr; e = e->next; } diff --git a/c/main_dreamcast.c b/c/main_dreamcast.c index eeb0eff..4006fa3 100644 --- a/c/main_dreamcast.c +++ b/c/main_dreamcast.c @@ -4,6 +4,8 @@ #include "class_resolver.h" #include "frame.h" #include "printf.h" +#include "malloc.h" +#include "memory_allocator.h" #include "sh7091_scif.h" @@ -26,13 +28,17 @@ void main() scif_character(main_class[i]); scif_character('\n'); + memory_reset_free_list(); + malloc_class_arena_reset(); + int class_hash_table_length; struct hash_table_entry * class_hash_table = class_resolver_load_from_buffers(class_file_buffers, class_file_buffers_length, &class_hash_table_length); - vm_start(class_hash_table_length, - class_hash_table, - main_class, - main_class_length); + struct vm * vm = vm_start(class_hash_table_length, + class_hash_table, + main_class, + main_class_length); + vm_execute(vm); } diff --git a/c/main_hosted.c b/c/main_hosted.c index 2c7a997..065d657 100644 --- a/c/main_hosted.c +++ b/c/main_hosted.c @@ -6,6 +6,8 @@ #include "class_resolver.h" #include "string.h" #include "file.h" +#include "malloc.h" +#include "memory_allocator.h" static struct hash_table_entry * load_from_filenames(const char * filenames[], int length, int * hash_table_length) { @@ -17,6 +19,9 @@ static struct hash_table_entry * load_from_filenames(const char * filenames[], i buffers[i] = file_read(filenames[i], &file_size[i]); } + memory_reset_free_list(); + malloc_class_arena_reset(); + struct hash_table_entry * class_hash_table = class_resolver_load_from_buffers((const uint8_t **)buffers, length, hash_table_length); @@ -42,8 +47,11 @@ int main(int argc, const char * argv[]) int class_hash_table_length; struct hash_table_entry * class_hash_table = load_from_filenames(class_filenames, num_class_filenames, &class_hash_table_length); - vm_start(class_hash_table_length, - class_hash_table, - main_class, - main_class_length); + debugf("vm_start\n"); + + struct vm * vm = vm_start(class_hash_table_length, + class_hash_table, + main_class, + main_class_length); + vm_execute(vm); } diff --git a/c/malloc.c b/c/malloc.c index de894b0..88433d4 100644 --- a/c/malloc.c +++ b/c/malloc.c @@ -15,6 +15,11 @@ struct arena class_arena = { .ix = 0, }; +void malloc_class_arena_reset() +{ + class_arena.ix = 0; +} + void * malloc_class_arena(uint32_t size) { if (size == 0) diff --git a/c/malloc.h b/c/malloc.h index c947ec3..94af943 100644 --- a/c/malloc.h +++ b/c/malloc.h @@ -2,4 +2,5 @@ #include +void malloc_class_arena_reset(); void * malloc_class_arena(uint32_t size); diff --git a/c/native.c b/c/native.c index 399c97b..25d19a8 100644 --- a/c/native.c +++ b/c/native.c @@ -1,5 +1,10 @@ #include "native.h" #include "printf.h" +#include "string.h" +#include "malloc.h" +#include "memory_allocator.h" +#include "class_resolver.h" +#include "frame.h" void native_java_io_printstream_write(uint32_t * arrayref) { @@ -128,3 +133,35 @@ uint32_t native_java_misc_memory_isbigendian() { return (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__); } + +static uint8_t loader_buffer[0x100000]; + +uint32_t native_jvm_internal_loader_getbuffer() +{ + return (uint32_t)&loader_buffer[0]; +} + +extern struct vm vm; + +void native_jvm_internal_loader_load(uint32_t * args) +{ + uint32_t * arrayref = (uint32_t *)args[0]; + int32_t buffers_length = (int32_t)arrayref[0]; + const uint8_t ** buffers = (const uint8_t **)&arrayref[1]; + + const uint8_t * main_class = (const uint8_t *)"Main"; + int main_class_length = string_length((const char *)main_class); + + memory_reset_free_list(); + malloc_class_arena_reset(); + + int class_hash_table_length; + struct hash_table_entry * class_hash_table = class_resolver_load_from_buffers(buffers, + buffers_length, + &class_hash_table_length); + + struct vm * vm = vm_start(class_hash_table_length, + class_hash_table, + main_class, + main_class_length); +} diff --git a/c/native.h b/c/native.h index 9eecb3c..d1bda9a 100644 --- a/c/native.h +++ b/c/native.h @@ -16,3 +16,5 @@ uint32_t native_java_lang_math_sin_1(uint32_t * args); uint32_t native_java_lang_math_cos_1(uint32_t * args); uint32_t java_misc_resource_getresource_1(uint32_t * args); uint32_t native_java_misc_memory_isbigendian(); +uint32_t native_jvm_internal_loader_getbuffer(); +void native_jvm_internal_loader_load(uint32_t * args); diff --git a/class_bytes.py b/class_bytes.py new file mode 100644 index 0000000..7c33819 --- /dev/null +++ b/class_bytes.py @@ -0,0 +1,24 @@ +filenames = [ + "Main.class", + "java/lang/Object.class", + "java/io/PrintStream.class", +] + +import struct + +def sign_extend(value, bits): + sign_bit = 1 << (bits - 1) + return (value & (sign_bit - 1)) - (value & sign_bit) + +def print_bytearray(buf): + print("new byte[] {") + for i in range(len(buf)): + print(f"{sign_extend(buf[i], 8)},", end=' ') + if i % 16 == 15: + print() + print("};") + +for filename in filenames: + with open(filename, 'rb') as f: + buf = f.read() + print_bytearray(buf) diff --git a/java/misc/Resource.java b/java/misc/Resource.java index a72284a..e92e2d6 100644 --- a/java/misc/Resource.java +++ b/java/misc/Resource.java @@ -4,5 +4,5 @@ public class Resource { private Resource() { } - public static native int[] getResource(String name); + public static native int getResource(String name); } diff --git a/jvm/internal/Loader.java b/jvm/internal/Loader.java new file mode 100644 index 0000000..5e55e81 --- /dev/null +++ b/jvm/internal/Loader.java @@ -0,0 +1,10 @@ +package jvm.internal; + +public class Loader { + private Loader() { + } + + public static native int getBuffer(); + + public static native void load(int[] buffers); +} diff --git a/p/TestLoader.java b/p/TestLoader.java new file mode 100644 index 0000000..399712b --- /dev/null +++ b/p/TestLoader.java @@ -0,0 +1,181 @@ +package p; + +import jvm.internal.Loader; +import java.misc.Memory; + +class TestLoader { + static byte[][] buffers; + + static { + buffers = new byte[3][]; + buffers[0] = new byte[] { + -54, -2, -70, -66, 0, 0, 0, 52, 0, 20, 10, 0, 2, 0, 3, 7, + 0, 4, 12, 0, 5, 0, 6, 1, 0, 16, 106, 97, 118, 97, 47, 108, + 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 1, 0, 6, 60, 105, 110, + 105, 116, 62, 1, 0, 3, 40, 41, 86, 10, 0, 8, 0, 9, 7, 0, + 10, 12, 0, 11, 0, 12, 1, 0, 19, 106, 97, 118, 97, 47, 105, 111, + 47, 80, 114, 105, 110, 116, 83, 116, 114, 101, 97, 109, 1, 0, 5, 119, + 114, 105, 116, 101, 1, 0, 5, 40, 91, 66, 41, 86, 7, 0, 14, 1, + 0, 4, 77, 97, 105, 110, 1, 0, 4, 67, 111, 100, 101, 1, 0, 15, + 76, 105, 110, 101, 78, 117, 109, 98, 101, 114, 84, 97, 98, 108, 101, 1, + 0, 4, 109, 97, 105, 110, 1, 0, 10, 83, 111, 117, 114, 99, 101, 70, + 105, 108, 101, 1, 0, 9, 77, 97, 105, 110, 46, 106, 97, 118, 97, 0, + 32, 0, 13, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 5, 0, + 6, 0, 1, 0, 15, 0, 0, 0, 29, 0, 1, 0, 1, 0, 0, 0, + 5, 42, -73, 0, 1, -79, 0, 0, 0, 1, 0, 16, 0, 0, 0, 6, + 0, 1, 0, 0, 0, 3, 0, 9, 0, 17, 0, 6, 0, 1, 0, 15, + 0, 0, 0, 114, 0, 4, 0, 1, 0, 0, 0, 82, 16, 13, -68, 8, + 89, 3, 16, 104, 84, 89, 4, 16, 101, 84, 89, 5, 16, 108, 84, 89, + 6, 16, 108, 84, 89, 7, 16, 111, 84, 89, 8, 16, 32, 84, 89, 16, + 6, 16, 119, 84, 89, 16, 7, 16, 111, 84, 89, 16, 8, 16, 114, 84, + 89, 16, 9, 16, 108, 84, 89, 16, 10, 16, 100, 84, 89, 16, 11, 16, + 33, 84, 89, 16, 12, 16, 10, 84, 75, 42, -72, 0, 7, -79, 0, 0, + 0, 1, 0, 16, 0, 0, 0, 14, 0, 3, 0, 0, 0, 5, 0, 77, + 0, 6, 0, 81, 0, 7, 0, 1, 0, 18, 0, 0, 0, 2, 0, 19, + }; + buffers[1] = new byte[] { + -54, -2, -70, -66, 0, 0, 0, 52, 0, 13, 8, 0, 2, 1, 0, 6, + 79, 98, 106, 101, 99, 116, 7, 0, 4, 1, 0, 16, 106, 97, 118, 97, + 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 1, 0, 6, 60, + 105, 110, 105, 116, 62, 1, 0, 3, 40, 41, 86, 1, 0, 4, 67, 111, + 100, 101, 1, 0, 15, 76, 105, 110, 101, 78, 117, 109, 98, 101, 114, 84, + 97, 98, 108, 101, 1, 0, 8, 116, 111, 83, 116, 114, 105, 110, 103, 1, + 0, 20, 40, 41, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, + 116, 114, 105, 110, 103, 59, 1, 0, 10, 83, 111, 117, 114, 99, 101, 70, + 105, 108, 101, 1, 0, 11, 79, 98, 106, 101, 99, 116, 46, 106, 97, 118, + 97, 0, 33, 0, 3, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, + 5, 0, 6, 0, 1, 0, 7, 0, 0, 0, 25, 0, 0, 0, 1, 0, + 0, 0, 1, -79, 0, 0, 0, 1, 0, 8, 0, 0, 0, 6, 0, 1, + 0, 0, 0, 4, 0, 1, 0, 9, 0, 10, 0, 1, 0, 7, 0, 0, + 0, 27, 0, 1, 0, 1, 0, 0, 0, 3, 18, 1, -80, 0, 0, 0, + 1, 0, 8, 0, 0, 0, 6, 0, 1, 0, 0, 0, 7, 0, 1, 0, + 11, 0, 0, 0, 2, 0, 12, + }; + buffers[2] = new byte[] { + -54, -2, -70, -66, 0, 0, 0, 52, 0, 61, 10, 0, 2, 0, 3, 7, + 0, 4, 12, 0, 5, 0, 6, 1, 0, 16, 106, 97, 118, 97, 47, 108, + 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 1, 0, 6, 60, 105, 110, + 105, 116, 62, 1, 0, 3, 40, 41, 86, 9, 0, 8, 0, 9, 7, 0, + 10, 12, 0, 11, 0, 12, 1, 0, 19, 106, 97, 118, 97, 47, 105, 111, + 47, 80, 114, 105, 110, 116, 83, 116, 114, 101, 97, 109, 1, 0, 7, 110, + 101, 119, 108, 105, 110, 101, 1, 0, 2, 91, 66, 10, 0, 14, 0, 15, + 7, 0, 16, 12, 0, 17, 0, 18, 1, 0, 16, 106, 97, 118, 97, 47, + 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 1, 0, 8, 103, 101, + 116, 66, 121, 116, 101, 115, 1, 0, 4, 40, 41, 91, 66, 10, 0, 8, + 0, 20, 12, 0, 21, 0, 22, 1, 0, 5, 119, 114, 105, 116, 101, 1, + 0, 5, 40, 91, 66, 41, 86, 10, 0, 14, 0, 24, 12, 0, 25, 0, + 26, 1, 0, 7, 118, 97, 108, 117, 101, 79, 102, 1, 0, 21, 40, 90, + 41, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, + 110, 103, 59, 10, 0, 8, 0, 28, 12, 0, 21, 0, 29, 1, 0, 21, + 40, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, + 110, 103, 59, 41, 86, 10, 0, 14, 0, 31, 12, 0, 25, 0, 32, 1, + 0, 21, 40, 67, 41, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, + 83, 116, 114, 105, 110, 103, 59, 10, 0, 14, 0, 34, 12, 0, 25, 0, + 35, 1, 0, 21, 40, 73, 41, 76, 106, 97, 118, 97, 47, 108, 97, 110, + 103, 47, 83, 116, 114, 105, 110, 103, 59, 10, 0, 14, 0, 37, 12, 0, + 25, 0, 38, 1, 0, 21, 40, 74, 41, 76, 106, 97, 118, 97, 47, 108, + 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 10, 0, 14, 0, 40, + 12, 0, 25, 0, 41, 1, 0, 21, 40, 70, 41, 76, 106, 97, 118, 97, + 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 10, 0, 14, + 0, 43, 12, 0, 25, 0, 44, 1, 0, 21, 40, 68, 41, 76, 106, 97, + 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 10, + 0, 14, 0, 46, 12, 0, 25, 0, 47, 1, 0, 38, 40, 76, 106, 97, + 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 59, 41, + 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, + 103, 59, 1, 0, 4, 67, 111, 100, 101, 1, 0, 15, 76, 105, 110, 101, + 78, 117, 109, 98, 101, 114, 84, 97, 98, 108, 101, 1, 0, 5, 112, 114, + 105, 110, 116, 1, 0, 4, 40, 90, 41, 86, 1, 0, 4, 40, 67, 41, + 86, 1, 0, 4, 40, 73, 41, 86, 1, 0, 4, 40, 74, 41, 86, 1, + 0, 4, 40, 70, 41, 86, 1, 0, 4, 40, 68, 41, 86, 1, 0, 21, + 40, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, + 99, 116, 59, 41, 86, 1, 0, 7, 112, 114, 105, 110, 116, 108, 110, 1, + 0, 10, 83, 111, 117, 114, 99, 101, 70, 105, 108, 101, 1, 0, 16, 80, + 114, 105, 110, 116, 83, 116, 114, 101, 97, 109, 46, 106, 97, 118, 97, 0, + 33, 0, 8, 0, 2, 0, 0, 0, 1, 0, 18, 0, 11, 0, 12, 0, + 0, 0, 20, 0, 1, 0, 5, 0, 6, 0, 1, 0, 48, 0, 0, 0, + 49, 0, 5, 0, 1, 0, 0, 0, 17, 42, -73, 0, 1, 42, 4, -68, + 8, 89, 3, 16, 10, 84, -75, 0, 7, -79, 0, 0, 0, 1, 0, 49, + 0, 0, 0, 14, 0, 3, 0, 0, 0, 8, 0, 4, 0, 11, 0, 16, + 0, 9, 1, 9, 0, 21, 0, 22, 0, 0, 0, 9, 0, 21, 0, 29, + 0, 1, 0, 48, 0, 0, 0, 36, 0, 1, 0, 1, 0, 0, 0, 8, + 42, -74, 0, 13, -72, 0, 19, -79, 0, 0, 0, 1, 0, 49, 0, 0, + 0, 10, 0, 2, 0, 0, 0, 16, 0, 7, 0, 17, 0, 1, 0, 50, + 0, 22, 0, 1, 0, 48, 0, 0, 0, 33, 0, 1, 0, 2, 0, 0, + 0, 5, 43, -72, 0, 19, -79, 0, 0, 0, 1, 0, 49, 0, 0, 0, + 10, 0, 2, 0, 0, 0, 20, 0, 4, 0, 21, 0, 1, 0, 50, 0, + 51, 0, 1, 0, 48, 0, 0, 0, 36, 0, 1, 0, 2, 0, 0, 0, + 8, 27, -72, 0, 23, -72, 0, 27, -79, 0, 0, 0, 1, 0, 49, 0, + 0, 0, 10, 0, 2, 0, 0, 0, 24, 0, 7, 0, 25, 0, 1, 0, + 50, 0, 52, 0, 1, 0, 48, 0, 0, 0, 36, 0, 1, 0, 2, 0, + 0, 0, 8, 27, -72, 0, 30, -72, 0, 27, -79, 0, 0, 0, 1, 0, + 49, 0, 0, 0, 10, 0, 2, 0, 0, 0, 28, 0, 7, 0, 29, 0, + 1, 0, 50, 0, 53, 0, 1, 0, 48, 0, 0, 0, 36, 0, 1, 0, + 2, 0, 0, 0, 8, 27, -72, 0, 33, -72, 0, 27, -79, 0, 0, 0, + 1, 0, 49, 0, 0, 0, 10, 0, 2, 0, 0, 0, 32, 0, 7, 0, + 33, 0, 1, 0, 50, 0, 54, 0, 1, 0, 48, 0, 0, 0, 36, 0, + 2, 0, 3, 0, 0, 0, 8, 31, -72, 0, 36, -72, 0, 27, -79, 0, + 0, 0, 1, 0, 49, 0, 0, 0, 10, 0, 2, 0, 0, 0, 36, 0, + 7, 0, 37, 0, 1, 0, 50, 0, 55, 0, 1, 0, 48, 0, 0, 0, + 36, 0, 1, 0, 2, 0, 0, 0, 8, 35, -72, 0, 39, -72, 0, 27, + -79, 0, 0, 0, 1, 0, 49, 0, 0, 0, 10, 0, 2, 0, 0, 0, + 40, 0, 7, 0, 41, 0, 1, 0, 50, 0, 56, 0, 1, 0, 48, 0, + 0, 0, 36, 0, 2, 0, 3, 0, 0, 0, 8, 39, -72, 0, 42, -72, + 0, 27, -79, 0, 0, 0, 1, 0, 49, 0, 0, 0, 10, 0, 2, 0, + 0, 0, 44, 0, 7, 0, 45, 0, 1, 0, 50, 0, 57, 0, 1, 0, + 48, 0, 0, 0, 36, 0, 1, 0, 2, 0, 0, 0, 8, 43, -72, 0, + 45, -72, 0, 27, -79, 0, 0, 0, 1, 0, 49, 0, 0, 0, 10, 0, + 2, 0, 0, 0, 48, 0, 7, 0, 49, 0, 1, 0, 58, 0, 6, 0, + 1, 0, 48, 0, 0, 0, 36, 0, 1, 0, 1, 0, 0, 0, 8, 42, + -76, 0, 7, -72, 0, 19, -79, 0, 0, 0, 1, 0, 49, 0, 0, 0, + 10, 0, 2, 0, 0, 0, 52, 0, 7, 0, 53, 0, 1, 0, 58, 0, + 22, 0, 1, 0, 48, 0, 0, 0, 44, 0, 1, 0, 2, 0, 0, 0, + 12, 43, -72, 0, 19, 42, -76, 0, 7, -72, 0, 19, -79, 0, 0, 0, + 1, 0, 49, 0, 0, 0, 14, 0, 3, 0, 0, 0, 56, 0, 4, 0, + 57, 0, 11, 0, 58, 0, 1, 0, 58, 0, 51, 0, 1, 0, 48, 0, + 0, 0, 47, 0, 1, 0, 2, 0, 0, 0, 15, 27, -72, 0, 23, -72, + 0, 27, 42, -76, 0, 7, -72, 0, 19, -79, 0, 0, 0, 1, 0, 49, + 0, 0, 0, 14, 0, 3, 0, 0, 0, 61, 0, 7, 0, 62, 0, 14, + 0, 63, 0, 1, 0, 58, 0, 52, 0, 1, 0, 48, 0, 0, 0, 47, + 0, 1, 0, 2, 0, 0, 0, 15, 27, -72, 0, 30, -72, 0, 27, 42, + -76, 0, 7, -72, 0, 19, -79, 0, 0, 0, 1, 0, 49, 0, 0, 0, + 14, 0, 3, 0, 0, 0, 66, 0, 7, 0, 67, 0, 14, 0, 68, 0, + 1, 0, 58, 0, 53, 0, 1, 0, 48, 0, 0, 0, 47, 0, 1, 0, + 2, 0, 0, 0, 15, 27, -72, 0, 33, -72, 0, 27, 42, -76, 0, 7, + -72, 0, 19, -79, 0, 0, 0, 1, 0, 49, 0, 0, 0, 14, 0, 3, + 0, 0, 0, 71, 0, 7, 0, 72, 0, 14, 0, 73, 0, 1, 0, 58, + 0, 54, 0, 1, 0, 48, 0, 0, 0, 47, 0, 2, 0, 3, 0, 0, + 0, 15, 31, -72, 0, 36, -72, 0, 27, 42, -76, 0, 7, -72, 0, 19, + -79, 0, 0, 0, 1, 0, 49, 0, 0, 0, 14, 0, 3, 0, 0, 0, + 76, 0, 7, 0, 77, 0, 14, 0, 78, 0, 1, 0, 58, 0, 55, 0, + 1, 0, 48, 0, 0, 0, 47, 0, 1, 0, 2, 0, 0, 0, 15, 35, + -72, 0, 39, -72, 0, 27, 42, -76, 0, 7, -72, 0, 19, -79, 0, 0, + 0, 1, 0, 49, 0, 0, 0, 14, 0, 3, 0, 0, 0, 81, 0, 7, + 0, 82, 0, 14, 0, 83, 0, 1, 0, 58, 0, 56, 0, 1, 0, 48, + 0, 0, 0, 47, 0, 2, 0, 3, 0, 0, 0, 15, 39, -72, 0, 42, + -72, 0, 27, 42, -76, 0, 7, -72, 0, 19, -79, 0, 0, 0, 1, 0, + 49, 0, 0, 0, 14, 0, 3, 0, 0, 0, 86, 0, 7, 0, 87, 0, + 14, 0, 88, 0, 1, 0, 58, 0, 57, 0, 1, 0, 48, 0, 0, 0, + 47, 0, 1, 0, 2, 0, 0, 0, 15, 43, -72, 0, 45, -72, 0, 27, + 42, -76, 0, 7, -72, 0, 19, -79, 0, 0, 0, 1, 0, 49, 0, 0, + 0, 14, 0, 3, 0, 0, 0, 91, 0, 7, 0, 92, 0, 14, 0, 93, + 0, 1, 0, 59, 0, 0, 0, 2, 0, 60, + }; + } + + public static int copyBuffer(byte[] buf, int address) { + for (int i = 0; i < buf.length; i++) { + Memory.putU1(address + i, buf[i]); + } + return buf.length; + } + + public static void main() { + int address = Loader.getBuffer(); + int[] buffer_addresses = new int[buffers.length]; + for (int i = 0; i < buffers.length; i++) { + buffer_addresses[i] = address; + address += copyBuffer(buffers[i], address); + } + Loader.load(buffer_addresses); + } +}