Created
July 10, 2009 01:49
-
-
Save glongman/144182 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "ruby.h" | |
/* | |
* Ruby access into the interpreter. | |
*/ | |
/* Classes */ | |
extern VALUE Z; | |
extern VALUE Machine; | |
extern VALUE Memory; | |
extern VALUE Header; | |
extern VALUE ObjectTable; | |
extern VALUE Object; | |
extern VALUE Status; | |
extern VALUE Dictionary; | |
extern VALUE Entry; | |
extern VALUE InputStream; | |
extern VALUE Program; | |
extern VALUE RuntimeError; | |
extern VALUE RandomNumberGenerator; | |
/* Prototypes */ | |
VALUE memory_alloc( VALUE klass ); | |
VALUE memory_initialize( VALUE self, VALUE filename ); | |
VALUE memory_initialize_copy( VALUE self, VALUE original ); | |
VALUE memory_length( VALUE self ); | |
VALUE memory_dynamic_length( VALUE self ); | |
VALUE memory_static_length( VALUE self ); | |
VALUE memory_read_byte( VALUE self, VALUE addr ); | |
VALUE memory_read_word( VALUE self, VALUE addr ); | |
VALUE memory_read_string( VALUE self, VALUE addr ); | |
VALUE memory_read_string_array( VALUE self, VALUE addr, VALUE length ); | |
void memory_mark( void * ); | |
void memory_free( void * ); | |
VALUE machine_alloc( VALUE klass ); | |
VALUE machine_initialize( VALUE self, VALUE filename ); | |
VALUE machine_step( VALUE self ); | |
VALUE machine_finished( VALUE self ); | |
VALUE machine_marshal_dump( VALUE self ); | |
VALUE machine_marshal_load( VALUE self, VALUE ary ); | |
void machine_free( void * ); | |
VALUE program_alloc( VALUE klass ); | |
VALUE program_initialize( VALUE self, VALUE filename ); | |
VALUE program_checksum( VALUE self ); | |
VALUE program_version( VALUE self ); | |
VALUE program_release( VALUE self ); | |
VALUE program_serial( VALUE self ); | |
void program_free( void * ); | |
VALUE object_table_find( VALUE self, VALUE n ); | |
VALUE object_table_each( VALUE self ); | |
VALUE object_name( VALUE self ); | |
VALUE object_parent( VALUE self ); | |
VALUE object_child( VALUE self ); | |
VALUE object_sibling( VALUE self ); | |
VALUE object_attributes( VALUE self ); | |
VALUE status_type( VALUE self ); | |
VALUE status_score( VALUE self ); | |
VALUE status_turns( VALUE self ); | |
VALUE status_hours( VALUE self ); | |
VALUE status_minutes( VALUE self ); | |
VALUE status_location( VALUE self ); | |
VALUE header_version( VALUE self ); | |
VALUE header_status_line_score( VALUE self ); | |
VALUE header_status_line_time( VALUE self ); | |
VALUE header_story_split( VALUE self ); | |
VALUE header_status_line_available( VALUE self ); | |
VALUE header_screen_splitting_available( VALUE self ); | |
VALUE header_variable_width_font_default( VALUE self ); | |
VALUE header_colors_available( VALUE self ); | |
VALUE header_picture_display_available( VALUE self ); | |
VALUE header_bold_available( VALUE self ); | |
VALUE header_italics_available( VALUE self ); | |
VALUE header_fixed_width_available( VALUE self ); | |
VALUE header_sound_available( VALUE self ); | |
VALUE header_timed_input_available( VALUE self ); | |
VALUE header_transcripting_on( VALUE self ); | |
VALUE header_force_fixed_width( VALUE self ); | |
VALUE header_status_line_redraw( VALUE self ); | |
VALUE header_wants_pictures( VALUE self ); | |
VALUE header_wants_undo( VALUE self ); | |
VALUE header_wants_mouse( VALUE self ); | |
VALUE header_wants_color( VALUE self ); | |
VALUE header_wants_sound( VALUE self ); | |
VALUE header_wants_menus( VALUE self ); | |
VALUE header_set_status_line_available( VALUE self, VALUE b ); | |
VALUE header_set_screen_splitting_available( VALUE self, VALUE b ); | |
VALUE header_set_variable_width_font_default( VALUE self, VALUE b ); | |
VALUE header_set_colors_available( VALUE self, VALUE b ); | |
VALUE header_set_picture_display_available( VALUE self, VALUE b ); | |
VALUE header_set_bold_available( VALUE self, VALUE b ); | |
VALUE header_set_italics_available( VALUE self, VALUE b ); | |
VALUE header_set_fixed_width_available( VALUE self, VALUE b ); | |
VALUE header_set_sound_available( VALUE self, VALUE b ); | |
VALUE header_set_timed_input_available( VALUE self, VALUE b ); | |
VALUE header_set_transcripting_on( VALUE self, VALUE b ); | |
VALUE header_set_force_fixed_width( VALUE self, VALUE b ); | |
VALUE header_set_status_line_redraw( VALUE self, VALUE b ); | |
VALUE header_set_wants_pictures( VALUE self, VALUE b ); | |
VALUE header_set_wants_undo( VALUE self, VALUE b ); | |
VALUE header_set_wants_mouse( VALUE self, VALUE b ); | |
VALUE header_set_wants_color( VALUE self, VALUE b ); | |
VALUE header_set_wants_sound( VALUE self, VALUE b ); | |
VALUE header_set_wants_menus( VALUE self, VALUE b ); | |
VALUE header_static_memory( VALUE self ); | |
VALUE header_high_memory( VALUE self ); | |
VALUE header_initial_program_counter( VALUE self ); | |
VALUE header_main_routine( VALUE self ); | |
VALUE header_dictionary( VALUE self ); | |
VALUE header_object_table( VALUE self ); | |
VALUE header_global_table( VALUE self ); | |
VALUE header_abbreviations_table( VALUE self ); | |
VALUE header_terminating_table( VALUE self ); | |
VALUE header_alphabet_table( VALUE self ); | |
VALUE header_routines( VALUE self ); | |
VALUE header_strings( VALUE self ); | |
VALUE header_extension_table( VALUE self ); | |
VALUE header_extension_table_size( VALUE self ); | |
VALUE header_mouse_x( VALUE self ); | |
VALUE header_mouse_y( VALUE self ); | |
VALUE header_set_mouse_x( VALUE self, VALUE x ); | |
VALUE header_set_mouse_y( VALUE self, VALUE y ); | |
VALUE header_unicode_table( VALUE self ); | |
VALUE header_program_length( VALUE self ); | |
VALUE header_program_checksum( VALUE self ); | |
VALUE header_interpreter_number( VALUE self ); | |
VALUE header_interpreter_version( VALUE self ); | |
VALUE header_set_interpreter_number( VALUE self, VALUE n ); | |
VALUE header_set_interpreter_version( VALUE self, VALUE v ); | |
VALUE header_screen_rows( VALUE self ); | |
VALUE header_screen_cols( VALUE self ); | |
VALUE header_set_screen_rows( VALUE self, VALUE r ); | |
VALUE header_set_screen_cols( VALUE self, VALUE c ); | |
VALUE header_screen_width( VALUE self ); | |
VALUE header_screen_height( VALUE self ); | |
VALUE header_set_screen_width( VALUE self, VALUE w ); | |
VALUE header_set_screen_height( VALUE self, VALUE h ); | |
VALUE header_font_width( VALUE self ); | |
VALUE header_font_height( VALUE self ); | |
VALUE header_set_font_width( VALUE self, VALUE w ); | |
VALUE header_set_font_height( VALUE self, VALUE h ); | |
VALUE header_default_background_color( VALUE self ); | |
VALUE header_default_foreground_color( VALUE self ); | |
VALUE header_set_default_background_color( VALUE self, VALUE c ); | |
VALUE header_set_default_foreground_color( VALUE self, VALUE c ); | |
VALUE header_output_stream3_width( VALUE self ); | |
VALUE header_set_output_stream3_width( VALUE self, VALUE w ); | |
VALUE header_standard_major( VALUE self ); | |
VALUE header_standard_minor( VALUE self ); | |
VALUE header_set_standard_major( VALUE self, VALUE n ); | |
VALUE header_set_standard_minor( VALUE self, VALUE n ); | |
VALUE dictionary_load( VALUE self ); | |
extern ID id_new, id_dup, id_srand, id_rand, | |
id_line_available, id_char_available, id_read_line, id_read_char, | |
id_dictionary, id_parse, | |
id_score, id_time; | |
extern VALUE sym_score, sym_time; | |
/*** Ruby 1.9 and 1.8 compatibility ***/ | |
#ifndef RSTRING_PTR | |
#define RSTRING_PTR(x) (RSTRING(x)->ptr) | |
#endif | |
#ifndef RSTRING_LEN | |
#define RSTRING_LEN(x) (RSTRING(x)->len) | |
#endif | |
#ifndef RARRAY_PTR | |
#define RARRAY_PTR(x) (RARRAY(x)->ptr) | |
#endif | |
#ifndef RARRAY_LEN | |
#define RARRAY_LEN(x) (RARRAY(x)->len) | |
#endif | |
/*** Constants ***/ | |
#define true 1 | |
#define false 0 | |
#define STACK_SIZE 1024 | |
#define MAX_NESTING 16 | |
/*** Various Z-machine constants ***/ | |
#define V1 1 | |
#define V2 2 | |
#define V3 3 | |
#define V4 4 | |
#define V5 5 | |
#define V6 6 | |
#define V7 7 | |
#define V8 8 | |
#define CONFIG_BYTE_SWAPPED 0x01 /* Story file is byte swapped - V3 */ | |
#define CONFIG_TIME 0x02 /* Status line displays time - V3 */ | |
#define CONFIG_TWODISKS 0x04 /* Story file occupied two disks - V3 */ | |
#define CONFIG_TANDY 0x08 /* Tandy licensed game - V3 */ | |
#define CONFIG_NOSTATUSLINE 0x10 /* Interpr can't support status lines - V3 */ | |
#define CONFIG_SPLITSCREEN 0x20 /* Interpr supports split screen mode - V3 */ | |
#define CONFIG_PROPORTIONAL 0x40 /* Interpr uses proportional font - V3 */ | |
#define CONFIG_COLOUR 0x01 /* Interpr supports colour - V5+ */ | |
#define CONFIG_PICTURES 0x02 /* Interpr supports pictures - V6 */ | |
#define CONFIG_BOLDFACE 0x04 /* Interpr supports boldface style - V4+ */ | |
#define CONFIG_EMPHASIS 0x08 /* Interpr supports emphasis style - V4+ */ | |
#define CONFIG_FIXED 0x10 /* Interpr supports fixed width style - V4+ */ | |
#define CONFIG_SOUND 0x20 /* Interpr supports sound - V6 */ | |
#define CONFIG_TIMEDINPUT 0x80 /* Interpr supports timed input - V4+ */ | |
#define CONFIG_TIMEDINPUT 0x80 /* Interpr supports timed input - V4+ */ | |
#define SCRIPTING_FLAG 0x0001 /* Outputting to transscription file - V1+ */ | |
#define FIXED_FONT_FLAG 0x0002 /* Use fixed width font - V3+ */ | |
#define REFRESH_FLAG 0x0004 /* Refresh the screen - V6 */ | |
#define GRAPHICS_FLAG 0x0008 /* Game wants to use graphics - V5+ */ | |
#define OLD_SOUND_FLAG 0x0010 /* Game wants to use sound effects - V3 */ | |
#define UNDO_FLAG 0x0010 /* Game wants to use UNDO feature - V5+ */ | |
#define MOUSE_FLAG 0x0020 /* Game wants to use a mouse - V5+ */ | |
#define COLOUR_FLAG 0x0040 /* Game wants to use colours - V5+ */ | |
#define SOUND_FLAG 0x0080 /* Game wants to use sound effects - V5+ */ | |
#define MENU_FLAG 0x0100 /* Game wants to use menus - V6 */ | |
#define INTERP_DEFAULT 0 | |
#define INTERP_DEC_20 1 | |
#define INTERP_APPLE_IIE 2 | |
#define INTERP_MACINTOSH 3 | |
#define INTERP_AMIGA 4 | |
#define INTERP_ATARI_ST 5 | |
#define INTERP_MSDOS 6 | |
#define INTERP_CBM_128 7 | |
#define INTERP_CBM_64 8 | |
#define INTERP_APPLE_IIC 9 | |
#define INTERP_APPLE_IIGS 10 | |
#define INTERP_TANDY 11 | |
#define BLACK_COLOUR 2 | |
#define RED_COLOUR 3 | |
#define GREEN_COLOUR 4 | |
#define YELLOW_COLOUR 5 | |
#define BLUE_COLOUR 6 | |
#define MAGENTA_COLOUR 7 | |
#define CYAN_COLOUR 8 | |
#define WHITE_COLOUR 9 | |
#define GREY_COLOUR 10 /* INTERP_MSDOS only */ | |
#define LIGHTGREY_COLOUR 10 /* INTERP_AMIGA only */ | |
#define MEDIUMGREY_COLOUR 11 /* INTERP_AMIGA only */ | |
#define DARKGREY_COLOUR 12 /* INTERP_AMIGA only */ | |
#define REVERSE_STYLE 1 | |
#define BOLDFACE_STYLE 2 | |
#define EMPHASIS_STYLE 4 | |
#define FIXED_WIDTH_STYLE 8 | |
#define TEXT_FONT 1 | |
#define PICTURE_FONT 2 | |
#define GRAPHICS_FONT 3 | |
#define FIXED_WIDTH_FONT 4 | |
#define BEEP_HIGH 1 | |
#define BEEP_LOW 2 | |
/*** Constants for os_restart_game */ | |
#define RESTART_BEGIN 0 | |
#define RESTART_WPROP_SET 1 | |
#define RESTART_END 2 | |
/*** Character codes ***/ | |
#define ZC_TIME_OUT 0x00 | |
#define ZC_NEW_STYLE 0x01 | |
#define ZC_NEW_FONT 0x02 | |
#define ZC_BACKSPACE 0x08 | |
#define ZC_INDENT 0x09 | |
#define ZC_GAP 0x0b | |
#define ZC_RETURN 0x0d | |
#define ZC_HKEY_MIN 0x0e | |
#define ZC_HKEY_RECORD 0x0e | |
#define ZC_HKEY_PLAYBACK 0x0f | |
#define ZC_HKEY_SEED 0x10 | |
#define ZC_HKEY_UNDO 0x11 | |
#define ZC_HKEY_RESTART 0x12 | |
#define ZC_HKEY_QUIT 0x13 | |
#define ZC_HKEY_DEBUG 0x14 | |
#define ZC_HKEY_HELP 0x15 | |
#define ZC_HKEY_MAX 0x15 | |
#define ZC_ESCAPE 0x1b | |
#define ZC_ASCII_MIN 0x20 | |
#define ZC_ASCII_MAX 0x7e | |
#define ZC_BAD 0x7f | |
#define ZC_ARROW_MIN 0x81 | |
#define ZC_ARROW_UP 0x81 | |
#define ZC_ARROW_DOWN 0x82 | |
#define ZC_ARROW_LEFT 0x83 | |
#define ZC_ARROW_RIGHT 0x84 | |
#define ZC_ARROW_MAX 0x84 | |
#define ZC_FKEY_MIN 0x85 | |
#define ZC_FKEY_MAX 0x90 | |
#define ZC_NUMPAD_MIN 0x91 | |
#define ZC_NUMPAD_MAX 0x9a | |
#define ZC_SINGLE_CLICK 0x9b | |
#define ZC_DOUBLE_CLICK 0x9c | |
#define ZC_MENU_CLICK 0x9d | |
#define ZC_LATIN1_MIN 0xa0 | |
#define ZC_LATIN1_MAX 0xff | |
/*** File types ***/ | |
#define FILE_RESTORE 0 | |
#define FILE_SAVE 1 | |
#define FILE_SCRIPT 2 | |
#define FILE_PLAYBACK 3 | |
#define FILE_RECORD 4 | |
#define FILE_LOAD_AUX 5 | |
#define FILE_SAVE_AUX 6 | |
/*** Macros ***/ | |
/*** Access data from the program the machine is running. */ | |
#define mem(zm, addr) \ | |
(((addr) < zm->m->dynamic_length) ? zm->m->m_dynamic : zm->m->m_static) | |
#define maddr(zm, addr) \ | |
(((addr) < zm->m->dynamic_length) ? (addr) : (addr) - zm->m->dynamic_length) | |
#define read_byte(zm,addr) \ | |
(mem(zm,addr)[maddr(zm,addr)]) | |
#define read_word(zm,addr) \ | |
(((zword) read_byte(zm,(addr)) << 8) | read_byte(zm, (addr)+1)) | |
#define read_n(zm,addr,n) \ | |
((n) == 1 ? read_byte( zm, (addr) ) : read_word( zm, (addr) )) | |
#define write_byte(zm,addr,value) (read_byte(zm,addr) = (value)) | |
#define write_word(zm,addr,value) \ | |
{ read_byte(zm,addr) = (value) >> 8; \ | |
read_byte(zm,addr+1) = (value) & 0xff; } | |
#define PC(zm) (zm->pcp - zm->m->m_static + zm->m->dynamic_length) | |
#define m_output(zm) (rb_iv_get( zm->self, "@output" )) | |
#define print_cstr(zm,str) \ | |
(rb_ary_push( m_output( zm ), rb_str_new2( (char *)str ) )) | |
#define print_rstr(zm,str) (rb_ary_push( m_output( zm ), str )) | |
#define m_trace(zm) (rb_iv_get( zm->self, "@trace" )) | |
#define trace(zm,fmt,...) \ | |
{ char * buf = ALLOC_N( char, 255 ); \ | |
sprintf( buf, fmt, ##__VA_ARGS__ ); \ | |
rb_ary_push( m_trace(zm), rb_str_new2( (char *)buf ) ); } | |
/*** Access data from the header of the program running. */ | |
/*** These are higher-level functions, intended to extract info from | |
* the header, not individual zbytes and zwords. | |
*/ | |
#define h_version(zm) (read_byte( zm, 0x00 )) | |
#define h_release(zm) (read_word( zm, 0x02 )) | |
#define h_status_line_score(zm) ((read_byte( zm, 0x01 ) & 0x02) == 0) | |
#define h_status_line_time(zm) ((read_byte( zm, 0x01 ) & 0x02) == 1) | |
#define h_story_split(zm) (read_byte( zm, 0x01 ) & 0x04) | |
#define h_status_line_available(zm) (! (read_byte( zm, 0x01 ) & 0x10)) | |
#define h_screen_splitting_available(zm) (read_byte( zm, 0x01 ) & 0x20) | |
#define h_variable_width_font_default(zm) (read_byte( zm, 0x01 ) & 0x40) | |
#define h_colors_available(zm) (read_byte( zm, 0x02 ) & 0x01) | |
#define h_picture_display_available(zm) (read_byte( zm, 0x02 ) & 0x02) | |
#define h_bold_available(zm) (read_byte( zm, 0x02 ) & 0x04) | |
#define h_italics_available(zm) (read_byte( zm, 0x02 ) & 0x08) | |
#define h_fixed_width_available(zm) (read_byte( zm, 0x02 ) & 0x10) | |
#define h_sound_available(zm) (read_byte( zm, 0x02 ) & 0x20) | |
#define h_timed_input_available(zm) (read_byte( zm, 0x02 ) & 0x80) | |
#define h_transcripting_on(zm) (read_word( zm, 0x10 ) & 0x0001) | |
#define h_force_fixed_width(zm) (read_word( zm, 0x10 ) & 0x0002) | |
#define h_status_line_redraw(zm) (read_word( zm, 0x10 ) & 0x0004) | |
#define h_wants_pictures(zm) (read_word( zm, 0x10 ) & 0x0008) | |
#define h_wants_undo(zm) (read_word( zm, 0x10 ) & 0x0010) | |
#define h_wants_mouse(zm) (read_word( zm, 0x10 ) & 0x0020) | |
#define h_wants_color(zm) (read_word( zm, 0x10 ) & 0x0040) | |
#define h_wants_sound(zm) (h_version(zm) == V3 ? \ | |
(read_word( zm, 0x10 ) & 0x0010) : \ | |
(read_word( zm, 0x10 ) & 0x0080)) | |
#define h_wants_menus(zm) (read_word( zm, 0x10 ) & 0x0100) | |
#define h_static_memory(zm) (read_word( zm, 0x0e )) | |
#define h_high_memory(zm) (read_word( zm, 0x04 )) | |
#define h_initial_program_counter(zm) (read_word( zm, 0x06 )) | |
#define h_main_routine(zm) (read_word( zm, 0x06 )) | |
#define h_dictionary(zm) (read_word( zm, 0x08 )) | |
#define h_object_table(zm) (read_word( zm, 0x0a )) | |
#define h_global_table(zm) (read_word( zm, 0x0c )) | |
#define h_abbreviations_table(zm) (read_word( zm, 0x18 )) | |
#define h_terminating_table(zm) (read_word( zm, 0x2e )) | |
#define h_alphabet_table(zm) (read_word( zm, 0x34 )) | |
#define h_routines(zm) (read_word( zm, 0x28 )) | |
#define h_strings(zm) (read_word( zm, 0x2a )) | |
#define h_extension_table(zm) (read_word( zm, 0x36 )) | |
#define h_extension_table_size(zm) (read_word( zm, h_extension_table( zm ) )) | |
#define h_mouse_x(zm) (read_word( zm, h_extension_table( zm ) + 2 )) | |
#define h_mouse_y(zm) (read_word( zm, h_extension_table( zm ) + 4 )) | |
#define h_unicode_table(zm) (read_word( zm, h_extension_table( zm ) + 6 )) | |
#define h_program_checksum(zm) (read_word( zm, 0x1c )) | |
#define h_interpreter_number(zm) (read_byte( zm, 0x1e )) | |
#define h_interpreter_version(zm) (read_byte( zm, 0x1f )) | |
#define h_screen_rows(zm) (read_byte( zm, 0x20 )) | |
#define h_screen_cols(zm) (read_byte( zm, 0x21 )) | |
#define h_screen_width(zm) (read_word( zm, 0x22 )) | |
#define h_screen_height(zm) (read_word( zm, 0x24 )) | |
#define h_font_width(zm) (h_version(zm) == V5 ? read_byte( zm, 0x26 ) : \ | |
read_byte( zm, 0x27 )) | |
#define h_font_height(zm) (h_version(zm) == V5 ? read_byte( zm, 0x27 ) : \ | |
read_byte( zm, 0x26 )) | |
#define h_default_background_color(zm) (read_byte( zm, 0x2c )) | |
#define h_default_foreground_color(zm) (read_byte( zm, 0x2d )) | |
#define h_output_stream3_width(zm) (read_word( zm, 0x30 )) | |
#define h_standard_major(zm) (read_byte( zm, 0x32 )) | |
#define h_standard_minor(zm) (read_byte( zm, 0x33 )) | |
#define dict_num_word_separators(zm,dict) (read_byte( zm, dict )) | |
#define dict_get_word_separator(zm,dict,i) \ | |
((i) < dict_num_word_separators( zm, (dict) ) ? \ | |
read_byte( zm, (dict) + 1 + (i) ) : \ | |
0) | |
#define dict_entry_length(zm,dict) \ | |
(read_byte( zm, (dict) + 1 + dict_num_word_separators( zm, (dict) ) )) | |
#define dict_num_entries(zm,dict) \ | |
(read_word( zm, (dict) + 1 + dict_num_word_separators( zm, (dict) ) + 1 )) | |
#define keyboard(zm) (rb_iv_get( zm->self, "@keyboard" )) | |
#define line_available(zm) \ | |
(RTEST(rb_funcall( keyboard(zm), id_line_available, 0))) | |
#define char_available(zm) \ | |
(RTEST(rb_funcall( keyboard(zm), id_char_available, 0))) | |
#define text_buffer_offset(zm) (h_version(zm) < 5 ? 1 : 2) | |
#define runtime_error(s) \ | |
(rb_raise( RuntimeError, "Error running program: %s", (s) )) | |
#define obj_max_objects(zm) (h_version(zm) < 4 ? 255 : 65535) | |
#define obj_parent_offset(zm) (h_version(zm) < 4 ? 4 : 6) | |
#define obj_sibling_offset(zm) (h_version(zm) < 4 ? 5 : 8) | |
#define obj_child_offset(zm) (h_version(zm) < 4 ? 6 : 10) | |
#define obj_parent_size(zm) (h_version(zm) < 4 ? 1 : 2) | |
#define obj_sibling_size(zm) (h_version(zm) < 4 ? 1 : 2) | |
#define obj_child_size(zm) (h_version(zm) < 4 ? 1 : 2) | |
#define obj_prop_offset(zm) (h_version(zm) < 4 ? 7 : 12) | |
#define obj_prop_mask(zm) (h_version(zm) < 4 ? 0x1f : 0x3f) | |
#define obj_size(zm) (h_version(zm) < 4 ? 9 : 14) | |
#define obj_defaults_offset(zm) (h_version(zm) < 4 ? 62 : 126) | |
#define obj_addr(zm,n) \ | |
(h_object_table(zm) + ((n)-1) * obj_size(zm) + obj_defaults_offset(zm)) | |
#define obj_name_addr(zm,n) \ | |
(read_word( zm, obj_addr(zm,(n)) + obj_prop_offset(zm) )) | |
#define obj_name_size(zm,n) \ | |
(read_byte( zm, obj_name_addr(zm,(n)) )) | |
#define obj_first_prop_addr(zm,n) \ | |
(obj_name_addr(zm,(n)) + 1 + 2 * obj_name_size(zm,(n))) | |
#define obj_default_prop(zm,n) \ | |
(read_word( zm, h_object_table(zm) + ((n) - 1) * 2 )) | |
#define obj_parent(zm,n) \ | |
(read_n( zm, obj_addr(zm,(n)) + obj_parent_offset(zm), obj_parent_size(zm) )) | |
#define obj_sibling(zm,n) \ | |
(read_n( zm, obj_addr(zm,(n)) + obj_sibling_offset(zm), obj_sibling_size(zm))) | |
#define obj_child(zm,n) \ | |
(read_n( zm, obj_addr(zm,(n)) + obj_child_offset(zm), obj_child_size(zm) )) | |
#define obj_max_attr(zm) (h_version(zm) < 4 ? 31 : 47) | |
#define obj_attr(zm,n,a) \ | |
(read_byte( zm, obj_addr(zm,(n)) + (a)/8 ) & (0x80 >> ((a) & 7))) | |
#define obj_set_attr(zm,n,a) \ | |
(write_byte( zm, obj_addr(zm,(n)) + (a)/8, \ | |
read_byte( zm, obj_addr(zm,(n)) + (a)/8 ) | (0x80 >> ((a) & 7)) )) | |
#define obj_clear_attr(zm,n,a) \ | |
(write_byte( zm, obj_addr(zm,(n)) + (a)/8, \ | |
read_byte( zm, obj_addr(zm,(n)) + (a)/8 ) & ~(0x80 >> ((a) & 7)) )) | |
/* | |
* The data and functions for the interpreter (C). | |
*/ | |
typedef int bool; | |
typedef unsigned char zbyte; | |
typedef unsigned short zword; | |
typedef unsigned char zchar; | |
typedef unsigned short zaddr; | |
struct smemory; | |
typedef struct smemory zmemory; | |
struct smemory { | |
long length; | |
long dynamic_length; | |
long static_length; | |
zbyte *m_dynamic; | |
zbyte *m_static; | |
zmemory *m; /* Pointer back to self, allows using zmemory, zmachine */ | |
/* and zprogram interchangably. */ | |
zmemory *parent; /* zmemory structs can share static memory, so to */ | |
long children; /* assist ruby's gc, we need to track the parent and */ | |
/* and count refs. */ | |
VALUE self; | |
}; | |
struct sprogram; | |
typedef struct sprogram zprogram; | |
struct sprogram { | |
zbyte version; | |
zword release; | |
char serial[6]; | |
zmemory *m; | |
zword checksum; | |
VALUE self; | |
}; | |
struct smachine; | |
typedef struct smachine zmachine; | |
typedef void (*z_op)( zmachine * ); | |
struct smachine { | |
zbyte version; | |
zprogram *zp; | |
zmemory *m; | |
zbyte *pcp; | |
zword stack[STACK_SIZE]; | |
zword *sp; | |
zword *fp; | |
zword frame_count; | |
zword zargs[8]; | |
int zargc; | |
int finished; | |
VALUE self; | |
}; | |
/* Function prototypes */ | |
long h_program_length( zmemory *m ); | |
void h_set_status_line_available( zmemory *m, bool b ); | |
void h_set_screen_splitting_available( zmemory *m, bool b ); | |
void h_set_variable_width_font_default( zmemory *m, bool b ); | |
void h_set_colors_available( zmemory *m, bool b ); | |
void h_set_picture_display_available( zmemory *m, bool b ); | |
void h_set_bold_available( zmemory *m, bool b ); | |
void h_set_italics_available( zmemory *m, bool b ); | |
void h_set_fixed_width_available( zmemory *m, bool b ); | |
void h_set_sound_available( zmemory *m, bool b ); | |
void h_set_timed_input_available( zmemory *m, bool b ); | |
void h_set_transcripting_on( zmemory *m, bool b ); | |
void h_set_force_fixed_width( zmemory *m, bool b ); | |
void h_set_status_line_redraw( zmemory *m, bool b ); | |
void h_set_wants_pictures( zmemory *m, bool b ); | |
void h_set_wants_undo( zmemory *m, bool b ); | |
void h_set_wants_mouse( zmemory *m, bool b ); | |
void h_set_wants_color( zmemory *m, bool b ); | |
void h_set_wants_sound( zmemory *m, bool b ); | |
void h_set_wants_menus( zmemory *m, bool b ); | |
void h_set_mouse_x( zmemory *m, int x ); | |
void h_set_mouse_y( zmemory *m, int y ); | |
void h_set_interpreter_number( zmemory *m, int n ); | |
void h_set_interpreter_version( zmemory *m, int v ); | |
void h_set_screen_rows( zmemory *m, int r ); | |
void h_set_screen_cols( zmemory *m, int c ); | |
void h_set_screen_width( zmemory *m, int w ); | |
void h_set_screen_height( zmemory *m, int h ); | |
void h_set_font_width( zmemory *m, int w ); | |
void h_set_font_height( zmemory *m, int h ); | |
void h_set_default_background_color( zmemory *m, int c ); | |
void h_set_default_foreground_color( zmemory *m, int c ); | |
void h_set_output_stream3_width( zmemory *m, int w ); | |
void h_set_standard_major( zmemory *m, int n ); | |
void h_set_standard_minor( zmemory *m, int n ); | |
/** Object related functions. **/ | |
zaddr obj_next_prop_addr( zmachine *zm, zaddr prop ); | |
void obj_set_parent( zmachine *zm, zword n, zword pn ); | |
void obj_set_sibling( zmachine *zm, zword n, zword sn ); | |
void obj_set_child( zmachine *zm, zword n, zword cn ); | |
/** Processor related functions. **/ | |
void load_operand( zmachine *zm, zbyte type ); | |
void load_all_operands( zmachine *zm, zbyte specifier ); | |
bool p_step( zmachine *zm ); | |
zword p_load_global( zmachine *zm, zbyte variable ); | |
zword p_load( zmachine *zm ); | |
void p_store_global( zmachine *zm, zbyte variable, zword value ); | |
void p_store( zmachine *zm, zword value ); | |
void p_call( zmachine *zm, zword routine, int argc, zword *args, int ct ); | |
void p_ret( zmachine *zm, zword value ); | |
void p_branch( zmachine *zm, bool flag ); | |
void p_skip_embedded_string( zmachine *zm ); | |
void storew( zmachine *zm, zaddr addr, zword value ); | |
void storeb( zmachine *zm, zaddr addr, zbyte value ); | |
/** Text processing **/ | |
zchar translate_from_zscii( zmemory *zm, zbyte c ); | |
zbyte translate_to_zscii( zmemory *zm, zchar c ); | |
zchar alphabet( zmemory *zm, int set, int index ); | |
/* Ops */ | |
void z_add( zmachine *zm ); | |
void z_and( zmachine * ); | |
void z_art_shift( zmachine * ); | |
void z_buffer_mode( zmachine * ); | |
void z_call_n( zmachine * ); | |
void z_call_s( zmachine * ); | |
void z_catch( zmachine * ); | |
void z_check_arg_count( zmachine * ); | |
void z_check_unicode( zmachine * ); | |
void z_clear_attr( zmachine * ); | |
void z_copy_table( zmachine * ); | |
void z_dec( zmachine * ); | |
void z_dec_chk( zmachine * ); | |
void z_div( zmachine * ); | |
void z_draw_picture( zmachine * ); | |
void z_encode_text( zmachine * ); | |
void z_erase_line( zmachine * ); | |
void z_erase_picture( zmachine * ); | |
void z_erase_window( zmachine * ); | |
void z_extended( zmachine * ); | |
void z_get_child( zmachine * ); | |
void z_get_cursor( zmachine * ); | |
void z_get_next_prop( zmachine * ); | |
void z_get_parent( zmachine * ); | |
void z_get_prop( zmachine * ); | |
void z_get_prop_addr( zmachine * ); | |
void z_get_prop_len( zmachine * ); | |
void z_get_sibling( zmachine * ); | |
void z_get_wind_prop( zmachine * ); | |
void z_illegal( zmachine * ); | |
void z_inc( zmachine * ); | |
void z_inc_chk( zmachine * ); | |
void z_input_stream( zmachine * ); | |
void z_insert_obj( zmachine * ); | |
void z_je( zmachine * ); | |
void z_jg( zmachine * ); | |
void z_jin( zmachine * ); | |
void z_jl( zmachine * ); | |
void z_jump( zmachine * ); | |
void z_jz( zmachine * ); | |
void z_load( zmachine * ); | |
void z_loadb( zmachine * ); | |
void z_loadw( zmachine * ); | |
void z_log_shift( zmachine * ); | |
void z_make_menu( zmachine * ); | |
void z_mod( zmachine * ); | |
void z_mouse_window( zmachine * ); | |
void z_move_window( zmachine * ); | |
void z_mul( zmachine * ); | |
void z_new_line( zmachine * ); | |
void z_nop( zmachine * ); | |
void z_not( zmachine * ); | |
void z_or( zmachine * ); | |
void z_output_stream( zmachine * ); | |
void z_picture_data( zmachine * ); | |
void z_picture_table( zmachine * ); | |
void z_piracy( zmachine * ); | |
void z_pop( zmachine * ); | |
void z_pop_stack( zmachine * ); | |
void z_print( zmachine * ); | |
void z_print_addr( zmachine * ); | |
void z_print_char( zmachine * ); | |
void z_print_form( zmachine * ); | |
void z_print_num( zmachine * ); | |
void z_print_obj( zmachine * ); | |
void z_print_paddr( zmachine * ); | |
void z_print_ret( zmachine * ); | |
void z_print_table( zmachine * ); | |
void z_print_unicode( zmachine * ); | |
void z_pull( zmachine * ); | |
void z_push( zmachine * ); | |
void z_push_stack( zmachine * ); | |
void z_put_prop( zmachine * ); | |
void z_put_wind_prop( zmachine * ); | |
void z_quit( zmachine * ); | |
void z_random( zmachine * ); | |
void z_read( zmachine * ); | |
void z_read_char( zmachine * ); | |
void z_read_mouse( zmachine * ); | |
void z_remove_obj( zmachine * ); | |
void z_restart( zmachine * ); | |
void z_restore( zmachine * ); | |
void z_restore_undo( zmachine * ); | |
void z_ret( zmachine * ); | |
void z_ret_popped( zmachine * ); | |
void z_rfalse( zmachine * ); | |
void z_rtrue( zmachine * ); | |
void z_save( zmachine * ); | |
void z_save_undo( zmachine * ); | |
void z_scan_table( zmachine * ); | |
void z_scroll_window( zmachine * ); | |
void z_set_attr( zmachine * ); | |
void z_set_font( zmachine * ); | |
void z_set_colour( zmachine * ); | |
void z_set_cursor( zmachine * ); | |
void z_set_margins( zmachine * ); | |
void z_set_window( zmachine * ); | |
void z_set_text_style( zmachine * ); | |
void z_show_status( zmachine * ); | |
void z_sound_effect( zmachine * ); | |
void z_split_window( zmachine * ); | |
void z_store( zmachine * ); | |
void z_storeb( zmachine * ); | |
void z_storew( zmachine * ); | |
void z_sub( zmachine * ); | |
void z_test( zmachine * ); | |
void z_test_attr( zmachine * ); | |
void z_throw( zmachine * ); | |
void z_tokenise( zmachine * ); | |
void z_verify( zmachine * ); | |
void z_window_size( zmachine * ); | |
void z_window_style( zmachine * ); | |
extern z_op op0_opcodes[0x10]; | |
extern z_op op1_opcodes[0x10]; | |
extern z_op var_opcodes[0x40]; | |
extern z_op ext_opcodes[0x1d]; | |
extern char* op0_opcode_names[0x10]; | |
extern char* op1_opcode_names[0x10]; | |
extern char* var_opcode_names[0x40]; | |
extern char* ext_opcode_names[0x1d]; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment