From 3955659b94488304e4b7349f15faac7afaa7e902455b4e7dbbabe967b3271729 Mon Sep 17 00:00:00 2001 From: Gabriel Lorenzo Date: Sun, 1 Jun 2003 23:03:22 +0000 Subject: [PATCH] graphics limpiada y documentada ;) --- dlls/src/edivstd/edivstd.c | 64 +- dlls/src/edivstd/edivstd.h | 3 - dlls/src/graphics/advance.c | 49 + dlls/src/graphics/carga.c | 151 +++ dlls/src/graphics/collision.c | 125 +++ dlls/src/graphics/default_palette.h | 71 ++ dlls/src/graphics/draw.c | 162 +++ dlls/src/graphics/graphics.c | 1323 +++-------------------- dlls/src/graphics/graphics.h | 157 ++- dlls/src/graphics/map_ops.c | 602 +++++++++++ dlls/src/graphics/misc.c | 81 ++ dlls/src/graphics/paleta.c | 126 +++ dlls/src/graphics/regiones.c | 71 ++ dlls/src/graphics/win32/graphics.vcproj | 24 + dlls/src/include/export.h | 93 +- 15 files changed, 1839 insertions(+), 1263 deletions(-) create mode 100644 dlls/src/graphics/advance.c create mode 100644 dlls/src/graphics/carga.c create mode 100644 dlls/src/graphics/collision.c create mode 100644 dlls/src/graphics/default_palette.h create mode 100644 dlls/src/graphics/draw.c create mode 100644 dlls/src/graphics/map_ops.c create mode 100644 dlls/src/graphics/misc.c create mode 100644 dlls/src/graphics/paleta.c create mode 100644 dlls/src/graphics/regiones.c diff --git a/dlls/src/edivstd/edivstd.c b/dlls/src/edivstd/edivstd.c index 49a5077..fbd350b 100644 --- a/dlls/src/edivstd/edivstd.c +++ b/dlls/src/edivstd/edivstd.c @@ -30,8 +30,9 @@ unsigned int tiempo; unsigned int ultimo_tiempo; #else - #error ¡adapta las rutinas de timer a Linux! + #error ¡adapta las rutinas de timer a Linux! (edivstd no debe usar SDL) #endif +#include #include #include @@ -42,6 +43,7 @@ int last_type ; int last_proc ; +#ifdef _DEBUG int DEBUG_PROCESOS(FUNCTION_PARAMS) { int i,n; @@ -56,6 +58,7 @@ int DEBUG_PROCESOS(FUNCTION_PARAMS) fclose(f); return 0; } +#endif int ExportaFuncs(EXPORTAFUNCS_PARAMS) { @@ -93,8 +96,8 @@ int ExportaFuncs(EXPORTAFUNCS_PARAMS) CONST("false",0); /* Rango de INT */ - CONST("max_int",2147483647); - CONST("min_int",-2147483648); + CONST("max_int",INT_MAX); + CONST("min_int",INT_MIN); /* Señales entre procesos */ CONST("s_kill",0); @@ -159,30 +162,19 @@ int ExportaFuncs(EXPORTAFUNCS_PARAMS) /* Variables locales varias */ LOCAL("priority",0); LOCAL("ctype",0); - LOCAL("x",0); - LOCAL("y",0); - LOCAL("z",0); - LOCAL("graph",0); - LOCAL("size",0); - LOCAL("angle",0); - LOCAL("region",0); - LOCAL("file",0); - LOCAL("xgraph",0); LOCAL("height",1); LOCAL("cnumber",0); - LOCAL("resolution",0); - LOCAL("flags",0); - LOCAL("transparency",128) ; FUNCTION("exit",2,eDIV_Exit); FUNCTION("get_id",1,eDiv_GetId) ; - FUNCTION("define_region",5,eDiv_DefineRegion) ; FUNCTION("signal",2,eDIV_Signal); FUNCTION("let_me_alone",0,eDIV_Let_Me_Alone); +#ifdef _DEBUG FUNCTION("debug_procesos",0,DEBUG_PROCESOS); +#endif - ENTRYPOINT( first_load ) ; + ENTRYPOINT(first_load) ; ENTRYPOINT(frame); /* @@ -243,29 +235,6 @@ int eDiv_GetId(FUNCTION_PARAMS) return 0 ; } -int eDiv_DefineRegion(FUNCTION_PARAMS) -{ - int n , x , y , w , h ; - h = getparm() ; - w = getparm() ; - y = getparm() ; - x = getparm() ; - n = getparm() ; - - if ( n > 31 || n < 1 ) { - fp->Runtime_Error(108); /* nº de región inválido */ - return 0; - } - - regions[n].x = x ; - regions[n].y = y ; - regions[n].w = w ; - regions[n].h = h ; - - - return 1 ; -} - void signal_tree(int proc, int signal, FUNCTION_PARAMS) { int id2; @@ -334,26 +303,11 @@ int eDIV_Let_Me_Alone(FUNCTION_PARAMS) */ void first_load(FUNCTION_PARAMS) { - int i ; - #ifdef _WIN32 struct timeb tiempob; ftime(&tiempob); ultimo_tiempo=tiempob.time*100+tiempob.millitm/10; #endif - - for ( i = 0 ; i < 32 ; i++ ) - { - regions[i].x = 0 ; - regions[i].y = 0 ; - regions[i].w = 0 ; - regions[i].h = 0 ; - } - - - fp->regions = regions ; - fp->existe.regions = 1 ; - } void frame(FUNCTION_PARAMS) diff --git a/dlls/src/edivstd/edivstd.h b/dlls/src/edivstd/edivstd.h index f1fc680..5422bf7 100644 --- a/dlls/src/edivstd/edivstd.h +++ b/dlls/src/edivstd/edivstd.h @@ -1,12 +1,9 @@ #ifndef __EDIV_EDIVSTD_H_ #define __EDIV_EDIVSTD_H_ -struct _regions regions[32] ; - /* Prototipos */ int eDIV_Exit(FUNCTION_PARAMS); int eDiv_GetId(FUNCTION_PARAMS) ; -int eDiv_DefineRegion(FUNCTION_PARAMS) ; int eDIV_Signal(FUNCTION_PARAMS); int eDIV_Let_Me_Alone(FUNCTION_PARAMS); diff --git a/dlls/src/graphics/advance.c b/dlls/src/graphics/advance.c new file mode 100644 index 0000000..5767214 --- /dev/null +++ b/dlls/src/graphics/advance.c @@ -0,0 +1,49 @@ +/*! \file advance.c + * \brief Contiene las funciones advance() y xadvance() para el movimiento en 2D. + * \todo Hacer que les afecte la local resolution + */ + +#include + +#include + +#include "export.h" +#include "graphics.h" + +/*! \brief Avanza 'a' unidades según el ángulo del proceso. + * @param a Distancia que se quiere avanzar + * @return 1 + * @see eDIV_XADVANCE() + */ +int eDIV_ADVANCE(FUNCTION_PARAMS) +{ + int a , id1 , x , y , angulo ; + a = getparm() ; + id1 = fp->procs_s[ fp->proc_orden[ *fp->proceso_actual ] ].id ; + angulo = local("angle",id1) ; + x = (int) ((double)a * cos( (angulo/1000) * PIOVER180 )) ; + y = (int) ((double)a * sin( (angulo/1000) * PIOVER180 )) ; + local("x",id1) += x; + local("y",id1) += y ; + return 1 ; +} + +/*! \brief Avanza 'b' unidades según el ángulo 'a' + * @param a Ángulo + * @param b Distancia que se quiere avanzar + * @return 1 + * @see eDIV_ADVANCE() + */ +int eDIV_XADVANCE(FUNCTION_PARAMS) +{ + int a , b , id1 , x , y , angulo ; + b = getparm() ; + a = getparm() ; + id1 = fp->procs_s[ fp->proc_orden[ *fp->proceso_actual ] ].id ; + angulo = a ; + x = (int) ((double)b * cos( (angulo/1000) * PIOVER180 )) ; + y = (int) ((double)b * sin( (angulo/1000) * PIOVER180 )) ; + local("x",id1) += x ; + local("y",id1) += y ; + return 1 ; +} diff --git a/dlls/src/graphics/carga.c b/dlls/src/graphics/carga.c new file mode 100644 index 0000000..ab921a7 --- /dev/null +++ b/dlls/src/graphics/carga.c @@ -0,0 +1,151 @@ +/* +** carga.c +** Incluye las funciones de carga y descarga de recursos gráficos +** (bmp, fpg, map, pcx, pal, png...) +*/ + +#include + +#include "export.h" +#include "graphics.h" + +/* +** +** eDIV_LOAD_BMP(filename); +** +** Carga un BMP donde 'filename' es el fichero a cargar. +** +** Retorna: El numero de Mapa. +** -1 : Si no se ha podido cargar el mapa. +** +*/ +int eDIV_LOAD_BMP(FUNCTION_PARAMS) +{ + int i ; + const char *filename=getstrparm(); /* Fichero a cargar */ + for ( i = 1000 ; i < files[0].num ; i++ ) + { + if ( files[0].mapa[i].existe == 0 ) + { + files[0].mapa[i].Surface = SDL_LoadBMP( filename ) ; + if(files[0].mapa[i].Surface == NULL) + fp->Runtime_Error(143); /* "No se pudo cargar el mapa, archivo no encontrado." */ + files[0].mapa[i].existe = 1 ; + files[0].mapa[i].cpoint[0].x = (int)files[0].mapa[i].Surface->w / 2 ; + files[0].mapa[i].cpoint[0].y = (int)files[0].mapa[i].Surface->h / 2 ; + SDL_SetColorKey( files[0].mapa[i].Surface , SDL_SRCCOLORKEY | SDL_RLEACCEL , color_transparente ) ; + if ( i > last_map[0] ) + last_map[0] = i ; + return i ; + } + } + return -1 ; +} + +/* +** +** eDIV_LOAD_FPG(filename); +** +** Carga un FPG, de cualquier bpp. +** +** Retorna: El numero de FPG. +** +*/ + +int eDIV_LOAD_FPG(FUNCTION_PARAMS) +{ + char * archivo ; + FILE *f; + FPGHEADER8 cabecera8; + FPGHEADER cabecera; + FPGMAPINFO infomapa; + int tamano; + int cont=0,num,i; + int bpp; + char* graphic; + + SDL_Color p[256]; + + archivo = getstrparm() ; + + f=fopen(archivo,"rb"); + if(f==NULL) { + fp->Runtime_Error(ERR_FILENOTFOUND); + } + + fseek(f,0,SEEK_END); + tamano=ftell(f); + fseek(f,0,SEEK_SET); + + fread(&cabecera,1,sizeof(FPGHEADER),f); + + /* + * TODO: optimizar esto ligeramente (comprobar primero los bytes comunes y luego + * leer "pg","16","24","32") + */ + + if(strcmp(cabecera.header,"fpg\x1A\x0D\x0A")) { + if(strcmp(cabecera.header,"f16\x1A\x0D\x0A")) { + if(strcmp(cabecera.header,"f24\x1A\x0D\x0A")) { + if(strcmp(cabecera.header,"f32\x1A\x0D\x0A")) { + fp->Runtime_Error(ERR_INVALIDFPGHEADER); + } + else { + bpp=32; + } + } + else { + bpp=24; + } + } + else { + bpp=16; + } + } + else { + bpp=8; + fseek(f,0,SEEK_SET); + fread(&cabecera8,1,sizeof(FPGHEADER8),f); + + for(i=0;i<256;i++) { + p[i].r=cabecera8.palette[i].r*4; + p[i].g=cabecera8.palette[i].g*4; + p[i].b=cabecera8.palette[i].b*4; + } + SDL_SetPalette(screen,SDL_LOGPAL|SDL_PHYSPAL,p,0,256); + } + + + + while(ftell(f)999 || num<0) { + fp->Runtime_Error(ERR_INVALIDMAPCODE); + } + if ( files[0].mapa[num].existe == 1 ) + return -1 ; + files[0].mapa[num].existe = 1 ; + + if(infomapa.number_of_points==0) { + files[0].mapa[num].cpoint[0].x = (int) infomapa.wide/2 ; + files[0].mapa[num].cpoint[0].y = (int) infomapa.height/2 ; + } else { + fread(files[0].mapa[num].cpoint,2,2*infomapa.number_of_points,f) ; + } + + graphic = (char*)malloc(infomapa.wide*infomapa.height*bpp/8); + fread(graphic,1,infomapa.wide*infomapa.height*bpp/8,f); + + files[0].mapa[num].Surface = SDL_CreateRGBSurfaceFrom(graphic,infomapa.wide,infomapa.height,bpp,infomapa.wide*bpp/8,0,0,0,0) ; + + cont++; + if(bpp==8) { + SDL_SetPalette(files[0].mapa[num].Surface,SDL_LOGPAL|SDL_PHYSPAL,p,0,256); + } + SDL_SetColorKey(files[0].mapa[num].Surface,SDL_SRCCOLORKEY|SDL_RLEACCEL,0); + } + + fclose(f); + return 0; +} diff --git a/dlls/src/graphics/collision.c b/dlls/src/graphics/collision.c new file mode 100644 index 0000000..36c0966 --- /dev/null +++ b/dlls/src/graphics/collision.c @@ -0,0 +1,125 @@ +/* +** collision.c +** Incluye las rutinas de detección de colisiones entre sprites +*/ + +#include + +#include "export.h" +#include "graphics.h" + +/* +** int IntersectionRR(int rc1left,int rc1top,int rc1right,int rc1bottom,int rc2left,int rc2top,int rc2right,int rc2bottom) +** Comprueba si hay colisión entre dos regiones rectangulares. +** +** Devuelve: +** 0 - No hay colisión +** 1 - Hay colisión +*/ +int IntersectionRR(int rc1left,int rc1top,int rc1right,int rc1bottom,int rc2left,int rc2top,int rc2right,int rc2bottom) +{ + if(rc1left==rc2left || rc1top==rc2top || rc1right==rc2right || rc1bottom==rc2bottom) + return 1; + + return ((Miedzy(rc1left,rc2left,rc2right) || Miedzy(rc1right,rc2left,rc2right) || + Miedzy(rc2left,rc1left,rc1right) || Miedzy(rc2right,rc1left,rc1right)) && + (Miedzy(rc1top,rc2top,rc2bottom) || Miedzy(rc1bottom,rc2top,rc2bottom) || + Miedzy(rc2top,rc1top,rc1bottom) || Miedzy(rc2bottom,rc1top,rc1bottom))); +} + +/* +** eDIV_COLLISION (id) +** +** Detecta si el proceso actual está colisionando con el del id indicado, o, si +** se le indica un type, si colisiona con algún proceso de ese tipo +** +** Devuelve: - el ID del proceso con el que se está colisionando (si se indica +** un type y se está colisionando a la vez con varios procesos de +** ese type, en sucesivas llamadas se irán devolviendo sus respec- +** tivos IDs, hasta devolver 0 cuando ya no queden más). +** - 0 si no se colisiona con ningún proceso del ID o type indicado. +*/ +int eDIV_COLLISION(FUNCTION_PARAMS) +{ + int g1 , g2 ; + int f1 , f2 ; + int id1, id2 ; + int a, i ; + SDL_Rect r1 , r2 ; + int _status=reservedptr("status"); + a = getparm() ; + + id1 = fp->procs_s[ fp->proc_orden[ *fp->proceso_actual ] ].id ; + + g1 = local("graph",id1) ; + f1 = local("file",id1) ; + if ( files[f1].existe == 0 || files[f1].mapa[g1].existe == 0 ) + return 0; + + /* Si se le pasa un ID */ + if (aimem_max) + { + if(a==id1 || (fp->mem[id1+_status]!=2 && fp->mem[id1+_status]!=4)) + return 0; + r1.x = local("x",id1) ; + r1.y = local("y",id1) ; + r1.w = files[f1].mapa[g1].Surface->w ; + r1.h = files[f1].mapa[g1].Surface->h ; + id2 = a ; + g2 = local("graph",id2) ; + f2 = local("file",id2); + if ( files[f2].existe == 0 || files[f2].mapa[g2].existe == 0 ) + return 0; + r2.x = local("x",id2) ; + r2.y = local("y",id2) ; + r2.w = files[f2].mapa[g2].Surface->w ; + r2.h = files[f2].mapa[g1].Surface->h ; + /* Colision barata :P */ + if(IntersectionRR(r1.x,r1.y,r1.x+r1.w-1,r1.x+r1.h-1,r2.x,r2.y,r2.x+r2.w-1,r2.y+r2.h-1)) + return id2; + } + else { + int* type_scan=&reserved("type_scan",id1); + int* id_scan=&reserved("id_scan",id1); + /* Si se le pasa un type */ + + if(*type_scan!=a) { + *id_scan=0; + *type_scan=a; + } + + for ( i = *id_scan+1 ; i < *fp->num_procs ; i++ ) + { + id2 = fp->procs_s[ fp->proc_orden[ i ] ].id; + if(id2==id1 || (fp->mem[id1+_status]!=2 && fp->mem[id1+_status]!=4)) + continue; + + /* Si el proceso se corresponde con el type */ + if ( reserved("process_type",id2) == a ) + { + + r1.x = local("x",id1) ; + r1.y = local("y",id1) ; + r1.w = files[f1].mapa[g1].Surface->w ; + r1.h = files[f1].mapa[g1].Surface->h ; + g2 = local("graph",id2) ; + f2 = local("file",id2) ; + if ( files[f2].existe == 0 || files[f2].mapa[g2].existe == 0 ) + continue; + r2.x = local("x",id2) ; + r2.y = local("y",id2) ; + r2.w = files[f2].mapa[g2].Surface->w ; + r2.h = files[f2].mapa[g1].Surface->h ; + /* Colision barata :P */ + if(IntersectionRR(r1.x,r1.y,r1.x+r1.w-1,r1.x+r1.h-1,r2.x,r2.y,r2.x+r2.w-1,r2.y+r2.h-1)) { + *id_scan=i; + + return id2; + } + } + } + *type_scan=0; + } + + return 0 ; +} diff --git a/dlls/src/graphics/default_palette.h b/dlls/src/graphics/default_palette.h new file mode 100644 index 0000000..e183634 --- /dev/null +++ b/dlls/src/graphics/default_palette.h @@ -0,0 +1,71 @@ +/*! \file default_palette.h + * \brief Contiene la definición de la paleta por defecto + * + * Este fichero contiene la definición de #default_palette, que es un array + * de bytes que contienen la información RGBA de los colores de la paleta que + * se inicializa por defecto (ya que el modo por defecto es de 8 bits). + */ + +#ifndef __EDIV_DEFAULT_PALETTE_H_ +#define __EDIV_DEFAULT_PALETTE_H_ + +#include + +/*! esta es la paleta ke usa por defecto el DIV2, asi k el eDIV tambien xD */ + +byte default_palette[]={ +0,0,0,0,16,16,16,0,32,32,32,0,48,48,48,0,64,64,64,0, +84,84,84,0,100,100,100,0,116,116,116,0,132,132,132,0,148,148,148,0, +168,168,168,0,184,184,184,0,200,200,200,0,216,216,216,0,232,232,232,0, +252,252,252,0,40,0,0,0,72,0,0,0,108,0,0,0,144,0,0,0, +180,0,0,0,216,0,0,0,252,0,0,0,252,32,0,0,252,64,0,0, +252,96,0,0,252,128,0,0,252,160,0,0,252,180,56,0,252,200,112,0, +252,220,168,0,252,240,224,0,0,40,0,0,0,60,0,0,0,84,0,0, +0,108,0,0,0,132,0,0,0,156,0,0,0,180,0,0,0,204,0,0, +0,228,0,0,0,252,0,0,48,252,32,0,96,252,64,0,144,252,96,0, +192,252,132,0,216,252,176,0,240,252,220,0,0,0,40,0,0,0,72,0, +0,0,104,0,0,0,140,0,0,0,172,0,0,0,208,0,0,0,252,0, +0,48,252,0,0,100,252,0,0,148,252,0,0,200,252,0,0,252,252,0, +56,252,252,0,112,252,252,0,168,252,252,0,224,252,252,0,28,28,0,0, +52,52,0,0,76,76,0,0,100,100,0,0,124,124,0,0,152,152,0,0, +176,176,0,0,200,200,0,0,224,224,0,0,252,252,0,0,252,252,36,0, +252,252,72,0,252,252,108,0,252,252,144,0,252,252,180,0,252,252,220,0, +28,0,28,0,52,0,52,0,76,0,76,0,100,0,100,0,124,0,124,0, +152,0,152,0,176,0,176,0,200,0,200,0,224,0,224,0,252,0,252,0, +252,36,252,0,252,72,252,0,252,112,252,0,252,148,252,0,252,184,252,0, +252,224,252,0,0,20,20,0,0,40,40,0,0,60,60,0,0,80,80,0, +0,104,100,0,0,124,120,0,0,144,144,0,0,164,164,0,0,188,184,0, +0,208,204,0,0,228,224,0,0,252,248,0,44,252,248,0,92,252,248,0, +140,252,248,0,188,252,248,0,24,12,0,0,44,24,0,0,64,36,0,0, +84,48,0,0,108,60,0,0,128,72,0,0,148,84,0,0,168,96,0,0, +192,112,0,0,196,128,28,0,204,144,60,0,212,160,92,0,216,180,120,0, +224,196,152,0,232,212,184,0,240,232,216,0,24,12,12,0,40,20,20,0, +60,32,32,0,80,44,44,0,96,52,52,0,116,64,64,0,136,76,76,0, +156,88,88,0,176,104,104,0,196,120,120,0,216,136,136,0,240,152,152,0, +240,168,168,0,244,188,188,0,244,204,204,0,248,224,224,0,24,20,12,0, +44,36,24,0,68,52,36,0,88,72,48,0,112,88,60,0,132,104,72,0, +156,124,88,0,172,140,100,0,188,156,112,0,204,176,124,0,220,192,136,0, +240,212,152,0,240,216,168,0,244,224,188,0,244,232,204,0,248,240,224,0, +32,8,0,0,60,16,0,0,88,28,0,0,120,36,0,0,148,48,0,0, +176,56,0,0,208,68,0,0,216,88,0,0,224,112,0,0,232,136,0,0, +240,160,0,0,252,184,0,0,252,200,56,0,252,216,112,0,252,232,168,0, +252,252,224,0,20,12,12,0,36,24,24,0,56,36,36,0,72,48,48,0, +92,64,64,0,108,76,76,0,128,88,88,0,144,100,100,0,164,116,116,0, +172,132,132,0,184,148,148,0,192,164,164,0,204,180,180,0,212,196,196,0, +224,212,212,0,236,232,232,0,12,20,12,0,24,36,24,0,36,56,36,0, +48,72,48,0,64,92,64,0,76,108,76,0,88,128,88,0,100,144,100,0, +116,164,116,0,132,172,132,0,148,184,148,0,164,192,164,0,180,204,180,0, +196,212,196,0,212,224,212,0,232,236,232,0,12,12,16,0,24,24,32,0, +36,36,48,0,48,48,64,0,64,64,80,0,76,76,96,0,88,88,112,0, +100,100,128,0,116,116,148,0,132,132,160,0,148,148,172,0,164,164,184,0, +180,180,196,0,196,196,208,0,212,212,220,0,232,232,236,0,40,0,0,0, +80,0,0,0,124,0,0,0,164,0,0,0,208,0,0,0,252,0,0,0, +252,40,0,0,252,84,0,0,252,124,0,0,252,168,0,0,252,208,0,0, +252,252,0,0,252,252,44,0,252,252,92,0,252,252,140,0,252,252,188,0, +0,0,0,0,0,0,88,0,0,0,128,0,0,0,168,0,0,0,208,0, +0,0,248,0,40,0,248,0,84,0,248,0,124,0,248,0,168,0,248,0, +208,0,248,0,252,0,252,0,252,52,252,0,252,108,252,0,252,164,252,0, +252,220,252,0 +}; + +#endif /* __EDIV_DEFAULT_PALETTE_H_ */ diff --git a/dlls/src/graphics/draw.c b/dlls/src/graphics/draw.c new file mode 100644 index 0000000..ab62cc3 --- /dev/null +++ b/dlls/src/graphics/draw.c @@ -0,0 +1,162 @@ +/*! \file draw.c + * \brief Funciones de dibujo de figuras 2D (draw's) + */ + +#include + +#include "export.h" +#include "graphics.h" + +/*! \brief Crea un nuevo draw + * \todo Permitir más tipos de figuras, y hacer que se dibujen en tiempo real, para que sean más rápidos y no consuman memoria + * @param t Tipo de figura (1=línea, 2=rectángulo, 3=rectángulo relleno, 4=elipse, 5=elipse rellena) + * @param c Color + * @param o Opacidad (0..15) + * @param r Región + * @param x0 Coordenada X inicial + * @param y0 Coordenada Y inicial + * @param x1 Coordenada X final + * @param y1 Coordenada Y final + * @return El identificador del draw, o -1 si hubo un error + * @see eDIV_MOVE_DRAW(), eDIV_DELETE_DRAW(), #draws, frame() + */ +int eDIV_DRAW(FUNCTION_PARAMS) +{ + int i ; + int t , c , o , r , x0, y0 , x1 , y1 ; + SDL_Rect dstrect ; + y1 = getparm() ; + x1 = getparm() ; + y0 = getparm() ; + x0 = getparm() ; + r = getparm() ; + o = getparm() ; + c = getparm() ; + t = getparm() ; + + for ( i = 0 ; i < 1024 ; i++ ) + { + if ( draws[i].existe == 0 ) + { + draws[i].Surface = SDL_CreateRGBSurface( SDL_HWSURFACE , x1 - x0 , y1 - y0 , screen->format->BitsPerPixel , 0xFF0000 , 0x00FF00 , 0x0000FF , 0x000000 ) ; + switch ( t ) + { + case 3: + dstrect.x = 0 ; + dstrect.y = 0 ; + dstrect.w = x1 - x0 ; + dstrect.h = y1 - y0 ; + SDL_FillRect( draws[i].Surface , &dstrect , c ) ; + break ; + } + draws[i].region = r ; + draws[i].x = x0 ; + draws[i].y = y0 ; + draws[i].t = t ; + draws[i].c = c ; + if ( o < 15 && o > -1 ) + SDL_SetAlpha( draws[i].Surface , SDL_SRCALPHA | SDL_RLEACCEL , 17 * (o) ) ; + draws[i].existe = 1 ; + if ( i > last_draw ) + last_draw = i ; + return i ; + } + } + return -1 ; +} + + +/*! \brief Cambia los atributos de un draw + * @param id Identificador del draw a modificar + * @param c Color + * @param o Opacidad (0..15) + * @param x0 Coordenada X inicial + * @param y0 Coordenada X inicial + * @param x1 Coordenada Y final + * @param y1 Coordenada X final + * @return 1 si todo fue bien, -1 si hubo un error + * @see eDIV_DRAW(), eDIV_DELETE_DRAW(), #draws + */ +int eDIV_MOVE_DRAW(FUNCTION_PARAMS) +{ + SDL_Rect dstrect ; + int id , c , o , x0 , y0 , x1 , y1 ; + y1 = getparm() ; + x1 = getparm() ; + y0 = getparm() ; + x0 = getparm() ; + o = getparm() ; + c = getparm() ; + id = getparm() ; + + if ( !draws[id].existe ) + return -1 ; + + if ( x1 - x0 != draws[id].Surface->w || y1 - y0 != draws[id].Surface->h || c != draws[id].c ) + { + if ( x1 - x0 != draws[id].Surface->w || y1 - y0 != draws[id].Surface->h ) + { + SDL_FreeSurface( draws[id].Surface ) ; + draws[id].Surface = SDL_CreateRGBSurface( SDL_HWSURFACE , x1 - x0 , y1 - y0 , screen->format->BitsPerPixel , 0xFF0000 , 0x00FF00 , 0x0000FF , 0x000000 ) ; + } + switch ( draws[id].t ) + { + case 3: + dstrect.x = 0 ; + dstrect.y = 0 ; + dstrect.w = x1 - x0 ; + dstrect.h = y1 - y0 ; + SDL_FillRect( draws[id].Surface , &dstrect , c ) ; + break ; + } + } + + draws[id].x = x0 ; + draws[id].y = y0 ; + draws[id].c = c ; + if ( o < 15 && o > -1 ) + SDL_SetAlpha( draws[id].Surface , SDL_SRCALPHA | SDL_RLEACCEL , 17 * (o) ) ; + else + if ( o == 15 ) + SDL_SetAlpha( draws[id].Surface , 0 , 255 ) ; + + return 1 ; +} + +/*! \brief Elimina un draw + * @param n Identificador del draw o \a all_drawing (-1). + * @return 1 si todo fue bien, -1 si hubo un error + * @see eDIV_DRAW(), eDIV_MOVE_DRAW(), #draws + */ +int eDIV_DELETE_DRAW(FUNCTION_PARAMS) +{ + int n ; + n = getparm() ; + + if(n==-1) { + for(n=0;n 0 ; last_draw-- ) + { + if ( draws[last_draw].existe ) + break ; + } + return 1 ; + + + +} diff --git a/dlls/src/graphics/graphics.c b/dlls/src/graphics/graphics.c index 2f19b59..bc40b33 100644 --- a/dlls/src/graphics/graphics.c +++ b/dlls/src/graphics/graphics.c @@ -1,3 +1,11 @@ +/*! \file graphics.c + * \brief DLL principal del motor gráfico 2D de eDIV + * + * En esta DLL se encuentran las principales funciones relacionadas con el + * manejo de gráficos. Tiene prioridad P_SIEMPRE ya que se supone que la + * mayoría de los programas hechos con eDIV requerirán tratamiento de gráficos. + */ + #include #include #include @@ -15,88 +23,14 @@ #include "export.h" #include "graphics.h" #include "SDL_rotozoom.h" -#include "default_palette.h" - -#define ERR_FILENOTFOUND 105 -#define ERR_INVALIDFPGHEADER 106 -#define ERR_INVALIDMAPCODE 110 - -#define Miedzy(x,a,b) (((x) >= (a)) && ((x) <= (b))) - -#define PaletteCopy(dst,src) SDL_SetPalette(dst,SDL_LOGPAL|SDL_PHYSPAL,src->format->palette->colors,0,256); - -#define MAX_DRAWS 1024 -struct _files files[ 0xFF ] ; - -SDL_Surface *Mapa[0xFFF] ; - -struct _file file0[0xFFF] ; -int last_map[0xFF] ; -int color_transparente ; -int define_region ; -BOOL primer_frame=TRUE; - -typedef struct { - unsigned char r,g,b; - } pal_t; - -typedef struct _FPGHEADER8{ - char header[8]; - pal_t palette[256]; - /* char palette[768]; */ - char colorbars[576]; -}FPGHEADER8; - -typedef struct _FPGHEADER{ - char header[8]; - /* pal_t palette[256]; */ - /* char palette[768]; */ - /* char colorbars[576]; */ -}FPGHEADER; - -typedef struct _FPGMAPINFO{ - int code; - int lenght; - char description[32]; - char filename[12]; - int wide; - int height; - int number_of_points; -}FPGMAPINFO; - -//char *graphic; /* wide*height */ - - -struct{ - int existe ; - int region ; - int x , y ; - int t , c ; /* requerido para move_draw() */ - SDL_Surface *Surface ; -} draws[MAX_DRAWS] ; - -int last_draw ; - -struct _blits { - SDL_Surface *src ; - SDL_Rect srcrect ; - SDL_Surface *dst ; - SDL_Rect dstrect ; - int z ; - int trans ; -} blits[0xFFFF] , *orden[0xFFFF]; - -int last_blit ; - -int gamma[3] ; - -int smooth=0; /* Smooth para el ZOOM */ - +/*! \brief Función de exportación de símbolos de la DLL + * @return TRUE si la DLL da su permiso para ser cargada, en caso contrario, FALSE + */ int ExportaFuncs(EXPORTAFUNCS_PARAMS) { - + /* Modos predefinidos para set_mode (sólo 8 bpp, compatibilidad DIV2) */ CONST("m320x200",320200); CONST("m320x240",320240); CONST("m320x400",320400); @@ -116,23 +50,29 @@ int ExportaFuncs(EXPORTAFUNCS_PARAMS) CONST("m1600x1200",16001200); CONST("m1900x1600",19001600); + /* flags para set_mode */ CONST("_fullscreen",GR_FULLSCREEN); + /* valores para dump_type */ CONST("partial_dump",0); CONST("complete_dump",1); + /* valores para restore_type */ CONST("no_restore",-1); CONST("partial_restore",0); CONST("complete_restore",1); + /* valores para graphic_info() */ CONST("g_wide",0); CONST("g_height",1); CONST("g_x_center",2); CONST("g_y_center",3); + /* constante para delete_draw() */ CONST("all_drawing",-1); + /* estructura para get_video_modes() */ GLOBAL_STRUCT("video_modes",31); _INT("wide",0); _INT("height",0); @@ -140,6 +80,7 @@ int ExportaFuncs(EXPORTAFUNCS_PARAMS) _INT("mode",0); END_STRUCT; + /* variables globales */ GLOBAL("dump_type",1); GLOBAL("restore_type",1); GLOBAL("fading",0); @@ -149,13 +90,42 @@ int ExportaFuncs(EXPORTAFUNCS_PARAMS) GLOBAL("draw_z",-255); GLOBAL("smooth",smooth); /* > Atención una nueva variable que indica si se activa o no el SMOOTH al ZOOMEAR. */ + /* variables locales */ + LOCAL("x",0); + LOCAL("y",0); + LOCAL("z",0); + LOCAL("graph",0); + LOCAL("size",0); + LOCAL("angle",0); + LOCAL("region",0); + LOCAL("file",0); + LOCAL("xgraph",0); + LOCAL("resolution",0); + LOCAL("flags",0); + LOCAL("transparency",128); + + /* FUNCIONES */ + + /* Carga/descarga */ FUNCTION("load_bmp",1,eDIV_LOAD_BMP) ; + FUNCTION("load_fpg",1,eDIV_LOAD_FPG) ; + + /* Colisiones */ FUNCTION("collision",1,eDIV_COLLISION) ; + + /* Paleta */ FUNCTION("set_transparent_color",1,eDIV_SET_TRANSPARENT_COLOR) ; FUNCTION("get_transparent_color",0,eDIV_GET_TRANSPARENT_COLOR) ; FUNCTION("rgb",3,eDIV_RGB) ; + FUNCTION("find_color",3,eDIV_FIND_COLOR); + FUNCTION("fade",4,eDIV_FADE) ; + FUNCTION("get_rgb",4,eDIV_GET_RGB); + + /* Advance y xadvance */ FUNCTION("advance",1,eDIV_ADVANCE) ; FUNCTION("xadvance",2,eDIV_XADVANCE) ; + + /* Operaciones con mapas */ FUNCTION("map_block_copy",9,eDIV_MAP_BLOCK_COPY) ; FUNCTION("map_get_pixel",4,eDIV_MAP_GET_PIXEL) ; FUNCTION("map_put",5,eDIV_MAP_PUT); @@ -167,1046 +137,49 @@ int ExportaFuncs(EXPORTAFUNCS_PARAMS) FUNCTION("get_pixel",2,eDIV_GET_PIXEL); FUNCTION("new_map",5,eDIV_NEW_MAP) ; FUNCTION("screen_copy",7,eDIV_SCREEN_COPY) ; - FUNCTION("out_region",2,eDIV_OUT_REGION) ; - FUNCTION("draw",8,eDIV_DRAW) ; - FUNCTION("move_draw",7,eDIV_MOVE_DRAW) ; - FUNCTION("delete_draw",1,eDIV_DELETE_DRAW) ; - FUNCTION("load_fpg",1,eDIV_LOAD_FPG) ; FUNCTION("get_point",5,eDIV_GET_POINT) ; FUNCTION("get_real_point",3,eDIV_GET_REAL_POINT) ; FUNCTION("graphic_info",3,eDIV_GRAPHIC_INFO) ; - FUNCTION("fade",4,eDIV_FADE) ; FUNCTION("xput",6,eDIV_XPUT); - FUNCTION("get_rgb",4,eDIV_GET_RGB); + + /* Regiones */ + FUNCTION("define_region",5,eDIV_DEFINE_REGION) ; + FUNCTION("out_region",2,eDIV_OUT_REGION) ; + + /* Draws */ + FUNCTION("draw",8,eDIV_DRAW) ; + FUNCTION("move_draw",7,eDIV_MOVE_DRAW) ; + FUNCTION("delete_draw",1,eDIV_DELETE_DRAW) ; + + /* Otras */ FUNCTION("set_mode",1,eDIV_SET_MODE); FUNCTION("set_mode",3,eDIV_SET_MODE); FUNCTION("set_mode",4,eDIV_SET_MODE); + + /* Entrypoints */ ENTRYPOINT( frame ) ; ENTRYPOINT( first_load ) ; - return TRUE; } -/* - * int IntersectionRR(int rc1left,int rc1top,int rc1right,int rc1bottom,int rc2left,int rc2top,int rc2right,int rc2bottom) - * Comprueba si hay colisión entre dos regiones rectangulares. - * - * Devuelve: - * 0 - No hay colisión - * 1 - Hay colisión - */ -int IntersectionRR(int rc1left,int rc1top,int rc1right,int rc1bottom,int rc2left,int rc2top,int rc2right,int rc2bottom) -{ - return ((Miedzy(rc1left,rc2left,rc2right) || Miedzy(rc1right,rc2left,rc2right) || - Miedzy(rc2left,rc1left,rc1right) || Miedzy(rc2right,rc1left,rc1right)) && - (Miedzy(rc1top,rc2top,rc2bottom) || Miedzy(rc1bottom,rc2top,rc2bottom) || - Miedzy(rc2top,rc1top,rc1bottom) || Miedzy(rc2bottom,rc1top,rc1bottom))); -} - -/* - * A continuación las funciones que queremos exportar. Para una mayor - * sencillez las hemos puesto en este mismo archivo, aunque puede ser - * aconsejable ponerlas en archivos aparte. - */ -int eDIV_COLLISION(FUNCTION_PARAMS) -{ - int g1 , g2 ; - int f1 , f2 ; - int id1, id2 ; - int a, i ; - SDL_Rect r1 , r2 ; - int _status=reservedptr("status"); - a = getparm() ; - - id1 = fp->procs_s[ fp->proc_orden[ *fp->proceso_actual ] ].id ; - - g1 = local("graph",id1) ; - f1 = local("file",id1) ; - if ( files[f1].existe == 0 || files[f1].mapa[g1].existe == 0 ) - return 0; - - /* Si se le pasa un ID */ - if (aimem_max) - { - if(a==id1 || (fp->mem[id1+_status]!=2 && fp->mem[id1+_status]!=4)) - return 0; - r1.x = local("x",id1) ; - r1.y = local("y",id1) ; - r1.w = files[f1].mapa[g1].Surface->w ; - r1.h = files[f1].mapa[g1].Surface->h ; - id2 = a ; - g2 = local("graph",id2) ; - f2 = local("file",id2); - if ( files[f2].existe == 0 || files[f2].mapa[g2].existe == 0 ) - return 0; - r2.x = local("x",id2) ; - r2.y = local("y",id2) ; - r2.w = files[f2].mapa[g2].Surface->w ; - r2.h = files[f2].mapa[g1].Surface->h ; - /* Colision barata :P */ - if(IntersectionRR(r1.x,r1.y,r1.x+r1.w-1,r1.x+r1.h-1,r2.x,r2.y,r2.x+r2.w-1,r2.y+r2.h-1)) - return id2; - } - else { - int* type_scan=&reserved("type_scan",id1); - int* id_scan=&reserved("id_scan",id1); - /* Si se le pasa un type */ - - if(*type_scan!=a) { - *id_scan=0; - *type_scan=a; - } - - for ( i = *id_scan+1 ; i < *fp->num_procs ; i++ ) - { - id2 = fp->procs_s[ fp->proc_orden[ i ] ].id; - if(id2==id1 || (fp->mem[id1+_status]!=2 && fp->mem[id1+_status]!=4)) - continue; - - /* Si el proceso se corresponde con el type */ - if ( reserved("process_type",id2) == a ) - { - - r1.x = local("x",id1) ; - r1.y = local("y",id1) ; - r1.w = files[f1].mapa[g1].Surface->w ; - r1.h = files[f1].mapa[g1].Surface->h ; - g2 = local("graph",id2) ; - f2 = local("file",id2) ; - if ( files[f2].existe == 0 || files[f2].mapa[g2].existe == 0 ) - continue; - r2.x = local("x",id2) ; - r2.y = local("y",id2) ; - r2.w = files[f2].mapa[g2].Surface->w ; - r2.h = files[f2].mapa[g1].Surface->h ; - /* Colision barata :P */ - if(IntersectionRR(r1.x,r1.y,r1.x+r1.w-1,r1.x+r1.h-1,r2.x,r2.y,r2.x+r2.w-1,r2.y+r2.h-1)) { - *id_scan=i; - - return id2; - } - } - } - *type_scan=0; - } - - return 0 ; -} - -/*****************************************************************/ -/* */ -/* eDIV_LOAD_BMP(filename); */ -/* */ -/* Carga un BMP donde 'filename' es el fichero a cargar. */ -/* */ -/* Retorna: El numero de Mapa. */ -/* -1 : Si no se ha podido cargar el mapa. */ -/* */ -/*****************************************************************/ -int eDIV_LOAD_BMP(FUNCTION_PARAMS) -{ - int i ; - const char *filename=getstrparm(); /* Fichero a cargar */ - for ( i = 1000 ; i < files[0].num ; i++ ) - { - if ( files[0].mapa[i].existe == 0 ) - { - files[0].mapa[i].Surface = SDL_LoadBMP( filename ) ; - if(files[0].mapa[i].Surface == NULL) - fp->Runtime_Error(143); /* "No se pudo cargar el mapa, archivo no encontrado." */ - files[0].mapa[i].existe = 1 ; - files[0].mapa[i].cpoint[0].x = (int)files[0].mapa[i].Surface->w / 2 ; - files[0].mapa[i].cpoint[0].y = (int)files[0].mapa[i].Surface->h / 2 ; - SDL_SetColorKey( files[0].mapa[i].Surface , SDL_SRCCOLORKEY | SDL_RLEACCEL , color_transparente ) ; - if ( i > last_map[0] ) - last_map[0] = i ; - return i ; - } - } - return -1 ; -} - -/*****************************************************************/ -/* */ -/* eDIV_SET_TRANSPARENT_COLOR(a); */ -/* */ -/* Coloca cual es el color transparente donde 'a' es el color. */ -/* */ -/* Retorna: El antiguo color transparente. */ -/* */ -/*****************************************************************/ - -int eDIV_SET_TRANSPARENT_COLOR(FUNCTION_PARAMS) -{ - int b , i; - int a = getparm() ; - b = color_transparente ; - color_transparente = a ; - for ( i = 1 ; i <= last_map[0] ; i++ ) - { - if ( files[0].mapa[i].existe ) - SDL_SetColorKey( files[0].mapa[i].Surface , SDL_SRCCOLORKEY | SDL_RLEACCEL , color_transparente ) ; - } - return b ; -} - -/*****************************************************************/ -/* */ -/* eDIV_GET_TRANSPARENT_COLOR(); */ -/* */ -/* Retorna: El color transparente. */ -/* */ -/*****************************************************************/ - -int eDIV_GET_TRANSPARENT_COLOR(FUNCTION_PARAMS) -{ - return color_transparente ; -} - -/*****************************************************************/ -/* */ -/* eDIV_RGB(r,g,b); */ -/* */ -/* Crea un color a partir de los 3 colores basicos. . */ -/* */ -/* r=Rojo (Red) g=Verde (Green) b=Blue (Azul) */ -/* */ -/* Retorna: El color generado. */ -/* */ -/*****************************************************************/ - -int eDIV_RGB(FUNCTION_PARAMS) -{ - int r,g,b ; - b = getparm() ; - g = getparm() ; - r = getparm() ; - - //return ( b + g*256 + r*65536 ) ; - return SDL_MapRGB(screen->format,r,g,b); -} - -/*****************************************************************/ -/* */ -/* eDIV_GET_RGB(color, offset r, offset g, offset b); */ -/* */ -/* Obtiene las componentes RGB de un color dado. */ -/* */ -/* r=Rojo (Red) g=Verde (Green) b=Blue (Azul) */ -/* */ -/* Retorna: 1 */ -/* */ -/*****************************************************************/ -int eDIV_GET_RGB(FUNCTION_PARAMS) -{ - unsigned int color,roff,goff,boff; - unsigned char r,g,b; - boff=getparm(); - goff=getparm(); - roff=getparm(); - color=getparm(); - SDL_GetRGB(color,screen->format,&r,&g,&b); - if(roff) fp->mem[roff]=(int)r; - if(goff) fp->mem[goff]=(int)g; - if(boff) fp->mem[boff]=(int)b; - return 1; -} - -/*****************************************************************/ -/* */ -/* eDIV_ADVANCE(a); */ -/* */ -/* Avanza 'a' unidades segun el angulo del proceso. . */ -/* */ -/* Retorna: 1. */ -/* */ -/*****************************************************************/ - -int eDIV_ADVANCE(FUNCTION_PARAMS) -{ - int a , id1 , x , y , angulo ; - a = getparm() ; - id1 = fp->procs_s[ fp->proc_orden[ *fp->proceso_actual ] ].id ; - angulo = local("angle",id1) ; - x = (int) ((double)a * cos( (angulo/1000) * PIOVER180 )) ; - y = (int) ((double)a * sin( (angulo/1000) * PIOVER180 )) ; - local("x",id1) += x; - local("y",id1) += y ; - return 1 ; -} - -/*****************************************************************/ -/* */ -/* eDIV_XADVANCE(angle,b) */ -/* */ -/* Avanza 'b' unidades segun el angulo 'angle' . . */ -/* */ -/* Retorna: 1 */ -/* */ -/*****************************************************************/ - -int eDIV_XADVANCE(FUNCTION_PARAMS) -{ - int a , b , id1 , x , y , angulo ; - b = getparm() ; - a = getparm() ; - id1 = fp->procs_s[ fp->proc_orden[ *fp->proceso_actual ] ].id ; - angulo = a ; - x = (int) ((double)b * cos( (angulo/1000) * PIOVER180 )) ; - y = (int) ((double)b * sin( (angulo/1000) * PIOVER180 )) ; - local("x",id1) += x ; - local("y",id1) += y ; - return 1 ; -} - -int eDIV_MAP_BLOCK_COPY(FUNCTION_PARAMS) -{ - int f , g2 , x2 , y2 , g1 , x1 , y1 , w , h ; - SDL_Rect srcrect , dstrect ; - h = getparm() ; - w = getparm() ; - y1 = getparm() ; - x1 = getparm() ; - g1 = getparm() ; - y2 = getparm() ; - x2 = getparm() ; - g2 = getparm() ; - f = getparm() ; - - srcrect.x = x1 ; - srcrect.y = y1 ; - srcrect.w = w ; - srcrect.h = h ; - - dstrect.x = x2 ; - dstrect.y = y2 ; - dstrect.w = srcrect.w ; - dstrect.h = srcrect.h ; - - if ( !files[f].existe || !files[f].mapa[g1].existe || !files[f].mapa[g2].existe ) - return -1 ; - - SDL_BlitSurface( files[f].mapa[g1].Surface , &srcrect , files[f].mapa[g2].Surface , &dstrect ) ; - return 1 ; - -} - -/*****************************************************************/ -/* */ -/* eDIV_MAP_GET_PIXEL(y,x,g,f); */ -/* */ -/* Coje el color de un pixel, de un mapa. Coordenadas, x e y */ -/* */ -/* del mapa 'g' del fichero 'f'. */ -/* */ -/* Retorna: El color del pixel. */ -/* */ -/*****************************************************************/ - -int eDIV_MAP_GET_PIXEL(FUNCTION_PARAMS) -{ - int f , g , x , y , bpp ; - Uint8 *p ; - y = getparm() ; - x = getparm() ; - g = getparm() ; - f = getparm() ; - - if ( !files[f].existe || !files[f].mapa[g].existe ) - return -1 ; - - if ( x > files[f].mapa[g].Surface->w || y > files[f].mapa[g].Surface->h || x < 0 || y < 0 ) - return -2 ; - - bpp = files[f].mapa[g].Surface->format->BytesPerPixel; - p = (Uint8 *)files[f].mapa[g].Surface->pixels + y * files[f].mapa[g].Surface->pitch + x * bpp; - - switch(bpp) { - case 1: - return *p; - case 2: - return *(Uint16 *)p; - case 3: - if(SDL_BYTEORDER == SDL_BIG_ENDIAN) - { - return p[0] << 16 | p[1] << 8 | p[2]; - }else - { - return p[0] | p[1] << 8 | p[2] << 16; - } - case 4: - return *(Uint32 *)p; - } - - return 0; -} - -int eDIV_MAP_PUT(FUNCTION_PARAMS) -{ - int f , g2 , g1 , x , y ; - SDL_Rect dstrect ; - y = getparm() ; - x = getparm() ; - g1 = getparm() ; - g2 = getparm() ; - f = getparm() ; - - if ( !files[f].existe || !files[f].mapa[g1].existe || !files[f].mapa[g2].existe ) - return -1 ; - - dstrect.x = x ; - dstrect.y = y ; - dstrect.w = 0 ; /* Se ignora */ - dstrect.h = 0 ; /* Se ignora */ - - SDL_BlitSurface( files[f].mapa[g1].Surface , NULL , files[f].mapa[g2].Surface , &dstrect ) ; - return 1 ; - -} - -int eDIV_MAP_PUT_PIXEL(FUNCTION_PARAMS) -{ - int f , g , x , y , c , bpp ; - Uint8 *p ; - - - c = getparm() ; - y = getparm() ; - x = getparm() ; - g = getparm() ; - f = getparm() ; - - if ( !files[f].existe || !files[0].mapa[g].existe ) - return -1 ; - - if ( x > files[f].mapa[g].Surface->w || y > files[f].mapa[g].Surface->h || x < 0 || y < 0 ) - return -2 ; - - if ( SDL_MUSTLOCK( files[f].mapa[g].Surface ) ) { - if ( SDL_LockSurface( files[f].mapa[g].Surface ) < 0 ) { - return -3; - } - } - - - bpp = files[f].mapa[g].Surface->format->BytesPerPixel ; - p = (Uint8 *)files[f].mapa[g].Surface->pixels + y * files[f].mapa[g].Surface->pitch + x * bpp ; - - switch(bpp) { - - case 1: - *p = c; - break; - - case 2: - *(Uint16 *)p = c; - break; - - case 3: - if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { - p[0] = (c >> 16) & 0xff; - p[1] = (c >> 8) & 0xff; - p[2] = c & 0xff; - } else { - p[0] = c & 0xff; - p[1] = (c >> 8) & 0xff; - p[2] = (c >> 16) & 0xff; - } - break; - - case 4: - *(Uint32 *)p = c; - break; - } - - if ( SDL_MUSTLOCK( files[f].mapa[g].Surface ) ) { - SDL_UnlockSurface( files[f].mapa[g].Surface ); - } - - - return 1 ; -} - - -int eDIV_PUT(FUNCTION_PARAMS) -{ - int f , g , x , y ; - SDL_Rect dstrect ; - - y = getparm() ; - x = getparm() ; - g = getparm() ; - f = getparm() ; - - if ( !files[f].existe || !files[f].mapa[g].existe ) - return -1 ; - - dstrect.x = x - files[f].mapa[g].cpoint[0].x ; - dstrect.y = y - files[f].mapa[g].cpoint[0].y ; - dstrect.w = 0 ; /* Se ignora */ - dstrect.h = 0 ; /* Se ignora */ - - SDL_BlitSurface( files[f].mapa[g].Surface , NULL , fondo , &dstrect ) ; - - return 1 ; - -} - -/*****************************************************************/ -/* */ -/* eDIV_XPUT(f,g,x,y,angle,zoom); */ -/* */ -/* Coloca un MAPA 'g' del fichero 'f' en x e y con un angulo */ -/* angle y un tamaño zoom/100; */ -/* */ -/* Retorna: 1: Si se ha colocado correctamente */ -/* -1: Si el mapa no existe. */ -/*****************************************************************/ - -int eDIV_XPUT(FUNCTION_PARAMS) -{ - int f , g , x , y ; - double zoom,angle; - SDL_Surface *map; - SDL_Rect dstrect ; - - zoom = getparm(); - angle = getparm(); - y = getparm() ; - x = getparm() ; - g = getparm() ; - f = getparm() ; - - if ( !files[f].existe || !files[f].mapa[g].existe ) - return -1 ; - - dstrect.x = x - files[f].mapa[g].cpoint[0].x ; - dstrect.y = y - files[f].mapa[g].cpoint[0].y ; - dstrect.w = 0 ; /* Se ignora */ - dstrect.h = 0 ; /* Se ignora */ - - map=xput(files[f].mapa[g].Surface,zoom,angle); - - SDL_BlitSurface(map , NULL , fondo , &dstrect ) ; - SDL_FreeSurface (map); - - return 1 ; - -} - - - - -int eDIV_PUT_SCREEN(FUNCTION_PARAMS) -{ - int f , g ; - - g = getparm() ; - f = getparm() ; - - if ( !files[f].existe || !files[f].mapa[g].existe ) - return -1 ; - - SDL_BlitSurface( files[f].mapa[g].Surface , NULL , fondo , NULL ) ; - - return 1 ; - -} - -int eDIV_PUT_PIXEL(FUNCTION_PARAMS) -{ - int x , y , c , bpp ; - Uint8 *p ; - - - c = getparm() ; - y = getparm() ; - x = getparm() ; - - if ( x > fondo->w || y > fondo->h || x < 0 || y < 0 ) - return -1 ; - - if ( SDL_MUSTLOCK(fondo) ) { - if ( SDL_LockSurface(fondo) < 0 ) { - return -2; - } - } - - - bpp = fondo->format->BytesPerPixel ; - p = (Uint8 *)fondo->pixels + y * fondo->pitch + x * bpp ; - - switch(bpp) { - - case 1: - *p = c; - break; - - case 2: - *(Uint16 *)p = c; - break; - - case 3: - if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { - p[0] = (c >> 16) & 0xff; - p[1] = (c >> 8) & 0xff; - p[2] = c & 0xff; - } else { - p[0] = c & 0xff; - p[1] = (c >> 8) & 0xff; - p[2] = (c >> 16) & 0xff; - } - break; - - case 4: - *(Uint32 *)p = c; - break; - } - - if ( SDL_MUSTLOCK(fondo) ) { - SDL_UnlockSurface(fondo); - } - - - return 1 ; -} - - - -int eDIV_CLEAR_SCREEN(FUNCTION_PARAMS) -{ - SDL_FillRect( fondo , NULL , 0 ) ; - - return 1; -} - - -int eDIV_GET_PIXEL(FUNCTION_PARAMS) -{ - int x , y , bpp; - Uint8 *p ; - y = getparm() ; - x = getparm() ; - - if ( x > fondo->w || y > fondo->h || x < 0 || y < 0 ) - return -1 ; - - bpp = fondo->format->BytesPerPixel; - p = (Uint8 *)fondo->pixels + y * fondo->pitch + x * bpp; - - switch(bpp) { - case 1: - return *p; - case 2: - return *(Uint16 *)p; - case 3: - if(SDL_BYTEORDER == SDL_BIG_ENDIAN) - { - return p[0] << 16 | p[1] << 8 | p[2]; - }else - { - return p[0] | p[1] << 8 | p[2] << 16; - } - case 4: - return *(Uint32 *)p; - } - - return 0; -} - - -int eDIV_NEW_MAP(FUNCTION_PARAMS) -{ - int i ; - int w , h , cx , cy , c ; - c = getparm() ; - cy = getparm() ; - cx = getparm() ; - h = getparm() ; - w = getparm() ; - - for ( i = 1000 ; i < files[0].num ; i++ ) - { - if ( !files[0].mapa[i].existe ) - { - files[0].mapa[i].Surface = SDL_CreateRGBSurface( SDL_HWSURFACE , w , h , screen->format->BitsPerPixel , 0xFF0000 , 0x00FF00 , 0x0000FF , 0x000000 ) ; - files[0].mapa[i].existe = 1 ; - files[0].mapa[i].cpoint[0].x = cx ; - files[0].mapa[i].cpoint[0].y = cy ; - SDL_FillRect( files[0].mapa[i].Surface , NULL , c ) ; - SDL_SetColorKey( files[0].mapa[i].Surface , SDL_SRCCOLORKEY | SDL_RLEACCEL , color_transparente ) ; - if ( i > last_map[0] ) - last_map[0] = i ; - return i ; - } - } - return -1 ; -} - - -int eDIV_SCREEN_COPY(FUNCTION_PARAMS) -{ - SDL_Rect srcrect , dstrect ; - int r, f, g , x, y , w , h ; - h = getparm() ; - w = getparm() ; - y = getparm() ; - x = getparm() ; - g = getparm() ; - f = getparm() ; - r = getparm() ; - - if ( !files[f].existe || !files[f].mapa[g].existe ) - return -1 ; - - srcrect.x = 0 ; - srcrect.y = 0 ; - srcrect.w = w ; - srcrect.h = h ; - - dstrect.x = x ; - dstrect.y = y ; - dstrect.w = 0 ; - dstrect.h = 0 ; - - SDL_BlitSurface( screen, &srcrect , files[f].mapa[g].Surface , &dstrect ) ; - return 1 ; -} - -int eDIV_OUT_REGION(FUNCTION_PARAMS) -{ - int id , r ; - int f, g , x , y ; - r = getparm() ; - id = getparm() ; - - f = local("file",id) ; - g = local("graph",id) ; - - if ( !files[f].existe || !files[f].mapa[g].existe ) - return -1 ; - - x = local("x",id) ; - y = local("y",id) ; - - if ( x < fp->regions[r].x + fp->regions[r].w && x + files[f].mapa[g].Surface->w > fp->regions[r].x && - y < fp->regions[r].y + fp->regions[r].h && y + files[f].mapa[g].Surface->h > fp->regions[r].y ) - return 0 ; - else - return 1 ; -} - -int eDIV_DRAW(FUNCTION_PARAMS) -{ - int i ; - int t , c , o , r , x0, y0 , x1 , y1 ; - SDL_Rect dstrect ; - y1 = getparm() ; - x1 = getparm() ; - y0 = getparm() ; - x0 = getparm() ; - r = getparm() ; - o = getparm() ; - c = getparm() ; - t = getparm() ; - - for ( i = 0 ; i < 1024 ; i++ ) - { - if ( draws[i].existe == 0 ) - { - draws[i].Surface = SDL_CreateRGBSurface( SDL_HWSURFACE , x1 - x0 , y1 - y0 , screen->format->BitsPerPixel , 0xFF0000 , 0x00FF00 , 0x0000FF , 0x000000 ) ; - switch ( t ) - { - case 3: - dstrect.x = 0 ; - dstrect.y = 0 ; - dstrect.w = x1 - x0 ; - dstrect.h = y1 - y0 ; - SDL_FillRect( draws[i].Surface , &dstrect , c ) ; - break ; - } - draws[i].region = r ; - draws[i].x = x0 ; - draws[i].y = y0 ; - draws[i].t = t ; - draws[i].c = c ; - if ( o < 15 && o > -1 ) - SDL_SetAlpha( draws[i].Surface , SDL_SRCALPHA | SDL_RLEACCEL , 17 * (o) ) ; - draws[i].existe = 1 ; - if ( i > last_draw ) - last_draw = i ; - return i ; - } - } - return -1 ; -} - -int eDIV_MOVE_DRAW(FUNCTION_PARAMS) -{ - SDL_Rect dstrect ; - int id , c , o , x0 , y0 , x1 , y1 ; - y1 = getparm() ; - x1 = getparm() ; - y0 = getparm() ; - x0 = getparm() ; - o = getparm() ; - c = getparm() ; - id = getparm() ; - - if ( !draws[id].existe ) - return -1 ; - - if ( x1 - x0 != draws[id].Surface->w || y1 - y0 != draws[id].Surface->h || c != draws[id].c ) - { - if ( x1 - x0 != draws[id].Surface->w || y1 - y0 != draws[id].Surface->h ) - { - SDL_FreeSurface( draws[id].Surface ) ; - draws[id].Surface = SDL_CreateRGBSurface( SDL_HWSURFACE , x1 - x0 , y1 - y0 , screen->format->BitsPerPixel , 0xFF0000 , 0x00FF00 , 0x0000FF , 0x000000 ) ; - } - switch ( draws[id].t ) - { - case 3: - dstrect.x = 0 ; - dstrect.y = 0 ; - dstrect.w = x1 - x0 ; - dstrect.h = y1 - y0 ; - SDL_FillRect( draws[id].Surface , &dstrect , c ) ; - break ; - } - } - - draws[id].x = x0 ; - draws[id].y = y0 ; - draws[id].c = c ; - if ( o < 15 && o > -1 ) - SDL_SetAlpha( draws[id].Surface , SDL_SRCALPHA | SDL_RLEACCEL , 17 * (o) ) ; - else - if ( o == 15 ) - SDL_SetAlpha( draws[id].Surface , 0 , 255 ) ; - - return 1 ; -} - -int eDIV_DELETE_DRAW(FUNCTION_PARAMS) -{ - int n ; - n = getparm() ; - - if(n==-1) { - for(n=0;n 0 ; last_draw-- ) - { - if ( draws[last_draw].existe ) - break ; - } - return 1 ; - - - -} - - -int eDIV_LOAD_FPG(FUNCTION_PARAMS) -{ - char * archivo ; - FILE *f; - FPGHEADER8 cabecera8; - FPGHEADER cabecera; - FPGMAPINFO infomapa; - int tamano; - int cont=0,num,i; - int bpp; - char* graphic; - - SDL_Color p[256]; - - archivo = getstrparm() ; - - f=fopen(archivo,"rb"); - if(f==NULL) { - fp->Runtime_Error(ERR_FILENOTFOUND); - } - - fseek(f,0,SEEK_END); - tamano=ftell(f); - fseek(f,0,SEEK_SET); - - fread(&cabecera,1,sizeof(FPGHEADER),f); - - /* - * TODO: optimizar esto ligeramente (comprobar primero los bytes comunes y luego - * leer "pg","16","24","32") - */ - - if(strcmp(cabecera.header,"fpg\x1A\x0D\x0A")) { - if(strcmp(cabecera.header,"f16\x1A\x0D\x0A")) { - if(strcmp(cabecera.header,"f24\x1A\x0D\x0A")) { - if(strcmp(cabecera.header,"f32\x1A\x0D\x0A")) { - fp->Runtime_Error(ERR_INVALIDFPGHEADER); - } - else { - bpp=32; - } - } - else { - bpp=24; - } - } - else { - bpp=16; - } - } - else { - bpp=8; - fseek(f,0,SEEK_SET); - fread(&cabecera8,1,sizeof(FPGHEADER8),f); - - for(i=0;i<256;i++) { - p[i].r=cabecera8.palette[i].r*4; - p[i].g=cabecera8.palette[i].g*4; - p[i].b=cabecera8.palette[i].b*4; - } - SDL_SetPalette(screen,SDL_LOGPAL|SDL_PHYSPAL,p,0,256); - } - - - - while(ftell(f)999 || num<0) { - fp->Runtime_Error(ERR_INVALIDMAPCODE); - } - if ( files[0].mapa[num].existe == 1 ) - return -1 ; - files[0].mapa[num].existe = 1 ; - - if(infomapa.number_of_points==0) { - files[0].mapa[num].cpoint[0].x = (int) infomapa.wide/2 ; - files[0].mapa[num].cpoint[0].y = (int) infomapa.height/2 ; - } else { - fread(files[0].mapa[num].cpoint,2,2*infomapa.number_of_points,f) ; - } - - graphic = (char*)malloc(infomapa.wide*infomapa.height*bpp/8); - fread(graphic,1,infomapa.wide*infomapa.height*bpp/8,f); - - files[0].mapa[num].Surface = SDL_CreateRGBSurfaceFrom(graphic,infomapa.wide,infomapa.height,bpp,infomapa.wide*bpp/8,0,0,0,0) ; - - cont++; - if(bpp==8) { - SDL_SetPalette(files[0].mapa[num].Surface,SDL_LOGPAL|SDL_PHYSPAL,p,0,256); - } - SDL_SetColorKey(files[0].mapa[num].Surface,SDL_SRCCOLORKEY|SDL_RLEACCEL,0); - } - - fclose(f); - return 0; -} - -int eDIV_GET_POINT(FUNCTION_PARAMS) -{ - int f , g , n , dx , dy ; - dy = getparm() ; - dx = getparm() ; - n = getparm() ; - g = getparm() ; - f = getparm() ; - - if ( !files[f].existe || !files[f].mapa[g].existe ) - return -1 ; - - fp->mem[ dx ] = files[f].mapa[g].cpoint[n].x ; - fp->mem[ dy ] = files[f].mapa[g].cpoint[n].y ; - - return 0 ; -} - -int eDIV_GET_REAL_POINT(FUNCTION_PARAMS) -{ - int f , g , n , dx , dy , x , y , id; - dy = getparm() ; - dx = getparm() ; - n = getparm() ; - id = fp->procs_s[ fp->proc_orden[ *fp->proceso_actual ] ].id; - f = local("file",id) ; - g = local("graph",id) ; - x = local("x",id) ; - y = local("y",id) ; - - if ( !files[f].existe || !files[f].mapa[g].existe ) - return -1 ; - - fp->mem[ dx ] = files[f].mapa[g].cpoint[n].x - files[f].mapa[g].cpoint[0].x + x ; - fp->mem[ dy ] = files[f].mapa[g].cpoint[n].y - files[f].mapa[g].cpoint[0].y + y ; - - return 0 ; -} - -int eDIV_GRAPHIC_INFO(FUNCTION_PARAMS) -{ - int f , g , i ; - i = getparm() ; - g = getparm() ; - f = getparm() ; - - if ( !files[f].existe || !files[f].mapa[g].existe ) - return -1 ; - - switch (i) - { - case 0: - return files[f].mapa[g].Surface->w ; - case 1: - return files[f].mapa[g].Surface->h ; - case 2: - return files[f].mapa[g].cpoint[0].x ; - case 3: - return files[f].mapa[g].cpoint[0].y ; - } - return -1; -} - - -int eDIV_FADE(FUNCTION_PARAMS) -{ - int r , g , b , v ; - v = getparm() ; - b = getparm() ; - g = getparm() ; - r = getparm() ; - - return SDL_SetGamma( 1.0f , 1.0f , 1.0f ) ; - return 1 ; -} - -/* - * Entrypoints - */ FILE * fichero ; FILE * memo ; +/*! \brief Guarda una captura de la pantalla en un .bmp + * + * Esta función es llamada cuando se pulsa ALT+P. Primero busca un nombre de + * fichero válido del tipo nombre_programa####.bmp, donde #### es el primer + * número que haya disponible, para ir numerando las capturas automáticamente. + * Luego simplemente usa SDL_SaveBMP() para guardar el backbuffer con ese + * nombre. + * @param nombre_program Nombre del programa, obtenido de fp->nombre_program + */ void guarda_pantallazo(char* nombre_program) { - char capturef[256], num[5]; + char capturef[256]; int c,i; FILE* f; @@ -1230,8 +203,15 @@ void guarda_pantallazo(char* nombre_program) SDL_SaveBMP(screen,capturef); } -/* - * Función para usar con qsort() para ordenar los blits por su Z +/*! \brief Función para usar con qsort() para ordenar los blits por su Z + * + * Esta función se pasa a qsort() para que la graphics (en el entrypoint frame) + * ordene los blits (del tipo struct _blits) según su Z, para que se dibujen + * en el backbuffer en el orden correcto. + * @param a Primer blit a ordenar + * @param b Segundo blit a ordenar + * @return -1 si a está detrás de b, 1 si a está delante de b, 0 si tienen la misma Z + * @see frame(), struct _blits */ int ordena_por_z(const void* a, const void* b) { @@ -1239,13 +219,26 @@ int ordena_por_z(const void* a, const void* b) struct _blits* bb=(struct _blits*)b; return (aa->z>bb->z)?-1:((aa->zz)?1:0); } + +/* + * Entrypoints + */ + +/*! \brief Entrypoint frame + * + * Este entrypoint se ejecuta una vez todos los procesos han ejecutado su código + * correspondiente al frame actual. Se encarga de procesar todos los gráficos + * en pantalla (fondo, draws, procesos y los creados por otras DLL's mediante + * fp->Dibuja()), blitearlos en el backbuffer y actualizar la pantalla. + * @see Dibuja(), draw.c + */ void frame(FUNCTION_PARAMS) { static int una_vez = 1 ; int i , id , f , g , r , z , trans,angle,size,resolution; SDL_Rect dstrect , srcrect ; - Uint32 rmask , gmask , bmask , amask ; +// Uint32 rmask , gmask , bmask , amask ; SDL_Surface* temp; int noevent; SDL_Event event; @@ -1271,7 +264,7 @@ void frame(FUNCTION_PARAMS) temp = SDL_SetVideoMode(fp->graphics->ancho,fp->graphics->alto,fp->graphics->bpp,SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_HWACCEL|((fp->graphics->flags&GR_FULLSCREEN)?SDL_FULLSCREEN:0)|((fp->graphics->bpp==8)?SDL_HWPALETTE:0)); if(fp->graphics->bpp==8) PaletteCopy(temp,screen); - + if(fp->graphics->resflags&GR_CHANGED) { SDL_FreeSurface(screen); SDL_FreeSurface(fondo); @@ -1295,6 +288,12 @@ void frame(FUNCTION_PARAMS) return; } + if(fp->graphics->bpp==8) { + fp->graphics->palette=(struct _palette*)screen->format->palette->colors; + fp->graphics->activepal=(struct _palette*)activepal; + memcpy(activepal,fp->graphics->palette,256*4); + } + SDL_WM_SetCaption(fp->nombre_program, NULL); SDL_ShowCursor(0); } @@ -1483,6 +482,12 @@ void frame(FUNCTION_PARAMS) } +/*! \brief Entrypoint first_load + * + * Este entrypoint se ejecuta cuando la DLL se carga en el comienzo de la ejecución + * del programa. Se usa para inicializar todos los datos internos de la DLL y + * realizar alguna operación inicial si es preciso. + */ void first_load(FUNCTION_PARAMS) { int i ; @@ -1492,7 +497,9 @@ void first_load(FUNCTION_PARAMS) fp->files = files ; fp->existe.dibuja = 1 ; - + adaptar_paleta=FALSE; + primer_frame=TRUE; + smooth=0; for ( i = 0 ; i < 0xFF ; i++ ) last_map[i] = 0 ; @@ -1519,6 +526,20 @@ void first_load(FUNCTION_PARAMS) define_region = 1 ; + for (i=1;iregions = regions ; + fp->existe.regions = 1 ; + fp->graphics->ancho=320; fp->graphics->alto=200; fp->graphics->bpp=8; @@ -1549,13 +570,25 @@ void first_load(FUNCTION_PARAMS) * Funciones Internas de la DLL */ -/* - * Dibuja - * Se encarga de meter un registro en la pila de bliteos, segun su z - * Esta funcion no se encarga de discernir si esta dentro o fuera de la region o pantalla, - * eso se debe calcular antes y pasarle la informacion resultante a Dibuja +/*! \brief Agrega un gráfico a la lista de blits + * + * Esta función puede usarse desde cualquier DLL (se exporta en la estructura fp) + * y se encarga de meter un registro en la pila de bliteos, permitiendo especificar + * ciertos parámetros describiendo cómo debe dibujarse el gráfico, incluyendo Z, + * transparencia, etc. + * Esta función no se encarga de discernir si el gráfico esta dentro o fuera de + * la región o pantalla, eso se debe calcular antes y pasarle la información + * resultante a Dibuja(). + * @param src Superficie donde se encuentra el gráfico a dibujar + * @param srcrect Región del gráfico que queremos dibujar + * @param dstrect Región de la pantalla en la que debe aparecer el gráfico + * @param z Profundidad del gráfico, permite que pueda dibujarse delante o detrás de otros gráficos + * @param trans Transparencia del gráfico (0..255) + * @param size Tamaño (en porcentaje) al que debe escalarse el gráfico, 100% es el tamaño original + * @param angle Ángulo (en milésimas de grado) para rotar el gráfico. (0 = sin rotación) + * @return 1 + * @see frame(), xput(), ordena_por_z(), #blits */ - int Dibuja(SDL_Surface *src , SDL_Rect srcrect , SDL_Rect dstrect , int z , int trans,int size,int angle) { float zoom; @@ -1567,8 +600,8 @@ int Dibuja(SDL_Surface *src , SDL_Rect srcrect , SDL_Rect dstrect , int z , int if (size==0) size=100; - if (size>100) - size=100; +/* if (size>100) + size=100;*/ zoom=size*0.01f; @@ -1578,7 +611,7 @@ int Dibuja(SDL_Surface *src , SDL_Rect srcrect , SDL_Rect dstrect , int z , int /* * Pequeño hack para arreglar transparency - * Debería limpiarse y revisarse un poco :P + * TODO: Debería limpiarse y revisarse un poco :P */ if(blits[last_blit].src->flags & SDL_SRCALPHA) { for(i=0;ih*blits[last_blit].src->w*blits[last_blit].src->format->BytesPerPixel;i+=blits[last_blit].src->format->BytesPerPixel) { @@ -1604,70 +637,28 @@ int Dibuja(SDL_Surface *src , SDL_Rect srcrect , SDL_Rect dstrect , int z , int return 1 ; } +/*! \brief Escala y rota un gráfico + * + * Esta función recibe una superficie y la rota y escala según los valores deseados, + * y devuelve una nueva superficie que contiene el gráfico transformado. + * @param src La superficie con el gráfico que se desea transformar + * @param size Tamaño al que se desea escalar el gráfico (1.0 es el tamaño original) + * @param angle Ángulo (en grados) al que se desea rotar el gráfico (0.0 = sin rotación) + * @return Una nueva superficie con el gráfico transformado + * @see Dibuja(), SDL_rotozoom.c + */ SDL_Surface *xput(SDL_Surface *src,double size,double angle) { int s; SDL_Surface *dst; SDL_Surface *tmp; - + s=smooth; - if(size==1 && angle ==0)s=0; + if(size==1 && angle ==0) s=0; tmp= zoomSurface (src, size, size,s); dst=rotozoomSurface (tmp, angle, 1,s); SDL_FreeSurface (tmp); return dst; } - -int eDIV_SET_MODE(FUNCTION_PARAMS) -{ - int modo; - - switch(fp->num_params) { - case 4: - fp->graphics->flags=getparm(); - case 3: - fp->graphics->bpp=getparm(); - fp->graphics->alto=getparm(); - fp->graphics->ancho=getparm(); - break; - case 1: - modo=getparm(); - if(modo>1280960) { - fp->graphics->ancho=modo/10000; - fp->graphics->alto=modo%10000; - } - else { - fp->graphics->ancho=modo/1000; - fp->graphics->alto=modo%1000; - } - fp->graphics->bpp=8; - fp->graphics->flags=0; - } - - /* Esto avisa a las DLLs */ - fp->graphics->resflags|=GR_CHANGED; - - SDL_FreeSurface(fondo); - SDL_FreeSurface(screen); - - screen=SDL_SetVideoMode(fp->graphics->ancho,fp->graphics->alto,fp->graphics->bpp,SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_HWACCEL|((fp->graphics->flags&GR_FULLSCREEN)?SDL_FULLSCREEN:0)|((fp->graphics->bpp==8)?SDL_HWPALETTE:0)); - fp->graphics->buffer=screen->pixels; - - if(fp->graphics->bpp==8) - SDL_SetPalette(screen,SDL_LOGPAL|SDL_PHYSPAL,(SDL_Color*)default_palette,0,256); - - if ( screen == NULL ) { - fp->Critical_Error(7); /* No se pudo inicializar SDL */ - return 0; - } - - fondo=SDL_CreateRGBSurface(SDL_HWSURFACE,fp->graphics->ancho,fp->graphics->alto,fp->graphics->bpp,0,0,0,0); - fp->graphics->background=fondo->pixels; - - if(fp->graphics->bpp==8) - PaletteCopy(fondo,screen); - - return 0; -} diff --git a/dlls/src/graphics/graphics.h b/dlls/src/graphics/graphics.h index 661841a..0034254 100644 --- a/dlls/src/graphics/graphics.h +++ b/dlls/src/graphics/graphics.h @@ -1,44 +1,175 @@ +/*! \file graphics.h + * \brief Cabecera principal de la librería + * + * Este fichero, aparte de otras cosas, contiene los prototipos de todos los .c + * (excepto de SDL_rotozoom.c). + * \todo hacer video_modes[] y num_video_modes + */ + #ifndef __EDIV_GRAPHICS_H_ #define __EDIV_GRAPHICS_H_ #include -#define PIOVER180 0.017453292519943295769236907684886 -SDL_Surface *screen; -SDL_Surface *fondo; +/* Constantes */ +#define PIOVER180 0.017453292519943295769236907684886 /*!< Constante para pasar de grados a radianes y viceversa */ + +#define ERR_FILENOTFOUND 105 +#define ERR_INVALIDFPGHEADER 106 +#define ERR_INVALIDMAPCODE 110 + +#define MAX_DRAWS 1024 /*!< Número máximo de objetos que soporta draw() (en el DIV2 eran 256) */ +#define MAX_REGIONS 32 /*!< Número máximo de regiones de pantalla (en el DIV2 eran 32) */ + +/* Macros */ + +/*! Se usa para la colisión por bounding-box */ +#define Miedzy(x,a,b) (((x) >= (a)) && ((x) <= (b))) + +/*! Asigna a una superficie la paleta de otra superficie */ +#define PaletteCopy(dst,src) SDL_SetPalette(dst,SDL_LOGPAL|SDL_PHYSPAL,src->format->palette->colors,0,256); + + +/* Globales */ + +/*! Color en la paleta de un MAP, FPG, etc */ +typedef struct { + unsigned char r,g,b; +} pal_t; + +/*! Cabecera de los FPG de 8 bits */ +typedef struct _FPGHEADER8{ + char header[8]; + pal_t palette[256]; + /* char palette[768]; */ + char colorbars[576]; +}FPGHEADER8; + +/*! Cabecera de los FPG no paletizados */ +typedef struct _FPGHEADER{ + char header[8]; + /* pal_t palette[256]; */ + /* char palette[768]; */ + /* char colorbars[576]; */ +}FPGHEADER; + +/*! Cabecera de un mapa dentro de un FPG */ +typedef struct _FPGMAPINFO{ + int code; + int lenght; + char description[32]; + char filename[12]; + int wide; + int height; + int number_of_points; +}FPGMAPINFO; + +//char *graphic; /* wide*height */ + +/*! Tabla de objetos creados con draw() + * @see eDIV_DRAW(), frame() + */ +struct{ + int existe ; + int region ; + int x , y ; + int t , c ; /* requerido para move_draw() */ + SDL_Surface *Surface ; +} draws[MAX_DRAWS] ; + +int last_draw ; + +/*! Tabla de blits + * @see Dibuja(), frame(), ordena_por_z() + */ +struct _blits { + SDL_Surface *src ; + SDL_Rect srcrect ; + SDL_Surface *dst ; + SDL_Rect dstrect ; + int z ; + int trans ; +} blits[0xFFFF] , *orden[0xFFFF]; + +struct _regions regions[MAX_REGIONS]; /*!< Tabla de regiones */ + +SDL_Surface *screen; /*!< Superficie del backbuffer */ +SDL_Surface *fondo; /*!< Superficie del fondo */ +SDL_Color activepal[256]; /*!< Paleta activa (fades, etc) */ + +BOOL adaptar_paleta; /*!< Para el force_pal() */ + +struct _files files[ 0xFF ] ; /*!< Tabla de FPG's */ + +SDL_Surface *Mapa[0xFFF] ; + +struct _file file0[0xFFF] ; +int last_map[0xFF] ; +int color_transparente ; /*!< Color transparente actual (por defecto, 0) */ +int define_region ; +BOOL primer_frame; /*!< Indica a frame() si es la primera vez que se ejecuta */ + +int last_blit ; + +int gamma[3] ; + +int smooth; /*!< Indica si se desea suavizar los gráficos @see xput() */ + +/* +** Prototipos +*/ + +/* Carga/descarga */ int eDIV_LOAD_BMP(FUNCTION_PARAMS); +int eDIV_LOAD_FPG(FUNCTION_PARAMS) ; + +/* Colisiones */ int eDIV_COLLISION(FUNCTION_PARAMS); + +/* Paleta */ int eDIV_SET_TRANSPARENT_COLOR(FUNCTION_PARAMS); int eDIV_GET_TRANSPARENT_COLOR(FUNCTION_PARAMS); int eDIV_RGB(FUNCTION_PARAMS); +int eDIV_FIND_COLOR(FUNCTION_PARAMS); int eDIV_GET_RGB(FUNCTION_PARAMS); +int eDIV_FADE(FUNCTION_PARAMS) ; + +/* Advance y xadvance*/ int eDIV_ADVANCE(FUNCTION_PARAMS); int eDIV_XADVANCE(FUNCTION_PARAMS) ; -int eDIV_MAP_BLOCK_COPY(FUNCION_PARMAS) ; -int eDIV_MAP_GET_PIXEL(FUNCION_PARMAS) ; -int eDIV_MAP_PUT(FUNCION_PARMAS) ; + +/* Operaciones con mapas */ +int eDIV_MAP_BLOCK_COPY(FUNCTION_PARAMS) ; +int eDIV_MAP_GET_PIXEL(FUNCTION_PARAMS) ; +int eDIV_MAP_PUT(FUNCTION_PARAMS) ; int eDIV_MAP_PUT_PIXEL(FUNCTION_PARAMS); int eDIV_PUT(FUNCTION_PARAMS); int eDIV_PUT_PIXEL(FUNCTION_PARAMS); -int eDIV_PUT_SCREEN(FUNCION_PARAMS); +int eDIV_PUT_SCREEN(FUNCTION_PARAMS); int eDIV_CLEAR_SCREEN(FUNCTION_PARAMS); int eDIV_GET_PIXEL(FUNCTION_PARAMS); int eDIV_NEW_MAP(FUNCTION_PARAMS) ; int eDIV_SCREEN_COPY(FUNCTION_PARAMS) ; -int eDIV_OUT_REGION(FUNCTION_PARAMS) ; -int eDIV_DRAW(FUNCTION_PARAMS) ; -int eDIV_MOVE_DRAW(FUNCTION_PARAMS) ; -int eDIV_DELETE_DRAW(FUNCTION_PARAMS) ; -int eDIV_LOAD_FPG(FUNCTION_PARAMS) ; int eDIV_GET_POINT(FUNCTION_PARAMS) ; int eDIV_GET_REAL_POINT(FUNCTION_PARAMS) ; int eDIV_GRAPHIC_INFO(FUNCTION_PARAMS) ; -int eDIV_FADE(FUNCTION_PARAMS) ; int eDIV_XPUT(FUNCTION_PARAMS); + +/* Regiones */ +int eDIV_DEFINE_REGION(FUNCTION_PARAMS) ; +int eDIV_OUT_REGION(FUNCTION_PARAMS) ; + +/* Draws */ +int eDIV_DRAW(FUNCTION_PARAMS) ; +int eDIV_MOVE_DRAW(FUNCTION_PARAMS) ; +int eDIV_DELETE_DRAW(FUNCTION_PARAMS) ; + +/* Otras */ int eDIV_SET_MODE(FUNCTION_PARAMS); +/* Funciones internas */ int Dibuja(SDL_Surface *src , SDL_Rect srcrect , SDL_Rect dstrect , int z , int trans,int size,int angle); SDL_Surface *xput(SDL_Surface *src,double size,double angle); diff --git a/dlls/src/graphics/map_ops.c b/dlls/src/graphics/map_ops.c new file mode 100644 index 0000000..91464ca --- /dev/null +++ b/dlls/src/graphics/map_ops.c @@ -0,0 +1,602 @@ +/*! \file map_ops.c + * \brief Funciones de operaciones con mapas + * + * Este fichero contiene las funciones para las operaciones con mapas + * (modificación, obtención de información, bliteos, etc). + * + * \todo Falta respetar el centro del gráfico, y soporte para FLAGS 1 y 2 + */ + +#include + +#include "export.h" +#include "graphics.h" + +/*! \brief Copia un trozo de mapa y lo pega en otro mapa + * + * Esta función sólo permite operaciones en el mismo FPG. + * \todo ¿sobrecargar para permitir operaciones entre FPG's? + * @param f FPG donde se encuentran los dos mapas + * @param g2 Gráfico de destino + * @param x2 Coordenada X destino + * @param y2 Coordenada Y destino + * @param g1 Gráfico de origen + * @param x1 Coordenada X origen + * @param y1 Coordenada Y origen + * @param w Anchura del bloque a copiar + * @param h Altura del bloque a copiar + * @return 1 + * @see eDIV_MAP_PUT(), eDIV_MAP_XPUT() + */ +int eDIV_MAP_BLOCK_COPY(FUNCTION_PARAMS) +{ + int f , g2 , x2 , y2 , g1 , x1 , y1 , w , h ; + SDL_Rect srcrect , dstrect ; + h = getparm() ; + w = getparm() ; + y1 = getparm() ; + x1 = getparm() ; + g1 = getparm() ; + y2 = getparm() ; + x2 = getparm() ; + g2 = getparm() ; + f = getparm() ; + + srcrect.x = x1 ; + srcrect.y = y1 ; + srcrect.w = w ; + srcrect.h = h ; + + dstrect.x = x2 ; + dstrect.y = y2 ; + dstrect.w = srcrect.w ; + dstrect.h = srcrect.h ; + + if ( !files[f].existe || !files[f].mapa[g1].existe || !files[f].mapa[g2].existe ) + return -1 ; + + SDL_BlitSurface( files[f].mapa[g1].Surface , &srcrect , files[f].mapa[g2].Surface , &dstrect ) ; + return 1 ; + +} + + +/*! \brief Obtiene el color del pixel, en las coordenadas (x,y), de un mapa. + * @param f Fichero (FPG) donde se encuentra el mapa + * @param g Código del gráfico dentro del FPG. + * @param x Coordenada X del pixel + * @param y Coordenada Y del pixel + * @return El color del píxel. + * @see eDIV_MAP_PUT_PIXEL(), eDIV_PUT_PIXEL(), eDIV_GET_PIXEL() + */ +int eDIV_MAP_GET_PIXEL(FUNCTION_PARAMS) +{ + int f , g , x , y , bpp ; + Uint8 *p ; + y = getparm() ; + x = getparm() ; + g = getparm() ; + f = getparm() ; + + if ( !files[f].existe || !files[f].mapa[g].existe ) + return -1 ; + + if ( x > files[f].mapa[g].Surface->w || y > files[f].mapa[g].Surface->h || x < 0 || y < 0 ) + return -2 ; + + bpp = files[f].mapa[g].Surface->format->BytesPerPixel; + p = (Uint8 *)files[f].mapa[g].Surface->pixels + y * files[f].mapa[g].Surface->pitch + x * bpp; + + switch(bpp) { + case 1: + return *p; + case 2: + return *(Uint16 *)p; + case 3: + if(SDL_BYTEORDER == SDL_BIG_ENDIAN) + { + return p[0] << 16 | p[1] << 8 | p[2]; + }else + { + return p[0] | p[1] << 8 | p[2] << 16; + } + case 4: + return *(Uint32 *)p; + } + + return 0; +} + + +/*! \brief Blitea un mapa dentro de otro mapa + * + * Esta función sólo permite operaciones en el mismo FPG. + * \todo ¿sobrecargar para permitir operaciones entre FPG's? + * @param f Fichero (FPG) donde se encuentran los dos mapas. + * @param g2 Gráfico de destino + * @param g1 Gráfico de origen + * @param x Coordenada X + * @param y Coordenada Y + * @return 1 + * @see eDIV_MAP_BLOCK_COPY(), eDIV_XPUT() + */ +int eDIV_MAP_PUT(FUNCTION_PARAMS) +{ + int f , g2 , g1 , x , y ; + SDL_Rect dstrect ; + y = getparm() ; + x = getparm() ; + g1 = getparm() ; + g2 = getparm() ; + f = getparm() ; + + if ( !files[f].existe || !files[f].mapa[g1].existe || !files[f].mapa[g2].existe ) + return -1 ; + + dstrect.x = x ; + dstrect.y = y ; + dstrect.w = 0 ; /* Se ignora */ + dstrect.h = 0 ; /* Se ignora */ + + SDL_BlitSurface( files[f].mapa[g1].Surface , NULL , files[f].mapa[g2].Surface , &dstrect ) ; + return 1 ; + +} + + +/*! \brief Cambia el color de un píxel determinado de un mapa + * @param fichero Fichero (FPG) donde se encuentra el mapa + * @param grafico Código del mapa dentro del FPG + * @param x Coordenada X del píxel + * @param y Coordenada y del píxel + * @param color Color + * @return 1 + * @see eDIV_MAP_GET_PIXEL(), eDIV_PUT_PIXEL(), eDIV_GET_PIXEL() + */ +int eDIV_MAP_PUT_PIXEL(FUNCTION_PARAMS) +{ + int f , g , x , y , c , bpp ; + Uint8 *p ; + + + c = getparm() ; + y = getparm() ; + x = getparm() ; + g = getparm() ; + f = getparm() ; + + if ( !files[f].existe || !files[0].mapa[g].existe ) + return -1 ; + + if ( x > files[f].mapa[g].Surface->w || y > files[f].mapa[g].Surface->h || x < 0 || y < 0 ) + return -2 ; + + if ( SDL_MUSTLOCK( files[f].mapa[g].Surface ) ) { + if ( SDL_LockSurface( files[f].mapa[g].Surface ) < 0 ) { + return -3; + } + } + + + bpp = files[f].mapa[g].Surface->format->BytesPerPixel ; + p = (Uint8 *)files[f].mapa[g].Surface->pixels + y * files[f].mapa[g].Surface->pitch + x * bpp ; + + switch(bpp) { + + case 1: + *p = c; + break; + + case 2: + *(Uint16 *)p = c; + break; + + case 3: + if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { + p[0] = (c >> 16) & 0xff; + p[1] = (c >> 8) & 0xff; + p[2] = c & 0xff; + } else { + p[0] = c & 0xff; + p[1] = (c >> 8) & 0xff; + p[2] = (c >> 16) & 0xff; + } + break; + + case 4: + *(Uint32 *)p = c; + break; + } + + if ( SDL_MUSTLOCK( files[f].mapa[g].Surface ) ) { + SDL_UnlockSurface( files[f].mapa[g].Surface ); + } + + + return 1 ; +} + + +/*! \brief Blitea un mapa sobre el buffer del fondo + * @param fichero Fichero (FPG) donde se encuentra el gráfico + * @param grafico Código del mapa dentro del FPG + * @param x Coordenada X destino + * @param y Coordenada Y destino + * @return 1 + * @see eDIV_MAP_PUT(), eDIV_XPUT() + */ +int eDIV_PUT(FUNCTION_PARAMS) +{ + int f , g , x , y ; + SDL_Rect dstrect ; + + y = getparm() ; + x = getparm() ; + g = getparm() ; + f = getparm() ; + + if ( !files[f].existe || !files[f].mapa[g].existe ) + return -1 ; + + dstrect.x = x - files[f].mapa[g].cpoint[0].x ; + dstrect.y = y - files[f].mapa[g].cpoint[0].y ; + dstrect.w = 0 ; /* Se ignora */ + dstrect.h = 0 ; /* Se ignora */ + + SDL_BlitSurface( files[f].mapa[g].Surface , NULL , fondo , &dstrect ) ; + + return 1 ; + +} + + +/*! \brief Como eDIV_PUT() pero permitiendo indicar ángulo, tamaño y flags. + * \todo Falta soporte para flags. Revisar y añadir fp->Runtime_Error() + * @param fichero Fichero (FPG) donde se encuentra el gráfico + * @param grafico Código del mapa dentro del FPG + * @param x Coordenada X destino + * @param y Coordenada Y destino + * @param angle Ángulo (en milésimas de grado) + * @param zoom Tamaño (en porcentaje) + * @return 1 si se ha colocado correctamente, -1 si el mapa no existe. + * @see eDIV_PUT(), eDIV_MAP_XPUT(), eDIV_MAP_PUT() + */ +int eDIV_XPUT(FUNCTION_PARAMS) +{ + int f , g , x , y ; + double zoom,angle; + SDL_Surface *map; + SDL_Rect dstrect ; + + zoom = getparm(); + angle = getparm(); + y = getparm() ; + x = getparm() ; + g = getparm() ; + f = getparm() ; + + if ( !files[f].existe || !files[f].mapa[g].existe ) + return -1 ; + + dstrect.x = x - files[f].mapa[g].cpoint[0].x ; + dstrect.y = y - files[f].mapa[g].cpoint[0].y ; + dstrect.w = 0 ; /* Se ignora */ + dstrect.h = 0 ; /* Se ignora */ + + map=xput(files[f].mapa[g].Surface,zoom,angle); + + SDL_BlitSurface(map , NULL , fondo , &dstrect ) ; + SDL_FreeSurface (map); + + return 1 ; + +} + + +/*! \brief Blitea un mapa sobre el buffer del fondo en la ESQUINA SUPERIOR IZQUIERDA de la pantalla + * @param fichero Fichero (FPG) donde se encuentra el gráfico + * @param grafico Código del mapa dentro del FPG + * @return 1 + * @see eDIV_PUT(), eDIV_LOAD_SCREEN() + */ +int eDIV_PUT_SCREEN(FUNCTION_PARAMS) +{ + int f , g ; + + g = getparm() ; + f = getparm() ; + + if ( !files[f].existe || !files[f].mapa[g].existe ) + return -1 ; + + SDL_BlitSurface( files[f].mapa[g].Surface , NULL , fondo , NULL ) ; + + return 1 ; + +} + +/*! \brief Cambia el color del pixel, en las coordenadas (x,y), del fondo. + * @param x Coordenada X del pixel + * @param y Coordenada Y del pixel + * @param color Color + * @return 1 + * @see eDIV_MAP_PUT_PIXEL(), eDIV_GET_PIXEL() + */ +int eDIV_PUT_PIXEL(FUNCTION_PARAMS) +{ + int x , y , c , bpp ; + Uint8 *p ; + + + c = getparm() ; + y = getparm() ; + x = getparm() ; + + if ( x > fondo->w || y > fondo->h || x < 0 || y < 0 ) + return -1 ; + + if ( SDL_MUSTLOCK(fondo) ) { + if ( SDL_LockSurface(fondo) < 0 ) { + return -2; + } + } + + + bpp = fondo->format->BytesPerPixel ; + p = (Uint8 *)fondo->pixels + y * fondo->pitch + x * bpp ; + + switch(bpp) { + + case 1: + *p = c; + break; + + case 2: + *(Uint16 *)p = c; + break; + + case 3: + if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { + p[0] = (c >> 16) & 0xff; + p[1] = (c >> 8) & 0xff; + p[2] = c & 0xff; + } else { + p[0] = c & 0xff; + p[1] = (c >> 8) & 0xff; + p[2] = (c >> 16) & 0xff; + } + break; + + case 4: + *(Uint32 *)p = c; + break; + } + + if ( SDL_MUSTLOCK(fondo) ) { + SDL_UnlockSurface(fondo); + } + + + return 1 ; +} + + +/*! \brief Rellena el buffer del fondo con el color 0. + * @return 1 + */ +int eDIV_CLEAR_SCREEN(FUNCTION_PARAMS) +{ + SDL_FillRect( fondo , NULL , 0 ) ; + + return 1; +} + +/*! \brief Obtiene el color del pixel, en las coordenadas (x,y), del buffer del fondo. + * @param x Coordenada X del pixel + * @param y Coordenada Y del pixel + * @return El color del píxel. + * @see eDIV_PUT_PIXEL(), eDIV_MAP_GET_PIXEL() + */ +int eDIV_GET_PIXEL(FUNCTION_PARAMS) +{ + int x , y , bpp; + Uint8 *p ; + y = getparm() ; + x = getparm() ; + + if ( x > fondo->w || y > fondo->h || x < 0 || y < 0 ) + return -1 ; + + bpp = fondo->format->BytesPerPixel; + p = (Uint8 *)fondo->pixels + y * fondo->pitch + x * bpp; + + switch(bpp) { + case 1: + return *p; + case 2: + return *(Uint16 *)p; + case 3: + if(SDL_BYTEORDER == SDL_BIG_ENDIAN) + { + return p[0] << 16 | p[1] << 8 | p[2]; + }else + { + return p[0] | p[1] << 8 | p[2] << 16; + } + case 4: + return *(Uint32 *)p; + } + + return 0; +} + + +/*! \brief Crea un nuevo mapa con las características indicadas. + * + * El nuevo mapa se creará en el fichero 0, como si se hubiera cargado con + * \link eDIV_LOAD_MAP() load_map() \endlink. + * @param w Anchura del mapa + * @param h Altura del mapa + * @param cx Coordenada X del centro del mapa + * @param cy Coordenada Y del centro del mapa + * @param c Color con el que se rellenará el nuevo mapa + * @return El código del nuevo gráfico, o -1 si ocurrió un error + * @see eDIV_LOAD_MAP(), eDIV_UNLOAD_MAP() + */ +int eDIV_NEW_MAP(FUNCTION_PARAMS) +{ + int i ; + int w , h , cx , cy , c ; + c = getparm() ; + cy = getparm() ; + cx = getparm() ; + h = getparm() ; + w = getparm() ; + + for ( i = 1000 ; i < files[0].num ; i++ ) + { + if ( !files[0].mapa[i].existe ) + { + files[0].mapa[i].Surface = SDL_CreateRGBSurface( SDL_HWSURFACE , w , h , screen->format->BitsPerPixel , 0xFF0000 , 0x00FF00 , 0x0000FF , 0x000000 ) ; + files[0].mapa[i].existe = 1 ; + files[0].mapa[i].cpoint[0].x = cx ; + files[0].mapa[i].cpoint[0].y = cy ; + SDL_FillRect( files[0].mapa[i].Surface , NULL , c ) ; + SDL_SetColorKey( files[0].mapa[i].Surface , SDL_SRCCOLORKEY | SDL_RLEACCEL , color_transparente ) ; + if ( i > last_map[0] ) + last_map[0] = i ; + return i ; + } + } + return -1 ; +} + + +/*! \brief Copia una región de la pantalla en un mapa + * \todo La región copiada debe ESTIRARSE para adaptarse a la región destino + * @param r Región de la pantalla + * @param f Fichero del mapa destino + * @param g Gráfico destino + * @param x Coordenada X destino + * @param y Coordenada Y destino + * @param w Ancho de la región destino dentro del mapa + * @param h Alto de la región destino dentro del mapa + * @return 1 + * @see eDIV_DEFINE_REGION(), eDIV_MAP_BLOCK_COPY() + */ +int eDIV_SCREEN_COPY(FUNCTION_PARAMS) +{ + SDL_Rect srcrect , dstrect ; + int r, f, g , x, y , w , h ; + h = getparm() ; + w = getparm() ; + y = getparm() ; + x = getparm() ; + g = getparm() ; + f = getparm() ; + r = getparm() ; + + if ( !files[f].existe || !files[f].mapa[g].existe ) + return -1 ; + + srcrect.x = 0 ; + srcrect.y = 0 ; + srcrect.w = w ; + srcrect.h = h ; + + dstrect.x = x ; + dstrect.y = y ; + dstrect.w = 0 ; + dstrect.h = 0 ; + + SDL_BlitSurface( screen, &srcrect , files[f].mapa[g].Surface , &dstrect ) ; + return 1 ; +} + +/*! \brief Obtiene las coordenadas de un punto de control de un mapa + * @param f Fichero en el que se encuentra el mapa + * @param g Código del mapa dentro del FPG + * @param n Número del punto de control + * @param offset_x Offset de la variable donde guardar la coordenada X + * @param offset_y Offset de la variable donde guardar la coordenada Y + * @return 0 si todo va bien, -1 si el mapa no existe + * @see eDIV_GET_REAL_POINT() + */ +int eDIV_GET_POINT(FUNCTION_PARAMS) +{ + int f , g , n , dx , dy ; + dy = getparm() ; + dx = getparm() ; + n = getparm() ; + g = getparm() ; + f = getparm() ; + + if ( !files[f].existe || !files[f].mapa[g].existe ) + return -1 ; + + if(dx) fp->mem[ dx ] = files[f].mapa[g].cpoint[n].x ; + if(dy) fp->mem[ dy ] = files[f].mapa[g].cpoint[n].y ; + + return 0 ; +} + +/*! \brief Obtiene las coordenadas en pantalla de un punto de control del proceso actual + * \todo Tener en cuenta angle, size, etc + * @param n Número del punto de control + * @param offset_x Offset de la variable donde guardar la coordenada X + * @param offset_y Offset de la variable donde guardar la coordenada Y + * @return 0 si todo va bien, -1 si el mapa no existe + * @see eDIV_GET_POINT() + */ +int eDIV_GET_REAL_POINT(FUNCTION_PARAMS) +{ + int f , g , n , dx , dy , x , y , id; + dy = getparm() ; + dx = getparm() ; + n = getparm() ; + id = fp->procs_s[ fp->proc_orden[ *fp->proceso_actual ] ].id; + f = local("file",id) ; + g = local("graph",id) ; + x = local("x",id) ; + y = local("y",id) ; + + if ( !files[f].existe || !files[f].mapa[g].existe ) + return -1 ; + + if(dx) fp->mem[ dx ] = files[f].mapa[g].cpoint[n].x - files[f].mapa[g].cpoint[0].x + x ; + if(dy) fp->mem[ dy ] = files[f].mapa[g].cpoint[n].y - files[f].mapa[g].cpoint[0].y + y ; + + return 0 ; +} + +/*! \brief Obtiene información sobre un mapa + * @param f Fichero donde se encuentra el mapa + * @param g Código del gráfico dentro del FPG + * @param i Indica qué información quiere extraerse del mapa, puede ser uno de: + * \a g_wide (0), \a g_height (1), \a g_x_center (2) ó \a g_y_center (3). + * @return La información solicitada, o -1 si hubo un error. + * @see eDIV_GET_POINT() + */ +int eDIV_GRAPHIC_INFO(FUNCTION_PARAMS) +{ + int f , g , i ; + i = getparm() ; + g = getparm() ; + f = getparm() ; + + if ( !files[f].existe || !files[f].mapa[g].existe ) + return -1 ; + + switch (i) + { + case 0: + return files[f].mapa[g].Surface->w ; + case 1: + return files[f].mapa[g].Surface->h ; + case 2: + return files[f].mapa[g].cpoint[0].x ; + case 3: + return files[f].mapa[g].cpoint[0].y ; + } + return -1; +} diff --git a/dlls/src/graphics/misc.c b/dlls/src/graphics/misc.c new file mode 100644 index 0000000..46c3ee2 --- /dev/null +++ b/dlls/src/graphics/misc.c @@ -0,0 +1,81 @@ +/*! \file misc.c + * \brief Funciones varias + */ + +#include + +#include "export.h" +#include "graphics.h" +#include "default_palette.h" + +/*! \brief Cambia el modo de la pantalla + * \todo ¿más flags? + * + * Esta función permite distintas sintaxis: + * - Sintaxis de DIV2: + * @param modo Modo de pantalla indicado por una constante tipo mWWWxHHH ó por un identificador de video_modes[] + * + * - Sintaxis de eDIV: + * @param anchura Ancho de la nueva resolución + * @param altura Alto de la nueva resolución + * @param [bpp] Profundidad de color, puede ser 8, 16, 24 ó 32 (por defecto es 8) + * @param [flags] Flags de la ventana del juego, puede ser una combinación de: + * _fullscreen (1), ... ya veremos si añadimos más xD + * . + * + * @return 0 + */ +int eDIV_SET_MODE(FUNCTION_PARAMS) +{ + int modo; + + switch(fp->num_params) { + case 4: + fp->graphics->flags=getparm(); + case 3: + fp->graphics->bpp=getparm(); + fp->graphics->alto=getparm(); + fp->graphics->ancho=getparm(); + break; + case 1: + modo=getparm(); + if(modo>1280960) { + fp->graphics->ancho=modo/10000; + fp->graphics->alto=modo%10000; + } + else { + fp->graphics->ancho=modo/1000; + fp->graphics->alto=modo%1000; + } + fp->graphics->bpp=8; + fp->graphics->flags=0; + } + + /* Esto avisa a las DLLs */ + fp->graphics->resflags|=GR_CHANGED; + + SDL_FreeSurface(fondo); + SDL_FreeSurface(screen); + + screen=SDL_SetVideoMode(fp->graphics->ancho,fp->graphics->alto,fp->graphics->bpp,SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_HWACCEL|((fp->graphics->flags&GR_FULLSCREEN)?SDL_FULLSCREEN:0)|((fp->graphics->bpp==8)?SDL_HWPALETTE:0)); + fp->graphics->buffer=screen->pixels; + + if(fp->graphics->bpp==8) + SDL_SetPalette(screen,SDL_LOGPAL|SDL_PHYSPAL,(SDL_Color*)default_palette,0,256); + + if ( screen == NULL ) { + fp->Critical_Error(7); /* No se pudo inicializar SDL */ + return 0; + } + + fondo=SDL_CreateRGBSurface(SDL_HWSURFACE,fp->graphics->ancho,fp->graphics->alto,fp->graphics->bpp,0,0,0,0); + fp->graphics->background=fondo->pixels; + + if(fp->graphics->bpp==8) + PaletteCopy(fondo,screen); + + regions[0].w=fp->graphics->ancho; + regions[0].h=fp->graphics->alto; + + return 0; +} diff --git a/dlls/src/graphics/paleta.c b/dlls/src/graphics/paleta.c new file mode 100644 index 0000000..da0ff27 --- /dev/null +++ b/dlls/src/graphics/paleta.c @@ -0,0 +1,126 @@ +/*! \file paleta.c + * \brief Funciones relacionadas con el manejo de la paleta y los colores + */ + +#include + +#include "export.h" +#include "graphics.h" + +/*! \brief Cambia el color transparente (colorkey) actual + * @param a Color que desea usarse como transparente. + * @return El antiguo color transparente. + * @see color_transparente + */ +int eDIV_SET_TRANSPARENT_COLOR(FUNCTION_PARAMS) +{ + int b , i; + int a = getparm() ; + b = color_transparente ; + color_transparente = a ; + for ( i = 1 ; i <= last_map[0] ; i++ ) + { + if ( files[0].mapa[i].existe ) + SDL_SetColorKey( files[0].mapa[i].Surface , SDL_SRCCOLORKEY | SDL_RLEACCEL , color_transparente ) ; + } + return b ; +} + +/*! \brief Obtiene el color transparente actual + * @return El color transparente. + * @see color_transparente + */ +int eDIV_GET_TRANSPARENT_COLOR(FUNCTION_PARAMS) +{ + return color_transparente ; +} + +/*! \brief Crea un color a partir de las componentes RGB dadas. + * + * Esta función devuelve el color más próximo posible a las componentes RGB + * dadas. En modos de color paletizado (8 bits) puede devolver un color muy + * distinto al esperado si no se encuentra otro mejor en la paleta. + * Esta función difiere de \link eDIV_FIND_COLOR() find_color() \endlink en + * que recibe los parámetros en un rango de 0..255 en vez de 0..63. + * @param r Componente roja (red) + * @param g Componente verde (green) + * @param b Componente azul (blue) + * @return El color generado. + * @see eDIV_FIND_COLOR() + */ +int eDIV_RGB(FUNCTION_PARAMS) +{ + int r,g,b ; + b = getparm() ; + g = getparm() ; + r = getparm() ; + + return SDL_MapRGB(screen->format,r,g,b); +} + +/*! \brief Crea un color a partir de las componentes RGB dadas. + * + * Esta función devuelve el color más próximo posible a las componentes RGB + * dadas. En modos de color paletizado (8 bits) puede devolver un color muy + * distinto al esperado si no se encuentra otro mejor en la paleta. + * Esta función difiere de \link eDIV_RGB() RGB() \endlink en que recibe los + * parámetros en un rango de 0..63 en vez de 0..255. Se ha incluido para + * mantener la compatibilidad con DIV2. + * @param r Componente roja (red) + * @param g Componente verde (green) + * @param b Componente azul (blue) + * @return El color generado. + * @see eDIV_RGB() + */ +int eDIV_FIND_COLOR(FUNCTION_PARAMS) +{ + int r,g,b ; + b = getparm() ; + g = getparm() ; + r = getparm() ; + + return SDL_MapRGB(screen->format,r*4,g*4,b*4); +} + +/*! \brief Obtiene las componentes RGB de un color dado. + * + * Esta función recibe un color y almacena en las variables indicadas sus + * componentes RGB (siempre en un rango de 0..255). Si en lugar de un offset + * se recibe un 0, se ignorará esa componente. + * @param color Color del que se quiere obtener la información + * @param offset_r Offset de la variable donde se quiere guardar el valor de la componente roja (red) + * @param offset_g Offset de la variable donde se quiere guardar el valor de la componente verde (green) + * @param offset_b Offset de la variable donde se quiere guardar el valor de la componente azul (blue) + * @return 1 + * @see eDIV_SET_COLOR() + */ +int eDIV_GET_RGB(FUNCTION_PARAMS) +{ + unsigned int color,roff,goff,boff; + unsigned char r,g,b; + boff=getparm(); + goff=getparm(); + roff=getparm(); + color=getparm(); + SDL_GetRGB(color,screen->format,&r,&g,&b); + if(roff) fp->mem[roff]=(int)r; + if(goff) fp->mem[goff]=(int)g; + if(boff) fp->mem[boff]=(int)b; + return 1; +} + +/*! \brief Hace un fundido de pantalla + * + * \todo ¡¡función sin acabar!! + */ +int eDIV_FADE(FUNCTION_PARAMS) +{ + int r , g , b , v ; + v = getparm() ; + b = getparm() ; + g = getparm() ; + r = getparm() ; + + return SDL_SetGamma( 1.0f , 1.0f , 1.0f ) ; + return 1 ; +} diff --git a/dlls/src/graphics/regiones.c b/dlls/src/graphics/regiones.c new file mode 100644 index 0000000..990153a --- /dev/null +++ b/dlls/src/graphics/regiones.c @@ -0,0 +1,71 @@ +/*! \file regiones.c + * \brief Funciones para manejo de regiones de pantalla + */ + +#include + +#include "export.h" +#include "graphics.h" + + +/*! \brief Define una región de pantalla + * \todo Añadir un poco de comprobación de errores + * @param n Número de la región a definir (1..31) + * @param x Coordenada X de la esquina superior izquierda de la región + * @param y Coordenada Y de la esquina superior izquierda de la región + * @param w Anchura de la región + * @param h Altura de la región + * @return 1 si todo fue bien o 0 si hubo un error + * @see eDIV_OUT_REGION(), eDIV_SCREEN_COPY() + */ +int eDIV_DEFINE_REGION(FUNCTION_PARAMS) +{ + int n , x , y , w , h ; + h = getparm() ; + w = getparm() ; + y = getparm() ; + x = getparm() ; + n = getparm() ; + + if ( n > 31 || n < 1 ) { + fp->Runtime_Error(108); /* nº de región inválido */ + return 0; + } + + fp->regions[n].x = x ; + fp->regions[n].y = y ; + fp->regions[n].w = w ; + fp->regions[n].h = h ; + + + return 1 ; +} + +/*! \brief Indica si un proceso está fuera de la región indicada + * @param id Identificador del proceso + * @param r Región + * @return 1 si el proceso está fuera de la región o 0 en caso contrario + * @see eDIV_DEFINE_REGION() + */ +int eDIV_OUT_REGION(FUNCTION_PARAMS) +{ + int id , r ; + int f, g , x , y ; + r = getparm() ; + id = getparm() ; + + f = local("file",id) ; + g = local("graph",id) ; + + if ( !files[f].existe || !files[f].mapa[g].existe ) + return -1 ; + + x = local("x",id) ; + y = local("y",id) ; + + if ( x < fp->regions[r].x + fp->regions[r].w && x + files[f].mapa[g].Surface->w > fp->regions[r].x && + y < fp->regions[r].y + fp->regions[r].h && y + files[f].mapa[g].Surface->h > fp->regions[r].y ) + return 0 ; + else + return 1 ; +} diff --git a/dlls/src/graphics/win32/graphics.vcproj b/dlls/src/graphics/win32/graphics.vcproj index 2443e2d..6950d35 100644 --- a/dlls/src/graphics/win32/graphics.vcproj +++ b/dlls/src/graphics/win32/graphics.vcproj @@ -123,9 +123,33 @@ + + + + + + + + + + + + + + + + mem[fp->GetVarOffset(v_global,nombre)] @@ -61,6 +72,8 @@ typedef struct { #define globalptr(nombre) fp->GetVarOffset(v_global,nombre) #define reservedptr(nombre) fp->GetVarOffset(v_reserved,nombre) #define localptr(nombre) fp->GetVarOffset(v_local,nombre) + +/*! @} */ /* FIN DE VARINDEX */ @@ -89,22 +102,23 @@ typedef int (TYPEOF_Call_Entrypoint)(int ep, ...); typedef int (TYPEOF_Dibuja)(SDL_Surface *, SDL_Rect, SDL_Rect, int, int, int, int); /* Errores */ -typedef enum { /* Tipos de error para custom_error() */ - _runtime_error=1, - _critical_error=2 +/*! Tipos de error para custom_error() */ +typedef enum { + _runtime_error=1, /*!< Error normal (se puede depurar y/o ignorar) */ + _critical_error=2 /*!< Error crítico (interrumpe obligatoriamente el programa) */ } tipoerror; typedef void (TYPEOF_Runtime_Error)(int, ...); typedef void (TYPEOF_Critical_Error)(int, ...); typedef void (TYPEOF_Custom_Error)(tipoerror,char*); -/* Obtiene offset de variable indexada dinámicamente */ +/*! Obtiene offset de variable indexada dinámicamente */ typedef int (TYPEOF_GetVarOffset)(tipo_t tipo,char* nombre); -/* Finaliza el stub (exit) */ +/*! Finaliza el stub (exit) */ typedef void (TYPEOF_Stub_Quit)(int n); -/* EXPORTAFUNCS_PARAMS deben usarse como parámetros para ExportaFuncs */ +/*! EXPORTAFUNCS_PARAMS deben usarse como parámetros para ExportaFuncs */ #define EXPORTAFUNCS_PARAMS \ TYPEOF_EDIV_Export *EDIV_Export ,\ TYPEOF_EDIV_Export_Const *EDIV_Export_Const ,\ @@ -130,8 +144,10 @@ TYPEOF_EDIV_Export_Priority *EDIV_Export_Priority * a las correspondientes rutinas de las dll's, ordenadas por prioridad) */ -// Constantes para EDIV_Export_Entrypoint +/* Constantes para EDIV_Export_Entrypoint */ +/*! \defgroup entrypoints Entrypoints */ +/*! @{ */ #define EDIV_set_video_mode 1 /* Al activar un nuevo modo de vídeo */ #define EDIV_process_palette 2 /* Al cargar una paleta */ #define EDIV_process_active_palette 3 /* Al modificar la paleta activa (usada en los fades) */ @@ -155,7 +171,7 @@ TYPEOF_EDIV_Export_Priority *EDIV_Export_Priority #define EDIV_debug 21 /* Invocar al trazador - sentencia debug (solo en debug) */ #define EDIV_first_load 22 /* Se ejecuta al cargar la DLL en ejecucion */ #define EDIV_quit 23 /* Llamado por stub_quit() */ - +/*! @} */ /* #defines para que la declaración de datos sea un poco más BASIC... :p */ #ifdef CONST @@ -176,13 +192,13 @@ TYPEOF_EDIV_Export_Priority *EDIV_Export_Priority #define ENTRYPOINT(e) EDIV_Export_Entrypoint(EDIV_##e,e) #define PRIORITY EDIV_Export_Priority - -/* +/*! * FUNCTION_PARAMS deben usarse como parametros para TODAS las funciones - * ¡ojo! debe ser igual en extern.h + * ¡OJO! debe ser igual en extern.h */ #define FUNCTION_PARAMS struct _fun_params * fp +/*! Estructura de una entrada de la tabla de procesos */ struct _procs_s{ int id ; /* offset de los datos locales del proceso */ int tipo ; /* tipo de proceso */ @@ -194,15 +210,18 @@ struct _procs_s{ int graph ; }; -struct _regions -{ +/*! Estructura de una región de pantalla */ +struct _regions { int x , y , w , h ; -} ; +}; +/*! Permite asegurarnos de que ciertos recursos están cargados */ struct _existe { int regions ; int dibuja ; -} ; +}; + +/*! Mapa dentro de un FPG */ struct _file { SDL_Surface *Surface; @@ -213,15 +232,23 @@ struct _file { int x , y ; } cpoint[ 20 ] ; -} ; +}; +/*! Vector de FPG's */ struct _files { int num ; int existe ; struct _file *mapa ; -} ; +}; +/*! Datos de la paleta en la estructura _graphics */ +struct _palette { + byte r,g,b; + byte unused; +}; + +/*! Estructura graphics, permite acceder a la pantalla */ typedef struct { int ancho; int alto; @@ -230,8 +257,11 @@ typedef struct { int resflags; byte* buffer; byte* background; + struct _palette* palette; + struct _palette* activepal; } _graphics; +/*! Parámetros para las funciones exportadas */ struct _fun_params{ int *pila ; int *sp ; @@ -265,6 +295,9 @@ struct _fun_params{ #define GR_ACTIVE 0x01 #define GR_CHANGED 0x02 +/* Valores para PRIORITY() */ +#define P_SIEMPRE 512 +#define P_NUNCA -512 /* Se usa igual que el getparm() de DIV */ #define getparm() fp->pila[(*fp->sp)--] @@ -274,7 +307,12 @@ struct _fun_params{ #define retval(a) return (a) -/* Prototipos de los entrypoints */ +/* + * Prototipos de los entrypoints + */ + +/*! \addtogroup entrypoints */ +/*! @{ */ void set_video_mode(void); void process_palette(void); void process_active_palette(void); @@ -299,9 +337,12 @@ void trace(int imem, char* nombreprg, int* lin, void* dbg); void debug(int imem, char* nombreprg, int* lin, void* dbg); void first_load(FUNCTION_PARAMS) ; void quit(void); +/*! @} */ #ifdef __cplusplus } #endif #endif /* __EDIV_EXPORT_H_ */ + +/*! @} */