#include #include #include #include "struct.h" #include "sdlscreen.h" #include "global.h" #include "graph.h" //Afficher_curseur #include "erreurs.h" #include "boutons.h" #include "moteur.h" #include "divers.h" // Gestion du mode texte de départ (pour pouvoir y retourner en cas de problème byte Recuperer_nb_lignes(void) { puts("Recuperer_nb_lignes non implémenté!\n"); return 0; } word Palette_Compter_nb_couleurs_utilisees(dword* Tableau) { int Nombre_De_Pixels=0; Uint8* Pixel_Courant=Principal_Ecran; Uint8 Couleur; word Nombre_Couleurs=0; int i; //Calcul du nombre de pixels dans l'image Nombre_De_Pixels=Principal_Hauteur_image*Principal_Largeur_image; // On parcourt l'écran courant pour compter les utilisations des couleurs for(i=0;i>4); //Les couleurs VGA ne vont que de 0 à 63 PaletteSDL[i].g=(Palette[i].V<<2) + (Palette[i].V>>4); PaletteSDL[i].b=(Palette[i].B<<2) + (Palette[i].B>>4); } SDL_SetPalette(Ecran_SDL,SDL_PHYSPAL|SDL_LOGPAL,PaletteSDL,0,256); } void Attendre_fin_de_click(void) { SDL_Event event; //On attend que l'utilisateur relache la souris. Tous les autres évènements //sont ignorés while(SDL_PollEvent(&event) && event.type == SDL_MOUSEBUTTONUP); //On indique à la gestion des E/S que le bouton est laché et on rend la main Mouse_K=0; INPUT_Nouveau_Mouse_K=0; } void Effacer_image_courante_Stencil(byte Couleur, byte * Pochoir) //Effacer l'image courante avec une certaine couleur en mode Stencil { int Nombre_De_Pixels=0; //ECX //al=Couleur //edi=Ecran byte* Pixel_Courant=Ecran; //dl int i; Nombre_De_Pixels=Principal_Hauteur_image*Principal_Largeur_image; for(i=0;i 0) Retour = Sym.sym; else if (Sym.unicode > 0) Retour = (Sym.unicode & 0x07FF) | 0x0800; if (Sym.mod & (KMOD_LSHIFT | KMOD_RSHIFT)) Retour |= 0x1000; if (Sym.mod & (KMOD_LCTRL | KMOD_RCTRL)) Retour |= 0x2000; if (Sym.mod & (KMOD_LALT | KMOD_RALT | KMOD_MODE)) Retour |= 0x4000; return Retour; } const char * Nom_touche(word Touche) { typedef struct { word Sym; char *Nom_touche; } S_Libelle_touche; S_Libelle_touche Table_touches[] = { { SDLK_BACKSPACE , "Backspace" }, { SDLK_TAB , "Tab" }, { SDLK_CLEAR , "Clear" }, { SDLK_RETURN , "Return" }, { SDLK_PAUSE , "Pause" }, { SDLK_ESCAPE , "Esc" }, { SDLK_DELETE , "Del" }, { SDLK_KP0 , "KP 0" }, { SDLK_KP1 , "KP 1" }, { SDLK_KP2 , "KP 2" }, { SDLK_KP3 , "KP 3" }, { SDLK_KP4 , "KP 4" }, { SDLK_KP5 , "KP 5" }, { SDLK_KP6 , "KP 6" }, { SDLK_KP7 , "KP 7" }, { SDLK_KP8 , "KP 8" }, { SDLK_KP9 , "KP 9" }, { SDLK_KP_PERIOD , "KP ." }, { SDLK_KP_DIVIDE , "KP /" }, { SDLK_KP_MULTIPLY, "KP *" }, { SDLK_KP_MINUS , "KP -" }, { SDLK_KP_PLUS , "KP Plus" }, { SDLK_KP_ENTER , "KP Enter" }, { SDLK_KP_EQUALS , "KP =" }, { SDLK_UP , "Up" }, { SDLK_DOWN , "Down" }, { SDLK_RIGHT , "Right" }, { SDLK_LEFT , "Left" }, { SDLK_INSERT , "Ins" }, { SDLK_HOME , "Home" }, { SDLK_END , "End" }, { SDLK_PAGEUP , "PgUp" }, { SDLK_PAGEDOWN , "PgDn" }, { SDLK_F1 , "F1" }, { SDLK_F2 , "F2" }, { SDLK_F3 , "F3" }, { SDLK_F4 , "F4" }, { SDLK_F5 , "F5" }, { SDLK_F6 , "F6" }, { SDLK_F7 , "F7" }, { SDLK_F8 , "F8" }, { SDLK_F9 , "F9" }, { SDLK_F10 , "F10" }, { SDLK_F11 , "F11" }, { SDLK_F12 , "F12" }, { SDLK_F13 , "F13" }, { SDLK_F14 , "F14" }, { SDLK_F15 , "F15" }, { SDLK_NUMLOCK , "NumLock" }, { SDLK_CAPSLOCK , "CapsLck" }, { SDLK_SCROLLOCK , "ScrlLock" }, { SDLK_RSHIFT , "RShift" }, { SDLK_LSHIFT , "LShift" }, { SDLK_RCTRL , "RCtrol" }, { SDLK_LCTRL , "LCtrl" }, { SDLK_RALT , "RAlt" }, { SDLK_LALT , "LAlt" }, { SDLK_RMETA , "RMeta" }, { SDLK_LMETA , "LMeta" }, { SDLK_LSUPER , "LWin" }, { SDLK_RSUPER , "RWin" }, { SDLK_MODE , "AltGr" }, { SDLK_COMPOSE , "Comp" }, { SDLK_HELP , "Help" }, { SDLK_PRINT , "Print" }, { SDLK_SYSREQ , "SysReq" }, { SDLK_BREAK , "Break" }, { SDLK_MENU , "Menu" }, { SDLK_POWER , "Power" }, { SDLK_EURO , "Euro" }, { SDLK_UNDO , "Undo" } }; int Indice; static char Buffer[25]; Buffer[0] = '\0'; if (Touche & 0x2000) strcat(Buffer, "Ctrl+"); if (Touche & 0x4000) strcat(Buffer, "Alt+"); if (Touche & 0x1000) strcat(Buffer, "Shift+"); if (Touche & 0x8000) { sprintf(Buffer+strlen(Buffer), "[%d]", Touche & 0xFFF); return Buffer; } Touche = Touche & 0xFFF; // Touches ASCII if (Touche>=' ' && Touche < 127) { sprintf(Buffer+strlen(Buffer), "'%c'", Touche); return Buffer; } // Touches 'World' if (Touche>=SDLK_WORLD_0 && Touche <= SDLK_WORLD_95) { sprintf(Buffer+strlen(Buffer), "w%d", Touche - SDLK_WORLD_0); return Buffer; } // Touches au libellé connu for (Indice=0; Indice < sizeof(Table_touches)/sizeof(S_Libelle_touche);Indice++) { if (Touche == Table_touches[Indice].Sym) { sprintf(Buffer+strlen(Buffer), "%s", Table_touches[Indice].Nom_touche); return Buffer; } } // Autres touches inconnues sprintf(Buffer+strlen(Buffer), "(%d)", Touche); return Buffer; } void Get_input(void) //Gestion des évènements: mouvement de la souris, clic sur les boutons, et utilisation du clavier. { SDL_Event event; Touche=0; Touche_ASCII=0; // Par défaut, il n'y a pas d'action sur le clavier. if( SDL_PollEvent(&event)) /* Il y a un évènement en attente */ { switch( event.type) { case SDL_MOUSEMOTION: //Mouvement de la souris INPUT_Nouveau_Mouse_X = event.motion.x>>Mouse_Facteur_de_correction_X; INPUT_Nouveau_Mouse_Y = event.motion.y>>Mouse_Facteur_de_correction_Y; break; case SDL_MOUSEBUTTONDOWN: //Clic sur un des boutons de la souris switch(event.button.button) { case SDL_BUTTON_LEFT: INPUT_Nouveau_Mouse_K = 1; break; case SDL_BUTTON_MIDDLE: // Pour SDL, 2 = clic milieu. Pour nous c'est le clic droit case SDL_BUTTON_RIGHT: // Clic droit SDL, clic droit pour nous aussi ( pour le moment en tout cas) INPUT_Nouveau_Mouse_K = 2; } break; case SDL_MOUSEBUTTONUP: //Bouton souris relaché INPUT_Nouveau_Mouse_K=0; break; case SDL_KEYDOWN: { byte ok = 0; //Appui sur une touche du clavier Touche = Touche_SDL(event.key.keysym); //Cas particulier: déplacement du curseur avec haut bas gauche droite //On doit interpréter ça comme un mvt de la souris if(Touche == Config_Touche[0]) { //[Touche] = Emulation de MOUSE UP //si on est déjà en haut on peut plus bouger if(INPUT_Nouveau_Mouse_Y!=0) { INPUT_Nouveau_Mouse_Y--; ok=1; } } else if(Touche == Config_Touche[1]) { //[Touche] = Emulation de MOUSE DOWN if(INPUT_Nouveau_Mouse_Y=Principal_Split) { bl++; INPUT_Nouveau_Mouse_X=Principal_Split-1; } } else { if(INPUT_Nouveau_Mouse_X>= 32; Ellipse_Limite_High = Ellipse_Limite; } byte Pixel_dans_ellipse(void) { uint64_t ediesi = Table_des_carres[abs(Ellipse_Curseur_X)] * (Ellipse_Rayon_vertical_au_carre) + Table_des_carres[abs(Ellipse_Curseur_Y)] * (Ellipse_Rayon_horizontal_au_carre); if((ediesi >> 32) <= Ellipse_Limite_High && (ediesi & 0xFFFFFFFF) <= Ellipse_Limite_Low) return 255; return 0; } byte Pixel_dans_cercle(void) { if((Table_des_carres[abs(Cercle_Curseur_X)] + Table_des_carres[abs(Cercle_Curseur_Y)] ) <= Cercle_Limite) return 255; return 0; } void Copier_une_partie_d_image_dans_une_autre(byte * Source,word S_Pos_X,word S_Pos_Y,word Largeur,word Hauteur,word Largeur_source,byte * Destination,word D_Pos_X,word D_Pos_Y,word Largeur_destination) { // ESI = adresse de la source en (S_Pox_X,S_Pos_Y) byte* esi = Source + S_Pos_Y * Largeur_source + S_Pos_X; // EDI = adresse de la destination (D_Pos_X,D_Pos_Y) byte* edi = Destination + D_Pos_Y * Largeur_destination + D_Pos_X; int Ligne; // Pour chaque ligne for (Ligne=0;Ligne < Hauteur; Ligne++) { memcpy(edi,esi,Largeur); // Passe à la ligne suivante esi+=Largeur_source; edi+=Largeur_destination; } } byte Lit_pixel_dans_ecran_brouillon(word X,word Y) { return *(Brouillon_Ecran+Y*Brouillon_Largeur_image+X); } void Rotate_90_deg_LOWLEVEL(byte * Source,byte * Destination) { byte* esi; byte* edi; word dx,bx,cx; //ESI = Point haut droit de la source byte* Debut_de_colonne = Source + Brosse_Largeur - 1; edi = Destination; // Largeur de la source = Hauteur de la destination dx = bx = Brosse_Largeur; // Pour chaque ligne for(dx = Brosse_Largeur;dx>0;dx--) { esi = Debut_de_colonne; // Pout chaque colonne for(cx=Brosse_Hauteur;cx>0;cx--) { *edi = *esi; esi+=Brosse_Largeur; edi++; } Debut_de_colonne--; } } // Remplacer une couleur par une autre dans un buffer void Remap_general_LOWLEVEL(byte * Table_conv,byte * Buffer,short Largeur,short Hauteur,short Largeur_buffer) { int dx,cx; // Pour chaque ligne for(dx=Hauteur;dx>0;dx--) { // Pour chaque pixel for(cx=Largeur;cx>0;cx--) { *Buffer = Table_conv[*Buffer]; Buffer++; } Buffer += Largeur_buffer-Largeur; } } void Copier_image_dans_brosse(short Debut_X,short Debut_Y,short Brosse_Largeur,short Brosse_Hauteur,word Largeur_image) { byte* Src=Debut_Y*Largeur_image+Debut_X+Principal_Ecran; //Adr départ image (ESI) byte* Dest=Brosse; //Adr dest brosse (EDI) int dx; for (dx=Brosse_Hauteur;dx!=0;dx--) //Pour chaque ligne { // On fait une copie de la ligne memcpy(Dest,Src,Brosse_Largeur); // On passe à la ligne suivante Src+=Largeur_image; Dest+=Brosse_Largeur; } } byte Lit_pixel_dans_ecran_feedback (word X,word Y) { return *(FX_Feedback_Ecran+Y*Principal_Largeur_image+X); } dword Round_div(dword Numerateur,dword Diviseur) { return Numerateur/Diviseur; } byte Effet_Trame(word X,word Y) { return Trame[X % Trame_Largeur][Y % Trame_Hauteur]; } void Set_mouse_position(void) { SDL_WarpMouse( Mouse_X << Mouse_Facteur_de_correction_X, Mouse_Y << Mouse_Facteur_de_correction_Y ); } void Clip_mouse(void) { UNIMPLEMENTED } void Remplacer_toutes_les_couleurs_dans_limites(byte * Table_de_remplacement) { int Ligne; int Compteur; byte* Adresse; byte Ancien; // Pour chaque ligne : for(Ligne = Limite_Haut;Ligne <= Limite_Bas; Ligne++) { // Pour chaque pixel sur la ligne : for (Compteur = Limite_Gauche;Compteur <= Limite_Droite;Compteur ++) { Adresse = Principal_Ecran+Ligne*Principal_Largeur_image+Compteur; Ancien=*Adresse; *Adresse = Table_de_remplacement[Ancien]; } } } byte Lit_pixel_dans_ecran_backup (word X,word Y) { return *(Ecran_backup + X + Principal_Largeur_image * Y); } byte Type_de_lecteur_de_disquette(byte Numero_de_lecteur) // Numero_de_lecteur compris entre 0 et 3 (4 lecteurs de disquettes) // // Résultat = 0 : Pas de lecteur // 1 : Lecteur 360 Ko // 2 : Lecteur 1.2 Mo // 3 : Lecteur 720 Ko // 4 : Lecteur 1.4 Mo // 5 : Lecteur 2.8 Mo (??? pas sur ???) // 6 : Lecteur 2.8 Mo { UNIMPLEMENTED return 0; } byte Disk_map(byte Numero_de_lecteur) { UNIMPLEMENTED return 0; } byte Disque_dur_present(byte Numero_de_disque) { UNIMPLEMENTED return 0; } byte Lecteur_CDROM_present(byte Numero_de_lecteur) { UNIMPLEMENTED return 0; } long Freespace(byte Numero_de_lecteur) { UNIMPLEMENTED return 0; } // Les images ILBM sont stockés en bitplanes donc on doit trifouiller les bits pour // en faire du chunky byte Couleur_ILBM_line(word Pos_X, word Vraie_taille_ligne) { // CL sera le rang auquel on extrait les bits de la couleur byte cl = 7 - (Pos_X & 7); int ax,bh,dx; byte bl=0; for(dx = HBPm1;dx>0;dx--); { //CIL_Loop ax = (Vraie_taille_ligne * dx + Pos_X) >> 3; bh = (LBM_Buffer[ax] >> cl) & 1; bl = (bl << 1) + bh; } return bl; } void Palette_256_to_64(T_Palette Palette) { int i; for(i=0;i<256;i++) { Palette[i].R = Palette[i].R >> 2; Palette[i].V = Palette[i].V >> 2; Palette[i].B = Palette[i].B >> 2; } } void Palette_64_to_256(T_Palette Palette) { int i; for(i=0;i<256;i++) { Palette[i].R = Palette[i].R << 2; Palette[i].V = Palette[i].V << 2; Palette[i].B = Palette[i].B << 2; } } byte Effet_Colorize_interpole (word X,word Y,byte Couleur) { // Facteur_A = 256*(100-Colorize_Opacite)/100 // Facteur_B = 256*( Colorize_Opacite)/100 // // (Couleur_dessous*Facteur_A+Couleur*facteur_B)/256 // // On place dans ESI 3*Couleur_dessous ( = position de cette couleur dans la // palette des teintes) et dans EDI, 3*Couleur. byte Bleu_dessous=Principal_Palette[*(FX_Feedback_Ecran + Y * Principal_Largeur_image + X)].B; byte Bleu=Principal_Palette[Couleur].B; byte Vert_dessous=Principal_Palette[*(FX_Feedback_Ecran + Y * Principal_Largeur_image + X)].V; byte Vert=Principal_Palette[Couleur].V; byte Rouge_dessous=Principal_Palette[*(FX_Feedback_Ecran + Y * Principal_Largeur_image + X)].R; byte Rouge=Principal_Palette[Couleur].R; // On récupère les 3 composantes RVB // Bleu Bleu = (Table_de_multiplication_par_Facteur_B[Bleu] + Table_de_multiplication_par_Facteur_A[Bleu_dessous]) / 256; Vert = (Table_de_multiplication_par_Facteur_B[Vert] + Table_de_multiplication_par_Facteur_A[Vert_dessous]) / 256; Rouge = (Table_de_multiplication_par_Facteur_B[Rouge] + Table_de_multiplication_par_Facteur_A[Rouge_dessous]) / 256; return Meilleure_couleur(Rouge,Vert,Bleu); } byte Effet_Colorize_additif (word X,word Y,byte Couleur) { UNIMPLEMENTED return 0; } byte Effet_Colorize_soustractif(word X,word Y,byte Couleur) { UNIMPLEMENTED return 0; } void Tester_chrono(void) { if((SDL_GetTicks()/55)-Chrono_delay>Chrono_cmp) Etat_chrono=1; } // Effectue une inversion de la brosse selon une droite horizontale void Flip_Y_LOWLEVEL(void) { // ESI pointe sur la partie haute de la brosse // EDI sur la partie basse byte* ESI = Brosse ; byte* EDI = Brosse + (Brosse_Hauteur - 1) *Brosse_Largeur; byte tmp; word cx; while(ESI < EDI) { // Il faut inverser les lignes pointées par ESI et // EDI ("Brosse_Largeur" octets en tout) for(cx = Brosse_Largeur;cx>0;cx--) { tmp = *ESI; *ESI = *EDI; *EDI = tmp; ESI++; EDI++; } // On change de ligne : // ESI pointe déjà sur le début de la ligne suivante // EDI pointe sur la fin de la ligne en cours, il // doit pointer sur le début de la précédente... EDI -= 2 * Brosse_Largeur; // On recule de 2 lignes } } // Effectue une inversion de la brosse selon une droite verticale void Flip_X_LOWLEVEL(void) { // ESI pointe sur la partie gauche et EDI sur la partie // droite byte* ESI = Brosse; byte* EDI = Brosse + Brosse_Largeur - 1; byte* Debut_Ligne; byte* Fin_Ligne; byte tmp; word cx; while(ESI0;cx--) { tmp=*ESI; *ESI=*EDI; *EDI=tmp; EDI+=Brosse_Largeur; ESI+=Brosse_Largeur; } // On change de colonne // ESI > colonne suivante // EDI > colonne précédente ESI = Debut_Ligne + 1; EDI = Fin_Ligne - 1; } } // Faire une rotation de 180º de la brosse void Rotate_180_deg_LOWLEVEL(void) { // ESI pointe sur la partie supérieure de la brosse // EDI pointe sur la partie basse byte* ESI = Brosse; byte* EDI = Brosse + Brosse_Hauteur*Brosse_Largeur - 1; // EDI pointe sur le dernier pixel de la derniere ligne byte tmp; word cx; while(ESI < EDI) { // On échange les deux lignes pointées par EDI et // ESI (Brosse_Largeur octets) // En même temps, on échange les pixels, donc EDI // pointe sur la FIN de sa ligne for(cx=Brosse_Largeur;cx>0;cx--) { tmp = *ESI; *ESI = *EDI; *EDI = tmp; EDI--; // Attention ici on recule ! ESI++; } } } void Tempo_jauge(byte Vitesse) //Boucle d'attente pour faire bouger les scrollbars à une vitesse correcte { while (Vitesse!=0) { Wait_VBL(); Vitesse--; } } byte Meilleure_couleur_sans_exclusion(byte Rouge,byte Vert,byte Bleu) { UNIMPLEMENTED return 0; } void Set_color(byte Couleur, byte Rouge, byte Vert, byte Bleu) { SDL_Color comp; comp.r=Rouge << 2; comp.g=Vert << 2; comp.b=Bleu << 2; SDL_SetColors(Ecran_SDL,&comp,Couleur,1); } void Scroll_picture(short Decalage_X,short Decalage_Y) { byte* esi = Ecran_backup; //Source de la copie byte* edi = Principal_Ecran + Decalage_Y * Principal_Largeur_image + Decalage_X; const word ax = Principal_Largeur_image - Decalage_X; // Nombre de pixels à copier à droite word dx; for(dx = Principal_Hauteur_image - Decalage_Y;dx>0;dx--) { // Pour chaque ligne memcpy(edi,esi,ax); memcpy(edi - Decalage_X,esi+ax,Decalage_X); // On passe à la ligne suivante edi += Principal_Largeur_image; esi += Principal_Largeur_image; } // On vient de faire le traitement pour otutes les lignes au-dessous de Decalage_Y // Maintenant on traite celles au dessus edi = Decalage_X + Principal_Ecran; for(dx = Decalage_Y;dx>0;dx--) { memcpy(edi,esi,ax); memcpy(edi - Decalage_X,esi+ax,Decalage_X); edi += Principal_Largeur_image; esi += Principal_Largeur_image; } SDL_UpdateRect(Ecran_SDL,0,0,0,0); } word Get_key(void) { SDL_Event event; Attendre_fin_de_click(); // On prend le controle de la boucle d'évènements, donc il ne faut pas qu'on rate la fin de click ! Clavier_de_depart(); while(1) { SDL_WaitEvent(&event); if(event.type == SDL_KEYDOWN) { if ( event.key.keysym.unicode == 0) { return event.key.keysym.sym; } if ( event.key.keysym.unicode < 127) { //printf("ascii %x, %d %s\n",event.key.keysym.unicode, event.key.keysym.sym ,SDL_GetKeyName(event.key.keysym.sym) ); return event.key.keysym.unicode; // Pas de souci, on est en ASCII standard } // Quelques conversions Unicode-ANSI switch(event.key.keysym.unicode) { case 0x8100: return 'ü'; // ü case 0x1A20: return 'é'; // é case 0x201A: return 'è'; // è case 0x9201: return 'â'; // â case 0x1E20: return 'ä'; // ä case 0x2620: return 'à'; // à case 0x2020: return 'å'; // å case 0x2120: return 'ç'; // ç case 0xC602: return 'ê'; // ê case 0x3020: return 'ë'; // ë case 0x6001: return 'è'; // è case 0x3920: return 'ï'; // ï case 0x5201: return 'î'; // î case 0x8D00: return 'ì'; // ì case 0x1C20: return 'ô'; // ô case 0x1D20: return 'ö'; // ö case 0x2220: return 'ò'; // ò case 0x1320: return 'û'; // û case 0x1420: return 'ù'; // ù case 0xDC02: return 'ÿ'; // ÿ case 0x5301: return '£'; // £ case 0xA000: return 'á'; // á case 0xA100: return 'í'; // í case 0xA200: return 'ó'; // ó case 0xA300: return 'ú'; // ú case 0xA400: return 'ñ'; // ñ case 0xA700: return 'º'; // º case 0xC600: return 'ã'; // ã } // Touche entre 127 et 255 if (event.key.keysym.unicode<256) { //printf("ascii etendu %x, %d %s\n",event.key.keysym.unicode, event.key.keysym.sym ,SDL_GetKeyName(event.key.keysym.sym) ); return event.key.keysym.unicode; } // Sinon c'est une touche spéciale, on retourne son scancode //printf("non ascii %x, %d %s\n",event.key.keysym.unicode, event.key.keysym.sym ,SDL_GetKeyName(event.key.keysym.sym) ); return event.key.keysym.sym; } } } void Zoomer_une_ligne(byte* Ligne_originale, byte* Ligne_zoomee, word Facteur, word Largeur ) { byte couleur; word larg; // Pour chaque pixel for(larg=0;larg