From dce12aedb7f597d85daf4ae5dfc4e058ae2f7b5c Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Tue, 13 Dec 2005 01:21:58 +0100 Subject: [PATCH] rnd-20051213-1-src * added level file chunk "CONF" for generic level and element settings * uploaded pre-release (test) version 3.2.0-4 binary and source code --- ChangeLog | 6 + Makefile | 3 + src/conftime.h | 2 +- src/editor.c | 44 +++---- src/files.c | 309 ++++++++++++++++++++++++++++++++++++++++----- src/game.c | 20 +-- src/libgame/misc.c | 89 +++++++++---- src/libgame/misc.h | 16 ++- src/main.h | 16 ++- 9 files changed, 409 insertions(+), 96 deletions(-) diff --git a/ChangeLog b/ChangeLog index bf34b624..e6e0dd62 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2005-12-12 + * added level file chunk "CONF" for generic level and element settings + +2005-12-11 + * uploaded pre-release (test) version 3.2.0-4 binary and source code + 2005-12-11 * skip empty level sets (with "levels: 0"; may be artwork base sets) * added sound action ".page[1]" to ".page[32]" for each CE change page diff --git a/Makefile b/Makefile index 832269b0..4a242ed0 100644 --- a/Makefile +++ b/Makefile @@ -135,6 +135,9 @@ backup_lev: backup_gfx: ./Scripts/make_backup.sh gfx +# prerelease: +# ./Scripts/make_prerelease.sh + dist-unix: ./Scripts/make_dist.sh unix . diff --git a/src/conftime.h b/src/conftime.h index bfeeb185..fa2b987c 100644 --- a/src/conftime.h +++ b/src/conftime.h @@ -1 +1 @@ -#define COMPILE_DATE_STRING "[2005-12-11 03:16]" +#define COMPILE_DATE_STRING "[2005-12-13 01:12]" diff --git a/src/editor.c b/src/editor.c index d141e16a..8c68e5c1 100644 --- a/src/editor.c +++ b/src/editor.c @@ -4170,7 +4170,7 @@ static void DrawDrawingArea(int id) for (x = 0; x < 3; x++) DrawMiniGraphicExt(drawto, gi->x + x * MINI_TILEX, gi->y + y * MINI_TILEY, - el2edimg(custom_element.content[x][y])); + el2edimg(custom_element.content.e[x][y])); else if (id == ED_DRAWING_ID_CUSTOM_MOVE_ENTER) DrawMiniGraphicExt(drawto, gi->x, gi->y, el2edimg(custom_element.move_enter_element)); @@ -4185,7 +4185,7 @@ static void DrawDrawingArea(int id) for (x = 0; x < 3; x++) DrawMiniGraphicExt(drawto, gi->x + x * MINI_TILEX, gi->y + y * MINI_TILEY, - el2edimg(custom_element_change.target_content[x][y])); + el2edimg(custom_element_change.target_content.e[x][y])); else if (id == ED_DRAWING_ID_CUSTOM_CHANGE_TRIGGER) DrawMiniGraphicExt(drawto, gi->x, gi->y, el2edimg(custom_element_change.trigger_element)); @@ -4202,7 +4202,7 @@ static void DrawDrawingArea(int id) for (x = 0; x < 3; x++) DrawMiniGraphicExt(drawto, gi->x + x * MINI_TILEX, gi->y + y * MINI_TILEY, - el2edimg(level.yamyam_content[nr][x][y])); + el2edimg(level.yamyam_content[nr].e[x][y])); } else if (id >= ED_DRAWING_ID_MAGIC_BALL_CONTENT_0 && id <= ED_DRAWING_ID_MAGIC_BALL_CONTENT_7) @@ -4213,7 +4213,7 @@ static void DrawDrawingArea(int id) for (x = 0; x < 3; x++) DrawMiniGraphicExt(drawto, gi->x + x * MINI_TILEX, gi->y + y * MINI_TILEY, - el2edimg(level.ball_content[nr][x][y])); + el2edimg(level.ball_content[nr].e[x][y])); } } @@ -5737,7 +5737,7 @@ static void copy_custom_element_settings(int element_from, int element_to) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - ei_to->content[x][y] = ei_from->content[x][y]; + ei_to->content.e[x][y] = ei_from->content.e[x][y]; ei_to->explosion_type = ei_from->explosion_type; ei_to->explosion_delay = ei_from->explosion_delay; @@ -5772,8 +5772,8 @@ static void replace_custom_element_in_settings(int element_from, for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - if (ei->content[x][y] == element_from) - ei->content[x][y] = element_to; + if (ei->content.e[x][y] == element_from) + ei->content.e[x][y] = element_to; for (j = 0; j < ei->num_change_pages; j++) { @@ -5787,8 +5787,8 @@ static void replace_custom_element_in_settings(int element_from, for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - if (change->target_content[x][y] == element_from) - change->target_content[x][y] = element_to; + if (change->target_content.e[x][y] == element_from) + change->target_content.e[x][y] = element_to; } if (ei->group != NULL) /* group or internal */ @@ -6558,7 +6558,7 @@ static void DrawMagicBallContentAreas() int y = SY + ED_AREA_MAGIC_BALL_CONTENT_YPOS(0) + ED_BORDER_AREA_YSIZE; int i; - for (i = 0; i < NUM_MAGIC_BALL_CONTENTS; i++) + for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) MapDrawingArea(ED_DRAWING_ID_MAGIC_BALL_CONTENT_0 + i); DrawText(x, y + 0 * MINI_TILEY, "generated", FONT_TEXT_1); @@ -8124,7 +8124,7 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) } else if (id == GADGET_ID_CUSTOM_CONTENT) { - custom_element.content[sx][sy] = new_element; + custom_element.content.e[sx][sy] = new_element; CopyCustomElementPropertiesToGame(properties_element); } @@ -8148,7 +8148,7 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) } else if (id == GADGET_ID_CUSTOM_CHANGE_CONTENT) { - custom_element_change.target_content[sx][sy] = new_element; + custom_element_change.target_content.e[sx][sy] = new_element; CopyCustomElementPropertiesToGame(properties_element); } @@ -8168,11 +8168,11 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) random_placement_background_element = new_element; else if (id >= GADGET_ID_YAMYAM_CONTENT_0 && id <= GADGET_ID_YAMYAM_CONTENT_7) - level.yamyam_content[id - GADGET_ID_YAMYAM_CONTENT_0][sx][sy] = + level.yamyam_content[id - GADGET_ID_YAMYAM_CONTENT_0].e[sx][sy] = new_element; else if (id >= GADGET_ID_MAGIC_BALL_CONTENT_0 && id <= GADGET_ID_MAGIC_BALL_CONTENT_7) - level.ball_content[id - GADGET_ID_MAGIC_BALL_CONTENT_0][sx][sy] = + level.ball_content[id - GADGET_ID_MAGIC_BALL_CONTENT_0].e[sx][sy] = new_element; } break; @@ -8277,7 +8277,7 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) else if (id == GADGET_ID_CUSTOM_GRAPHIC) PickDrawingElement(button, custom_element.gfx_element); else if (id == GADGET_ID_CUSTOM_CONTENT) - PickDrawingElement(button, custom_element.content[sx][sy]); + PickDrawingElement(button, custom_element.content.e[sx][sy]); else if (id == GADGET_ID_CUSTOM_MOVE_ENTER) PickDrawingElement(button, custom_element.move_enter_element); else if (id == GADGET_ID_CUSTOM_MOVE_LEAVE) @@ -8285,7 +8285,7 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) else if (id == GADGET_ID_CUSTOM_CHANGE_TARGET) PickDrawingElement(button, custom_element_change.target_element); else if (id == GADGET_ID_CUSTOM_CHANGE_CONTENT) - PickDrawingElement(button, custom_element_change.target_content[sx][sy]); + PickDrawingElement(button, custom_element_change.target_content.e[sx][sy]); else if (id == GADGET_ID_CUSTOM_CHANGE_TRIGGER) PickDrawingElement(button, custom_element_change.trigger_element); else if (id == GADGET_ID_GROUP_CONTENT) @@ -8297,14 +8297,14 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) { int i = id - GADGET_ID_YAMYAM_CONTENT_0; - PickDrawingElement(button, level.yamyam_content[i][sx][sy]); + PickDrawingElement(button, level.yamyam_content[i].e[sx][sy]); } else if (id >= GADGET_ID_MAGIC_BALL_CONTENT_0 && id <= GADGET_ID_MAGIC_BALL_CONTENT_7) { int i = id - GADGET_ID_MAGIC_BALL_CONTENT_0; - PickDrawingElement(button, level.ball_content[i][sx][sy]); + PickDrawingElement(button, level.ball_content[i].e[sx][sy]); } break; @@ -9267,7 +9267,7 @@ static void HandleDrawingAreaInfo(struct GadgetInfo *gi) else if (id == GADGET_ID_CUSTOM_GRAPHIC) element = custom_element.gfx_element; else if (id == GADGET_ID_CUSTOM_CONTENT) - element = custom_element.content[sx][sy]; + element = custom_element.content.e[sx][sy]; else if (id == GADGET_ID_CUSTOM_MOVE_ENTER) element = custom_element.move_enter_element; else if (id == GADGET_ID_CUSTOM_MOVE_LEAVE) @@ -9275,7 +9275,7 @@ static void HandleDrawingAreaInfo(struct GadgetInfo *gi) else if (id == GADGET_ID_CUSTOM_CHANGE_TARGET) element = custom_element_change.target_element; else if (id == GADGET_ID_CUSTOM_CHANGE_CONTENT) - element = custom_element_change.target_content[sx][sy]; + element = custom_element_change.target_content.e[sx][sy]; else if (id == GADGET_ID_CUSTOM_CHANGE_TRIGGER) element = custom_element_change.trigger_element; else if (id == GADGET_ID_GROUP_CONTENT) @@ -9284,10 +9284,10 @@ static void HandleDrawingAreaInfo(struct GadgetInfo *gi) element = random_placement_background_element; else if (id >= GADGET_ID_YAMYAM_CONTENT_0 && id <= GADGET_ID_YAMYAM_CONTENT_7) - element = level.yamyam_content[id - GADGET_ID_YAMYAM_CONTENT_0][sx][sy]; + element = level.yamyam_content[id -GADGET_ID_YAMYAM_CONTENT_0].e[sx][sy]; else if (id >= GADGET_ID_MAGIC_BALL_CONTENT_0 && id <= GADGET_ID_MAGIC_BALL_CONTENT_7) - element = level.ball_content[id -GADGET_ID_MAGIC_BALL_CONTENT_0][sx][sy]; + element =level.ball_content[id-GADGET_ID_MAGIC_BALL_CONTENT_0].e[sx][sy]; strncpy(infotext, getElementInfoText(element), max_infotext_len); } diff --git a/src/files.c b/src/files.c index f15e9070..95268e5f 100644 --- a/src/files.c +++ b/src/files.c @@ -49,6 +49,81 @@ #define TAPE_COOKIE_TMPL "ROCKSNDIAMONDS_TAPE_FILE_VERSION_x.x" #define SCORE_COOKIE "ROCKSNDIAMONDS_SCORE_FILE_VERSION_1.2" +/* values for "CONF" chunk */ +#define CONF_MASK_1_BYTE 0x00 +#define CONF_MASK_2_BYTE 0x40 +#define CONF_MASK_4_BYTE 0x80 +#define CONF_MASK_MULTI_BYTES 0xc0 + +#define CONF_MASK_BYTES 0xc0 +#define CONF_MASK_TOKEN 0x3f + +#define CONF_LAST_ENTRY (CONF_MASK_1_BYTE | 0) + +#define CONF_VALUE_SCORE_1 (CONF_MASK_1_BYTE | 1) +#define CONF_VALUE_SCORE_2 (CONF_MASK_1_BYTE | 2) +#define CONF_VALUE_SCORE_3 (CONF_MASK_1_BYTE | 3) +#define CONF_VALUE_SCORE_4 (CONF_MASK_1_BYTE | 4) +#define CONF_VALUE_TIME_1 (CONF_MASK_1_BYTE | 5) +#define CONF_VALUE_TIME_2 (CONF_MASK_1_BYTE | 6) +#define CONF_VALUE_TIME_3 (CONF_MASK_1_BYTE | 7) +#define CONF_VALUE_TIME_4 (CONF_MASK_1_BYTE | 8) +#define CONF_VALUE_SWITCH_1 (CONF_MASK_1_BYTE | 9) +#define CONF_VALUE_SWITCH_2 (CONF_MASK_1_BYTE | 10) +#define CONF_VALUE_SWITCH_3 (CONF_MASK_1_BYTE | 11) +#define CONF_VALUE_SWITCH_4 (CONF_MASK_1_BYTE | 12) +#define CONF_VALUE_USE_BUG_1 (CONF_MASK_1_BYTE | 13) +#define CONF_VALUE_USE_BUG_2 (CONF_MASK_1_BYTE | 14) +#define CONF_VALUE_USE_BUG_3 (CONF_MASK_1_BYTE | 15) +#define CONF_VALUE_USE_BUG_4 (CONF_MASK_1_BYTE | 16) + +#define CONF_VALUE_ELEMENT_1 (CONF_MASK_2_BYTE | 1) +#define CONF_VALUE_ELEMENT_2 (CONF_MASK_2_BYTE | 2) + +#define CONF_VALUE_CONTENT_1 (CONF_MASK_MULTI_BYTES | 1) +#define CONF_VALUE_CONTENT_8 (CONF_MASK_MULTI_BYTES | 2) + +#define CONF_VALUE_BOOLEAN(x) ((x) >= CONF_VALUE_SWITCH_1 && \ + (x) <= CONF_VALUE_USE_BUG_4) + +#define CONF_VALUE_NUM_BYTES(x) ((x) == CONF_MASK_1_BYTE ? 1 : \ + (x) == CONF_MASK_2_BYTE ? 2 : \ + (x) == CONF_MASK_4_BYTE ? 4 : 0) + +#define CONF_CONTENT_NUM_ELEMENTS (3 * 3) +#define CONF_CONTENT_NUM_BYTES (CONF_CONTENT_NUM_ELEMENTS * 2) + +#define CONF_CONTENT_ELEMENT_POS(c,x,y) ((c) * CONF_CONTENT_NUM_ELEMENTS + \ + (y) * 3 + (x)) +#define CONF_CONTENT_BYTE_POS(c,x,y) (CONF_CONTENT_ELEMENT_POS(c,x,y) * 2) +#define CONF_CONTENT_ELEMENT(b,c,x,y) ((b[CONF_CONTENT_BYTE_POS(c,x,y)] << 8)|\ + (b[CONF_CONTENT_BYTE_POS(c,x,y) + 1])) + +static struct LevelInfo li; + +static struct +{ + int element; + int type; + void *value; +} element_conf[] = +{ + /* 1-byte values */ + { EL_EMC_ANDROID, CONF_VALUE_TIME_1, &li.android_move_time }, + { EL_EMC_ANDROID, CONF_VALUE_TIME_2, &li.android_clone_time }, + { EL_EMC_MAGIC_BALL, CONF_VALUE_TIME_1, &li.ball_time }, + { EL_EMC_LENSES, CONF_VALUE_SCORE_1, &li.lenses_score }, + { EL_EMC_LENSES, CONF_VALUE_TIME_1, &li.lenses_time }, + { EL_EMC_MAGNIFIER, CONF_VALUE_SCORE_1, &li.magnify_score }, + { EL_EMC_MAGNIFIER, CONF_VALUE_TIME_1, &li.magnify_time }, + { EL_ROBOT, CONF_VALUE_SCORE_2, &li.slurp_score }, + + /* multi-byte values */ + { EL_EMC_MAGIC_BALL, CONF_VALUE_CONTENT_8, &li.ball_content }, + + { -1, -1, NULL }, +}; + static struct { int filetype; @@ -121,7 +196,7 @@ void setElementChangeInfoToDefaults(struct ElementChangeInfo *change) for (x = 0; x < 3; x++) for (y = 0; y < 3; y++) - change->target_content[x][y] = EL_EMPTY_SPACE; + change->target_content.e[x][y] = EL_EMPTY_SPACE; change->direct_action = 0; change->other_action = 0; @@ -196,10 +271,10 @@ static void setLevelInfoToDefaults(struct LevelInfo *level) level->lenses_time = 10; level->magnify_time = 10; level->wind_direction_initial = MV_NO_MOVING; - for (i = 0; i < NUM_MAGIC_BALL_CONTENTS; i++) + for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) for (x = 0; x < 3; x++) for (y = 0; y < 3; y++) - level->ball_content[i][x][y] = EL_EMPTY; + level->ball_content[i].e[x][y] = EL_EMPTY; for (i = 0; i < 16; i++) level->android_array[i] = FALSE; @@ -227,7 +302,7 @@ static void setLevelInfoToDefaults(struct LevelInfo *level) for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) for (x = 0; x < 3; x++) for (y = 0; y < 3; y++) - level->yamyam_content[i][x][y] = + level->yamyam_content[i].e[x][y] = (i < STD_ELEMENT_CONTENTS ? EL_ROCK : EL_EMPTY); level->field[0][0] = EL_PLAYER_1; @@ -295,7 +370,7 @@ static void setLevelInfoToDefaults(struct LevelInfo *level) for (x = 0; x < 3; x++) for (y = 0; y < 3; y++) - element_info[element].content[x][y] = EL_EMPTY_SPACE; + element_info[element].content.e[x][y] = EL_EMPTY_SPACE; element_info[element].access_type = 0; element_info[element].access_layer = 0; @@ -762,7 +837,7 @@ static int LoadLevel_HEAD(FILE *file, int chunk_size, struct LevelInfo *level) for (i = 0; i < STD_ELEMENT_CONTENTS; i++) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - level->yamyam_content[i][x][y] = getMappedElement(getFile8Bit(file)); + level->yamyam_content[i].e[x][y] = getMappedElement(getFile8Bit(file)); level->amoeba_speed = getFile8Bit(file); level->time_magic_wall = getFile8Bit(file); @@ -866,7 +941,7 @@ static int LoadLevel_CONT(FILE *file, int chunk_size, struct LevelInfo *level) for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - level->yamyam_content[i][x][y] = + level->yamyam_content[i].e[x][y] = getMappedElement(level->encoding_16bit_field ? getFile16BitBE(file) : getFile8Bit(file)); return chunk_size; @@ -902,7 +977,7 @@ static int LoadLevel_CNT2(FILE *file, int chunk_size, struct LevelInfo *level) for (i = 0; i < num_contents; i++) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - level->yamyam_content[i][x][y] = content_array[i][x][y]; + level->yamyam_content[i].e[x][y] = content_array[i][x][y]; } else if (element == EL_BD_AMOEBA) { @@ -1053,7 +1128,7 @@ static int LoadLevel_CUS3(FILE *file, int chunk_size, struct LevelInfo *level) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - element_info[element].content[x][y] = + element_info[element].content.e[x][y] = getMappedElement(getFile16BitBE(file)); event_bits = getFile32BitBE(file); @@ -1081,7 +1156,7 @@ static int LoadLevel_CUS3(FILE *file, int chunk_size, struct LevelInfo *level) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - element_info[element].change->target_content[x][y] = + element_info[element].change->target_content.e[x][y] = getMappedElement(getFile16BitBE(file)); element_info[element].slippery_type = getFile8Bit(file); @@ -1158,7 +1233,7 @@ static int LoadLevel_CUS4(FILE *file, int chunk_size, struct LevelInfo *level) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - ei->content[x][y] = getMappedElement(getFile16BitBE(file)); + ei->content.e[x][y] = getMappedElement(getFile16BitBE(file)); ei->move_enter_element = getMappedElement(getFile16BitBE(file)); ei->move_leave_element = getMappedElement(getFile16BitBE(file)); @@ -1211,7 +1286,7 @@ static int LoadLevel_CUS4(FILE *file, int chunk_size, struct LevelInfo *level) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - change->target_content[x][y] = getMappedElement(getFile16BitBE(file)); + change->target_content.e[x][y]= getMappedElement(getFile16BitBE(file)); change->can_change = getFile8Bit(file); @@ -1282,6 +1357,96 @@ static int LoadLevel_GRP1(FILE *file, int chunk_size, struct LevelInfo *level) return chunk_size; } +static int LoadLevel_CONF(FILE *file, int chunk_size, struct LevelInfo *level) +{ + int real_chunk_size = 0; + int i; + + while (!feof(file)) + { + int element = getFile16BitBE(file); + int type = getFile8Bit(file); + int bytes = type & CONF_MASK_BYTES; + boolean element_found = FALSE; + + real_chunk_size += 3; + + li = *level; /* copy level information into temporary buffer */ + + if (bytes == CONF_MASK_MULTI_BYTES) + { + int num_bytes = getFile16BitBE(file); + byte *buffer = checked_malloc(num_bytes); + + ReadBytesFromFile(file, buffer, num_bytes); + + for (i = 0; element_conf[i].element != -1; i++) + { + if (element_conf[i].element == element && + element_conf[i].type == type) + { + element_found = TRUE; + + if (type == CONF_VALUE_CONTENT_8) + { + struct Content *content= (struct Content *)(element_conf[i].value); + int num_contents = num_bytes / CONF_CONTENT_NUM_BYTES; + int c, x, y; + + for (c = 0; c < num_contents; c++) + for (y = 0; y < 3; y++) + for (x = 0; x < 3; x++) + content[c].e[x][y] = + getMappedElement(CONF_CONTENT_ELEMENT(buffer, c, x, y)); + } + else + element_found = FALSE; + + break; + } + } + + checked_free(buffer); + + real_chunk_size += 2 + num_bytes; + } + else + { + int value = (bytes == CONF_MASK_1_BYTE ? getFile8Bit (file) : + bytes == CONF_MASK_2_BYTE ? getFile16BitBE(file) : + bytes == CONF_MASK_4_BYTE ? getFile32BitBE(file) : 0); + + for (i = 0; element_conf[i].element != -1; i++) + { + if (element_conf[i].element == element && + element_conf[i].type == type) + { + if (CONF_VALUE_BOOLEAN(type)) + *(boolean *)(element_conf[i].value) = value; + else + *(int *) (element_conf[i].value) = value; + + element_found = TRUE; + + break; + } + } + + real_chunk_size += CONF_VALUE_NUM_BYTES(bytes); + } + + *level = li; /* copy temporary buffer back to level information */ + + if (!element_found) + Error(ERR_WARN, "cannot load CONF value for element %d", element); + + if (type == CONF_LAST_ENTRY || real_chunk_size >= chunk_size) + break; + } + + return real_chunk_size; +} + static void LoadLevelFromFileInfo_RND(struct LevelInfo *level, struct LevelFileInfo *level_file_info) { @@ -1373,6 +1538,8 @@ static void LoadLevelFromFileInfo_RND(struct LevelInfo *level, { "CUS3", -1, LoadLevel_CUS3 }, { "CUS4", -1, LoadLevel_CUS4 }, { "GRP1", -1, LoadLevel_GRP1 }, + { "CONF", -1, LoadLevel_CONF }, + { NULL, 0, NULL } }; @@ -1815,7 +1982,7 @@ static void OLD_LoadLevelFromFileInfo_EM(struct LevelInfo *level, for (i = 0; i < level->num_yamyam_contents; i++) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - level->yamyam_content[i][x][y] = + level->yamyam_content[i].e[x][y] = map_em_element_yam(header[i * 9 + y * 3 + x]); level->amoeba_speed = (header[52] * 256 + header[53]) % 256; @@ -1884,7 +2051,7 @@ void CopyNativeLevel_RND_to_EM(struct LevelInfo *level) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) lev->eater_array[i][y * 3 + x] = - map_element_RND_to_EM(level->yamyam_content[i][x][y]); + map_element_RND_to_EM(level->yamyam_content[i].e[x][y]); lev->amoeba_time = level->amoeba_speed; lev->wonderwall_time_initial = level->time_magic_wall; @@ -1904,11 +2071,11 @@ void CopyNativeLevel_RND_to_EM(struct LevelInfo *level) lev->magnify_time = level->magnify_time; lev->wind_direction_initial = level->wind_direction_initial; - for (i = 0; i < NUM_MAGIC_BALL_CONTENTS; i++) + for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) for (j = 0; j < 8; j++) lev->ball_array[i][j] = map_element_RND_to_EM(level-> - ball_content[i][ball_xy[j][0]][ball_xy[j][1]]); + ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]]); for (i = 0; i < 16; i++) lev->android_array[i] = FALSE; /* !!! YET TO COME !!! */ @@ -1996,7 +2163,7 @@ void CopyNativeLevel_EM_to_RND(struct LevelInfo *level) for (i = 0; i < level->num_yamyam_contents; i++) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - level->yamyam_content[i][x][y] = + level->yamyam_content[i].e[x][y] = map_element_EM_to_RND(lev->eater_array[i][y * 3 + x]); level->amoeba_speed = lev->amoeba_time; @@ -2017,9 +2184,9 @@ void CopyNativeLevel_EM_to_RND(struct LevelInfo *level) level->magnify_time = lev->magnify_time; level->wind_direction_initial = lev->wind_direction_initial; - for (i = 0; i < NUM_MAGIC_BALL_CONTENTS; i++) + for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) for (j = 0; j < 8; j++) - level->ball_content[i][ball_xy[j][0]][ball_xy[j][1]] = + level->ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]] = map_element_EM_to_RND(lev->ball_array[i][j]); for (i = 0; i < 16; i++) @@ -2223,7 +2390,7 @@ static void LoadLevelFromFileStream_SP(FILE *file, struct LevelInfo *level, for (i = 0; i < level->num_yamyam_contents; i++) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - level->yamyam_content[i][x][y] = EL_EMPTY; + level->yamyam_content[i].e[x][y] = EL_EMPTY; } static void LoadLevelFromFileInfo_SP(struct LevelInfo *level, @@ -2688,8 +2855,8 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename) for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) for (x = 0; x < 3; x++) for (y = 0; y < 3; y++) - level->yamyam_content[i][x][y] = - getMappedElementByVersion(level->yamyam_content[i][x][y], + level->yamyam_content[i].e[x][y] = + getMappedElementByVersion(level->yamyam_content[i].e[x][y], level->game_version); /* initialize element properties for level editor etc. */ @@ -2777,7 +2944,7 @@ static void SaveLevel_HEAD(FILE *file, struct LevelInfo *level) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) putFile8Bit(file, (level->encoding_16bit_yamyam ? EL_EMPTY : - level->yamyam_content[i][x][y])); + level->yamyam_content[i].e[x][y])); putFile8Bit(file, level->amoeba_speed); putFile8Bit(file, level->time_magic_wall); putFile8Bit(file, level->time_wheel); @@ -2841,9 +3008,9 @@ static void SaveLevel_CONT(FILE *file, struct LevelInfo *level) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) if (level->encoding_16bit_field) - putFile16BitBE(file, level->yamyam_content[i][x][y]); + putFile16BitBE(file, level->yamyam_content[i].e[x][y]); else - putFile8Bit(file, level->yamyam_content[i][x][y]); + putFile8Bit(file, level->yamyam_content[i].e[x][y]); } #endif @@ -2862,7 +3029,7 @@ static void SaveLevel_CNT2(FILE *file, struct LevelInfo *level, int element) for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - content_array[i][x][y] = level->yamyam_content[i][x][y]; + content_array[i][x][y] = level->yamyam_content[i].e[x][y]; } else if (element == EL_BD_AMOEBA) { @@ -3016,7 +3183,7 @@ static void SaveLevel_CUS3(FILE *file, struct LevelInfo *level, for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - putFile16BitBE(file, element_info[element].content[x][y]); + putFile16BitBE(file, element_info[element].content.e[x][y]); putFile32BitBE(file, element_info[element].change->events); @@ -3038,7 +3205,7 @@ static void SaveLevel_CUS3(FILE *file, struct LevelInfo *level, for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - putFile16BitBE(file, element_info[element].change->content[x][y]); + putFile16BitBE(file,element_info[element].change->content.e[x][y]); putFile8Bit(file, element_info[element].slippery_type); @@ -3097,7 +3264,7 @@ static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - putFile16BitBE(file, ei->content[x][y]); + putFile16BitBE(file, ei->content.e[x][y]); putFile16BitBE(file, ei->move_enter_element); putFile16BitBE(file, ei->move_leave_element); @@ -3146,7 +3313,7 @@ static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - putFile16BitBE(file, change->target_content[x][y]); + putFile16BitBE(file, change->target_content.e[x][y]); putFile8Bit(file, change->can_change); @@ -3191,9 +3358,82 @@ static void SaveLevel_GRP1(FILE *file, struct LevelInfo *level, int element) putFile16BitBE(file, group->element[i]); } +static int SaveLevel_CONF_Value(FILE *file, int element, int type, int value) +{ + int bytes = type & CONF_MASK_BYTES; + int num_bytes = 0; + + if (bytes == CONF_MASK_MULTI_BYTES) + Error(ERR_EXIT, "SaveLevel_CONF_INT: invalid type CONF_MASK_MULTI_BYTES"); + + num_bytes += putFile16BitBE(file, element); + num_bytes += putFile8Bit(file, type); + num_bytes += (bytes == CONF_MASK_1_BYTE ? putFile8Bit (file, value) : + bytes == CONF_MASK_2_BYTE ? putFile16BitBE(file, value) : + bytes == CONF_MASK_4_BYTE ? putFile32BitBE(file, value) : 0); + + return num_bytes; +} + +static int SaveLevel_CONF_Content(FILE *file, int element, int type, + struct Content *content, int num_contents) +{ + int num_bytes = 0; + int i, x, y; + + num_bytes += putFile16BitBE(file, element); + num_bytes += putFile8Bit(file, type); + num_bytes += putFile16BitBE(file, num_contents * CONF_CONTENT_NUM_BYTES); + + for (i = 0; i < num_contents; i++) + for (y = 0; y < 3; y++) + for (x = 0; x < 3; x++) + num_bytes += putFile16BitBE(file, content[i].e[x][y]); + + return num_bytes; +} + +static int SaveLevel_CONF(FILE *file, struct LevelInfo *level) +{ + int chunk_size = 0; + int i; + + li = *level; /* copy level information into temporary buffer */ + + for (i = 0; element_conf[i].element != -1; i++) + { + int element = element_conf[i].element; + int type = element_conf[i].type; + void *value = element_conf[i].value; + int bytes = type & CONF_MASK_BYTES; + + if (bytes == CONF_MASK_MULTI_BYTES) + { + if (type == CONF_VALUE_CONTENT_8) + { + struct Content *content = (struct Content *)value; + + chunk_size += SaveLevel_CONF_Content(file, element, type, + content, MAX_ELEMENT_CONTENTS); + } + else + Error(ERR_WARN, "cannot save CONF value for element %d", element); + } + else + { + int value_int = (CONF_VALUE_BOOLEAN(type) ? *(boolean *)value : + *(int *)value); + + chunk_size += SaveLevel_CONF_Value(file, element, type, value_int); + } + } + + return chunk_size; +} + static void SaveLevelFromFilename(struct LevelInfo *level, char *filename) { - int body_chunk_size; + int body_chunk_size, conf_chunk_size; int i, x, y; FILE *file; @@ -3218,7 +3458,7 @@ static void SaveLevelFromFilename(struct LevelInfo *level, char *filename) for (i = 0; i < level->num_yamyam_contents; i++) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - if (level->yamyam_content[i][x][y] > 255) + if (level->yamyam_content[i].e[x][y] > 255) level->encoding_16bit_yamyam = TRUE; /* check amoeba content for 16-bit elements */ @@ -3302,6 +3542,11 @@ static void SaveLevelFromFilename(struct LevelInfo *level, char *filename) } } + conf_chunk_size = SaveLevel_CONF(NULL, level); /* get chunk size */ + + putFileChunkBE(file, "CONF", conf_chunk_size); + SaveLevel_CONF(file, level); + fclose(file); SetFilePermissions(filename, PERMS_PRIVATE); diff --git a/src/game.c b/src/game.c index d67c64e6..c4cac805 100644 --- a/src/game.c +++ b/src/game.c @@ -25,7 +25,7 @@ #define USE_NEW_AMOEBA_CODE FALSE /* EXPERIMENTAL STUFF */ -#define USE_NEW_STUFF ( * 1) +#define USE_NEW_STUFF ( 1) #define USE_NEW_SP_SLIPPERY (USE_NEW_STUFF * 1) #define USE_NEW_COLLECT_COUNT (USE_NEW_STUFF * 1) @@ -1933,7 +1933,7 @@ void InitGame() for (yy = 0; yy < 3; yy++) for (xx = 0; xx < 3; xx++) { - content = element_info[element].content[xx][yy]; + content = element_info[element].content.e[xx][yy]; is_player = ELEM_IS_PLAYER(content); if (is_player && (found_rating < 2 || element < found_element)) @@ -1950,7 +1950,9 @@ void InitGame() for (i = 0; i < element_info[element].num_change_pages; i++) { - content= element_info[element].change_page[i].target_content[xx][yy]; + content = + element_info[element].change_page[i].target_content.e[xx][yy]; + is_player = ELEM_IS_PLAYER(content); if (is_player && (found_rating < 1 || element < found_element)) @@ -3066,10 +3068,10 @@ void Explode(int ex, int ey, int phase, int mode) else if (center_element == EL_AMOEBA_TO_DIAMOND) Store[x][y] = level.amoeba_content; else if (center_element == EL_YAMYAM) - Store[x][y] = level.yamyam_content[game.yamyam_content_nr][xx][yy]; + Store[x][y] = level.yamyam_content[game.yamyam_content_nr].e[xx][yy]; else if (IS_CUSTOM_ELEMENT(center_element) && - element_info[center_element].content[xx][yy] != EL_EMPTY) - Store[x][y] = element_info[center_element].content[xx][yy]; + element_info[center_element].content.e[xx][yy] != EL_EMPTY) + Store[x][y] = element_info[center_element].content.e[xx][yy]; else if (element == EL_WALL_EMERALD) Store[x][y] = EL_EMERALD; else if (element == EL_WALL_DIAMOND) @@ -3087,7 +3089,7 @@ void Explode(int ex, int ey, int phase, int mode) else if (element == EL_WALL_CRYSTAL) Store[x][y] = EL_CRYSTAL; else if (IS_CUSTOM_ELEMENT(element) && !CAN_EXPLODE(element)) - Store[x][y] = element_info[element].content[1][1]; + Store[x][y] = element_info[element].content.e[1][1]; else Store[x][y] = EL_EMPTY; @@ -6966,7 +6968,7 @@ static boolean ChangeElementNow(int x, int y, int element, int page) boolean is_destructible; int ex = x + xx - 1; int ey = y + yy - 1; - int content_element = change->target_content[xx][yy]; + int content_element = change->target_content.e[xx][yy]; int e; can_replace[xx][yy] = TRUE; @@ -7038,7 +7040,7 @@ static boolean ChangeElementNow(int x, int y, int element, int page) ChangeEvent[ex][ey] = ChangeEvent[x][y]; - content_element = change->target_content[xx][yy]; + content_element = change->target_content.e[xx][yy]; target_element = GET_TARGET_ELEMENT(content_element, change); ChangeElementNowExt(change, ex, ey, target_element); diff --git a/src/libgame/misc.c b/src/libgame/misc.c index 20962f8b..39eca58a 100644 --- a/src/libgame/misc.c +++ b/src/libgame/misc.c @@ -925,6 +925,25 @@ inline void swap_number_pairs(int *x1, int *y1, int *x2, int *y2) *y2 = help_y; } +/* the "put" variants of the following file access functions check for the file + pointer being != NULL and return the number of bytes they have or would have + written; this allows for chunk writing functions to first determine the size + of the (not yet written) chunk, write the correct chunk size and finally + write the chunk itself */ + +int getFile8BitInteger(FILE *file) +{ + return fgetc(file); +} + +int putFile8BitInteger(FILE *file, int value) +{ + if (file != NULL) + fputc(value, file); + + return 1; +} + int getFile16BitInteger(FILE *file, int byte_order) { if (byte_order == BYTE_ORDER_BIG_ENDIAN) @@ -935,18 +954,23 @@ int getFile16BitInteger(FILE *file, int byte_order) (fgetc(file) << 8)); } -void putFile16BitInteger(FILE *file, int value, int byte_order) +int putFile16BitInteger(FILE *file, int value, int byte_order) { - if (byte_order == BYTE_ORDER_BIG_ENDIAN) + if (file != NULL) { - fputc((value >> 8) & 0xff, file); - fputc((value >> 0) & 0xff, file); - } - else /* BYTE_ORDER_LITTLE_ENDIAN */ - { - fputc((value >> 0) & 0xff, file); - fputc((value >> 8) & 0xff, file); + if (byte_order == BYTE_ORDER_BIG_ENDIAN) + { + fputc((value >> 8) & 0xff, file); + fputc((value >> 0) & 0xff, file); + } + else /* BYTE_ORDER_LITTLE_ENDIAN */ + { + fputc((value >> 0) & 0xff, file); + fputc((value >> 8) & 0xff, file); + } } + + return 2; } int getFile32BitInteger(FILE *file, int byte_order) @@ -963,22 +987,27 @@ int getFile32BitInteger(FILE *file, int byte_order) (fgetc(file) << 24)); } -void putFile32BitInteger(FILE *file, int value, int byte_order) +int putFile32BitInteger(FILE *file, int value, int byte_order) { - if (byte_order == BYTE_ORDER_BIG_ENDIAN) + if (file != NULL) { - fputc((value >> 24) & 0xff, file); - fputc((value >> 16) & 0xff, file); - fputc((value >> 8) & 0xff, file); - fputc((value >> 0) & 0xff, file); - } - else /* BYTE_ORDER_LITTLE_ENDIAN */ - { - fputc((value >> 0) & 0xff, file); - fputc((value >> 8) & 0xff, file); - fputc((value >> 16) & 0xff, file); - fputc((value >> 24) & 0xff, file); + if (byte_order == BYTE_ORDER_BIG_ENDIAN) + { + fputc((value >> 24) & 0xff, file); + fputc((value >> 16) & 0xff, file); + fputc((value >> 8) & 0xff, file); + fputc((value >> 0) & 0xff, file); + } + else /* BYTE_ORDER_LITTLE_ENDIAN */ + { + fputc((value >> 0) & 0xff, file); + fputc((value >> 8) & 0xff, file); + fputc((value >> 16) & 0xff, file); + fputc((value >> 24) & 0xff, file); + } } + + return 4; } boolean getFileChunk(FILE *file, char *chunk_name, int *chunk_size, @@ -1035,6 +1064,22 @@ void putFileVersion(FILE *file, int version) fputc(version_build, file); } +void ReadBytesFromFile(FILE *file, byte *buffer, unsigned long bytes) +{ + int i; + + for(i = 0; i < bytes && !feof(file); i++) + buffer[i] = fgetc(file); +} + +void WriteBytesToFile(FILE *file, byte *buffer, unsigned long bytes) +{ + int i; + + for(i = 0; i < bytes; i++) + fputc(buffer[i], file); +} + void ReadUnusedBytesFromFile(FILE *file, unsigned long bytes) { while (bytes-- && !feof(file)) diff --git a/src/libgame/misc.h b/src/libgame/misc.h index b89be4e8..caa57ea3 100644 --- a/src/libgame/misc.h +++ b/src/libgame/misc.h @@ -118,19 +118,26 @@ void checked_free(void *); inline void swap_numbers(int *, int *); inline void swap_number_pairs(int *, int *, int *, int *); +int getFile8BitInteger(FILE *); +int putFile8BitInteger(FILE *, int); int getFile16BitInteger(FILE *, int); -void putFile16BitInteger(FILE *, int, int); +int putFile16BitInteger(FILE *, int, int); int getFile32BitInteger(FILE *, int); -void putFile32BitInteger(FILE *, int, int); +int putFile32BitInteger(FILE *, int, int); + boolean getFileChunk(FILE *, char *, int *, int); void putFileChunk(FILE *, char *, int, int); int getFileVersion(FILE *); void putFileVersion(FILE *, int); + +void ReadBytesFromFile(FILE *, byte *, unsigned long); +void WriteBytesToFile(FILE *, byte *, unsigned long); + void ReadUnusedBytesFromFile(FILE *, unsigned long); void WriteUnusedBytesToFile(FILE *, unsigned long); -#define getFile8Bit(f) fgetc(f) -#define putFile8Bit(f,x) fputc(x, f) +#define getFile8Bit(f) getFile8BitInteger(f) +#define putFile8Bit(f,x) putFile8BitInteger(f,x) #define getFile16BitBE(f) getFile16BitInteger(f,BYTE_ORDER_BIG_ENDIAN) #define getFile16BitLE(f) getFile16BitInteger(f,BYTE_ORDER_LITTLE_ENDIAN) #define putFile16BitBE(f,x) putFile16BitInteger(f,x,BYTE_ORDER_BIG_ENDIAN) @@ -139,6 +146,7 @@ void WriteUnusedBytesToFile(FILE *, unsigned long); #define getFile32BitLE(f) getFile32BitInteger(f,BYTE_ORDER_LITTLE_ENDIAN) #define putFile32BitBE(f,x) putFile32BitInteger(f,x,BYTE_ORDER_BIG_ENDIAN) #define putFile32BitLE(f,x) putFile32BitInteger(f,x,BYTE_ORDER_LITTLE_ENDIAN) + #define getFileChunkBE(f,s,x) getFileChunk(f,s,x,BYTE_ORDER_BIG_ENDIAN) #define getFileChunkLE(f,s,x) getFileChunk(f,s,x,BYTE_ORDER_LITTLE_ENDIAN) #define putFileChunkBE(f,s,x) putFileChunk(f,s,x,BYTE_ORDER_BIG_ENDIAN) diff --git a/src/main.h b/src/main.h index b52a5e8f..6e3a8293 100644 --- a/src/main.h +++ b/src/main.h @@ -651,7 +651,6 @@ #define MIN_ELEMENT_CONTENTS 1 #define STD_ELEMENT_CONTENTS 4 #define MAX_ELEMENT_CONTENTS 8 -#define NUM_MAGIC_BALL_CONTENTS 8 #define LEVEL_SCORE_ELEMENTS 16 /* level elements with score */ @@ -1482,7 +1481,7 @@ #define PROGRAM_VERSION_MAJOR 3 #define PROGRAM_VERSION_MINOR 2 #define PROGRAM_VERSION_PATCH 0 -#define PROGRAM_VERSION_BUILD 4 +#define PROGRAM_VERSION_BUILD 5 #endif #define PROGRAM_TITLE_STRING "Rocks'n'Diamonds" @@ -1584,6 +1583,11 @@ struct HiScore int Score; }; +struct Content +{ + int e[3][3]; +}; + struct PlayerInfo { boolean present; /* player present in level playfield */ @@ -1722,7 +1726,7 @@ struct LevelInfo int score[LEVEL_SCORE_ELEMENTS]; - int yamyam_content[MAX_ELEMENT_CONTENTS][3][3]; + struct Content yamyam_content[MAX_ELEMENT_CONTENTS]; int num_yamyam_contents; int amoeba_speed; @@ -1745,7 +1749,7 @@ struct LevelInfo int lenses_time; int magnify_time; int wind_direction_initial; - int ball_content[NUM_MAGIC_BALL_CONTENTS][3][3]; + struct Content ball_content[MAX_ELEMENT_CONTENTS]; boolean android_array[16]; int can_move_into_acid_bits; /* bitfield to store property for elements */ @@ -1886,7 +1890,7 @@ struct ElementChangeInfo short trigger_element; /* element triggering change */ - int target_content[3][3]; /* elements for extended change target */ + struct Content target_content;/* elements for extended change target */ boolean use_target_content; /* use extended change target */ boolean only_if_complete; /* only use complete target content */ boolean use_random_replace; /* use random value for replacing elements */ @@ -1997,7 +2001,7 @@ struct ElementInfo int slippery_type; /* how/where other elements slip away */ - int content[3][3]; /* new elements after explosion */ + struct Content content; /* new elements after explosion */ int explosion_type; /* type of explosion, like 3x3, 3+3 or 1x1 */ int explosion_delay; /* duration of explosion of this element */ -- 2.34.1