#include #include #include "grafx.h" #define TAILLE_ESPACE 4 // écran unsigned char *backScr; unsigned char *saveScr; unsigned char *pileScr; // carte unsigned char *shadows = NULL; unsigned char *usmap = NULL; unsigned char *selection = NULL; // grafx - en mode mémoire unsigned char *grafx = NULL; uint32 grafx_offcur_ram = 0; uint32 grafx_offset_ram = 0; // grafx - en mode fichier FILE *ttrficgrafx = NULL; uint32 grafx_offset_file = 0; unsigned char *lastBuffer = NULL; uint16 lastBufferNum = FILE_MAX_GRAFX + 1; // test alpha blending uint8 tabAlfa[0x40][0x40][0x100]; // écran inline void sauverScreen() { memcpy(saveScr, SCREEN_BASE_ADDRESS, SCREEN_BYTES_SIZE); } inline void remettreScreen() { memcpy(SCREEN_BASE_ADDRESS, saveScr, SCREEN_BYTES_SIZE); } inline void clearBackScreen() { memset(backScr, 0x00, SCREEN_BYTES_SIZE); } inline void afficherBackScreen() { memcpy(SCREEN_BASE_ADDRESS, backScr, SCREEN_BYTES_SIZE); } inline void savScrTobackScr() { memcpy(backScr, saveScr, SCREEN_BYTES_SIZE); } inline void empilerBackScr() { memcpy(pileScr, backScr, SCREEN_BYTES_SIZE); } inline void depilerBackScr() { memcpy(backScr, pileScr, SCREEN_BYTES_SIZE); } // fichiers char *getCheminFichier(char *nom) { memset(fic, 0, 256); strcpy(fic, ttrdir); strcat(fic, nom); return (char *)fic; } uint32 get_filesize(FILE *input_file) { uint32 file_length; fseek(input_file, 0, SEEK_END); file_length = (uint32)ftell(input_file); fseek(input_file, 0, SEEK_SET); return file_length; } unsigned char *lire_file(char *nom, uint32 *size) { size[0] = 0; char *nomfic = getCheminFichier(nom); FILE *ttrfic = fopen(nomfic, "rb"); if(!ttrfic) { #ifdef DEBUG puts("fichier introuvable"); puts(nomfic); #endif return NULL; } size[0] = get_filesize(ttrfic); unsigned char *source_buffer; source_buffer = (unsigned char *)malloc(size[0]); fseek(ttrfic, 0, SEEK_SET); fread(source_buffer, 1, size[0], ttrfic); fclose(ttrfic); return source_buffer; } // grafx -- RAM inline uint32 grafx_read3_ram() { uint8 b1 = grafx[grafx_offcur_ram++]; uint8 b2 = grafx[grafx_offcur_ram++]; uint8 b3 = grafx[grafx_offcur_ram++]; return (b1 << 16) + (b2 << 8) + b3; } inline uint16 grafx_read2_ram() { uint8 b1 = grafx[grafx_offcur_ram++]; uint8 b2 = grafx[grafx_offcur_ram++]; return (b1 << 8) + b2; } void grafx_set_position_ram(uint32 offset) { grafx_offcur_ram = offset; } void loadGrafx_ram() { uint32 dummy; grafx = lire_file("grafx/datar.tns", &dummy); grafx_set_position_ram(0); grafx_offset_ram = grafx_read3_ram(); } void doneGrafx_ram() { free(grafx); if (lastBufferNum <= FILE_MAX_GRAFX) { free(lastBuffer); } } void grafx_positionner_ram(uint16 num) { grafx_set_position_ram(grafx_offset_ram + num * 3); grafx_set_position_ram(grafx_read3_ram()); } uint16 afficherGrafx_internal(unsigned char *buffer, uint32 start, sint16 x, sint16 y, uint8 ou, uint16 colorisation, bool speedAlfa) { unsigned char *dest = backScr; uint16 maxX = 320; uint16 maxY = 240; switch (ou) { case SCREEN_SHADOW: dest = shadows; maxX = 640; maxY = 413; break; case SCREEN_WAGON: dest = usmap; maxX = 640; maxY = 413; break; case SCREEN_SELECT: dest = selection; maxX = 640; maxY = 413; break; case SCREEN_DIRECT: dest = SCREEN_BASE_ADDRESS; maxX = 320; maxY = 240; break; } unsigned char *savDest = dest; uint16 maxX2 = maxX * 2; if (x > 0) { dest += x * 2; } if (y > 0) { dest += y * maxX2; } uint32 offset = start; uint8 b1 = buffer[offset++]; uint8 b2 = buffer[offset++]; uint16 width = (b1 << 8) + b2; b1 = buffer[offset++]; b2 = buffer[offset++]; uint16 height = (b1 << 8) + b2; if ((x >= maxX) || (y >= maxY) || (x + width < 0) || (y + height < 0)) { // hors écran return 0; } uint8 alpha = buffer[offset++]; if (alpha == 0) { // pas de transparence unsigned char *src = &buffer[offset]; // pas de gestion de l'alpha blending ni de pixels invisibles // premier décalage sur les x if (x < 0) { src -= x * 2; } // calcul de la width affichée uint16 width_affichee = width; if (x < 0) { width_affichee += x; } if (x + width >= maxX) { width_affichee -= x + width - maxX; } // calcul du nombre de byte à sauter après chaque ligne uint16 srcDecalX = width * 2; width_affichee = width_affichee * 2; // calcul du nombre de ligne à afficher uint16 height_affichee = height; if (y < 0) { height_affichee += y; } if (y + height >= maxY) { height_affichee -= y + height - maxY; } // envoyer la puré for (uint ligne = 0; ligne < height_affichee; ligne ++) { memcpy(dest, src, width_affichee); src += srcDecalX; dest += maxX2; } } else { // alpha blending et pixels invisibles sint16 vx = x; // virtual x sur l'écran sint16 vy = y; // virtual y sur l'écran uint16 sx = 0; // virtual x sur le grafx uint16 sy = 0; // virtual y sur le grafx uint8 cmd = 1; if (speedAlfa) { if (colorisation != 0xFFFF) { // avec colorisation if ((vx >= 0) && (vy >= 0) && (vx + width < maxX) && (vy + height < maxY)) { // pas de clipping while (cmd != 0) { cmd = buffer[offset++]; if (cmd == 1) { // CMD_INC_X = $01; // décaler de xx pixels 01.FF uint8 nb = buffer[offset++]; vx += nb; sx += nb; // recalage dest = savDest; dest += vx * 2; dest += vy * maxX2; // saut de ligne ? if (sx >= width) { cmd = 2; } } if (cmd == 3) { // CMD_ALPHA = $03; // afficher les xx prochains pixels en mode alpha 03.FF [00][00.00] ... [00][00.00] uint8 nb = buffer[offset++]; for (uint i = 0; i < nb; i++) { uint8 al = buffer[offset++]; uint8 hi = buffer[offset++]; uint8 lo = buffer[offset++]; // pour l'instant on ne fait qu'afficher // composantes du pixel Hi[VVVB BBBB] Lo[RRRR RVVV] -> Lo[RRRR RVVV] Hi[VVVB BBBB] uint16 couleur = (lo << 8) + hi; couleur = couleur & colorisation; uint16 pr = (couleur & 0xF800) >> 11; uint16 pv = (couleur & 0x07E0) >> 5; uint16 pb = (couleur & 0x001F); // composantes du background couleur = (dest[1] << 8) + dest[0]; uint16 br = (couleur & 0xF800) >> 11; uint16 bv = (couleur & 0x07E0) >> 5; uint16 bb = (couleur & 0x001F); // alpha blender uint16 r = tabAlfa[pr][br][al]; uint16 v = tabAlfa[pv][bv][al]; uint16 b = tabAlfa[pb][bb][al]; couleur = ((r & 0x1F) << 11) + ((v & 0x3F) << 5) + (b & 0x1F); // paint hi = couleur & 0x00FF; lo = (couleur & 0xFF00) >> 8; dest[0] = hi; dest[1] = lo; dest += 2; vx++; sx++; } // saut de ligne ? if (sx >= width) { cmd = 2; } } else { if (cmd > 3) { // CMD_PAINT = $04; // afficher les prochains pixels en mode non alpha 04.[00.00] 05.[00.00][00.00] FF.[00.00]...[00.00] uint16 nb = cmd - 3; for (uint i = 0; i < nb; i++) { uint8 hi = buffer[offset++]; uint8 lo = buffer[offset++]; uint16 couleur = (lo << 8) + hi; couleur = couleur & colorisation; hi = couleur & 0x00FF; lo = (couleur & 0xFF00) >> 8; dest[0] = hi; dest[1] = lo; dest += 2; vx++; sx++; } // saut de ligne ? if (sx >= width) { cmd = 2; } } } if (cmd == 2) { // CMD_NEXT_Y = $02; // passer à la ligne suivante 02 vx = x; vy++; sx = 0; sy++; if ((vy >= maxY) || (sy >= height)) { cmd = 0; // fin } else { // recalage dest = savDest; dest += vx * 2; dest += vy * maxX2; } } } } else { // avec clipping while (cmd != 0) { cmd = buffer[offset++]; if (cmd == 1) { // CMD_INC_X = $01; // décaler de xx pixels 01.FF uint8 nb = buffer[offset++]; vx += nb; sx += nb; // recalage dest = savDest; if (vx > 0) { dest += vx * 2; } if (vy > 0) { dest += vy * maxX2; } // saut de ligne ? if (sx >= width) { cmd = 2; } } if (cmd == 3) { // CMD_ALPHA = $03; // afficher les xx prochains pixels en mode alpha 03.FF [00][00.00] ... [00][00.00] uint8 nb = buffer[offset++]; for (uint i = 0; i < nb; i++) { uint8 al = buffer[offset++]; uint8 hi = buffer[offset++]; uint8 lo = buffer[offset++]; // pour l'instant on ne fait qu'afficher if ((vx >= 0) && (vy >=0) && (vx < maxX) /*&& (vy < maxY)*/) { // composantes du pixel Hi[VVVB BBBB] Lo[RRRR RVVV] -> Lo[RRRR RVVV] Hi[VVVB BBBB] uint16 couleur = (lo << 8) + hi; couleur = couleur & colorisation; uint16 pr = (couleur & 0xF800) >> 11; uint16 pv = (couleur & 0x07E0) >> 5; uint16 pb = (couleur & 0x001F); // composantes du background couleur = (dest[1] << 8) + dest[0]; uint16 br = (couleur & 0xF800) >> 11; uint16 bv = (couleur & 0x07E0) >> 5; uint16 bb = (couleur & 0x001F); // alpha blender uint16 r = tabAlfa[pr][br][al]; uint16 v = tabAlfa[pv][bv][al]; uint16 b = tabAlfa[pb][bb][al]; couleur = ((r & 0x1F) << 11) + ((v & 0x3F) << 5) + (b & 0x1F); // paint hi = couleur & 0x00FF; lo = (couleur & 0xFF00) >> 8; dest[0] = hi; dest[1] = lo; dest += 2; } vx++; sx++; } // saut de ligne ? if (sx >= width) { cmd = 2; } } else { if (cmd > 3) { // CMD_PAINT = $04; // afficher les prochains pixels en mode non alpha 04.[00.00] 05.[00.00][00.00] FF.[00.00]...[00.00] uint8 nb = cmd - 3; for (uint i = 0; i < nb; i++) { uint8 hi = buffer[offset++]; uint8 lo = buffer[offset++]; if ((vx >= 0) && (vy >=0) && (vx < maxX) /*&& (vy < maxY)*/) { uint16 couleur = (lo << 8) + hi; couleur = couleur & colorisation; hi = couleur & 0x00FF; lo = (couleur & 0xFF00) >> 8; dest[0] = hi; dest[1] = lo; dest += 2; } vx++; sx++; } // saut de ligne ? if (sx >= width) { cmd = 2; } } } if (cmd == 2) { // CMD_NEXT_Y = $02; // passer à la ligne suivante 02 vx = x; vy++; sx = 0; sy++; if ((vy >= maxY) || (sy >= height)) { cmd = 0; // fin } else { // recalage dest = savDest; if (vx > 0) { dest += vx * 2; } if (vy > 0) { dest += vy * maxX2; } } } } } } else { // pas de colorisation if ((vx >= 0) && (vy >= 0) && (vx + width < maxX) && (vy + height < maxY)) { // pas de clipping while (cmd != 0) { cmd = buffer[offset++]; if (cmd == 1) { // CMD_INC_X = $01; // décaler de xx pixels 01.FF uint8 nb = buffer[offset++]; vx += nb; sx += nb; // recalage dest = savDest; dest += vx * 2; dest += vy * maxX2; // saut de ligne ? if (sx >= width) { cmd = 2; } } if (cmd == 3) { // CMD_ALPHA = $03; // afficher les xx prochains pixels en mode alpha 03.FF [00][00.00] ... [00][00.00] uint8 nb = buffer[offset++]; for (uint i = 0; i < nb; i++) { uint8 al = buffer[offset++]; uint8 hi = buffer[offset++]; uint8 lo = buffer[offset++]; // pour l'instant on ne fait qu'afficher // composantes du pixel Hi[VVVB BBBB] Lo[RRRR RVVV] -> Lo[RRRR RVVV] Hi[VVVB BBBB] uint16 couleur = (lo << 8) + hi; uint16 pr = (couleur & 0xF800) >> 11; uint16 pv = (couleur & 0x07E0) >> 5; uint16 pb = (couleur & 0x001F); // composantes du background couleur = (dest[1] << 8) + dest[0]; uint16 br = (couleur & 0xF800) >> 11; uint16 bv = (couleur & 0x07E0) >> 5; uint16 bb = (couleur & 0x001F); // alpha blender uint16 r = tabAlfa[pr][br][al]; uint16 v = tabAlfa[pv][bv][al]; uint16 b = tabAlfa[pb][bb][al]; couleur = ((r & 0x1F) << 11) + ((v & 0x3F) << 5) + (b & 0x1F); // paint hi = couleur & 0x00FF; lo = (couleur & 0xFF00) >> 8; dest[0] = hi; dest[1] = lo; dest += 2; vx++; sx++; } // saut de ligne ? if (sx >= width) { cmd = 2; } } else { if (cmd > 3) { // CMD_PAINT = $04; // afficher les prochains pixels en mode non alpha 04.[00.00] 05.[00.00][00.00] FF.[00.00]...[00.00] uint16 nb = (cmd - 3) * 2; memcpy(dest, &buffer[offset], nb); dest += nb; offset += nb; vx += cmd - 3; sx += cmd - 3; // saut de ligne ? if (sx >= width) { cmd = 2; } } } if (cmd == 2) { // CMD_NEXT_Y = $02; // passer à la ligne suivante 02 vx = x; vy++; sx = 0; sy++; if ((vy >= maxY) || (sy >= height)) { cmd = 0; // fin } else { // recalage dest = savDest; dest += vx * 2; dest += vy * maxX2; } } } } else { // avec clipping while (cmd != 0) { cmd = buffer[offset++]; if (cmd == 1) { // CMD_INC_X = $01; // décaler de xx pixels 01.FF uint8 nb = buffer[offset++]; vx += nb; sx += nb; // recalage dest = savDest; if (vx > 0) { dest += vx * 2; } if (vy > 0) { dest += vy * maxX2; } // saut de ligne ? if (sx >= width) { cmd = 2; } } if (cmd == 3) { // CMD_ALPHA = $03; // afficher les xx prochains pixels en mode alpha 03.FF [00][00.00] ... [00][00.00] uint8 nb = buffer[offset++]; for (uint i = 0; i < nb; i++) { uint8 al = buffer[offset++]; uint8 hi = buffer[offset++]; uint8 lo = buffer[offset++]; // pour l'instant on ne fait qu'afficher if ((vx >= 0) && (vy >=0) && (vx < maxX) /*&& (vy < maxY)*/) { // composantes du pixel Hi[VVVB BBBB] Lo[RRRR RVVV] -> Lo[RRRR RVVV] Hi[VVVB BBBB] uint16 couleur = (lo << 8) + hi; uint16 pr = (couleur & 0xF800) >> 11; uint16 pv = (couleur & 0x07E0) >> 5; uint16 pb = (couleur & 0x001F); // composantes du background couleur = (dest[1] << 8) + dest[0]; uint16 br = (couleur & 0xF800) >> 11; uint16 bv = (couleur & 0x07E0) >> 5; uint16 bb = (couleur & 0x001F); // alpha blender uint16 r = tabAlfa[pr][br][al]; uint16 v = tabAlfa[pv][bv][al]; uint16 b = tabAlfa[pb][bb][al]; couleur = ((r & 0x1F) << 11) + ((v & 0x3F) << 5) + (b & 0x1F); // paint hi = couleur & 0x00FF; lo = (couleur & 0xFF00) >> 8; dest[0] = hi; dest[1] = lo; dest += 2; } vx++; sx++; } // saut de ligne ? if (sx >= width) { cmd = 2; } } else { if (cmd > 3) { // CMD_PAINT = $04; // afficher les prochains pixels en mode non alpha 04.[00.00] 05.[00.00][00.00] FF.[00.00]...[00.00] uint8 nb = cmd - 3; for (uint i = 0; i < nb; i++) { uint8 hi = buffer[offset++]; uint8 lo = buffer[offset++]; if ((vx >= 0) && (vy >=0) && (vx < maxX) /*&& (vy < maxY)*/) { dest[0] = hi; dest[1] = lo; dest += 2; } vx++; sx++; } // saut de ligne ? if (sx >= width) { cmd = 2; } } } if (cmd == 2) { // CMD_NEXT_Y = $02; // passer à la ligne suivante 02 vx = x; vy++; sx = 0; sy++; if ((vy >= maxY) || (sy >= height)) { cmd = 0; // fin } else { // recalage dest = savDest; if (vx > 0) { dest += vx * 2; } if (vy > 0) { dest += vy * maxX2; } } } } } } } else { // pas de colorisation if ((vx >= 0) && (vy >= 0) && (vx + width < maxX) && (vy + height < maxY)) { // pas de clipping while (cmd != 0) { cmd = buffer[offset++]; if (cmd == 1) { // CMD_INC_X = $01; // décaler de xx pixels 01.FF uint8 nb = buffer[offset++]; vx += nb; sx += nb; // recalage dest = savDest; dest += vx * 2; dest += vy * maxX2; // saut de ligne ? if (sx >= width) { cmd = 2; } } if (cmd == 3) { // CMD_ALPHA = $03; // afficher les xx prochains pixels en mode alpha 03.FF [00][00.00] ... [00][00.00] uint8 nb = buffer[offset++]; for (uint i = 0; i < nb; i++) { uint8 al = buffer[offset++]; uint8 hi = buffer[offset++]; uint8 lo = buffer[offset++]; // pour l'instant on ne fait qu'afficher // composantes du pixel Hi[VVVB BBBB] Lo[RRRR RVVV] -> Lo[RRRR RVVV] Hi[VVVB BBBB] uint16 couleur = (lo << 8) + hi; uint16 pr = (couleur & 0xF800) >> 11; uint16 pv = (couleur & 0x07E0) >> 5; uint16 pb = (couleur & 0x001F); // composantes du background couleur = (dest[1] << 8) + dest[0]; uint16 br = (couleur & 0xF800) >> 11; uint16 bv = (couleur & 0x07E0) >> 5; uint16 bb = (couleur & 0x001F); // alpha blender uint16 r = trunc(((al * pr) + ((0xFF - al) * br)) / 0xFF); uint16 v = trunc(((al * pv) + ((0xFF - al) * bv)) / 0xFF); uint16 b = trunc(((al * pb) + ((0xFF - al) * bb)) / 0xFF); couleur = ((r & 0x1F) << 11) + ((v & 0x3F) << 5) + (b & 0x1F); // paint hi = couleur & 0x00FF; lo = (couleur & 0xFF00) >> 8; dest[0] = hi; dest[1] = lo; dest += 2; vx++; sx++; } // saut de ligne ? if (sx >= width) { cmd = 2; } } else { if (cmd > 3) { // CMD_PAINT = $04; // afficher les prochains pixels en mode non alpha 04.[00.00] 05.[00.00][00.00] FF.[00.00]...[00.00] uint16 nb = (cmd - 3) * 2; memcpy(dest, &buffer[offset], nb); dest += nb; offset += nb; vx += cmd - 3; sx += cmd - 3; // saut de ligne ? if (sx >= width) { cmd = 2; } } } if (cmd == 2) { // CMD_NEXT_Y = $02; // passer à la ligne suivante 02 vx = x; vy++; sx = 0; sy++; if ((vy >= maxY) || (sy >= height)) { cmd = 0; // fin } else { // recalage dest = savDest; dest += vx * 2; dest += vy * maxX2; } } } } else { // avec clipping while (cmd != 0) { cmd = buffer[offset++]; if (cmd == 1) { // CMD_INC_X = $01; // décaler de xx pixels 01.FF uint8 nb = buffer[offset++]; vx += nb; sx += nb; // recalage dest = savDest; if (vx > 0) { dest += vx * 2; } if (vy > 0) { dest += vy * maxX2; } // saut de ligne ? if (sx >= width) { cmd = 2; } } if (cmd == 3) { // CMD_ALPHA = $03; // afficher les xx prochains pixels en mode alpha 03.FF [00][00.00] ... [00][00.00] uint8 nb = buffer[offset++]; for (uint i = 0; i < nb; i++) { uint8 al = buffer[offset++]; uint8 hi = buffer[offset++]; uint8 lo = buffer[offset++]; // pour l'instant on ne fait qu'afficher if ((vx >= 0) && (vy >=0) && (vx < maxX) /*&& (vy < maxY)*/) { // composantes du pixel Hi[VVVB BBBB] Lo[RRRR RVVV] -> Lo[RRRR RVVV] Hi[VVVB BBBB] uint16 couleur = (lo << 8) + hi; uint16 pr = (couleur & 0xF800) >> 11; uint16 pv = (couleur & 0x07E0) >> 5; uint16 pb = (couleur & 0x001F); // composantes du background couleur = (dest[1] << 8) + dest[0]; uint16 br = (couleur & 0xF800) >> 11; uint16 bv = (couleur & 0x07E0) >> 5; uint16 bb = (couleur & 0x001F); // alpha blender uint16 r = trunc(((al * pr) + ((0xFF - al) * br)) / 0xFF); uint16 v = trunc(((al * pv) + ((0xFF - al) * bv)) / 0xFF); uint16 b = trunc(((al * pb) + ((0xFF - al) * bb)) / 0xFF); couleur = ((r & 0x1F) << 11) + ((v & 0x3F) << 5) + (b & 0x1F); // paint hi = couleur & 0x00FF; lo = (couleur & 0xFF00) >> 8; dest[0] = hi; dest[1] = lo; dest += 2; } vx++; sx++; } // saut de ligne ? if (sx >= width) { cmd = 2; } } else { if (cmd > 3) { // CMD_PAINT = $04; // afficher les prochains pixels en mode non alpha 04.[00.00] 05.[00.00][00.00] FF.[00.00]...[00.00] uint8 nb = cmd - 3; for (uint i = 0; i < nb; i++) { uint8 hi = buffer[offset++]; uint8 lo = buffer[offset++]; if ((vx >= 0) && (vy >=0) && (vx < maxX) /*&& (vy < maxY)*/) { dest[0] = hi; dest[1] = lo; dest += 2; } vx++; sx++; } // saut de ligne ? if (sx >= width) { cmd = 2; } } } if (cmd == 2) { // CMD_NEXT_Y = $02; // passer à la ligne suivante 02 vx = x; vy++; sx = 0; sy++; if ((vy >= maxY) || (sy >= height)) { cmd = 0; // fin } else { // recalage dest = savDest; if (vx > 0) { dest += vx * 2; } if (vy > 0) { dest += vy * maxX2; } } } } } } } return width; } uint16 afficherGrafx_internalMask(unsigned char *buffer, unsigned char *mask, uint32 start, uint32 startMask, sint16 x, sint16 y, uint8 ou) { unsigned char *dest = backScr; uint16 maxX = 320; uint16 maxY = 240; switch (ou) { case SCREEN_SHADOW: dest = shadows; maxX = 640; maxY = 413; break; case SCREEN_WAGON: dest = usmap; maxX = 640; maxY = 413; break; case SCREEN_SELECT: dest = selection; maxX = 640; maxY = 413; break; case SCREEN_DIRECT: dest = SCREEN_BASE_ADDRESS; maxX = 320; maxY = 240; break; } unsigned char *savDest = dest; uint16 maxX2 = maxX * 2; if (x > 0) { dest += x * 2; } if (y > 0) { dest += y * maxX2; } uint32 offset = start; uint32 offsetMask = startMask; uint8 b1 = buffer[offset++]; uint8 b2 = buffer[offset++]; uint16 width = (b1 << 8) + b2; b1 = buffer[offset++]; b2 = buffer[offset++]; uint16 height = (b1 << 8) + b2; uint8 alpha = buffer[offset++]; if ((x >= maxX) || (y >= maxY) || (x + width < 0) || (y + height < 0)) { // hors écran return 0; } if (alpha == 0) { unsigned char *src = &buffer[offset]; // pas de gestion de l'alpha blending ni de pixels invisibles // premier décalage sur les x if (x < 0) { src -= x * 2; } // calcul de la width affichée uint16 width_affichee = width; if (x < 0) { width_affichee += x; } if (x + width >= maxX) { width_affichee -= x + width - maxX; } // calcul du nombre de byte à sauter après chaque ligne uint16 srcDecalX = width * 2; width_affichee = width_affichee * 2; // calcul du nombre de ligne à afficher uint16 height_affichee = height; if (y < 0) { height_affichee += y; } if (y + height >= maxY) { height_affichee -= y + height - maxY; } // envoyer la puré for (uint ligne = 0; ligne < height_affichee; ligne ++) { memcpy(&dest[0], &src[0], width_affichee); src += srcDecalX; dest += maxX2; } } else { // alpha blending et pixels invisibles sint16 vx = x; // virtual x sur l'écran sint16 vy = y; // virtual y sur l'écran uint16 sx = 0; // virtual x sur le grafx uint16 sy = 0; // virtual y sur le grafx uint8 cmd = 1; if ((vx >= 0) && (vy >= 0) && (vx + width < maxX) && (vy + height < maxY)) { // pas de clipping while (cmd != 0) { cmd = buffer[offset++]; if (cmd == 1) { // CMD_INC_X = $01; // décaler de xx pixels 01.FF uint8 nb = buffer[offset++]; vx += nb; sx += nb; offsetMask += nb; // recalage dest = savDest; dest += vx * 2; dest += vy * maxX2; // saut de ligne ? if (sx >= width) { cmd = 2; } } if (cmd == 3) { // CMD_ALPHA = $03; // afficher les xx prochains pixels en mode alpha 03.FF [00][00.00] ... [00][00.00] uint8 nb = buffer[offset++]; for (uint i = 0; i < nb; i++) { uint8 al = mask[offsetMask++]; offset++; uint8 hi = buffer[offset++]; uint8 lo = buffer[offset++]; // pour l'instant on ne fait qu'afficher // composantes du pixel Hi[VVVB BBBB] Lo[RRRR RVVV] -> Lo[RRRR RVVV] Hi[VVVB BBBB] uint16 couleur = (lo << 8) + hi; uint16 pr = (couleur & 0xF800) >> 11; uint16 pv = (couleur & 0x07E0) >> 5; uint16 pb = (couleur & 0x001F); // composantes du background couleur = (dest[1] << 8) + dest[0]; uint16 br = (couleur & 0xF800) >> 11; uint16 bv = (couleur & 0x07E0) >> 5; uint16 bb = (couleur & 0x001F); // alpha blender uint16 r = tabAlfa[pr][br][al]; uint16 v = tabAlfa[pv][bv][al]; uint16 b = tabAlfa[pb][bb][al]; couleur = ((r & 0x1F) << 11) + ((v & 0x3F) << 5) + (b & 0x1F); // paint hi = couleur & 0x00FF; lo = (couleur & 0xFF00) >> 8; dest[0] = hi; dest[1] = lo; dest += 2; vx++; sx++; } // saut de ligne ? if (sx >= width) { cmd = 2; } } else { if (cmd > 3) { // CMD_PAINT = $04; // afficher les prochains pixels en mode non alpha 04.[00.00] 05.[00.00][00.00] FF.[00.00]...[00.00] uint16 nb = cmd - 3; for (uint i = 0; i < nb; i++) { uint8 al = mask[offsetMask++]; uint8 hi = buffer[offset++]; uint8 lo = buffer[offset++]; // pour l'instant on ne fait qu'afficher // composantes du pixel Hi[VVVB BBBB] Lo[RRRR RVVV] -> Lo[RRRR RVVV] Hi[VVVB BBBB] uint16 couleur = (lo << 8) + hi; uint16 pr = (couleur & 0xF800) >> 11; uint16 pv = (couleur & 0x07E0) >> 5; uint16 pb = (couleur & 0x001F); // composantes du background couleur = (dest[1] << 8) + dest[0]; uint16 br = (couleur & 0xF800) >> 11; uint16 bv = (couleur & 0x07E0) >> 5; uint16 bb = (couleur & 0x001F); // alpha blender uint16 r = tabAlfa[pr][br][al]; uint16 v = tabAlfa[pv][bv][al]; uint16 b = tabAlfa[pb][bb][al]; couleur = ((r & 0x1F) << 11) + ((v & 0x3F) << 5) + (b & 0x1F); // paint hi = couleur & 0x00FF; lo = (couleur & 0xFF00) >> 8; dest[0] = hi; dest[1] = lo; dest += 2; vx++; sx++; } // saut de ligne ? if (sx >= width) { cmd = 2; } } } if (cmd == 2) { // CMD_NEXT_Y = $02; // passer à la ligne suivante 02 vx = x; vy++; sx = 0; sy++; offsetMask = startMask; offsetMask += sy * width; if ((vy >= maxY) || (sy >= height)) { cmd = 0; // fin } else { // recalage dest = savDest; dest += vx * 2; dest += vy * maxX2; } } } } else { // avec clipping while (cmd != 0) { cmd = buffer[offset++]; if (cmd == 1) { // CMD_INC_X = $01; // décaler de xx pixels 01.FF uint8 nb = buffer[offset++]; vx += nb; sx += nb; offsetMask += nb; // recalage dest = savDest; if (vx > 0) { dest += vx * 2; } if (vy > 0) { dest += vy * maxX2; } // saut de ligne ? if (sx >= width) { cmd = 2; } } if (cmd == 3) { // CMD_ALPHA = $03; // afficher les xx prochains pixels en mode alpha 03.FF [00][00.00] ... [00][00.00] uint8 nb = buffer[offset++]; for (uint i = 0; i < nb; i++) { offset++; uint8 al = mask[offsetMask++]; uint8 hi = buffer[offset++]; uint8 lo = buffer[offset++]; // pour l'instant on ne fait qu'afficher if ((vx >= 0) && (vy >=0) && (vx < maxX) /*&& (vy < maxY)*/) { // composantes du pixel Hi[VVVB BBBB] Lo[RRRR RVVV] -> Lo[RRRR RVVV] Hi[VVVB BBBB] uint16 couleur = (lo << 8) + hi; uint16 pr = (couleur & 0xF800) >> 11; uint16 pv = (couleur & 0x07E0) >> 5; uint16 pb = (couleur & 0x001F); // composantes du background couleur = (dest[1] << 8) + dest[0]; uint16 br = (couleur & 0xF800) >> 11; uint16 bv = (couleur & 0x07E0) >> 5; uint16 bb = (couleur & 0x001F); // alpha blender uint16 r = tabAlfa[pr][br][al]; uint16 v = tabAlfa[pv][bv][al]; uint16 b = tabAlfa[pb][bb][al]; couleur = ((r & 0x1F) << 11) + ((v & 0x3F) << 5) + (b & 0x1F); // paint hi = couleur & 0x00FF; lo = (couleur & 0xFF00) >> 8; dest[0] = hi; dest[1] = lo; dest += 2; } vx++; sx++; } // saut de ligne ? if (sx >= width) { cmd = 2; } } else { if (cmd > 3) { // CMD_PAINT = $04; // afficher les prochains pixels en mode non alpha 04.[00.00] 05.[00.00][00.00] FF.[00.00]...[00.00] uint8 nb = cmd - 3; for (uint i = 0; i < nb; i++) { uint8 al = mask[offsetMask++]; uint8 hi = buffer[offset++]; uint8 lo = buffer[offset++]; // pour l'instant on ne fait qu'afficher if ((vx >= 0) && (vy >=0) && (vx < maxX) /*&& (vy < maxY)*/) { // composantes du pixel Hi[VVVB BBBB] Lo[RRRR RVVV] -> Lo[RRRR RVVV] Hi[VVVB BBBB] uint16 couleur = (lo << 8) + hi; uint16 pr = (couleur & 0xF800) >> 11; uint16 pv = (couleur & 0x07E0) >> 5; uint16 pb = (couleur & 0x001F); // composantes du background couleur = (dest[1] << 8) + dest[0]; uint16 br = (couleur & 0xF800) >> 11; uint16 bv = (couleur & 0x07E0) >> 5; uint16 bb = (couleur & 0x001F); // alpha blender uint16 r = tabAlfa[pr][br][al]; uint16 v = tabAlfa[pv][bv][al]; uint16 b = tabAlfa[pb][bb][al]; couleur = ((r & 0x1F) << 11) + ((v & 0x3F) << 5) + (b & 0x1F); // paint hi = couleur & 0x00FF; lo = (couleur & 0xFF00) >> 8; dest[0] = hi; dest[1] = lo; dest += 2; } vx++; sx++; } // saut de ligne ? if (sx >= width) { cmd = 2; } } } if (cmd == 2) { // CMD_NEXT_Y = $02; // passer à la ligne suivante 02 vx = x; vy++; sx = 0; sy++; offsetMask = startMask; offsetMask += sy * width; if ((vy >= maxY) || (sy >= height)) { cmd = 0; // fin } else { // recalage dest = savDest; if (vx > 0) { dest += vx * 2; } if (vy > 0) { dest += vy * maxX2; } } } } } } return width; } uint16 afficherGrafx_buffer(unsigned char *buffer, sint16 x, sint16 y, uint8 ou, uint16 colorisation) { return afficherGrafx_internal(buffer, 0, x, y, ou, colorisation, true); } uint16 afficherGrafx_bufferSlow(unsigned char *buffer, sint16 x, sint16 y, uint8 ou, uint16 colorisation) { return afficherGrafx_internal(buffer, 0, x, y, ou, colorisation, false); } uint16 afficherGrafx_bufferMask(unsigned char *buffer, unsigned char *mask, uint32 startMask, sint16 x, sint16 y, uint8 ou) { return afficherGrafx_internalMask(buffer, mask, 0, startMask, x, y, ou); } uint16 afficherGrafx_ram(uint16 num, sint16 x, sint16 y, uint8 ou, uint16 colorisation) { grafx_positionner_ram(num); return afficherGrafx_internal(grafx, grafx_offcur_ram, x, y, ou, colorisation, true); } // grafx -- FILE uint32 grafx_read3_file() { uint8 b1; uint8 b2; uint8 b3; fread(&b1, sizeof(uint8), 1, ttrficgrafx); fread(&b2, sizeof(uint8), 1, ttrficgrafx); fread(&b3, sizeof(uint8), 1, ttrficgrafx); return (b1 << 16) + (b2 << 8) + b3; } uint16 grafx_read2_file() { uint8 b1; uint8 b2; fread(&b1, sizeof(uint8), 1, ttrficgrafx); fread(&b2, sizeof(uint8), 1, ttrficgrafx); return (b1 << 8) + b2; } uint8 grafx_read1_file() { uint8 b1; fread(&b1, sizeof(uint8), 1, ttrficgrafx); return b1; } void grafx_set_position_file(uint32 offset) { fseek(ttrficgrafx, offset, SEEK_SET); } void loadGrafx_file() { char *nomfic = getCheminFichier("grafx/dataf.tns"); ttrficgrafx = fopen(nomfic, "rb"); if(!ttrficgrafx) { #ifdef DEBUG puts("fichier introuvable"); puts(nomfic); #endif return; } grafx_set_position_file(0); grafx_offset_file = grafx_read3_file(); } void doneGrafx_file() { fclose(ttrficgrafx); } uint32 grafx_positionner_file(uint16 num) { grafx_set_position_file(grafx_offset_file + num * 3); uint32 grafx_offcur_file = grafx_read3_file(); grafx_set_position_file(grafx_offcur_file); return grafx_offcur_file; } uint16 afficherGrafx_file(uint16 num, sint16 x, sint16 y, uint8 ou, uint16 colorisation) { // passer par le last buffer if (lastBufferNum != num) { if (lastBufferNum <= FILE_MAX_GRAFX) { free(lastBuffer); } lastBufferNum = num; uint32 taille = chargerTaille_file(num); lastBuffer = malloc(taille); chargerGrafx_file(lastBuffer, num, taille); } return afficherGrafx_buffer(lastBuffer, x, y, ou, colorisation); } uint16 afficherGrafx_ramMask(uint16 num, uint16 numMask, sint16 x, sint16 y, uint8 ou) { grafx_positionner_ram(num); uint32 offset = grafx_offcur_ram; grafx_positionner_ram(numMask); return afficherGrafx_internalMask(grafx, grafx, offset, grafx_offcur_ram, x, y, ou); } void afficherCarte(uint16 x, uint16 y, uint16 maxX, uint8 maxY) { // on affiche un block de 292x220 en 0x0 unsigned char *dest = backScr; unsigned char *src = selection; uint16 mx = maxX * 2; src += (x * 2) + (y * 640 * 2); for (uint8 j = 0; j <= maxY; j++) { memcpy(&dest[0], &src[0], mx); src += 640 * 2; dest += 320 * 2; } } void afficherMiniCarte(bool inGame) { // on affiche un block de 320x206 en 0x17 640x413 unsigned char *dest = SCREEN_BASE_ADDRESS; unsigned char *src = selection; if (inGame) { memset(dest, 0, 17 * 320 * 2); } dest += 17 * 320 * 2; for (uint8 j = 0; j < 207; j++) { for (uint16 i = 0; i < 320; i++) { uint16 c1 = (src[1] << 8) + src[0]; uint16 c2 = (src[3] << 8) + src[2]; uint16 c3 = (src[1281] << 8) + src[1280]; uint16 c4 = (src[1283] << 8) + src[1282]; uint32 r = (((c1 & 0xF800) >> 11) + ((c2 & 0xF800) >> 11) + ((c3 & 0xF800) >> 11) + ((c4 & 0xF800) >> 11)) >> 2; uint32 v = (((c1 & 0x07E0) >> 5) + ((c2 & 0x07E0) >> 5) + ((c3 & 0x07E0) >> 5) + ((c4 & 0x07E0) >> 5)) >> 2; uint32 b = ((c1 & 0x001F) + (c2 & 0x001F) + (c3 & 0x001F) + (c4 & 0x001F)) >> 2; uint16 couleur = ((r & 0x1F) << 11) + ((v & 0x3F) << 5) + (b & 0x1F); uint8 hi = couleur & 0x00FF; uint8 lo = (couleur & 0xFF00) >> 8; dest[0] = hi; dest[1] = lo; dest += 2; src += 4; // 1 pixel sur 2 } src += 640 * 2; // 1 ligne sur 2 } if (inGame) { memset(dest, 0, 16 * 320 * 2); while (isKeyPressed(KEY_NSPIRE_5)); } } void resetUsMap() { grafx_positionner_file(FILE_USMAP); fread(&shadows[0], 640 * 413 * 2, 1, ttrficgrafx); } void dumperScreen(uint16 num, uint32 size, uint8 ouY) { grafx_positionner_file(num); fread(&backScr[ouY * 320 * 2], size, 1, ttrficgrafx); } void loadUsMap() { usmap = (unsigned char *)malloc(640 * 413 * 2); shadows = (unsigned char *)malloc(640 * 413 * 2); selection = (unsigned char *)malloc(640 * 413 * 2); resetUsMap(); } void doneUsMap() { free(usmap); free(shadows); free(selection); } void effacerUsMap() { // recopie shadows dans usmap memcpy(usmap, shadows, 640 * 413 * 2); } void effacerMapSelection() { // recopie usmap dans selection memcpy(selection, usmap, 640 * 413 * 2); } // Global void initGlobal(char *argv) { char *test = argv; uint8 nb = 0; for (uint8 i=0; i= 640) { for (uint8 i=y0; i<=y1; i++) { memset(dest,0,2*(x1-x0+1)); dest+=320*2; } return; } src += ((x+x0) * 2) + ((y+y0) * 640 * 2); uint16 decSrc = (639 - (x1 - x0)) * 2; uint16 decDest = (319 - (x1 - x0)) * 2; for (uint8 j = y0; j <= y1; j++) { for (uint16 i = x0; i <= x1; i++) { if ((x + i >= 640) || (y + j > 412)) { dest[0] = 0; dest[1] = 0; } else { uint16 couleur = (src[1] << 8) + src[0]; uint16 r = (couleur & 0xF800) >> 11; uint16 v = (couleur & 0x07E0) >> 5; uint16 b = (couleur & 0x001F); couleur = ((r >> 1) << 11) + ((v >> 1) << 5) + (b >> 1); uint8 hi = couleur & 0x00FF; uint8 lo = (couleur & 0xFF00) >> 8; dest[0] = hi; dest[1] = lo; } dest += 2; src += 2; } src += decSrc; dest += decDest; } } uint8 routeSousCurseur(uint16 x, uint16 y) { uint32 grafx_offcur_file = grafx_positionner_file(FILE_IDXMAP); grafx_set_position_file(grafx_offcur_file + y * 320 + x); return grafx_read1_file(); } uint16 ecrireGrafxA(char *txt, uint16 ouX, uint8 ouY, uint16 colorisation) { uint16 x = ouX; for (uint8 i=0; i 9) { x = ecrireGrafx0(trunc(nb / 10), x, ouY, colorisation); return ecrireGrafx0(nb % 10, x, ouY, colorisation); } return x + afficherGrafx_ram(RAM_ALFA_0 + nb + 15, x, ouY, SCREEN_WORKING, colorisation); } uint16 taille(uint16 lettre) { grafx_positionner_ram(lettre); return grafx_read2_ram(); } uint16 taillerGrafx0(int nb) { if (nb < 0) { return taille(RAM_ALFA_0 + 44 - 32) + taillerGrafx0(-nb); } if (nb > 9) { return taillerGrafx0(trunc(nb / 10)) + taillerGrafx0(nb % 10); } return taille(RAM_ALFA_0 + nb + 15); } uint32 chargerTaille_file(uint16 num) { grafx_set_position_file(grafx_offset_file + num * 3); uint32 offset1 = grafx_read3_file(); uint32 offset2 = grafx_offset_file; if (num != FILE_MAX_GRAFX) { offset2 = grafx_read3_file(); } return offset2 - offset1; } void chargerGrafx_file(unsigned char *buffer, uint16 num, uint32 taille) { grafx_positionner_file(num); fread(&buffer[0], taille, 1, ttrficgrafx); } void assombrirBackScr() { unsigned char *dest = backScr; for (int i=0; i<320*240; i++) { uint16 couleur = (dest[1] << 8) + dest[0]; uint16 r = (couleur & 0xF800) >> 11; uint16 v = (couleur & 0x07E0) >> 5; uint16 b = (couleur & 0x001F); couleur = ((r >> 1) << 11) + ((v >> 1) << 5) + (b >> 1); uint8 hi = couleur & 0x00FF; uint8 lo = (couleur & 0xFF00) >> 8; dest[0] = hi; dest[1] = lo; dest += 2; } } uint16 ecrireGrafxPhrase(char *txt, uint16 ouX, uint8 ouY, uint8 interligne, uint16 colorisation) { uint16 x = ouX; uint16 y = ouY; uint16 maxi = strlen(txt); for (uint16 i=0; i= 320) { // saut à la ligne x = ouX; y += interligne; } for (uint16 k=i; k<=idx; k++) { lettre = txt[k]; x += afficherGrafx_ram(RAM_ALFA_0 + lettre - 33, x, y, SCREEN_WORKING, colorisation); } i = idx; } } return x; }