git » fp-git.git » commit 92ffd67

more bugfixes

author ecalot
2004-08-25 11:17:01 UTC
committer ecalot
2004-08-25 11:17:01 UTC
parent 6a22cf52c659416d725a0a488c2b0da35ccc00ad

more bugfixes

FP/src/include/types.h +1 -0
FP/src/ker/room.c +8 -4
FP/src/res/maps.c +1180 -1180

diff --git a/FP/src/include/types.h b/FP/src/include/types.h
index 7e96ef4..4bfb09d 100644
--- a/FP/src/include/types.h
+++ b/FP/src/include/types.h
@@ -86,6 +86,7 @@ typedef struct {
 	int hasChopper;
 	int hasBigPillar;
 	int isExit;
+	int isRaise;
 	int isGate;
 	tGate* gateInfo;
 	int bricks;
diff --git a/FP/src/ker/room.c b/FP/src/ker/room.c
index 054f9b6..ebcc71d 100644
--- a/FP/src/ker/room.c
+++ b/FP/src/ker/room.c
@@ -90,6 +90,7 @@ tTile roomGetTile(tRoom* room,int x, int y) {
 		result.block=0;
 		result.isPressable=0;
 		result.hasSkeleton=0;
+		result.isRaise=0;
 		result.hasSpikes=0;
 		result.hasTorch=0;
 		result.hasFloor=0;
@@ -121,6 +122,7 @@ tTile roomGetTile(tRoom* room,int x, int y) {
 		result.hasChopper=(result.code==T_CHOPPER);
 		result.isExit=(result.code==T_EXIT_LEFT)?1:((result.code==T_EXIT_RIGHT)?2:0);
 		result.block=0;
+		result.isRaise=(result.code==T_BTN_RAISE);
 		result.isPressable=(result.code==T_BTN_RAISE)|(result.code==T_BTN_DROP);
 		result.hasSkeleton=(result.code==T_SKELETON);
 		result.hasSpikes=(result.code==T_SPIKES);
@@ -134,6 +136,7 @@ tTile roomGetTile(tRoom* room,int x, int y) {
 		result.hasGateFrame=0;
 		result.bricks=0;
 		result.hasPillar=0;
+		result.isRaise=0;
 		result.hasBigPillar=0;
 		result.walkable=0;
 		result.hasChopper=0;
@@ -161,6 +164,7 @@ tTile roomGetTile(tRoom* room,int x, int y) {
 		result.isExit=0;
 		result.isGate=0;
 		result.hasChopper=0;
+		result.isRaise=0;
 		result.isPressable=0;
 		result.hasSkeleton=0;
 		result.hasSpikes=0;
@@ -270,7 +274,7 @@ void drawBackPanel(tRoom* room,int x, int y) {
 		}
 	}
 	/* pressable/left */
-	if (left.isPressable) {
+	if (left.isRaise) {
 		outputDrawBitmap(
 			roomGfx.environment->pFrames[10],
 			(x-1)*TILE_W,
@@ -405,9 +409,9 @@ void drawBackPanel(tRoom* room,int x, int y) {
 		}
 	}
 	/* pressable/this */
-	if (tile.isPressable) {
+	if (tile.isRaise) {
 		outputDrawBitmap(
-			roomGfx.environment->pFrames[58-((left.walkable)&&(!left.isPressable))],
+			roomGfx.environment->pFrames[58-((left.walkable)&&(!left.isRaise))],
 			(x-1)*TILE_W,
 			y*TILE_H
 		);
@@ -453,7 +457,7 @@ void drawBackBottomTile(tRoom* room,int x, int y) {
 	/* normal */
 	if (tile.walkable) {
 		outputDrawBitmap(
-			roomGfx.environment->pFrames[(tile.code==T_BTN_DROP||tile.code==T_BTN_RAISE)?47:11],
+			roomGfx.environment->pFrames[(tile.isPressable)?47:11],
 			(x-1)*TILE_W,
 			y*TILE_H+3
 		);
diff --git a/FP/src/res/maps.c b/FP/src/res/maps.c
index 0408518..621f9b3 100644
--- a/FP/src/res/maps.c
+++ b/FP/src/res/maps.c
@@ -1,1180 +1,1180 @@
-/*  FreePrince - POP1 remake
-    Copyright (C) 2003,2004 Princed Development Team
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-    The authors of this program may be contacted at http://forum.princed.com.ar
-*/
-
-/*
-maps.c: Freeprince : Map handling library
-\xaf\xaf\xaf\xaf\xaf\xaf
- Copyright 2003,2004 Princed Development Team
-  Created: 24 Mar 2003
-
-  Author: Enrique Calot <ecalot.cod@princed.com.ar>
-
- Note:
-  DO NOT remove this copyright notice
-*/
-
-#include <string.h> /* mempcy */
-#include <stdlib.h> /* malloc */
-#include "maps.h"
-#include "room.h"
-#include "kid.h"
-#include "types.h"
-
-#define slevel(field) (map->field)
-
-void* mapLoadLevel(tMemory level) {
-	tMap* map=(tMap*)malloc(sizeof(tMap));
-	int i,j;
-	int gates=0;
-	int gateInRoom=0;
-	tGate** auxGates=malloc(sizeof(tGate*)*24*30);
-	
-	/* copy maps, links and start position */
-	memcpy(map->fore,level.array+MAPS_BLOCK_OFFSET_WALL,30*24);
-	memcpy(map->back,level.array+MAPS_BLOCK_OFFSET_BACK,30*24);
-	memcpy(map->start,level.array+MAPS_BLOCK_OFFSET_START_POSITION,3);
-	memcpy(map->links,level.array+MAPS_BLOCK_OFFSET_LINK,4*24);
-
-	/* generate and load gate structures */
-	for (i=0;i<24;i++) { /* count gates and create gate tree middle nodes */
-		for (j=0;j<30;j++) {
-			if (((map->fore[i*30+j]&0x1f)==T_GATE)||((map->fore[i*30+j]&0x1f)==T_EXIT_LEFT)) {
-				gateInRoom++;
-				gates++;
-			}
-		}
-		fprintf(stderr,"Screen %d has %d gates.\n",i,gateInRoom);
-		if (gateInRoom) {
-			map->screenGates[i]=malloc(gateInRoom*sizeof(tGate*));
-		} else {
-			map->screenGates[i]=NULL;
-		}
-		gateInRoom=0;
-	}
-	/* create gates sctucture */
-	map->gates=malloc(gates*sizeof(tGate));
-	map->totalGates=gates;
-	gates=0;
-	for (i=0;i<24;i++) {
-		for (j=0;j<30;j++) {
-			if (((map->fore[i*30+j]&0x1f)==T_GATE)||((map->fore[i*30+j]&0x1f)==T_EXIT_LEFT)) {
-				tGate newGate;
-				newGate.frame=map->back[i*30+j];
-				newGate.action=map->back[i*30+j]?eOpen:eClose;
-				map->back[i*30+j]=gateInRoom;
-				fprintf(stderr,"mapLoadLevel: Asignando gate pointer: screen %d, gate number %d\n",i,gateInRoom);
-				map->screenGates[i][gateInRoom]=map->gates+gates;
-				auxGates[i*30+j]=map->gates+gates;
-				fprintf(stderr,"mapLoadLevel: Loading gate: indexed=%d gate pointer=%p\n",i,(void*)auxGates[i*30+j]);
-				map->gates[gates++]=newGate;
-				gateInRoom++;
-			}
-		}
-		if (!gateInRoom) map->screenGates[i]=NULL;
-		gateInRoom=0;
-	}
-	for (i=0;i<256;i++) {
-		unsigned char byte1=level.array[MAPS_BLOCK_OFFSET_GATE_1+i];
-		unsigned char byte2=level.array[MAPS_BLOCK_OFFSET_GATE_2+i];
-		int S,L,T;
-		S=((byte1>>5)&3)|((byte2>>3)&28);
-		L=byte1&31;
-		T=!((byte1>>7)&1);
-		map->events[i].triggerNext=T;
-		map->events[i].gate=auxGates[(S-1)*30+L]; /* in case of error null is assigned */
-		fprintf(stderr,"mapLoadLevel: Loading event: S=%d L=%d T=%d gate number=%d gate pointer=%p\n",S,L,T,(S-1)*30+L,(void*)auxGates[(S-1)*30+L]);
-	}
-	free(auxGates);
-	return (void*)map;
-}
-
-tRoom mapGetRoom(tMap* map, tRoomId roomAux) {
-	tRoom result;
-
-	/* SET room id*/
-	result.id=roomAux;
-	result.level=map;
-	
-	/* SET room links */
-	memcpy(result.links,slevel(links)+((roomAux-1)*4),4);
-	/* up corners */
-	roomAux=result.links[2];
-	if (roomAux) {
-		result.corners[0]=*(slevel(links)+((roomAux-1)*4)+0);
-		result.corners[1]=*(slevel(links)+((roomAux-1)*4)+1);
-	} else {
-		result.corners[0]=0;
-		result.corners[1]=0;
-	}
-	/* down corners */
-	roomAux=result.links[3];
-	if (roomAux) {
-		result.corners[2]=*(slevel(links)+((roomAux-1)*4)+0);
-		result.corners[3]=*(slevel(links)+((roomAux-1)*4)+1);
-	} else {
-		result.corners[2]=0;
-		result.corners[3]=0;
-	}
-	
-	/* SET corner bytes */
-	/* left+up */
-	if ((roomAux=result.corners[0])) {
-		result.fore[0]=*(slevel(fore)+30*(roomAux-1)+29);
-		result.back[0]=*(slevel(back)+30*(roomAux-1)+29);
-	} else {
-		result.fore[0]=MAP_F_WALL;
-		result.back[0]=MAP_B_NONE;
-	}
-	/* right+up */
-	if ((roomAux=result.corners[1])) {
-		result.fore[11]=*(slevel(fore)+30*(roomAux-1)+20);
-		result.back[11]=*(slevel(back)+30*(roomAux-1)+20);
-	} else {
-		result.fore[11]=MAP_F_FREE;
-		result.back[11]=MAP_B_NONE;
-	}
-	/* left+down */
-	if ((roomAux=result.corners[2])) {
-		result.fore[48]=*(slevel(fore)+30*(roomAux-1)+9);
-		result.back[48]=*(slevel(back)+30*(roomAux-1)+9);
-	} else {
-		result.fore[48]=MAP_F_WALL;
-		result.back[48]=MAP_B_NONE;
-	}
-	/* right+down */
-	if ((roomAux=result.corners[3])) {
-		result.fore[59]=*(slevel(fore)+30*(roomAux-1)+0);
-		result.back[59]=*(slevel(back)+30*(roomAux-1)+0);
-	} else {
-		result.fore[59]=MAP_F_WALL;
-		result.back[59]=MAP_B_NONE;
-	}
-
-	/* Left room */
-	if ((roomAux=result.links[0])) {
-		result.fore[12]=*(slevel(fore)+30*(roomAux-1)+9);
-		result.back[12]=*(slevel(back)+30*(roomAux-1)+9);
-		result.fore[24]=*(slevel(fore)+30*(roomAux-1)+19);
-		result.back[24]=*(slevel(back)+30*(roomAux-1)+19);
-		result.fore[36]=*(slevel(fore)+30*(roomAux-1)+29);
-		result.back[36]=*(slevel(back)+30*(roomAux-1)+29);
-	} else {
-		result.fore[12]=MAP_F_WALL;
-		result.back[12]=MAP_B_NONE;
-		result.fore[24]=MAP_F_WALL;
-		result.back[24]=MAP_B_NONE;
-		result.fore[36]=MAP_F_WALL;
-		result.back[36]=MAP_B_NONE;	
-	}
-
-	/* Right room */
-	if ((roomAux=result.links[1])) {
-		result.fore[23]=*(slevel(fore)+30*(roomAux-1)+0);
-		result.back[23]=*(slevel(back)+30*(roomAux-1)+0);
-		result.fore[35]=*(slevel(fore)+30*(roomAux-1)+10);
-		result.back[35]=*(slevel(back)+30*(roomAux-1)+10);
-		result.fore[47]=*(slevel(fore)+30*(roomAux-1)+20);
-		result.back[47]=*(slevel(back)+30*(roomAux-1)+20);
-	} else {
-		result.fore[11]=MAP_F_WALL;
-		result.back[11]=MAP_B_NONE;
-		result.fore[23]=MAP_F_WALL;
-		result.back[23]=MAP_B_NONE;
-		result.fore[35]=MAP_F_WALL;
-		result.back[35]=MAP_B_NONE;	
-	}
-
-	/* Top room */
-	if ((roomAux=result.links[2])) {
-		memcpy(result.fore+1,slevel(fore)+30*(roomAux-1)+20,10);
-		memcpy(result.back+1,slevel(back)+30*(roomAux-1)+20,10);
-	} else {
-		memcpy(result.fore+1,"\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01",10); /* TODO: use tiles */
-		memcpy(result.back+1,"\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01",10); /* TODO: use tiles */
-	}
-
-	/* Bottom room */
-	if ((roomAux=result.links[3])) {
-		memcpy(result.fore+49,slevel(fore)+30*(roomAux-1)+0,10);
-		memcpy(result.back+49,slevel(back)+30*(roomAux-1)+0,10);
-	} else {
-		memcpy(result.fore+49,"\0\0\0\0\0\0\0\0\0\0",10); /* TODO: use tiles */
-		memcpy(result.back+49,"\0\0\0\0\0\0\0\0\0\0",10); /* TODO: use tiles */
-	}
-
-	/* Main room */
-	memcpy(result.fore+13,slevel(fore)+30*(result.id-1)+0,10);
-	memcpy(result.back+13,slevel(back)+30*(result.id-1)+0,10);
-	memcpy(result.fore+25,slevel(fore)+30*(result.id-1)+10,10);
-	memcpy(result.back+25,slevel(back)+30*(result.id-1)+10,10);
-	memcpy(result.fore+37,slevel(fore)+30*(result.id-1)+20,10);
-	memcpy(result.back+37,slevel(back)+30*(result.id-1)+20,10);
-
-/* This will save a screen map into data.
- * 
- * data is a pre-allocated array with 10x3=30 bytes with the screen map
- * dumped over it in left-to-right/upper-to-lower oreder. 
- *
- * borders is another pre-allocated array with 10 upper bytes, 10 bottom
- * bytes, 3 left-side bytes, 3 right-side bytes and 4 bytes for the
- * corners. This is another 30 bytes. The order has to be determined!
- * In case the screen doesn't exist the 0x00 (free foreground) byte will
- * be returned for the bottom and right sides, the wall foreground for
- * the left side and the simple tile byte for the top side.
- * int levelGetScreenItems(unsigned char* data,unsigned char* borders) {
- * This will save a screen map modifiers into data.
- *
- * data and borders are in the same form as Walls but they contain
- * additional modifiers that must be defined in maps.h.
- * e.g. MAPS_ITEMS_DOOROPEN 0x01
- */
-
-	return result;
-}
-
-void  mapStart(tMap* map, tKid* kid, tRoomId *roomId, int level) {
-	/* kid->x,y */
-	static char environments[]=MAP_ENVIRONMENTS;
-	*roomId=slevel(start)[0];
-	printf("mapStart: binding kid to map in room %d using the %d environment\n",*roomId,environments[level]);
-	slevel(time)=0;
-	roomLoadGfx(/*environments[level]?RES_IMG_ENV_PALACE:*/RES_IMG_ENV_DUNGEON);
-}
-
-void  mapMove(tMap* map) {
-	int i;
-	slevel(time)++;
-	if (slevel(time)==1000) slevel(time)=0;
-	/* check out all the gates in the level */
-	for (i=0;i<slevel(totalGates);i++) {
-		switch (map->gates[i].action) {
-		case eOpenTimer:
-			if (map->gates[i].time) {
-				map->gates[i].time--;
-			} else {
-				map->gates[i].action=eClosing;
-			}
-			break;
-		case eOpening:
-			map->gates[i].time=12*10;
-			if (map->gates[i].frame) {
-				map->gates[i].frame--;
-			} else {
-				map->gates[i].action=eOpenTimer;
-			}
-			break;
-		case eClosing:
-			if (map->gates[i].frame!=46) {
-				map->gates[i].frame++;
-			} else {
-				map->gates[i].action=eClose;
-			}
-			break;
-		case eClosingFast:
-			map->gates[i].frame+=30;
-			if (map->gates[i].frame>46) {
-				map->gates[i].action=eClose;
-				map->gates[i].frame=46;
-			}
-			break;
-		default:
-			break;
-		}
-	}
-}
-
-void  mapPressedTile(tMap* map, tTile tile, int s, int x, int y) {
-	if (tile.isPressable) {
-		/* drop or raise button */
-		fprintf(stderr,"mapPressedTile: throw event %d\n",tile.back);
-		do {
-			map->events[tile.back].gate->action=eOpening;
-		} while	(0&&map->events[tile.back++].triggerNext);
-	}
-
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-#ifdef OLD_MAP_SRC
-
-/***************************************************************\
-|                           Prototipos                          |
-\***************************************************************/
-
-	/* File management procedures */
-	char mLoadPED(char* vFile,tLevel* lev);
-	char mLoadDAT(char* vFile,tLevel* lev,char levelNumber); /* Tested 5 */
-	char mSavePED(char* vFile,tLevel* lev); /* Tested 8 */
-	char mSaveDAT(char* vFile,tLevel* lev); /* Tested 3 */
-
-	/* char mChangeLevel(tLevel* lev,char newLevel); //0 si no hay cambios; si hay cambios en paredes devuelve la camtidad de paredes cambiadas */
-	/* char mAllowedOn(char levelnumber,char wall); //1 si wall es permitido en levelnumber; 0 si no */
-
-	/* Information methods */
-	void mSetText (tLevel* lev,char* text);
-	void mGetText (tLevel* lev,char* text);
-
-	/* tLevel Set methods */
-	void mSetWall (tLevel* lev,char pantalla,char p,char b,char valor);
-	void mSetLink (tLevel* lev,char pantalla,char tipo,char valor);
-	void mSetGuard(tLevel* lev,char pantalla,char p,char b,char vidas,char color,char sentido,char erase);
-	void mSetBack (tLevel* lev,char pantalla,char p,char b,char valor);
-	/* tLevel Get Methods */
-	char mGetWall (tLevel* lev,char pantalla,char p,char b);
-	char mGetLink (tLevel* lev,char pantalla,char tipo);
-	void mGetGuard(tLevel* lev,char pantalla,char* p,char* b,char* vidas,char* color,char* sentido,char* erase);
-	char mGetBack (tLevel* lev,char pantalla,char p,char b);
-
-	/* Gate handling Methods */
-	/*
-	Public:
-	mCreateEventList
-	mAddToEventList
-	mGetEventList
-	mRemFromEventList
-	mRemoveEventList
-
-	Private:
-
-	mSaveEventList
-	mLoadEventList
-	*/
-
-
-	/* Screen Links Handling Methods */
-	char mGetScreen    (tLevel* lev, char i,char j, char* error);
-	void mGetMainScreen(tLevel* lev, char* i,char* j);
-	void mRemScreen    (tLevel* lev, char i,char j, char* error);
-	void mAddScreen    (tLevel* lev, char i,char j, char* error);
-	void mGetSize      (tLevel* lev, char* i,char* j);
-	char mGetScrCount  (tLevel* lev);
-		/* Nota: si mGetScrCount(lev) es 24, entonces el nivel esta lleno */
-	void mCpyScreen    (tLevel* lev, char fromi,char fromj,char toi,char toj, char* error);
-
-	/* Start position handling */
-	void mGetStartPosition(tLevel* lev,char* pantalla, char* p, char *b,char *sentido,char *sentido2);
-	void mSetStartPosition(tLevel* lev,char pantalla, char p, char b,char sentido,char sentido2);
-	void mGetDebugPosition(tLevel* lev,char* pantalla, char* p, char *b,char *sentido);
-	void mSetDebugPosition(tLevel* lev,char pantalla, char p, char b,char sentido);
-		/* Nota: DebugPosition puede no existir en lev, en ese caso la convension es no existe si pantalla igual a 0, de lo contrario existe y la pantalla inicial es pantalla */
-
-/***************************************************************\
-|                  I M P L E M E N T A T I O N                  |
-\***************************************************************/
-
-/*
-	Se utilizan partes del archivo como validadores, texto aparte,
-	etc. Aparentemente es texto desperdiciado, no se detectaron
-	cambios en el comportamiento de los niveles.
-*/
-
-/***************************************************************\
-|                Private memory stream handling                 |
-\***************************************************************/
-
-void mSetArray(tLevel* lev, char *pos,int from,unsigned int length,int validator) {
-	char validate=0;
-	while (length--) {
-		validate+=((*lev).levelArray[from]-pos[length]);
-		(*lev).levelArray[from++]=pos[length];
-	}
-	(*lev).levelArray[validator]+=validate;
-}
-
-void mGetArray(tLevel* lev, char *pos,int from,int length) {
-	while (length--) pos[length]=(*lev).levelArray[from++];
-}
-
-/***************************************************************\
-|                         Gate handling                         |
-\***************************************************************/
-
-/* Privados */
-void getRawEvent(tLevel* lev,char id,tGateEvent* event) { /* private */
-	unsigned char x1,x2,valor;
-	(*event).pos[0]  =(*lev).levelArray[MAPS_BLOCK_OFFSET_GATE_1+id];
-	(*event).pos[1]  =(*lev).levelArray[MAPS_BLOCK_OFFSET_GATE_2+id];
-}
-
-void setRawEvent(tLevel* lev,char id,tGateEvent* event) { /* private */
-	unsigned char x1,x2,validate;
-	x1=(*event).pos[0];
-	x2=(*event).pos[1];
-	validate  =((*lev).levelArray[MAPS_BLOCK_OFFSET_GATE_1+id]-x1)+((*lev).levelArray[MAPS_BLOCK_OFFSET_GATE_2+id]-x2);
-
-	(*lev).levelArray[MAPS_BLOCK_OFFSET_GATE_1+id]=x1;
-	(*lev).levelArray[MAPS_BLOCK_OFFSET_GATE_2+id]=x2;
-	(*lev).levelArray[MAPS_BLOCK_OFFSET_VALIDATOR_WALL]+=validate;
-}
-
-/* Privado, pero publico dentro de maps.c */
-void mLoadEventList(tLevel* lev) {
-	/* Esta funcion carga el TDA con los datos que lee del rigido */
-	char a=0;
-	char b=0;
-
-	/* Cargar gateList con las asociaciones del mapa */
-	int j=0;
-	for (int i=0;i<MAPS_BLOCK_SIZEOF_WALL;i++) {
-		switch ((*lev).levelArray[MAPS_BLOCK_OFFSET_WALL+i]) {
-			case MAPS_OBJ_BAL_D:
-			case MAPS_OBJ_BAL_U:
-				(*lev).gateList.item[j].door=i;
-				(*lev).gateList.item[j++].id=(*lev).levelArray[MAPS_BLOCK_OFFSET_BACK+i];
-		}
-	}
-	(*lev).gateList.size=j;
-
-	/* Cargar gateTDA con datos de la tabla */
-	j=0;
-	for (tGateEvent evento;j<MAPS_BLOCK_SIZEOF_GATE;j++) {
-		getRawEvent(lev,j,&evento);
-		if (evento.pos[0]>=(0x80)) {
-			(*lev).gateTDA.row[a].size=b;
-			b=0;
-			a++;
-		} else {
-			b++;
-		}
-		(*lev).gateTDA.row[a].event[b]=evento;
-	}
-	(*lev).gateTDA.size=a;
-}
-
-/* mSevEventList private functions */
-
-void anularEvento(tGateEvent *e) {
-	(*e).pos[0]=0;
-	(*e).pos[1]=0;
-}
-
-char obtenerFila(tGateRow *fila,unsigned char c,int k,tLevel* lev) {
-	char aux=((*lev).gateTDA.row[k].size==c);
-	if (aux) {
-		*fila=(*lev).gateTDA.row[k];
-	}
-	return aux;
-}
-
-char sameEvent(tGateEvent event1,tGateEvent event2) {
-	return ((event1.pos[1]==event2.pos[1]) && ((event1.pos[0]%0x80)==(event1.pos[0]%0x80)));
-}
-
-tGateEvent setFlag(tGateEvent evento,char flag) {
-	evento.pos[0]=(evento.pos[0]%0x80)+(0x80*flag);
-	return evento;
-}
-
-#define MAPS_GATE_DIFFERS 0
-#define MAPS_GATE_EQUALS  1
-#define MAPS_GATE_BELONGS 2
-
-char belongsToDiskList(tLevel* lev, tGateRow *fila,int i) {
-	tGateEvent evento;
-
-	char total=0;
-	char pertenece;
-	/* recorrer la lista de eventos */
-	for (int k=i;((*lev).gateEvents.event[k].pos[0]<(0x80));k++) {
-		total++;
-		pertenece=0;
-		for (char j=0;(j<(*fila).size) && (!pertenece);j++) {
-			pertenece=(sameEvent((*fila).event[j],(*lev).gateEvents.event[k]));
-		}
-		if (!pertenece) {
-			return MAPS_GATE_DIFFERS;
-		}
-	}
-	if (total==(*fila).size) {
-		return MAPS_GATE_EQUALS;
-	} else {
-		return MAPS_GATE_BELONGS;
-	}
-}
-
-void apuntar(tLevel* lev,unsigned char i) {
-	(*lev).gateList.item[(*lev).gateList.size].id=i;
-	(*lev).gateList.size++;
-}
-
-#define MAPS_GATE_SINGLE_EVENT    0
-#define MAPS_GATE_MULTIPLE_EVENT  1
-char intertLeft(tLevel* lev,tGateRow fila,int inicioFila,int numeroFila,char mode) {
-	/* Esta funcion inserta en gateEvents el o los eventos de fila que no estan insertados */
-	/* Por cada insersion deben ser modificados los ids correspondientes en la gateList */
-	/* devuelve 1 si entro */
-	/* devuelve 0 en caso de superarse lso 256 bytes */
-
-	/*
-	 1) En caso de MULTIPLE EVENT los elementos de la fila
-	    que ya estan enliastados en gateEvents deben ser
-	    eliminados de la fila. Se coloca el evento nulo en
-	    reemplazo de estos.
-	*/
-
-	char j,pertenece;
-	if (mode==MAPS_GATE_MULTIPLE_EVENT) {
-		for (int k=inicioFila;((*lev).gateEvents.event[k].pos[0]<(0x80));k++) {
-			pertenece=0;
-			for (j=0;(j<fila.size) && (!pertenece);j++) {
-				pertenece=(sameEvent(fila.event[j],(*lev).gateEvents.event[k]));
-			}
-			if (pertenece) {
-				anularEvento(&(fila.event[j]));
-			}
-		}
-	}
-
-	/*
-	 2) En caso de MAPS_GATE_SINGLE_EVENT el ultimo debe
-	    marcar fin de la lista. A tal fin, cambiaremos ese
-	    flag del evento. Como la inserion se hara de adelante
-	    hacia atras, simplemente debemos setear el flag al
-	    principio
-	*/
-
-	int c=(mode==MAPS_GATE_SINGLE_EVENT);
-
-	/*
-	 3) Se debera iterar para toda la fila e insertar
-	    evento por evento en la gateEvents en la posicion inicioFila.
-			Cada insersion implica un corrimiento de ids en la gateList
-	*/
-
-	for (j=0;(j<fila.size);j++) {
-		if (fila.event[j].pos[0]) { /* Para cada evento nonulo de la fila */
-			/* Adelantar todos los eventos posteriores a inicioFila */
-			for (int k=(*lev).gateEvents.size;k>inicioFila;k--) {
-				(*lev).gateEvents.event[k+1]=(*lev).gateEvents.event[k];
-			}
-
-			/* Insertar (*fila).event[j] en la gateEvents en la posicion generada en inicioFila. */
-			/* Se tendra en cuenta el flag de de fin de lista */
-			(*lev).gateEvents.event[inicioFila]=setFlag(fila.event[j],c);
-
-			/* El flag del fin de lista se cancela */
-			c=0;
-
-			/* Incrementar la cantidad de eventos de la gateEvent, en caso de no poder abortar */
-			if ((*lev).gateEvents.size==255) {
-				return 0;
-			} else {
-				(*lev).gateEvents.size++;
-			}
-
-			/* Finalmente se debe recorrer la gate list e incrementar el contenido que supere a inicioFila */
-			for (int k=0;k<(*lev).gateList.size;k++) {
-				if ((*lev).gateList.item[k].id>=inicioFila)
-					((*lev).gateList.item[k].id)++;
-			}
-		}
-	}
-	return 1;
-}
-
-/* Main function */
-char mSaveEventList(tLevel* lev) {
-	/* Lee el TDA, optimiza el espacio que ocupan los datos y lo guardaen disco */
-	/* devuelve 1 en caso de que entre en disco */
-	/* devuelve 0 en caso de que no hayan entrado los datos en disco */
-
-	/* Inicializar variables */
-	unsigned char n=(*lev).gateTDA.size;
-	unsigned char c=1;
-	char x;
-	tGateRow fila;
-	(*lev).gateEvents.size=0;
-	(*lev).gateList.size=0;
-
-	/* Generar a partir de gateTDA la lista de eventos gateEventList y de asociaciones gateList */
-	while (n) { /* Para todos los elementos */
-		for (int k=0;k<(*lev).gateTDA.size;k++) { /* Recorrer filas de gateTDA */
-			if (obtenerFila(&fila,c,k,lev)) {  /* mietras haya elementos con tamagno=c sin procesar fila=(*lev).gateTDA.row[n] where fila=(*lev).gateTDA.row[n].size=c; */
-				/* entra con fila seteada en la fila k con c elementos adentro. */
-				n--;
-				x=0;
-				for (int i=0;((i<(*lev).gateEvents.size) && (!x));i++) { /* recorrer lo ya creado de gateEvents */
-					x=belongsToDiskList(lev,&fila,i);
-					switch (x) {
-						case MAPS_GATE_BELONGS:
-							/*
-							  Pertenece, pero puede que este no sea el principio de la lista
-							  en ese caso no puedo insertar porque corromperia la puerta
-							  anterior, por eso voy a verificar que sea el primero de la lista
-							  o bien que el anterior tenga el flag c.
-							*/
-							if ((i=0) || ((*lev).gateEvents.event[i-1].pos[0]>0x80)) {
-								if (!intertLeft(lev,fila,i,k,MAPS_GATE_MULTIPLE_EVENT)) {
-									return 0;
-								}
-								apuntar(lev,i);
-							}
-							break;
-						case MAPS_GATE_EQUALS:
-							apuntar(lev,i);
-					}
-				}
-				if (!x) {
-					if (!intertLeft(lev,fila,(*lev).gateEvents.size,k,MAPS_GATE_SINGLE_EVENT)) {
-						return 0;
-					}
-				}
-			}
-		}
-		c++;
-	}
-
-	/* Guardar gateEvents y gateList en el formato. */
-	/* gateList */
-	for (int i=0;i<(*lev).gateEvents.size;i++) {
-		setRawEvent(lev,i,&((*lev).gateEvents.event[i]));
-	}
-	int location;
-	unsigned char validate=0;
-	for (int i=0;i<(*lev).gateList.size;i++) {
-		location=MAPS_BLOCK_OFFSET_BACK+(*lev).gateList.item[i].door;
-		validate+=(*lev).levelArray[location]-(*lev).gateList.item[i].id;
-		(*lev).levelArray[location]=(*lev).gateList.item[i].id;
-	}
-	(*lev).levelArray[MAPS_BLOCK_OFFSET_VALIDATOR_WALL]+=validate;
-
-	return 1;
-}
-
-void getGateAsociation(tLevel* lev,char id,char* scr,char* p,char* b, char *termino) {
-	unsigned char x1,x2,valor;
-	x1        =(*lev).levelArray[MAPS_BLOCK_OFFSET_GATE_1+id];
-	x2        =(*lev).levelArray[MAPS_BLOCK_OFFSET_GATE_2+id];
-
-	*scr      =(x2/8)+(x1%(0x80))/(0x20);
-	valor     =(x1%(0x20));
-	*b        =(valor%10);
-	*p        =(valor/10);
-	*termino  =(x1/(0x80)); /* c=(Se pasa a la siguiente)?0:1 */
-}
-
-void setGateAsociation(tLevel* lev,char id,char scr,char p,char b, char termino) {
-	unsigned char x1,x2,validate;
-
-	x1        =((scr%4)*0x20)+(p*10+b)+(termino?0x80:0);
-	x2        =((scr/4)*0x20);
-	validate  =((*lev).levelArray[MAPS_BLOCK_OFFSET_GATE_1+id]-x1)+((*lev).levelArray[MAPS_BLOCK_OFFSET_GATE_2+id]-x2);
-
-	(*lev).levelArray[MAPS_BLOCK_OFFSET_GATE_1+id]=x1;
-	(*lev).levelArray[MAPS_BLOCK_OFFSET_GATE_2+id]=x2;
-	(*lev).levelArray[MAPS_BLOCK_OFFSET_VALIDATOR_WALL]+=validate;
-}
-
-void shiftEventId(tLevel* lev,char from,char delta) { /* private */
-	char validate=0;
-	char aux;
-	for (int i=0;i<MAPS_BLOCK_SIZEOF_WALL;i++) {
-		switch ((*lev).levelArray[MAPS_BLOCK_OFFSET_WALL+i]) {
-			case MAPS_OBJ_BAL_D:
-			case MAPS_OBJ_BAL_U:
-				if ((*lev).levelArray[MAPS_BLOCK_OFFSET_BACK+i]>from) {
-					(*lev).levelArray[MAPS_BLOCK_OFFSET_BACK+i]+=delta;
-					validate-=delta;
-				}
-		}
-	}
-	(*lev).levelArray[MAPS_BLOCK_OFFSET_VALIDATOR_WALL]+=validate;
-}
-
-void insertEvent(tLevel* lev,char id,char scr,char p,char b) {
-	char x1,x2,x3,x4;
-
-	shiftEventId(lev,id,+1);
-	for (int i=20;i>id;i--) {
-		getGateAsociation(lev,i-1,&x1,&x2,&x3,&x4);
-		setGateAsociation(lev,i,x1,x2,x3,x4);
-	}
-	setGateAsociation(lev,id,scr,p,b,0);
-}
-
-/***************************************************************\
-|                         Text handling                         |
-\***************************************************************/
-
-#define MAPS_BLOCK_OFFSET_START_POSITION_SIZE3 3
-/* Actualmente guarda 1+MAPS_BLOCK_SIZEOF_UNKNOWN_1+MAPS_BLOCK_SIZEOF_UNKNOWN_2+MAPS_BLOCK_SIZEOF_UNKNOWN_4+unk_5+unk_6+unk_7 = 564 caracteres. *text debe medir 565 incluyendo el caracter nulo. */
-void mSetText (tLevel* lev,char* text) {
-	mSetArray(lev,text,MAPS_BLOCK_OFFSET_START_POSITION+MAPS_BLOCK_OFFSET_START_POSITION_SIZE3,1,MAPS_BLOCK_OFFSET_VALIDATOR_LINK);
-	mSetArray(lev,&(text[1]),MAPS_BLOCK_OFFSET_UNKNOWN_1,MAPS_BLOCK_SIZEOF_UNKNOWN_1,MAPS_BLOCK_OFFSET_VALIDATOR_WALL);
-	mSetArray(lev,&(text[MAPS_BLOCK_SIZEOF_UNKNOWN_1+1]),MAPS_BLOCK_OFFSET_UNKNOWN_2,MAPS_BLOCK_SIZEOF_UNKNOWN_2,MAPS_BLOCK_OFFSET_VALIDATOR_WALL);
-	mSetArray(lev,&(text[MAPS_BLOCK_SIZEOF_UNKNOWN_2+MAPS_BLOCK_SIZEOF_UNKNOWN_1+1]),MAPS_BLOCK_OFFSET_UNKNOWN_4,MAPS_BLOCK_SIZEOF_UNKNOWN_4,MAPS_BLOCK_OFFSET_VALIDATOR_LINK);
-	mSetArray(lev,&(text[MAPS_BLOCK_SIZEOF_UNKNOWN_4+MAPS_BLOCK_SIZEOF_UNKNOWN_2+MAPS_BLOCK_SIZEOF_UNKNOWN_1+1]),MAPS_BLOCK_OFFSET_UNKNOWN_5,MAPS_BLOCK_SIZEOF_UNKNOWN_5,MAPS_BLOCK_OFFSET_VALIDATOR_LINK);
-	mSetArray(lev,&(text[MAPS_BLOCK_SIZEOF_UNKNOWN_5+MAPS_BLOCK_SIZEOF_UNKNOWN_4+MAPS_BLOCK_SIZEOF_UNKNOWN_2+MAPS_BLOCK_SIZEOF_UNKNOWN_1+1]),MAPS_BLOCK_OFFSET_UNKNOWN_6,MAPS_BLOCK_SIZEOF_UNKNOWN_6,MAPS_BLOCK_OFFSET_VALIDATOR_LINK);
-	mSetArray(lev,&(text[MAPS_BLOCK_SIZEOF_UNKNOWN_6+MAPS_BLOCK_SIZEOF_UNKNOWN_5+MAPS_BLOCK_SIZEOF_UNKNOWN_4+MAPS_BLOCK_SIZEOF_UNKNOWN_2+MAPS_BLOCK_SIZEOF_UNKNOWN_1+1]),MAPS_BLOCK_OFFSET_UNKNOWN_7,MAPS_BLOCK_SIZEOF_UNKNOWN_7,MAPS_BLOCK_OFFSET_VALIDATOR_LINK);
-}
-
-void mGetText (tLevel* lev,char* text) {
-	mGetArray(lev,text,MAPS_BLOCK_OFFSET_START_POSITION+MAPS_BLOCK_OFFSET_START_POSITION_SIZE3,1);
-	mGetArray(lev,&(text[1]),MAPS_BLOCK_OFFSET_UNKNOWN_1,MAPS_BLOCK_SIZEOF_UNKNOWN_1);
-	mGetArray(lev,&(text[MAPS_BLOCK_SIZEOF_UNKNOWN_1+1]),MAPS_BLOCK_OFFSET_UNKNOWN_2,MAPS_BLOCK_SIZEOF_UNKNOWN_2);
-	mGetArray(lev,&(text[MAPS_BLOCK_SIZEOF_UNKNOWN_2+MAPS_BLOCK_SIZEOF_UNKNOWN_1+1]),MAPS_BLOCK_OFFSET_UNKNOWN_4,MAPS_BLOCK_SIZEOF_UNKNOWN_4);
-	mGetArray(lev,&(text[MAPS_BLOCK_SIZEOF_UNKNOWN_4+MAPS_BLOCK_SIZEOF_UNKNOWN_2+MAPS_BLOCK_SIZEOF_UNKNOWN_1+1]),MAPS_BLOCK_OFFSET_UNKNOWN_5,MAPS_BLOCK_SIZEOF_UNKNOWN_5);
-	mGetArray(lev,&(text[MAPS_BLOCK_SIZEOF_UNKNOWN_5+MAPS_BLOCK_SIZEOF_UNKNOWN_4+MAPS_BLOCK_SIZEOF_UNKNOWN_2+MAPS_BLOCK_SIZEOF_UNKNOWN_1+1]),MAPS_BLOCK_OFFSET_UNKNOWN_6,MAPS_BLOCK_SIZEOF_UNKNOWN_6);
-	mGetArray(lev,&(text[MAPS_BLOCK_SIZEOF_UNKNOWN_6+MAPS_BLOCK_SIZEOF_UNKNOWN_5+MAPS_BLOCK_SIZEOF_UNKNOWN_4+MAPS_BLOCK_SIZEOF_UNKNOWN_2+MAPS_BLOCK_SIZEOF_UNKNOWN_1+1]),MAPS_BLOCK_OFFSET_UNKNOWN_7,MAPS_BLOCK_SIZEOF_UNKNOWN_7);
-	text[MAPS_BLOCK_SIZEOF_UNKNOWN_7+MAPS_BLOCK_SIZEOF_UNKNOWN_6+MAPS_BLOCK_SIZEOF_UNKNOWN_5+MAPS_BLOCK_SIZEOF_UNKNOWN_4+MAPS_BLOCK_SIZEOF_UNKNOWN_2+MAPS_BLOCK_SIZEOF_UNKNOWN_1+1]=0;
-}
-
-/***************************************************************\
-|                     Start Position handling                   |
-\***************************************************************/
-
-void mGetDebugPosition(tLevel* lev,char* pantalla, char* p, char *b,char *sentido) {
-	unsigned char dp[2];
-	unsigned char valor;
-	mGetArray(lev,dp,MAPS_BLOCK_OFFSET_START_POSITION+4,2);
-	*pantalla =(dp[0]);
-	*sentido  =(dp[1]%2);
-	valor     =(dp[1]/2);
-	*b        =(valor%10);
-	*p        =(valor/10);
-}
-
-void mSetDebugPosition(tLevel* lev,char pantalla, char p, char b,char sentido) {
-	unsigned char dp[2];
-	dp[0]     =pantalla;
-	dp[1]     =pantalla?(((p*10+b)*2)+(sentido?1:0)):0;
-	mSetArray(lev,dp,MAPS_BLOCK_OFFSET_START_POSITION+4,2,MAPS_BLOCK_OFFSET_VALIDATOR_LINK);
-}
-
-void mSetStartPosition(tLevel* lev,char pantalla, char p, char b,char sentido,char sentido2) {
-	unsigned char valor=pantalla;
-	int location=MAPS_BLOCK_OFFSET_START_POSITION;
-	unsigned char offsetval=0;
-
-	/* pantalla */
-	offsetval+=(256-valor)+(*lev).levelArray[location];
-	(*lev).levelArray[location++]=valor;
-
-	/* Posicion */
-	valor     =p*10+b;
-	offsetval+=(256-valor)+(*lev).levelArray[location];
-	(*lev).levelArray[location++]=valor;
-
-	/* sentidos */
-	valor     =sentido?MAPS_DIRECTION_RIGHT:MAPS_DIRECTION_LEFT;
-	offsetval+=(256-valor)+(*lev).levelArray[location];
-	(*lev).levelArray[location]=valor;
-
-	location +=4;
-	valor     =sentido2?MAPS_DIRECTION_RIGHT:MAPS_DIRECTION_LEFT;
-	offsetval+=(256-valor)+(*lev).levelArray[location];
-	(*lev).levelArray[location]=valor;
-
-	/* Validacion */
-	(*lev).levelArray[MAPS_BLOCK_OFFSET_VALIDATOR_LINK]+=offsetval;
-}
-
-/***************************************************************\
-|                      S E T S  &  G E T S                      |
-\***************************************************************/
-
-
-void mSetWall  (tLevel* lev,char pantalla,char p,char b,char valor) {
-	int location=MAPS_BLOCK_OFFSET_WALL+30*(pantalla-1)+10*p+b;
-
-	(*lev).levelArray[MAPS_BLOCK_OFFSET_VALIDATOR_WALL]+=(*lev).levelArray[location]-valor;
-	(*lev).levelArray[location]=valor;
-}
-
-void mSetBack (tLevel* lev,char pantalla,char p,char b,char valor) {
-	int location=MAPS_BLOCK_OFFSET_BACK+30*(pantalla-1)+10*p+b;
-
-	(*lev).levelArray[MAPS_BLOCK_OFFSET_VALIDATOR_WALL]+=(*lev).levelArray[location]-valor;
-	(*lev).levelArray[location]=valor;
-}
-
-
-/***************************************************************\
-|                   Abstract Guard Handling                     |
-\***************************************************************/
-
-void mSetGuard(tLevel* lev,char pantalla,char p,char b,char vidas,char color,char sentido,char erase) {
-
-	/* Posicion */
-	unsigned char valor=erase?30:p*10+b;
-	int location=MAPS_BLOCK_OFFSET_GUARD_POSITION-1+pantalla;
-	unsigned char offsetval=((*lev).levelArray[MAPS_BLOCK_OFFSET_VALIDATOR_LINK]+(256-valor)+(*lev).levelArray[location]);
-	(*lev).levelArray[location]=valor;
-	/* sentido */
-	valor     =sentido?MAPS_DIRECTION_RIGHT:MAPS_DIRECTION_LEFT;
-	location  =MAPS_BLOCK_OFFSET_GUARD_DIRECTION-1+pantalla;
-	offsetval+=(256-valor)+(*lev).levelArray[location];
-	(*lev).levelArray[location]=valor;
-	/* skill */
-	valor     =erase?1:vidas;
-	location  =MAPS_BLOCK_OFFSET_GUARD_SKILL-1+pantalla;
-	offsetval+=(256-valor)+(*lev).levelArray[location];
-	(*lev).levelArray[location]=valor;
-	/* Color */
-	valor     =erase?0:color;
-	location  =MAPS_BLOCK_OFFSET_GUARD_COLOR-1+pantalla;
-	offsetval+=(256-valor)+(*lev).levelArray[location];
-	(*lev).levelArray[location]=valor;
-
-	/* Validar */
-	(*lev).levelArray[MAPS_BLOCK_OFFSET_VALIDATOR_LINK]=offsetval/*+(256-valor)+(*lev).levelArray[location]*/;
-}
-
-void mGetGuard(tLevel* lev,char pantalla,char* p,char* b,char* vidas,char* color,char* sentido,char* exists) {
-	/* Posicion */
-	unsigned char valor=((*lev).levelArray[(MAPS_BLOCK_OFFSET_GUARD_POSITION-1+pantalla)]);
-	*exists = (valor<30);
-	*b      = (valor%10);
-	*p      = (valor/10);
-	/* sentido */
-	*sentido=!(*lev).levelArray[MAPS_BLOCK_OFFSET_GUARD_DIRECTION-1+pantalla];
-	/* skill */
-	*vidas  =(*lev).levelArray[MAPS_BLOCK_OFFSET_GUARD_SKILL-1+pantalla];
-	/* Color */
-	*color  =(*lev).levelArray[MAPS_BLOCK_OFFSET_GUARD_COLOR-1+pantalla];
-}
-
-/***************************************************************\
-|                     Screen Link Handling                      |
-\***************************************************************/
-
-/* Recursive mapping sub procedures */
-void mRecLink(char i, char j, tLevel* lev); /* prototype */
-void mRecIndirect(char i, char j, tLevel* lev, char scr, char pos) {
-	char aux;
-	char auxb;
-	if ((*lev).handledLinks.linkMap[i][j]==255) {
-		aux=mGetLink (lev,scr,pos);
-		if (!(auxb=(!aux))) auxb=(!(*lev).handledLinks.linkList[aux]);
-		if (auxb) {
-			(*lev).handledLinks.linkMap[i][j]=aux;
-			if (aux) {
-				(*lev).handledLinks.linkList[aux]=1;
-				mRecLink(i,j,lev);
-			}
-		} else {
-			(*lev).handledLinks.linkMap[i][j]=0;
-		}
-	}
-}
-
-void mRecLink(char i, char j, tLevel* lev) {
-	char scr=(*lev).handledLinks.linkMap[i][j];
-
-	mRecIndirect(i,j-1,lev,scr,MAPS_sLeft);
-	mRecIndirect(i,j+1,lev,scr,MAPS_sRight);
-	mRecIndirect(i-1,j,lev,scr,MAPS_sUp);
-	mRecIndirect(i+1,j,lev,scr,MAPS_sDown);
-}
-
-void mCalcularLimUp (tLevel* lev) {
-	char i=0;
-	char j=0;
-	while (((*lev).handledLinks.linkMap[i][j]==255) && (j<MAPS_MAX_LENGTH)) {
-		if (++i==MAPS_MAX_LENGTH) {
-			j++;
-			i=0;
-		}
-	}
-	(*lev).handledLinks.limUp=j;
-}
-
-void mCalcularLimLeft (tLevel* lev) {
-	char i=0;
-	char j=0;
-	while (((*lev).handledLinks.linkMap[j][i]==255) && (j<MAPS_MAX_LENGTH)) {
-		if (++i==MAPS_MAX_LENGTH) {
-			j++;
-			i=0;
-		}
-	}
-	(*lev).handledLinks.limLeft=j;
-}
-
-void mCalcularLimDown (tLevel* lev) {
-	char i=0;
-	char j=MAPS_MAX_LENGTH-1;
-	while (((*lev).handledLinks.linkMap[i][j]==255) && j) {
-		if (++i==MAPS_MAX_LENGTH) {
-			j--;
-			i=0;
-		}
-	}
-	(*lev).handledLinks.limDown=j;
-}
-
-void mCalcularLimRight (tLevel* lev) {
-	char i=0;
-	char j=MAPS_MAX_LENGTH-1;
-	while (((*lev).handledLinks.linkMap[j][i]==255) && j) {
-		if (++i==MAPS_MAX_LENGTH) {
-			j--;
-			i=0;
-		}
-	}
-	(*lev).handledLinks.limRight=j;
-}
-
-
-/* 	Main mCreateLinkMap */
-void mCreateLinkMap(tLevel* lev) { /* private */
-	char	i,j,start;
-
-	/* Initialize arrays */
-	for (j=0;j<MAPS_MAX_LENGTH;j++)
-		for (i=0;i<MAPS_MAX_LENGTH;(*lev).handledLinks.linkMap[i++][j]=255);
-	for (j=1;j<=MAPS_MAX_SCREENS;(*lev).handledLinks.linkList[j++]=0);
-
-	/* Inicializar start en la pantalla de inicio */
-	mGetStartPosition(lev,&start,&i,&i,&i,&i);
-	(*lev).handledLinks.linkMap[MAPS_LINKMAP_CENTER][MAPS_LINKMAP_CENTER]=start;
-	(*lev).handledLinks.linkList[start]=1;
-
-	/* Start Recursive Mapper */
-	mRecLink(MAPS_LINKMAP_CENTER,MAPS_LINKMAP_CENTER,lev);
-
-	/* Buscar limites del nivel */
-	mCalcularLimUp   (lev);
-	mCalcularLimDown (lev);
-	mCalcularLimLeft (lev);
-	mCalcularLimRight(lev);
-
-}
-
-void mGetSize      (tLevel* lev, char* i,char* j) {
-	*i=(*lev).handledLinks.limRight - (*lev).handledLinks.limLeft;
-	*j=(*lev).handledLinks.limDown  - (*lev).handledLinks.limUp;
-}
-
-char mGetScrCount  (tLevel* lev) {
-	char l,aux;
-
-	aux=0;
-	for (l=1;l<=MAPS_MAX_SCREENS;aux+=((*lev).handledLinks.linkList[l++]?1:0));
-	return aux;
-}
-
-char mGetScreen    (tLevel* lev, char i,char j, char* error) {
-	char aux;
-
-	aux=(*lev).handledLinks.linkMap[(*lev).handledLinks.limLeft+i][(*lev).handledLinks.limUp+j];
-	*error=(aux==255);
-	return aux;
-}
-
-void mGetMainScreen(tLevel* lev, char* i,char* j) {
-	*i=(MAPS_LINKMAP_CENTER) - (*lev).handledLinks.limLeft;
-	*j=(MAPS_LINKMAP_CENTER) - (*lev).handledLinks.limUp;
-}
-
-void mAddScreen    (tLevel* lev, char i,char j, char* error) {
-	char scr=mGetScreen(lev,i,j,error);
-	*error=(*error || scr);
-	if (!*error) {
-		int l=1;
-		while ((*lev).handledLinks.linkList[l] && (l++<MAPS_MAX_SCREENS));
-		if ((*lev).handledLinks.linkList[l]) {
-			*error=1;
-		} else {
-			/* Pedir pantalla */
-			(*lev).handledLinks.linkList[l]=1;
-
-			i+=(*lev).handledLinks.limLeft;
-			j+=(*lev).handledLinks.limUp;
-
-			/* En caso de agregar una pantalla en alguno de los bordes, estos se amplian */
-			if ((*lev).handledLinks.limLeft=i) (*lev).handledLinks.limLeft--;
-			if ((*lev).handledLinks.limUp=j) (*lev).handledLinks.limUp--;
-			if ((*lev).handledLinks.limRight=i) (*lev).handledLinks.limRight++;
-			if ((*lev).handledLinks.limDown=j) (*lev).handledLinks.limDown++;
-
-
-			/* Poner 0 alrededor de l */
-			(*lev).handledLinks.linkMap[i][j-1]%=255;
-			(*lev).handledLinks.linkMap[i][j+1]%=255;
-			(*lev).handledLinks.linkMap[i+1][j]%=255;
-			(*lev).handledLinks.linkMap[i-1][j]%=255;
-
-			/* Poner l en l */
-			(*lev).handledLinks.linkMap[i][j]=l;
-
-			/* Setear links desde l a las 4 pantallas adyacentes */
-			mSetLink (lev,l,MAPS_sUp,(*lev).handledLinks.linkMap[i][j-1]);
-			mSetLink (lev,l,MAPS_sDown,(*lev).handledLinks.linkMap[i][j+1]);
-			mSetLink (lev,l,MAPS_sRight,(*lev).handledLinks.linkMap[i+1][j]);
-			mSetLink (lev,l,MAPS_sLeft,(*lev).handledLinks.linkMap[i-1][j]);
-
-			/* Setear links desde las 4 pantallas adyacentes a l */
-			mSetLink (lev,(*lev).handledLinks.linkMap[i][j+1],MAPS_sUp,l);
-			mSetLink (lev,(*lev).handledLinks.linkMap[i][j-1],MAPS_sDown,l);
-			mSetLink (lev,(*lev).handledLinks.linkMap[i-1][j],MAPS_sRight,l);
-			mSetLink (lev,(*lev).handledLinks.linkMap[i+1][j],MAPS_sLeft,l);
-
-			/* Limpiar contenido de la pantalla l */
-			for (i=0;i<3;i++) {
-				for (j=0;j<10;j++) {
-					mSetWall(lev,l,i,j,0);
-					mSetBack(lev,l,i,j,0);
-				}
-			}
-			mSetGuard(lev,l,1,1,1,1,1,1);
-			/* Listo, ya cree la pantalla y la linkie */
-		}
-	}
-}
-
-void mRemScreen    (tLevel* lev, char i,char j, char* error) {
-	/*{Q&D:
-		1) Si parten a la mitad un nivel se pierde una de las mitades
-		2) no se refresca la LinkMap en ese caso
-		3) tampoco une las pantallas que estaban a los costados}*/
-	unsigned char l=mGetScreen(lev,i,j,error);
-	*error=*error || (!l);
-	if (!*error) {
-		/* Liberar pantalla */
-		(*lev).handledLinks.linkList[l]=0;
-
-		/* Seteo posiciones absolutas */
-		i+=(*lev).handledLinks.limLeft;
-		j+=(*lev).handledLinks.limUp;
-
-		/* Poner 0 en l */
-		(*lev).handledLinks.linkMap[i][j]=0;
-
-		/* En caso de remover una pantalla en alguno de los bordes, estos se recalculan */
-		if ((*lev).handledLinks.limLeft=i) 	mCalcularLimLeft(lev);
-		if ((*lev).handledLinks.limUp=j)    mCalcularLimUp(lev);
-		if ((*lev).handledLinks.limRight=i) mCalcularLimRight(lev);
-		if ((*lev).handledLinks.limDown=j)  mCalcularLimDown(lev);
-
-		/* Borrar links desds las 4 pantallas adyacentes a l */
-		mSetLink (lev,(*lev).handledLinks.linkMap[i][j+1],MAPS_sLeft,0);
-		mSetLink (lev,(*lev).handledLinks.linkMap[i][j-1],MAPS_sRight,0);
-		mSetLink (lev,(*lev).handledLinks.linkMap[i-1][j],MAPS_sDown,0);
-		mSetLink (lev,(*lev).handledLinks.linkMap[i+1][j],MAPS_sUp,0);
-	}
-}
-
-void mCpyScreen    (tLevel* lev, char fromi,char fromj,char toi,char toj, char* error) {
-	char fromscr,toscr,i,j,k,l;
-	char sentido,existe;
-
-	/* Verificar que la pantalla source y la pantalla target existan */
-	fromscr=mGetScreen(lev,fromi,fromj,error); /* Verifico que existe la pantalla from */
-	*error=(*error || fromscr);
-	if (!*error) { /* Verifico que existe la pantalla to */
-		toscr=mGetScreen(lev,toi,toj,error);
-		*error=(*error || toscr);
-	}
-	if (!*error) { /* Si existen ambas pantallas */
-		/* Copiar contenido de la pantalla from a la pantalla to: */
-
-		/* Copiar wall y back */
-		char contenido[30];
-		mGetArray(lev,contenido,MAPS_BLOCK_OFFSET_WALL-30+fromscr*30,30);
-		mSetArray(lev,contenido,MAPS_BLOCK_OFFSET_WALL-30+toscr*30,30,MAPS_BLOCK_OFFSET_VALIDATOR_WALL);
-		mGetArray(lev,contenido,MAPS_BLOCK_OFFSET_BACK-30+fromscr*30,30);
-		mSetArray(lev,contenido,MAPS_BLOCK_OFFSET_BACK-30+toscr*30,30,MAPS_BLOCK_OFFSET_VALIDATOR_WALL);
-
-		/* Copiar Guards */
-		mGetGuard(lev,fromscr,&i,&j,&k,&l,&sentido,&existe);
-		mSetGuard(lev,toscr,i,j,k,l,sentido,existe);
-		/* Listo, ya se copio el contenido y el guardia */
-	}
-}
-
-/***************************************************************\
-|                         File handling                         |
-\***************************************************************/
-
-char mLoadPED(char* vFile,tLevel* lev) {
-	FILE *fp;
-	char aux;
-
-	if ((fp=fopen(vFile,"rb"))==NULL) {
-		return 0;
-	} else {
-		aux=fread (lev,sizeof(*lev),1,fp);
-		fclose(fp);
-		return aux;
-	}
-}
-
-char mLoadDAT(char* vFile,tLevel* lev,char levelNumber) {
-	FILE *fp;
-	char aux;
-
-	if ((fp=fopen(vFile,"rb"))==NULL) {
-		return 0;
-	} else {
-		(*lev).level=levelNumber;
-		fpos_t position=levelNumber*MAPS_BLOCK_SIZEOF_LEVEL+MAPS_BLOCK_OFFSET_LEVELS;
-		fsetpos (fp, &position);
-		aux=fread (&(*lev).levelArray,MAPS_BLOCK_SIZEOF_LEVEL,1,fp);
-		mCreateLinkMap(lev);
-		fclose(fp);
-		return aux;
-	}
-}
-
-char mSavePED(char* vFile,tLevel* lev) {
-  FILE * pFile;
-  if ((pFile = fopen (vFile , "wb"))==NULL) {
-		return 0;
-	}
-  fwrite (lev, 1, sizeof(*lev), pFile);
-  fclose (pFile);
-  return 1;
-}
-
-char mSaveDAT(char* vFile,tLevel* lev) {
-  FILE * pFile;
-  if ((pFile = fopen (vFile , "r+b"))==NULL) {
-		return 0;
-	}
-	fpos_t position=(*lev).level*MAPS_BLOCK_SIZEOF_LEVEL+MAPS_BLOCK_OFFSET_LEVELS;
-  fsetpos (pFile, &position);
-  fwrite ((*lev).levelArray, 1, MAPS_BLOCK_SIZEOF_LEVEL, pFile);
-  fclose (pFile);
-  return 1;
-}
-
-#endif
+/*  FreePrince - POP1 remake
+    Copyright (C) 2003,2004 Princed Development Team
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    The authors of this program may be contacted at http://forum.princed.com.ar
+*/
+
+/*
+maps.c: Freeprince : Map handling library
+\xaf\xaf\xaf\xaf\xaf\xaf
+ Copyright 2003,2004 Princed Development Team
+  Created: 24 Mar 2003
+
+  Author: Enrique Calot <ecalot.cod@princed.com.ar>
+
+ Note:
+  DO NOT remove this copyright notice
+*/
+
+#include <string.h> /* mempcy */
+#include <stdlib.h> /* malloc */
+#include "maps.h"
+#include "room.h"
+#include "kid.h"
+#include "types.h"
+
+#define slevel(field) (map->field)
+
+void* mapLoadLevel(tMemory level) {
+	tMap* map=(tMap*)malloc(sizeof(tMap));
+	int i,j;
+	int gates=0;
+	int gateInRoom=0;
+	tGate** auxGates=malloc(sizeof(tGate*)*24*30);
+	
+	/* copy maps, links and start position */
+	memcpy(map->fore,level.array+MAPS_BLOCK_OFFSET_WALL,30*24);
+	memcpy(map->back,level.array+MAPS_BLOCK_OFFSET_BACK,30*24);
+	memcpy(map->start,level.array+MAPS_BLOCK_OFFSET_START_POSITION,3);
+	memcpy(map->links,level.array+MAPS_BLOCK_OFFSET_LINK,4*24);
+
+	/* generate and load gate structures */
+	for (i=0;i<24;i++) { /* count gates and create gate tree middle nodes */
+		for (j=0;j<30;j++) {
+			if (((map->fore[i*30+j]&0x1f)==T_GATE)||((map->fore[i*30+j]&0x1f)==T_EXIT_LEFT)) {
+				gateInRoom++;
+				gates++;
+			}
+		}
+		fprintf(stderr,"Screen %d has %d gates.\n",i,gateInRoom);
+		if (gateInRoom) {
+			map->screenGates[i]=malloc(gateInRoom*sizeof(tGate*));
+		} else {
+			map->screenGates[i]=NULL;
+		}
+		gateInRoom=0;
+	}
+	/* create gates sctucture */
+	map->gates=malloc(gates*sizeof(tGate));
+	map->totalGates=gates;
+	gates=0;
+	for (i=0;i<24;i++) {
+		for (j=0;j<30;j++) {
+			if (((map->fore[i*30+j]&0x1f)==T_GATE)||((map->fore[i*30+j]&0x1f)==T_EXIT_LEFT)) {
+				tGate newGate;
+				newGate.frame=map->back[i*30+j];
+				newGate.action=map->back[i*30+j]?eOpen:eClose;
+				map->back[i*30+j]=gateInRoom;
+				fprintf(stderr,"mapLoadLevel: Asignando gate pointer: screen %d, gate number %d\n",i,gateInRoom);
+				map->screenGates[i][gateInRoom]=map->gates+gates;
+				auxGates[i*30+j]=map->gates+gates;
+				fprintf(stderr,"mapLoadLevel: Loading gate: indexed=%d gate pointer=%p\n",i,(void*)auxGates[i*30+j]);
+				map->gates[gates++]=newGate;
+				gateInRoom++;
+			}
+		}
+		if (!gateInRoom) map->screenGates[i]=NULL;
+		gateInRoom=0;
+	}
+	for (i=0;i<256;i++) {
+		unsigned char byte1=level.array[MAPS_BLOCK_OFFSET_GATE_1+i];
+		unsigned char byte2=level.array[MAPS_BLOCK_OFFSET_GATE_2+i];
+		int S,L,T;
+		S=((byte1>>5)&3)|((byte2>>3)&28);
+		L=byte1&31;
+		T=!((byte1>>7)&1);
+		map->events[i].triggerNext=T;
+		map->events[i].gate=auxGates[(S-1)*30+L]; /* in case of error null is assigned */
+		fprintf(stderr,"mapLoadLevel: Loading event: S=%d L=%d T=%d gate number=%d gate pointer=%p\n",S,L,T,(S-1)*30+L,(void*)auxGates[(S-1)*30+L]);
+	}
+	free(auxGates);
+	return (void*)map;
+}
+
+tRoom mapGetRoom(tMap* map, tRoomId roomAux) {
+	tRoom result;
+
+	/* SET room id*/
+	result.id=roomAux;
+	result.level=map;
+	
+	/* SET room links */
+	memcpy(result.links,slevel(links)+((roomAux-1)*4),4);
+	/* up corners */
+	roomAux=result.links[2];
+	if (roomAux) {
+		result.corners[0]=*(slevel(links)+((roomAux-1)*4)+0);
+		result.corners[1]=*(slevel(links)+((roomAux-1)*4)+1);
+	} else {
+		result.corners[0]=0;
+		result.corners[1]=0;
+	}
+	/* down corners */
+	roomAux=result.links[3];
+	if (roomAux) {
+		result.corners[2]=*(slevel(links)+((roomAux-1)*4)+0);
+		result.corners[3]=*(slevel(links)+((roomAux-1)*4)+1);
+	} else {
+		result.corners[2]=0;
+		result.corners[3]=0;
+	}
+	
+	/* SET corner bytes */
+	/* left+up */
+	if ((roomAux=result.corners[0])) {
+		result.fore[0]=*(slevel(fore)+30*(roomAux-1)+29);
+		result.back[0]=*(slevel(back)+30*(roomAux-1)+29);
+	} else {
+		result.fore[0]=MAP_F_WALL;
+		result.back[0]=MAP_B_NONE;
+	}
+	/* right+up */
+	if ((roomAux=result.corners[1])) {
+		result.fore[11]=*(slevel(fore)+30*(roomAux-1)+20);
+		result.back[11]=*(slevel(back)+30*(roomAux-1)+20);
+	} else {
+		result.fore[11]=MAP_F_FREE;
+		result.back[11]=MAP_B_NONE;
+	}
+	/* left+down */
+	if ((roomAux=result.corners[2])) {
+		result.fore[48]=*(slevel(fore)+30*(roomAux-1)+9);
+		result.back[48]=*(slevel(back)+30*(roomAux-1)+9);
+	} else {
+		result.fore[48]=MAP_F_WALL;
+		result.back[48]=MAP_B_NONE;
+	}
+	/* right+down */
+	if ((roomAux=result.corners[3])) {
+		result.fore[59]=*(slevel(fore)+30*(roomAux-1)+0);
+		result.back[59]=*(slevel(back)+30*(roomAux-1)+0);
+	} else {
+		result.fore[59]=MAP_F_WALL;
+		result.back[59]=MAP_B_NONE;
+	}
+
+	/* Left room */
+	if ((roomAux=result.links[0])) {
+		result.fore[12]=*(slevel(fore)+30*(roomAux-1)+9);
+		result.back[12]=*(slevel(back)+30*(roomAux-1)+9);
+		result.fore[24]=*(slevel(fore)+30*(roomAux-1)+19);
+		result.back[24]=*(slevel(back)+30*(roomAux-1)+19);
+		result.fore[36]=*(slevel(fore)+30*(roomAux-1)+29);
+		result.back[36]=*(slevel(back)+30*(roomAux-1)+29);
+	} else {
+		result.fore[12]=MAP_F_WALL;
+		result.back[12]=MAP_B_NONE;
+		result.fore[24]=MAP_F_WALL;
+		result.back[24]=MAP_B_NONE;
+		result.fore[36]=MAP_F_WALL;
+		result.back[36]=MAP_B_NONE;	
+	}
+
+	/* Right room */
+	if ((roomAux=result.links[1])) {
+		result.fore[23]=*(slevel(fore)+30*(roomAux-1)+0);
+		result.back[23]=*(slevel(back)+30*(roomAux-1)+0);
+		result.fore[35]=*(slevel(fore)+30*(roomAux-1)+10);
+		result.back[35]=*(slevel(back)+30*(roomAux-1)+10);
+		result.fore[47]=*(slevel(fore)+30*(roomAux-1)+20);
+		result.back[47]=*(slevel(back)+30*(roomAux-1)+20);
+	} else {
+		result.fore[11]=MAP_F_WALL;
+		result.back[11]=MAP_B_NONE;
+		result.fore[23]=MAP_F_WALL;
+		result.back[23]=MAP_B_NONE;
+		result.fore[35]=MAP_F_WALL;
+		result.back[35]=MAP_B_NONE;	
+	}
+
+	/* Top room */
+	if ((roomAux=result.links[2])) {
+		memcpy(result.fore+1,slevel(fore)+30*(roomAux-1)+20,10);
+		memcpy(result.back+1,slevel(back)+30*(roomAux-1)+20,10);
+	} else {
+		memcpy(result.fore+1,"\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01",10); /* TODO: use tiles */
+		memcpy(result.back+1,"\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01",10); /* TODO: use tiles */
+	}
+
+	/* Bottom room */
+	if ((roomAux=result.links[3])) {
+		memcpy(result.fore+49,slevel(fore)+30*(roomAux-1)+0,10);
+		memcpy(result.back+49,slevel(back)+30*(roomAux-1)+0,10);
+	} else {
+		memcpy(result.fore+49,"\0\0\0\0\0\0\0\0\0\0",10); /* TODO: use tiles */
+		memcpy(result.back+49,"\0\0\0\0\0\0\0\0\0\0",10); /* TODO: use tiles */
+	}
+
+	/* Main room */
+	memcpy(result.fore+13,slevel(fore)+30*(result.id-1)+0,10);
+	memcpy(result.back+13,slevel(back)+30*(result.id-1)+0,10);
+	memcpy(result.fore+25,slevel(fore)+30*(result.id-1)+10,10);
+	memcpy(result.back+25,slevel(back)+30*(result.id-1)+10,10);
+	memcpy(result.fore+37,slevel(fore)+30*(result.id-1)+20,10);
+	memcpy(result.back+37,slevel(back)+30*(result.id-1)+20,10);
+
+/* This will save a screen map into data.
+ * 
+ * data is a pre-allocated array with 10x3=30 bytes with the screen map
+ * dumped over it in left-to-right/upper-to-lower oreder. 
+ *
+ * borders is another pre-allocated array with 10 upper bytes, 10 bottom
+ * bytes, 3 left-side bytes, 3 right-side bytes and 4 bytes for the
+ * corners. This is another 30 bytes. The order has to be determined!
+ * In case the screen doesn't exist the 0x00 (free foreground) byte will
+ * be returned for the bottom and right sides, the wall foreground for
+ * the left side and the simple tile byte for the top side.
+ * int levelGetScreenItems(unsigned char* data,unsigned char* borders) {
+ * This will save a screen map modifiers into data.
+ *
+ * data and borders are in the same form as Walls but they contain
+ * additional modifiers that must be defined in maps.h.
+ * e.g. MAPS_ITEMS_DOOROPEN 0x01
+ */
+
+	return result;
+}
+
+void  mapStart(tMap* map, tKid* kid, tRoomId *roomId, int level) {
+	/* kid->x,y */
+	static char environments[]=MAP_ENVIRONMENTS;
+	*roomId=slevel(start)[0];
+	printf("mapStart: binding kid to map in room %d using the %d environment\n",*roomId,environments[level]);
+	slevel(time)=0;
+	roomLoadGfx(/*environments[level]?RES_IMG_ENV_PALACE:*/RES_IMG_ENV_DUNGEON);
+}
+
+void  mapMove(tMap* map) {
+	int i;
+	slevel(time)++;
+	if (slevel(time)==1000) slevel(time)=0;
+	/* check out all the gates in the level */
+	for (i=0;i<slevel(totalGates);i++) {
+		switch (map->gates[i].action) {
+		case eOpenTimer:
+			if (map->gates[i].time) {
+				map->gates[i].time--;
+			} else {
+				map->gates[i].action=eClosing;
+			}
+			break;
+		case eOpening:
+			map->gates[i].time=12*10;
+			if (map->gates[i].frame) {
+				map->gates[i].frame--;
+			} else {
+				map->gates[i].action=eOpenTimer;
+			}
+			break;
+		case eClosing:
+			if (map->gates[i].frame!=46) {
+				map->gates[i].frame++;
+			} else {
+				map->gates[i].action=eClose;
+			}
+			break;
+		case eClosingFast:
+			map->gates[i].frame+=30;
+			if (map->gates[i].frame>46) {
+				map->gates[i].action=eClose;
+				map->gates[i].frame=46;
+			}
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+void  mapPressedTile(tMap* map, tTile tile, int s, int x, int y) {
+	if (tile.isPressable) {
+		/* drop or raise button */
+		fprintf(stderr,"mapPressedTile: throw event %d\n",tile.back);
+		do {
+			map->events[tile.back].gate->action=tile.isRaise?eOpening:eClosingFast;
+		} while	(0&&map->events[tile.back++].triggerNext);
+	}
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#ifdef OLD_MAP_SRC
+
+/***************************************************************\
+|                           Prototipos                          |
+\***************************************************************/
+
+	/* File management procedures */
+	char mLoadPED(char* vFile,tLevel* lev);
+	char mLoadDAT(char* vFile,tLevel* lev,char levelNumber); /* Tested 5 */
+	char mSavePED(char* vFile,tLevel* lev); /* Tested 8 */
+	char mSaveDAT(char* vFile,tLevel* lev); /* Tested 3 */
+
+	/* char mChangeLevel(tLevel* lev,char newLevel); //0 si no hay cambios; si hay cambios en paredes devuelve la camtidad de paredes cambiadas */
+	/* char mAllowedOn(char levelnumber,char wall); //1 si wall es permitido en levelnumber; 0 si no */
+
+	/* Information methods */
+	void mSetText (tLevel* lev,char* text);
+	void mGetText (tLevel* lev,char* text);
+
+	/* tLevel Set methods */
+	void mSetWall (tLevel* lev,char pantalla,char p,char b,char valor);
+	void mSetLink (tLevel* lev,char pantalla,char tipo,char valor);
+	void mSetGuard(tLevel* lev,char pantalla,char p,char b,char vidas,char color,char sentido,char erase);
+	void mSetBack (tLevel* lev,char pantalla,char p,char b,char valor);
+	/* tLevel Get Methods */
+	char mGetWall (tLevel* lev,char pantalla,char p,char b);
+	char mGetLink (tLevel* lev,char pantalla,char tipo);
+	void mGetGuard(tLevel* lev,char pantalla,char* p,char* b,char* vidas,char* color,char* sentido,char* erase);
+	char mGetBack (tLevel* lev,char pantalla,char p,char b);
+
+	/* Gate handling Methods */
+	/*
+	Public:
+	mCreateEventList
+	mAddToEventList
+	mGetEventList
+	mRemFromEventList
+	mRemoveEventList
+
+	Private:
+
+	mSaveEventList
+	mLoadEventList
+	*/
+
+
+	/* Screen Links Handling Methods */
+	char mGetScreen    (tLevel* lev, char i,char j, char* error);
+	void mGetMainScreen(tLevel* lev, char* i,char* j);
+	void mRemScreen    (tLevel* lev, char i,char j, char* error);
+	void mAddScreen    (tLevel* lev, char i,char j, char* error);
+	void mGetSize      (tLevel* lev, char* i,char* j);
+	char mGetScrCount  (tLevel* lev);
+		/* Nota: si mGetScrCount(lev) es 24, entonces el nivel esta lleno */
+	void mCpyScreen    (tLevel* lev, char fromi,char fromj,char toi,char toj, char* error);
+
+	/* Start position handling */
+	void mGetStartPosition(tLevel* lev,char* pantalla, char* p, char *b,char *sentido,char *sentido2);
+	void mSetStartPosition(tLevel* lev,char pantalla, char p, char b,char sentido,char sentido2);
+	void mGetDebugPosition(tLevel* lev,char* pantalla, char* p, char *b,char *sentido);
+	void mSetDebugPosition(tLevel* lev,char pantalla, char p, char b,char sentido);
+		/* Nota: DebugPosition puede no existir en lev, en ese caso la convension es no existe si pantalla igual a 0, de lo contrario existe y la pantalla inicial es pantalla */
+
+/***************************************************************\
+|                  I M P L E M E N T A T I O N                  |
+\***************************************************************/
+
+/*
+	Se utilizan partes del archivo como validadores, texto aparte,
+	etc. Aparentemente es texto desperdiciado, no se detectaron
+	cambios en el comportamiento de los niveles.
+*/
+
+/***************************************************************\
+|                Private memory stream handling                 |
+\***************************************************************/
+
+void mSetArray(tLevel* lev, char *pos,int from,unsigned int length,int validator) {
+	char validate=0;
+	while (length--) {
+		validate+=((*lev).levelArray[from]-pos[length]);
+		(*lev).levelArray[from++]=pos[length];
+	}
+	(*lev).levelArray[validator]+=validate;
+}
+
+void mGetArray(tLevel* lev, char *pos,int from,int length) {
+	while (length--) pos[length]=(*lev).levelArray[from++];
+}
+
+/***************************************************************\
+|                         Gate handling                         |
+\***************************************************************/
+
+/* Privados */
+void getRawEvent(tLevel* lev,char id,tGateEvent* event) { /* private */
+	unsigned char x1,x2,valor;
+	(*event).pos[0]  =(*lev).levelArray[MAPS_BLOCK_OFFSET_GATE_1+id];
+	(*event).pos[1]  =(*lev).levelArray[MAPS_BLOCK_OFFSET_GATE_2+id];
+}
+
+void setRawEvent(tLevel* lev,char id,tGateEvent* event) { /* private */
+	unsigned char x1,x2,validate;
+	x1=(*event).pos[0];
+	x2=(*event).pos[1];
+	validate  =((*lev).levelArray[MAPS_BLOCK_OFFSET_GATE_1+id]-x1)+((*lev).levelArray[MAPS_BLOCK_OFFSET_GATE_2+id]-x2);
+
+	(*lev).levelArray[MAPS_BLOCK_OFFSET_GATE_1+id]=x1;
+	(*lev).levelArray[MAPS_BLOCK_OFFSET_GATE_2+id]=x2;
+	(*lev).levelArray[MAPS_BLOCK_OFFSET_VALIDATOR_WALL]+=validate;
+}
+
+/* Privado, pero publico dentro de maps.c */
+void mLoadEventList(tLevel* lev) {
+	/* Esta funcion carga el TDA con los datos que lee del rigido */
+	char a=0;
+	char b=0;
+
+	/* Cargar gateList con las asociaciones del mapa */
+	int j=0;
+	for (int i=0;i<MAPS_BLOCK_SIZEOF_WALL;i++) {
+		switch ((*lev).levelArray[MAPS_BLOCK_OFFSET_WALL+i]) {
+			case MAPS_OBJ_BAL_D:
+			case MAPS_OBJ_BAL_U:
+				(*lev).gateList.item[j].door=i;
+				(*lev).gateList.item[j++].id=(*lev).levelArray[MAPS_BLOCK_OFFSET_BACK+i];
+		}
+	}
+	(*lev).gateList.size=j;
+
+	/* Cargar gateTDA con datos de la tabla */
+	j=0;
+	for (tGateEvent evento;j<MAPS_BLOCK_SIZEOF_GATE;j++) {
+		getRawEvent(lev,j,&evento);
+		if (evento.pos[0]>=(0x80)) {
+			(*lev).gateTDA.row[a].size=b;
+			b=0;
+			a++;
+		} else {
+			b++;
+		}
+		(*lev).gateTDA.row[a].event[b]=evento;
+	}
+	(*lev).gateTDA.size=a;
+}
+
+/* mSevEventList private functions */
+
+void anularEvento(tGateEvent *e) {
+	(*e).pos[0]=0;
+	(*e).pos[1]=0;
+}
+
+char obtenerFila(tGateRow *fila,unsigned char c,int k,tLevel* lev) {
+	char aux=((*lev).gateTDA.row[k].size==c);
+	if (aux) {
+		*fila=(*lev).gateTDA.row[k];
+	}
+	return aux;
+}
+
+char sameEvent(tGateEvent event1,tGateEvent event2) {
+	return ((event1.pos[1]==event2.pos[1]) && ((event1.pos[0]%0x80)==(event1.pos[0]%0x80)));
+}
+
+tGateEvent setFlag(tGateEvent evento,char flag) {
+	evento.pos[0]=(evento.pos[0]%0x80)+(0x80*flag);
+	return evento;
+}
+
+#define MAPS_GATE_DIFFERS 0
+#define MAPS_GATE_EQUALS  1
+#define MAPS_GATE_BELONGS 2
+
+char belongsToDiskList(tLevel* lev, tGateRow *fila,int i) {
+	tGateEvent evento;
+
+	char total=0;
+	char pertenece;
+	/* recorrer la lista de eventos */
+	for (int k=i;((*lev).gateEvents.event[k].pos[0]<(0x80));k++) {
+		total++;
+		pertenece=0;
+		for (char j=0;(j<(*fila).size) && (!pertenece);j++) {
+			pertenece=(sameEvent((*fila).event[j],(*lev).gateEvents.event[k]));
+		}
+		if (!pertenece) {
+			return MAPS_GATE_DIFFERS;
+		}
+	}
+	if (total==(*fila).size) {
+		return MAPS_GATE_EQUALS;
+	} else {
+		return MAPS_GATE_BELONGS;
+	}
+}
+
+void apuntar(tLevel* lev,unsigned char i) {
+	(*lev).gateList.item[(*lev).gateList.size].id=i;
+	(*lev).gateList.size++;
+}
+
+#define MAPS_GATE_SINGLE_EVENT    0
+#define MAPS_GATE_MULTIPLE_EVENT  1
+char intertLeft(tLevel* lev,tGateRow fila,int inicioFila,int numeroFila,char mode) {
+	/* Esta funcion inserta en gateEvents el o los eventos de fila que no estan insertados */
+	/* Por cada insersion deben ser modificados los ids correspondientes en la gateList */
+	/* devuelve 1 si entro */
+	/* devuelve 0 en caso de superarse lso 256 bytes */
+
+	/*
+	 1) En caso de MULTIPLE EVENT los elementos de la fila
+	    que ya estan enliastados en gateEvents deben ser
+	    eliminados de la fila. Se coloca el evento nulo en
+	    reemplazo de estos.
+	*/
+
+	char j,pertenece;
+	if (mode==MAPS_GATE_MULTIPLE_EVENT) {
+		for (int k=inicioFila;((*lev).gateEvents.event[k].pos[0]<(0x80));k++) {
+			pertenece=0;
+			for (j=0;(j<fila.size) && (!pertenece);j++) {
+				pertenece=(sameEvent(fila.event[j],(*lev).gateEvents.event[k]));
+			}
+			if (pertenece) {
+				anularEvento(&(fila.event[j]));
+			}
+		}
+	}
+
+	/*
+	 2) En caso de MAPS_GATE_SINGLE_EVENT el ultimo debe
+	    marcar fin de la lista. A tal fin, cambiaremos ese
+	    flag del evento. Como la inserion se hara de adelante
+	    hacia atras, simplemente debemos setear el flag al
+	    principio
+	*/
+
+	int c=(mode==MAPS_GATE_SINGLE_EVENT);
+
+	/*
+	 3) Se debera iterar para toda la fila e insertar
+	    evento por evento en la gateEvents en la posicion inicioFila.
+			Cada insersion implica un corrimiento de ids en la gateList
+	*/
+
+	for (j=0;(j<fila.size);j++) {
+		if (fila.event[j].pos[0]) { /* Para cada evento nonulo de la fila */
+			/* Adelantar todos los eventos posteriores a inicioFila */
+			for (int k=(*lev).gateEvents.size;k>inicioFila;k--) {
+				(*lev).gateEvents.event[k+1]=(*lev).gateEvents.event[k];
+			}
+
+			/* Insertar (*fila).event[j] en la gateEvents en la posicion generada en inicioFila. */
+			/* Se tendra en cuenta el flag de de fin de lista */
+			(*lev).gateEvents.event[inicioFila]=setFlag(fila.event[j],c);
+
+			/* El flag del fin de lista se cancela */
+			c=0;
+
+			/* Incrementar la cantidad de eventos de la gateEvent, en caso de no poder abortar */
+			if ((*lev).gateEvents.size==255) {
+				return 0;
+			} else {
+				(*lev).gateEvents.size++;
+			}
+
+			/* Finalmente se debe recorrer la gate list e incrementar el contenido que supere a inicioFila */
+			for (int k=0;k<(*lev).gateList.size;k++) {
+				if ((*lev).gateList.item[k].id>=inicioFila)
+					((*lev).gateList.item[k].id)++;
+			}
+		}
+	}
+	return 1;
+}
+
+/* Main function */
+char mSaveEventList(tLevel* lev) {
+	/* Lee el TDA, optimiza el espacio que ocupan los datos y lo guardaen disco */
+	/* devuelve 1 en caso de que entre en disco */
+	/* devuelve 0 en caso de que no hayan entrado los datos en disco */
+
+	/* Inicializar variables */
+	unsigned char n=(*lev).gateTDA.size;
+	unsigned char c=1;
+	char x;
+	tGateRow fila;
+	(*lev).gateEvents.size=0;
+	(*lev).gateList.size=0;
+
+	/* Generar a partir de gateTDA la lista de eventos gateEventList y de asociaciones gateList */
+	while (n) { /* Para todos los elementos */
+		for (int k=0;k<(*lev).gateTDA.size;k++) { /* Recorrer filas de gateTDA */
+			if (obtenerFila(&fila,c,k,lev)) {  /* mietras haya elementos con tamagno=c sin procesar fila=(*lev).gateTDA.row[n] where fila=(*lev).gateTDA.row[n].size=c; */
+				/* entra con fila seteada en la fila k con c elementos adentro. */
+				n--;
+				x=0;
+				for (int i=0;((i<(*lev).gateEvents.size) && (!x));i++) { /* recorrer lo ya creado de gateEvents */
+					x=belongsToDiskList(lev,&fila,i);
+					switch (x) {
+						case MAPS_GATE_BELONGS:
+							/*
+							  Pertenece, pero puede que este no sea el principio de la lista
+							  en ese caso no puedo insertar porque corromperia la puerta
+							  anterior, por eso voy a verificar que sea el primero de la lista
+							  o bien que el anterior tenga el flag c.
+							*/
+							if ((i=0) || ((*lev).gateEvents.event[i-1].pos[0]>0x80)) {
+								if (!intertLeft(lev,fila,i,k,MAPS_GATE_MULTIPLE_EVENT)) {
+									return 0;
+								}
+								apuntar(lev,i);
+							}
+							break;
+						case MAPS_GATE_EQUALS:
+							apuntar(lev,i);
+					}
+				}
+				if (!x) {
+					if (!intertLeft(lev,fila,(*lev).gateEvents.size,k,MAPS_GATE_SINGLE_EVENT)) {
+						return 0;
+					}
+				}
+			}
+		}
+		c++;
+	}
+
+	/* Guardar gateEvents y gateList en el formato. */
+	/* gateList */
+	for (int i=0;i<(*lev).gateEvents.size;i++) {
+		setRawEvent(lev,i,&((*lev).gateEvents.event[i]));
+	}
+	int location;
+	unsigned char validate=0;
+	for (int i=0;i<(*lev).gateList.size;i++) {
+		location=MAPS_BLOCK_OFFSET_BACK+(*lev).gateList.item[i].door;
+		validate+=(*lev).levelArray[location]-(*lev).gateList.item[i].id;
+		(*lev).levelArray[location]=(*lev).gateList.item[i].id;
+	}
+	(*lev).levelArray[MAPS_BLOCK_OFFSET_VALIDATOR_WALL]+=validate;
+
+	return 1;
+}
+
+void getGateAsociation(tLevel* lev,char id,char* scr,char* p,char* b, char *termino) {
+	unsigned char x1,x2,valor;
+	x1        =(*lev).levelArray[MAPS_BLOCK_OFFSET_GATE_1+id];
+	x2        =(*lev).levelArray[MAPS_BLOCK_OFFSET_GATE_2+id];
+
+	*scr      =(x2/8)+(x1%(0x80))/(0x20);
+	valor     =(x1%(0x20));
+	*b        =(valor%10);
+	*p        =(valor/10);
+	*termino  =(x1/(0x80)); /* c=(Se pasa a la siguiente)?0:1 */
+}
+
+void setGateAsociation(tLevel* lev,char id,char scr,char p,char b, char termino) {
+	unsigned char x1,x2,validate;
+
+	x1        =((scr%4)*0x20)+(p*10+b)+(termino?0x80:0);
+	x2        =((scr/4)*0x20);
+	validate  =((*lev).levelArray[MAPS_BLOCK_OFFSET_GATE_1+id]-x1)+((*lev).levelArray[MAPS_BLOCK_OFFSET_GATE_2+id]-x2);
+
+	(*lev).levelArray[MAPS_BLOCK_OFFSET_GATE_1+id]=x1;
+	(*lev).levelArray[MAPS_BLOCK_OFFSET_GATE_2+id]=x2;
+	(*lev).levelArray[MAPS_BLOCK_OFFSET_VALIDATOR_WALL]+=validate;
+}
+
+void shiftEventId(tLevel* lev,char from,char delta) { /* private */
+	char validate=0;
+	char aux;
+	for (int i=0;i<MAPS_BLOCK_SIZEOF_WALL;i++) {
+		switch ((*lev).levelArray[MAPS_BLOCK_OFFSET_WALL+i]) {
+			case MAPS_OBJ_BAL_D:
+			case MAPS_OBJ_BAL_U:
+				if ((*lev).levelArray[MAPS_BLOCK_OFFSET_BACK+i]>from) {
+					(*lev).levelArray[MAPS_BLOCK_OFFSET_BACK+i]+=delta;
+					validate-=delta;
+				}
+		}
+	}
+	(*lev).levelArray[MAPS_BLOCK_OFFSET_VALIDATOR_WALL]+=validate;
+}
+
+void insertEvent(tLevel* lev,char id,char scr,char p,char b) {
+	char x1,x2,x3,x4;
+
+	shiftEventId(lev,id,+1);
+	for (int i=20;i>id;i--) {
+		getGateAsociation(lev,i-1,&x1,&x2,&x3,&x4);
+		setGateAsociation(lev,i,x1,x2,x3,x4);
+	}
+	setGateAsociation(lev,id,scr,p,b,0);
+}
+
+/***************************************************************\
+|                         Text handling                         |
+\***************************************************************/
+
+#define MAPS_BLOCK_OFFSET_START_POSITION_SIZE3 3
+/* Actualmente guarda 1+MAPS_BLOCK_SIZEOF_UNKNOWN_1+MAPS_BLOCK_SIZEOF_UNKNOWN_2+MAPS_BLOCK_SIZEOF_UNKNOWN_4+unk_5+unk_6+unk_7 = 564 caracteres. *text debe medir 565 incluyendo el caracter nulo. */
+void mSetText (tLevel* lev,char* text) {
+	mSetArray(lev,text,MAPS_BLOCK_OFFSET_START_POSITION+MAPS_BLOCK_OFFSET_START_POSITION_SIZE3,1,MAPS_BLOCK_OFFSET_VALIDATOR_LINK);
+	mSetArray(lev,&(text[1]),MAPS_BLOCK_OFFSET_UNKNOWN_1,MAPS_BLOCK_SIZEOF_UNKNOWN_1,MAPS_BLOCK_OFFSET_VALIDATOR_WALL);
+	mSetArray(lev,&(text[MAPS_BLOCK_SIZEOF_UNKNOWN_1+1]),MAPS_BLOCK_OFFSET_UNKNOWN_2,MAPS_BLOCK_SIZEOF_UNKNOWN_2,MAPS_BLOCK_OFFSET_VALIDATOR_WALL);
+	mSetArray(lev,&(text[MAPS_BLOCK_SIZEOF_UNKNOWN_2+MAPS_BLOCK_SIZEOF_UNKNOWN_1+1]),MAPS_BLOCK_OFFSET_UNKNOWN_4,MAPS_BLOCK_SIZEOF_UNKNOWN_4,MAPS_BLOCK_OFFSET_VALIDATOR_LINK);
+	mSetArray(lev,&(text[MAPS_BLOCK_SIZEOF_UNKNOWN_4+MAPS_BLOCK_SIZEOF_UNKNOWN_2+MAPS_BLOCK_SIZEOF_UNKNOWN_1+1]),MAPS_BLOCK_OFFSET_UNKNOWN_5,MAPS_BLOCK_SIZEOF_UNKNOWN_5,MAPS_BLOCK_OFFSET_VALIDATOR_LINK);
+	mSetArray(lev,&(text[MAPS_BLOCK_SIZEOF_UNKNOWN_5+MAPS_BLOCK_SIZEOF_UNKNOWN_4+MAPS_BLOCK_SIZEOF_UNKNOWN_2+MAPS_BLOCK_SIZEOF_UNKNOWN_1+1]),MAPS_BLOCK_OFFSET_UNKNOWN_6,MAPS_BLOCK_SIZEOF_UNKNOWN_6,MAPS_BLOCK_OFFSET_VALIDATOR_LINK);
+	mSetArray(lev,&(text[MAPS_BLOCK_SIZEOF_UNKNOWN_6+MAPS_BLOCK_SIZEOF_UNKNOWN_5+MAPS_BLOCK_SIZEOF_UNKNOWN_4+MAPS_BLOCK_SIZEOF_UNKNOWN_2+MAPS_BLOCK_SIZEOF_UNKNOWN_1+1]),MAPS_BLOCK_OFFSET_UNKNOWN_7,MAPS_BLOCK_SIZEOF_UNKNOWN_7,MAPS_BLOCK_OFFSET_VALIDATOR_LINK);
+}
+
+void mGetText (tLevel* lev,char* text) {
+	mGetArray(lev,text,MAPS_BLOCK_OFFSET_START_POSITION+MAPS_BLOCK_OFFSET_START_POSITION_SIZE3,1);
+	mGetArray(lev,&(text[1]),MAPS_BLOCK_OFFSET_UNKNOWN_1,MAPS_BLOCK_SIZEOF_UNKNOWN_1);
+	mGetArray(lev,&(text[MAPS_BLOCK_SIZEOF_UNKNOWN_1+1]),MAPS_BLOCK_OFFSET_UNKNOWN_2,MAPS_BLOCK_SIZEOF_UNKNOWN_2);
+	mGetArray(lev,&(text[MAPS_BLOCK_SIZEOF_UNKNOWN_2+MAPS_BLOCK_SIZEOF_UNKNOWN_1+1]),MAPS_BLOCK_OFFSET_UNKNOWN_4,MAPS_BLOCK_SIZEOF_UNKNOWN_4);
+	mGetArray(lev,&(text[MAPS_BLOCK_SIZEOF_UNKNOWN_4+MAPS_BLOCK_SIZEOF_UNKNOWN_2+MAPS_BLOCK_SIZEOF_UNKNOWN_1+1]),MAPS_BLOCK_OFFSET_UNKNOWN_5,MAPS_BLOCK_SIZEOF_UNKNOWN_5);
+	mGetArray(lev,&(text[MAPS_BLOCK_SIZEOF_UNKNOWN_5+MAPS_BLOCK_SIZEOF_UNKNOWN_4+MAPS_BLOCK_SIZEOF_UNKNOWN_2+MAPS_BLOCK_SIZEOF_UNKNOWN_1+1]),MAPS_BLOCK_OFFSET_UNKNOWN_6,MAPS_BLOCK_SIZEOF_UNKNOWN_6);
+	mGetArray(lev,&(text[MAPS_BLOCK_SIZEOF_UNKNOWN_6+MAPS_BLOCK_SIZEOF_UNKNOWN_5+MAPS_BLOCK_SIZEOF_UNKNOWN_4+MAPS_BLOCK_SIZEOF_UNKNOWN_2+MAPS_BLOCK_SIZEOF_UNKNOWN_1+1]),MAPS_BLOCK_OFFSET_UNKNOWN_7,MAPS_BLOCK_SIZEOF_UNKNOWN_7);
+	text[MAPS_BLOCK_SIZEOF_UNKNOWN_7+MAPS_BLOCK_SIZEOF_UNKNOWN_6+MAPS_BLOCK_SIZEOF_UNKNOWN_5+MAPS_BLOCK_SIZEOF_UNKNOWN_4+MAPS_BLOCK_SIZEOF_UNKNOWN_2+MAPS_BLOCK_SIZEOF_UNKNOWN_1+1]=0;
+}
+
+/***************************************************************\
+|                     Start Position handling                   |
+\***************************************************************/
+
+void mGetDebugPosition(tLevel* lev,char* pantalla, char* p, char *b,char *sentido) {
+	unsigned char dp[2];
+	unsigned char valor;
+	mGetArray(lev,dp,MAPS_BLOCK_OFFSET_START_POSITION+4,2);
+	*pantalla =(dp[0]);
+	*sentido  =(dp[1]%2);
+	valor     =(dp[1]/2);
+	*b        =(valor%10);
+	*p        =(valor/10);
+}
+
+void mSetDebugPosition(tLevel* lev,char pantalla, char p, char b,char sentido) {
+	unsigned char dp[2];
+	dp[0]     =pantalla;
+	dp[1]     =pantalla?(((p*10+b)*2)+(sentido?1:0)):0;
+	mSetArray(lev,dp,MAPS_BLOCK_OFFSET_START_POSITION+4,2,MAPS_BLOCK_OFFSET_VALIDATOR_LINK);
+}
+
+void mSetStartPosition(tLevel* lev,char pantalla, char p, char b,char sentido,char sentido2) {
+	unsigned char valor=pantalla;
+	int location=MAPS_BLOCK_OFFSET_START_POSITION;
+	unsigned char offsetval=0;
+
+	/* pantalla */
+	offsetval+=(256-valor)+(*lev).levelArray[location];
+	(*lev).levelArray[location++]=valor;
+
+	/* Posicion */
+	valor     =p*10+b;
+	offsetval+=(256-valor)+(*lev).levelArray[location];
+	(*lev).levelArray[location++]=valor;
+
+	/* sentidos */
+	valor     =sentido?MAPS_DIRECTION_RIGHT:MAPS_DIRECTION_LEFT;
+	offsetval+=(256-valor)+(*lev).levelArray[location];
+	(*lev).levelArray[location]=valor;
+
+	location +=4;
+	valor     =sentido2?MAPS_DIRECTION_RIGHT:MAPS_DIRECTION_LEFT;
+	offsetval+=(256-valor)+(*lev).levelArray[location];
+	(*lev).levelArray[location]=valor;
+
+	/* Validacion */
+	(*lev).levelArray[MAPS_BLOCK_OFFSET_VALIDATOR_LINK]+=offsetval;
+}
+
+/***************************************************************\
+|                      S E T S  &  G E T S                      |
+\***************************************************************/
+
+
+void mSetWall  (tLevel* lev,char pantalla,char p,char b,char valor) {
+	int location=MAPS_BLOCK_OFFSET_WALL+30*(pantalla-1)+10*p+b;
+
+	(*lev).levelArray[MAPS_BLOCK_OFFSET_VALIDATOR_WALL]+=(*lev).levelArray[location]-valor;
+	(*lev).levelArray[location]=valor;
+}
+
+void mSetBack (tLevel* lev,char pantalla,char p,char b,char valor) {
+	int location=MAPS_BLOCK_OFFSET_BACK+30*(pantalla-1)+10*p+b;
+
+	(*lev).levelArray[MAPS_BLOCK_OFFSET_VALIDATOR_WALL]+=(*lev).levelArray[location]-valor;
+	(*lev).levelArray[location]=valor;
+}
+
+
+/***************************************************************\
+|                   Abstract Guard Handling                     |
+\***************************************************************/
+
+void mSetGuard(tLevel* lev,char pantalla,char p,char b,char vidas,char color,char sentido,char erase) {
+
+	/* Posicion */
+	unsigned char valor=erase?30:p*10+b;
+	int location=MAPS_BLOCK_OFFSET_GUARD_POSITION-1+pantalla;
+	unsigned char offsetval=((*lev).levelArray[MAPS_BLOCK_OFFSET_VALIDATOR_LINK]+(256-valor)+(*lev).levelArray[location]);
+	(*lev).levelArray[location]=valor;
+	/* sentido */
+	valor     =sentido?MAPS_DIRECTION_RIGHT:MAPS_DIRECTION_LEFT;
+	location  =MAPS_BLOCK_OFFSET_GUARD_DIRECTION-1+pantalla;
+	offsetval+=(256-valor)+(*lev).levelArray[location];
+	(*lev).levelArray[location]=valor;
+	/* skill */
+	valor     =erase?1:vidas;
+	location  =MAPS_BLOCK_OFFSET_GUARD_SKILL-1+pantalla;
+	offsetval+=(256-valor)+(*lev).levelArray[location];
+	(*lev).levelArray[location]=valor;
+	/* Color */
+	valor     =erase?0:color;
+	location  =MAPS_BLOCK_OFFSET_GUARD_COLOR-1+pantalla;
+	offsetval+=(256-valor)+(*lev).levelArray[location];
+	(*lev).levelArray[location]=valor;
+
+	/* Validar */
+	(*lev).levelArray[MAPS_BLOCK_OFFSET_VALIDATOR_LINK]=offsetval/*+(256-valor)+(*lev).levelArray[location]*/;
+}
+
+void mGetGuard(tLevel* lev,char pantalla,char* p,char* b,char* vidas,char* color,char* sentido,char* exists) {
+	/* Posicion */
+	unsigned char valor=((*lev).levelArray[(MAPS_BLOCK_OFFSET_GUARD_POSITION-1+pantalla)]);
+	*exists = (valor<30);
+	*b      = (valor%10);
+	*p      = (valor/10);
+	/* sentido */
+	*sentido=!(*lev).levelArray[MAPS_BLOCK_OFFSET_GUARD_DIRECTION-1+pantalla];
+	/* skill */
+	*vidas  =(*lev).levelArray[MAPS_BLOCK_OFFSET_GUARD_SKILL-1+pantalla];
+	/* Color */
+	*color  =(*lev).levelArray[MAPS_BLOCK_OFFSET_GUARD_COLOR-1+pantalla];
+}
+
+/***************************************************************\
+|                     Screen Link Handling                      |
+\***************************************************************/
+
+/* Recursive mapping sub procedures */
+void mRecLink(char i, char j, tLevel* lev); /* prototype */
+void mRecIndirect(char i, char j, tLevel* lev, char scr, char pos) {
+	char aux;
+	char auxb;
+	if ((*lev).handledLinks.linkMap[i][j]==255) {
+		aux=mGetLink (lev,scr,pos);
+		if (!(auxb=(!aux))) auxb=(!(*lev).handledLinks.linkList[aux]);
+		if (auxb) {
+			(*lev).handledLinks.linkMap[i][j]=aux;
+			if (aux) {
+				(*lev).handledLinks.linkList[aux]=1;
+				mRecLink(i,j,lev);
+			}
+		} else {
+			(*lev).handledLinks.linkMap[i][j]=0;
+		}
+	}
+}
+
+void mRecLink(char i, char j, tLevel* lev) {
+	char scr=(*lev).handledLinks.linkMap[i][j];
+
+	mRecIndirect(i,j-1,lev,scr,MAPS_sLeft);
+	mRecIndirect(i,j+1,lev,scr,MAPS_sRight);
+	mRecIndirect(i-1,j,lev,scr,MAPS_sUp);
+	mRecIndirect(i+1,j,lev,scr,MAPS_sDown);
+}
+
+void mCalcularLimUp (tLevel* lev) {
+	char i=0;
+	char j=0;
+	while (((*lev).handledLinks.linkMap[i][j]==255) && (j<MAPS_MAX_LENGTH)) {
+		if (++i==MAPS_MAX_LENGTH) {
+			j++;
+			i=0;
+		}
+	}
+	(*lev).handledLinks.limUp=j;
+}
+
+void mCalcularLimLeft (tLevel* lev) {
+	char i=0;
+	char j=0;
+	while (((*lev).handledLinks.linkMap[j][i]==255) && (j<MAPS_MAX_LENGTH)) {
+		if (++i==MAPS_MAX_LENGTH) {
+			j++;
+			i=0;
+		}
+	}
+	(*lev).handledLinks.limLeft=j;
+}
+
+void mCalcularLimDown (tLevel* lev) {
+	char i=0;
+	char j=MAPS_MAX_LENGTH-1;
+	while (((*lev).handledLinks.linkMap[i][j]==255) && j) {
+		if (++i==MAPS_MAX_LENGTH) {
+			j--;
+			i=0;
+		}
+	}
+	(*lev).handledLinks.limDown=j;
+}
+
+void mCalcularLimRight (tLevel* lev) {
+	char i=0;
+	char j=MAPS_MAX_LENGTH-1;
+	while (((*lev).handledLinks.linkMap[j][i]==255) && j) {
+		if (++i==MAPS_MAX_LENGTH) {
+			j--;
+			i=0;
+		}
+	}
+	(*lev).handledLinks.limRight=j;
+}
+
+
+/* 	Main mCreateLinkMap */
+void mCreateLinkMap(tLevel* lev) { /* private */
+	char	i,j,start;
+
+	/* Initialize arrays */
+	for (j=0;j<MAPS_MAX_LENGTH;j++)
+		for (i=0;i<MAPS_MAX_LENGTH;(*lev).handledLinks.linkMap[i++][j]=255);
+	for (j=1;j<=MAPS_MAX_SCREENS;(*lev).handledLinks.linkList[j++]=0);
+
+	/* Inicializar start en la pantalla de inicio */
+	mGetStartPosition(lev,&start,&i,&i,&i,&i);
+	(*lev).handledLinks.linkMap[MAPS_LINKMAP_CENTER][MAPS_LINKMAP_CENTER]=start;
+	(*lev).handledLinks.linkList[start]=1;
+
+	/* Start Recursive Mapper */
+	mRecLink(MAPS_LINKMAP_CENTER,MAPS_LINKMAP_CENTER,lev);
+
+	/* Buscar limites del nivel */
+	mCalcularLimUp   (lev);
+	mCalcularLimDown (lev);
+	mCalcularLimLeft (lev);
+	mCalcularLimRight(lev);
+
+}
+
+void mGetSize      (tLevel* lev, char* i,char* j) {
+	*i=(*lev).handledLinks.limRight - (*lev).handledLinks.limLeft;
+	*j=(*lev).handledLinks.limDown  - (*lev).handledLinks.limUp;
+}
+
+char mGetScrCount  (tLevel* lev) {
+	char l,aux;
+
+	aux=0;
+	for (l=1;l<=MAPS_MAX_SCREENS;aux+=((*lev).handledLinks.linkList[l++]?1:0));
+	return aux;
+}
+
+char mGetScreen    (tLevel* lev, char i,char j, char* error) {
+	char aux;
+
+	aux=(*lev).handledLinks.linkMap[(*lev).handledLinks.limLeft+i][(*lev).handledLinks.limUp+j];
+	*error=(aux==255);
+	return aux;
+}
+
+void mGetMainScreen(tLevel* lev, char* i,char* j) {
+	*i=(MAPS_LINKMAP_CENTER) - (*lev).handledLinks.limLeft;
+	*j=(MAPS_LINKMAP_CENTER) - (*lev).handledLinks.limUp;
+}
+
+void mAddScreen    (tLevel* lev, char i,char j, char* error) {
+	char scr=mGetScreen(lev,i,j,error);
+	*error=(*error || scr);
+	if (!*error) {
+		int l=1;
+		while ((*lev).handledLinks.linkList[l] && (l++<MAPS_MAX_SCREENS));
+		if ((*lev).handledLinks.linkList[l]) {
+			*error=1;
+		} else {
+			/* Pedir pantalla */
+			(*lev).handledLinks.linkList[l]=1;
+
+			i+=(*lev).handledLinks.limLeft;
+			j+=(*lev).handledLinks.limUp;
+
+			/* En caso de agregar una pantalla en alguno de los bordes, estos se amplian */
+			if ((*lev).handledLinks.limLeft=i) (*lev).handledLinks.limLeft--;
+			if ((*lev).handledLinks.limUp=j) (*lev).handledLinks.limUp--;
+			if ((*lev).handledLinks.limRight=i) (*lev).handledLinks.limRight++;
+			if ((*lev).handledLinks.limDown=j) (*lev).handledLinks.limDown++;
+
+
+			/* Poner 0 alrededor de l */
+			(*lev).handledLinks.linkMap[i][j-1]%=255;
+			(*lev).handledLinks.linkMap[i][j+1]%=255;
+			(*lev).handledLinks.linkMap[i+1][j]%=255;
+			(*lev).handledLinks.linkMap[i-1][j]%=255;
+
+			/* Poner l en l */
+			(*lev).handledLinks.linkMap[i][j]=l;
+
+			/* Setear links desde l a las 4 pantallas adyacentes */
+			mSetLink (lev,l,MAPS_sUp,(*lev).handledLinks.linkMap[i][j-1]);
+			mSetLink (lev,l,MAPS_sDown,(*lev).handledLinks.linkMap[i][j+1]);
+			mSetLink (lev,l,MAPS_sRight,(*lev).handledLinks.linkMap[i+1][j]);
+			mSetLink (lev,l,MAPS_sLeft,(*lev).handledLinks.linkMap[i-1][j]);
+
+			/* Setear links desde las 4 pantallas adyacentes a l */
+			mSetLink (lev,(*lev).handledLinks.linkMap[i][j+1],MAPS_sUp,l);
+			mSetLink (lev,(*lev).handledLinks.linkMap[i][j-1],MAPS_sDown,l);
+			mSetLink (lev,(*lev).handledLinks.linkMap[i-1][j],MAPS_sRight,l);
+			mSetLink (lev,(*lev).handledLinks.linkMap[i+1][j],MAPS_sLeft,l);
+
+			/* Limpiar contenido de la pantalla l */
+			for (i=0;i<3;i++) {
+				for (j=0;j<10;j++) {
+					mSetWall(lev,l,i,j,0);
+					mSetBack(lev,l,i,j,0);
+				}
+			}
+			mSetGuard(lev,l,1,1,1,1,1,1);
+			/* Listo, ya cree la pantalla y la linkie */
+		}
+	}
+}
+
+void mRemScreen    (tLevel* lev, char i,char j, char* error) {
+	/*{Q&D:
+		1) Si parten a la mitad un nivel se pierde una de las mitades
+		2) no se refresca la LinkMap en ese caso
+		3) tampoco une las pantallas que estaban a los costados}*/
+	unsigned char l=mGetScreen(lev,i,j,error);
+	*error=*error || (!l);
+	if (!*error) {
+		/* Liberar pantalla */
+		(*lev).handledLinks.linkList[l]=0;
+
+		/* Seteo posiciones absolutas */
+		i+=(*lev).handledLinks.limLeft;
+		j+=(*lev).handledLinks.limUp;
+
+		/* Poner 0 en l */
+		(*lev).handledLinks.linkMap[i][j]=0;
+
+		/* En caso de remover una pantalla en alguno de los bordes, estos se recalculan */
+		if ((*lev).handledLinks.limLeft=i) 	mCalcularLimLeft(lev);
+		if ((*lev).handledLinks.limUp=j)    mCalcularLimUp(lev);
+		if ((*lev).handledLinks.limRight=i) mCalcularLimRight(lev);
+		if ((*lev).handledLinks.limDown=j)  mCalcularLimDown(lev);
+
+		/* Borrar links desds las 4 pantallas adyacentes a l */
+		mSetLink (lev,(*lev).handledLinks.linkMap[i][j+1],MAPS_sLeft,0);
+		mSetLink (lev,(*lev).handledLinks.linkMap[i][j-1],MAPS_sRight,0);
+		mSetLink (lev,(*lev).handledLinks.linkMap[i-1][j],MAPS_sDown,0);
+		mSetLink (lev,(*lev).handledLinks.linkMap[i+1][j],MAPS_sUp,0);
+	}
+}
+
+void mCpyScreen    (tLevel* lev, char fromi,char fromj,char toi,char toj, char* error) {
+	char fromscr,toscr,i,j,k,l;
+	char sentido,existe;
+
+	/* Verificar que la pantalla source y la pantalla target existan */
+	fromscr=mGetScreen(lev,fromi,fromj,error); /* Verifico que existe la pantalla from */
+	*error=(*error || fromscr);
+	if (!*error) { /* Verifico que existe la pantalla to */
+		toscr=mGetScreen(lev,toi,toj,error);
+		*error=(*error || toscr);
+	}
+	if (!*error) { /* Si existen ambas pantallas */
+		/* Copiar contenido de la pantalla from a la pantalla to: */
+
+		/* Copiar wall y back */
+		char contenido[30];
+		mGetArray(lev,contenido,MAPS_BLOCK_OFFSET_WALL-30+fromscr*30,30);
+		mSetArray(lev,contenido,MAPS_BLOCK_OFFSET_WALL-30+toscr*30,30,MAPS_BLOCK_OFFSET_VALIDATOR_WALL);
+		mGetArray(lev,contenido,MAPS_BLOCK_OFFSET_BACK-30+fromscr*30,30);
+		mSetArray(lev,contenido,MAPS_BLOCK_OFFSET_BACK-30+toscr*30,30,MAPS_BLOCK_OFFSET_VALIDATOR_WALL);
+
+		/* Copiar Guards */
+		mGetGuard(lev,fromscr,&i,&j,&k,&l,&sentido,&existe);
+		mSetGuard(lev,toscr,i,j,k,l,sentido,existe);
+		/* Listo, ya se copio el contenido y el guardia */
+	}
+}
+
+/***************************************************************\
+|                         File handling                         |
+\***************************************************************/
+
+char mLoadPED(char* vFile,tLevel* lev) {
+	FILE *fp;
+	char aux;
+
+	if ((fp=fopen(vFile,"rb"))==NULL) {
+		return 0;
+	} else {
+		aux=fread (lev,sizeof(*lev),1,fp);
+		fclose(fp);
+		return aux;
+	}
+}
+
+char mLoadDAT(char* vFile,tLevel* lev,char levelNumber) {
+	FILE *fp;
+	char aux;
+
+	if ((fp=fopen(vFile,"rb"))==NULL) {
+		return 0;
+	} else {
+		(*lev).level=levelNumber;
+		fpos_t position=levelNumber*MAPS_BLOCK_SIZEOF_LEVEL+MAPS_BLOCK_OFFSET_LEVELS;
+		fsetpos (fp, &position);
+		aux=fread (&(*lev).levelArray,MAPS_BLOCK_SIZEOF_LEVEL,1,fp);
+		mCreateLinkMap(lev);
+		fclose(fp);
+		return aux;
+	}
+}
+
+char mSavePED(char* vFile,tLevel* lev) {
+  FILE * pFile;
+  if ((pFile = fopen (vFile , "wb"))==NULL) {
+		return 0;
+	}
+  fwrite (lev, 1, sizeof(*lev), pFile);
+  fclose (pFile);
+  return 1;
+}
+
+char mSaveDAT(char* vFile,tLevel* lev) {
+  FILE * pFile;
+  if ((pFile = fopen (vFile , "r+b"))==NULL) {
+		return 0;
+	}
+	fpos_t position=(*lev).level*MAPS_BLOCK_SIZEOF_LEVEL+MAPS_BLOCK_OFFSET_LEVELS;
+  fsetpos (pFile, &position);
+  fwrite ((*lev).levelArray, 1, MAPS_BLOCK_SIZEOF_LEVEL, pFile);
+  fclose (pFile);
+  return 1;
+}
+
+#endif