From 006f70bb5360371d7bbd5a22e84ff190685ebf68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20Somolinos=20P=C3=A9rez?= Date: Thu, 18 Jul 2019 16:51:37 +0200 Subject: [PATCH] Feature i18n (#21) Traslation subsystem. --- DreeRally.vcxproj | 7 ++ DreeRally.vcxproj.filters | 32 +++++++++ config.c | 11 ++- config.h | 3 + dr.c | 138 +++++++++++++++++++++++++------------- i18n/i18n.c | 78 +++++++++++++++++++++ i18n/i18n.h | 9 +++ lang/langEs.txt | 39 +++++++++++ license/licenseScreen.c | 29 ++++---- menus.c | 17 ++--- translation.c | 15 +++++ translation.h | 7 ++ util/hash.c | 48 +++++++++++++ util/hash.h | 12 ++++ 14 files changed, 376 insertions(+), 69 deletions(-) create mode 100644 i18n/i18n.c create mode 100644 i18n/i18n.h create mode 100644 lang/langEs.txt create mode 100644 translation.c create mode 100644 translation.h create mode 100644 util/hash.c create mode 100644 util/hash.h diff --git a/DreeRally.vcxproj b/DreeRally.vcxproj index 777e4a2..81baedd 100644 --- a/DreeRally.vcxproj +++ b/DreeRally.vcxproj @@ -190,7 +190,9 @@ + + @@ -219,7 +221,9 @@ + + @@ -231,6 +235,9 @@ + + + diff --git a/DreeRally.vcxproj.filters b/DreeRally.vcxproj.filters index ec4ca0f..3af8781 100644 --- a/DreeRally.vcxproj.filters +++ b/DreeRally.vcxproj.filters @@ -58,6 +58,21 @@ {05c38d85-362d-47aa-b0fc-9f32074b7d2e} + + {4f0a99e6-3999-4119-baba-06eba08d0381} + + + {c197791c-9c41-43c1-a016-2e5899a8317b} + + + {46c7b985-1419-4744-b2e6-9dcd3c08789d} + + + {6fe8fa32-7524-4db3-b6db-3284b19f5dce} + + + {de194950-f540-4591-a1a2-4d3cc1d493cd} + @@ -129,6 +144,12 @@ Source Files\blackmarket + + Source Files\i18n + + + Source Files\util + @@ -221,5 +242,16 @@ Header Files\blackmarket + + Header Files\i18n + + + Header Files\util + + + + + Resource Files\lang + \ No newline at end of file diff --git a/config.c b/config.c index 8560f56..7a664c2 100644 --- a/config.c +++ b/config.c @@ -13,11 +13,12 @@ #include "defs.h" #include #include "hof/hallOfFame.h" +#include "i18n/i18n.h" -MainArgs mainArgs = { 0,1,1,1,1 }; +MainArgs mainArgs = { 0,1,1,1,1,NULL }; Configuration configuration; @@ -25,6 +26,8 @@ Configuration configuration; int checkArgs(char * args) { int result = 0; + char delim[] = "="; + char *s; if (strstr(args, "-nosound")) mainArgs.configNoSound = 0; @@ -34,6 +37,12 @@ int checkArgs(char * args) mainArgs.configGL = 0; if (strstr(args, "-smooth")) mainArgs.configSmooth = 0; + if (strstr(args, "-lang=")){ + s = strstr(args, "-lang="); + s = strstr(args, "="); + mainArgs.language = &s[1]; + + } result = strstr(args, "-window"); if (result) diff --git a/config.h b/config.h index 04b787c..629a59a 100644 --- a/config.h +++ b/config.h @@ -1,11 +1,14 @@ #include "hof/hallOfFame.h" + + typedef struct MainArgs { int configNoSound; int configSmooth; int configGL; int configWindow; int configNoSoundEffect; + char * language; } MainArgs; typedef struct Configuration { diff --git a/dr.c b/dr.c index 9282772..b372e0b 100644 --- a/dr.c +++ b/dr.c @@ -30,6 +30,7 @@ #include "race/powerup.h" #include "race/terrain.h" #include "race/3dSystem.h" +#include "i18n/i18n.h" //#include "fmod.h" //#include "system_file.h" //#include "Music.h" @@ -9221,7 +9222,7 @@ void calculateUserMovements_40BAB0() int v45; // edi@85 int v46; // edi@89 int v47; // edi@93 - unsigned __int64 v48; // rax@97 + int v48; // rax@97 //TODO FIX unsigned int64 int v49; // edi@97 int v50; // eax@97 int v51; // edx@97 @@ -9455,12 +9456,18 @@ void calculateUserMovements_40BAB0() dword_4AA924 = 0; raceParticipantIngame[ currentDriverSelectedIndex_503518].advanceXAxis_4A7E5C = (v88 + v86) * v34; raceParticipantIngame[ currentDriverSelectedIndex_503518].advanceYAxis_4A7E60 = (v27 + v25) * v34; + if(raceParticipantIngame[ currentDriverSelectedIndex_503518].advanceYAxis_4A7E60<-100 || raceParticipantIngame[ currentDriverSelectedIndex_503518].advanceYAxis_4A7E60>100) + raceParticipantIngame[ currentDriverSelectedIndex_503518].advanceYAxis_4A7E60=raceParticipantIngame[ currentDriverSelectedIndex_503518].advanceYAxis_4A7E60; v35 = flt_464F70; LODWORD(flt_464F70) = 0; raceParticipantIngame[ currentDriverSelectedIndex_503518].advanceXAxis_4A7E5C = v35 + raceParticipantIngame[ currentDriverSelectedIndex_503518].advanceXAxis_4A7E5C; raceParticipantIngame[ currentDriverSelectedIndex_503518].advanceYAxis_4A7E60 = v23 + raceParticipantIngame[ currentDriverSelectedIndex_503518].advanceYAxis_4A7E60; + if(raceParticipantIngame[ currentDriverSelectedIndex_503518].advanceYAxis_4A7E60<-100 || raceParticipantIngame[ currentDriverSelectedIndex_503518].advanceYAxis_4A7E60>100) + raceParticipantIngame[ currentDriverSelectedIndex_503518].advanceYAxis_4A7E60=raceParticipantIngame[ currentDriverSelectedIndex_503518].advanceYAxis_4A7E60; raceParticipantIngame[ currentDriverSelectedIndex_503518].advanceXAxis_4A7E5C = (raceParticipantIngame[currentDriverSelectedIndex_503518].unk_4A7DFC) + raceParticipantIngame[ currentDriverSelectedIndex_503518].advanceXAxis_4A7E5C; raceParticipantIngame[ currentDriverSelectedIndex_503518].advanceYAxis_4A7E60 = (raceParticipantIngame[currentDriverSelectedIndex_503518].unk_4A7E00) + raceParticipantIngame[ currentDriverSelectedIndex_503518].advanceYAxis_4A7E60; + if(raceParticipantIngame[ currentDriverSelectedIndex_503518].advanceYAxis_4A7E60<-100 || raceParticipantIngame[ currentDriverSelectedIndex_503518].advanceYAxis_4A7E60>100) + raceParticipantIngame[ currentDriverSelectedIndex_503518].advanceYAxis_4A7E60=raceParticipantIngame[ currentDriverSelectedIndex_503518].advanceYAxis_4A7E60; raceParticipantIngame[ currentDriverSelectedIndex_503518].dword_4A7DC4 = sin(( raceParticipantIngame[v0].carAngle_4A7DAC + 206.0) * 0.01745329251994444) * 18.0 + raceParticipantIngame[ currentDriverSelectedIndex_503518].advanceXAxis_4A7E5C; raceParticipantIngame[ currentDriverSelectedIndex_503518].dword_4A7DC8 = cos(( raceParticipantIngame[v0].carAngle_4A7DAC + 206.0) * 0.01745329251994444) * 14.999994 @@ -9550,7 +9557,9 @@ void calculateUserMovements_40BAB0() //fix porque esto no pude ser asi v50=0; } - else {v50 = sub_43BFE0( + else { + + v50 = sub_43BFE0( (int)((char *)participantCarBpk_5034FC + v49), (int)((char *)v41 +(unsigned __int64)raceParticipantIngame[currentDriverSelectedIndex_503518].advanceXAxis_4A7E5C+ @@ -9561,7 +9570,7 @@ void calculateUserMovements_40BAB0() v51 = currentDriverSelectedIndex_503518; - v52 = 864 * currentDriverSelectedIndex_503518; + v52 = currentDriverSelectedIndex_503518; raceParticipantIngame[currentDriverSelectedIndex_503518].dword_4A7D14= v50; if ( v50 >= 4 ) @@ -9574,15 +9583,15 @@ void calculateUserMovements_40BAB0() } v53 = v50; v54 = dword_4A7A40; - dword_4A7E90[v52 / 4] = v53; + dword_4A7E90[v52] = v53; v55 = dword_508D20 - 20; - dword_4A7E74[v52 / 4] = v54 - 20; - dword_4A7E78[v52 / 4] = v55; - if ( dword_4A7E94[v52 / 4] > 3 ) + dword_4A7E74[v52] = v54 - 20; + dword_4A7E78[v52] = v55; + if ( dword_4A7E94[v52] > 3 ) { raceParticipantIngame[ v52].carVelocity_4A7DB0 = 0; - dword_4A7E6C[v52 / 4] = 1; - dword_4A7E70[v52 / 4] = 0; + dword_4A7E6C[v52] = 1; + dword_4A7E70[v52] = 0; v56 = 0; //esto huele a derrapes @@ -9592,19 +9601,19 @@ void calculateUserMovements_40BAB0() { if ( v56 >= 100 ) break; - v57 = dword_4A7E6C[216 * v51]; + v57 = dword_4A7E6C[ v51]; ++v56; *((float *)&unk_4A7E64 + 216 * v51) = (double)(rand() % (2 * v57 + 1) - v57); - v58 = 864 * currentDriverSelectedIndex_503518; - v59 = dword_4A7E6C[216 * currentDriverSelectedIndex_503518]; + v58 = currentDriverSelectedIndex_503518; + v59 = dword_4A7E6C[currentDriverSelectedIndex_503518]; *(float *)(v58 + dword_4A7E68) = (double)(rand() % (2 * v59 + 1) - v59); - v60 = dword_4A7E70[v58 / 4] + 1; - dword_4A7E70[v58 / 4] = v60; + v60 = dword_4A7E70[v58] + 1; + dword_4A7E70[v58 ] = v60; if ( !(v60 % 5) ) { - v61 = dword_4A7E6C[v58 / 4]; + v61 = dword_4A7E6C[v58 ]; if ( v61 < 30 ) - dword_4A7E6C[v58 / 4] = v61 + 1; + dword_4A7E6C[v58 ] = v61 + 1; } v62 = circuitWidth_464F40 - 20; raceParticipantIngame[currentDriverSelectedIndex_503518].absolutePositionX_4A7DB4 = *(float *)(v58 + unk_4A7E64) + raceParticipantIngame[currentDriverSelectedIndex_503518].absolutePositionX_4A7DB4; @@ -9626,7 +9635,7 @@ void calculateUserMovements_40BAB0() (int)((char *)participantCarBpk_5034FC + raceParticipantIngame[currentDriverSelectedIndex_503518].participantBpkOffser_4A7D10), (int)((char *)trxImaBpk_50A16C + v65 + v66 + v67 - 20)); v51 = currentDriverSelectedIndex_503518; - v69 = 864 * currentDriverSelectedIndex_503518; + v69 = currentDriverSelectedIndex_503518; raceParticipantIngame[currentDriverSelectedIndex_503518].dword_4A7D14 = v68; if ( v68 < 4 ) { @@ -9640,15 +9649,18 @@ void calculateUserMovements_40BAB0() raceParticipantIngame[currentDriverSelectedIndex_503518].dword_4A7D14 = 0; } v52 = v51; - v70 = dword_4A7E94[v52 / 4]; + v70 = dword_4A7E94[v52]; if ( v70 && v70 <= 3 ) { raceParticipantIngame[v51].unk_4A7DFC = raceParticipantIngame[ v51].advanceXAxis_4A7E5C * -1.0; raceParticipantIngame[v51].unk_4A7E00 = raceParticipantIngame[ v51].advanceYAxis_4A7E60 * -1.0; + if( raceParticipantIngame[v51].unk_4A7E00<-100 || raceParticipantIngame[v51].unk_4A7E00>100 ){ + raceParticipantIngame[v75].unk_4A7E00= raceParticipantIngame[v75].unk_4A7E00; + } raceParticipantIngame[ v51].carVelocity_4A7DB0= 0; raceParticipantIngame[currentDriverSelectedIndex_503518].dword_4A7D14 = 1; } - if ( dword_4A7E94[v52 / 4] ) + if ( dword_4A7E94[v52 ] ) goto LABEL_134; if ( (v83 < 4 || v84 < 4) && v89 >= 4 ) raceParticipantIngame[v51].carAngle_4A7DAC = raceParticipantIngame[v51].carAngle_4A7DAC + 20.0; @@ -9835,6 +9847,7 @@ int recalculateRaceCarWithOrientation() --v2; raceParticipantIngame[v1-1].unk_4A7DFC = v3 * 0.8695652173913044; raceParticipantIngame[v1-1].unk_4A7E00 = raceParticipantIngame[v1-1].unk_4A7E00* 0.8695652173913044; + raceParticipantIngame[v1-1].unk_4A7E04 = raceParticipantIngame[v1-1].unk_4A7E04* 0.8333333333333334; /* @@ -9945,13 +9958,13 @@ int recalculateRaceCarWithOrientation() while ( v10 < v11 ); if ( v72 != 1 ) goto LABEL_114; - dword_4A7E74[v5 / 4] = v89; - dword_4A7E78[v5 / 4] = v80; + dword_4A7E74[v5] = v89; + dword_4A7E78[v5] = v80; v18 =raceParticipantIngame[v75].absolutePositionX_4A7DB4 - raceParticipantIngame[v75].dword_4A7E50; dword_4A7E74[v6] = v81; v19 = raceParticipantIngame[v75].absolutePositionY_4A7DB8; dword_4A7E78[v6] = v82; - v20 = v19 - raceParticipantIngame[v75].dword_4A7E50; + v20 = v19 - raceParticipantIngame[v75].dword_4A7E54; v21 = (unsigned __int64)((double)v80 * v18 - (double)v89 * v20); v22 = raceParticipantIngame[v5].absolutePositionX_4A7DB4 - raceParticipantIngame[v5].dword_4A7E50; v23 = raceParticipantIngame[v5].absolutePositionY_4A7DB8 - raceParticipantIngame[v5].dword_4A7E54; @@ -9959,6 +9972,7 @@ int recalculateRaceCarWithOrientation() v85 = (unsigned __int64)((double)v82 * v22 - (double)v81 * v23); (raceParticipantIngame[v5].unk_4A7DFC) = (v18 - v22) * 0.7 + (raceParticipantIngame[v5].unk_4A7DFC); (raceParticipantIngame[v5].unk_4A7E00) = (v20 - v23) * 0.7 + (raceParticipantIngame[v5].unk_4A7E00); + if ( v89 > 0 ) { if ( raceParticipantIngame[ v5].advanceXAxis_4A7E5C > 0.0 ) @@ -10000,7 +10014,8 @@ int recalculateRaceCarWithOrientation() * 0.7 + raceParticipantIngame[v75].unk_4A7DFC; raceParticipantIngame[v75].unk_4A7E00 = v27 * 0.7 + raceParticipantIngame[v75].unk_4A7E00; - if ( v81 > 0 ) + + if ( v81 > 0 ) { if ( raceParticipantIngame[ v75].advanceXAxis_4A7E5C > 0.0 ) goto LABEL_49; @@ -10029,11 +10044,11 @@ int recalculateRaceCarWithOrientation() LABEL_56: raceParticipantIngame[v75].dword_4A7D1C = 1; LABEL_58: - if(debug==1){ + /*if(debug==1){ raceParticipantIngame[v75].dword_4A7D1C =- 1; raceParticipantIngame[currentDriverSelectedIndex_503518].dword_4A7D1C = 1; raceParticipantIngame[currentDriverSelectedIndex_503518].dword_4A7D1C = 1; - } + }*/ //esto son calculos de choques entre v5 jugador actual y v6 if ( raceParticipantIngame[currentDriverSelectedIndex_503518].dword_4A7D18 == 1 && raceParticipantIngame[v75].dword_4A7D18 == 1 || raceParticipantIngame[currentDriverSelectedIndex_503518].dword_4A7D1C == 1 && raceParticipantIngame[v75].dword_4A7D1C == 1 ) @@ -10088,7 +10103,15 @@ int recalculateRaceCarWithOrientation() } v73 = raceParticipantIngame[v5].carAngle_4A7DAC - raceParticipantIngame[v75].carAngle_4A7DAC; v44 = v73; - /*if ( v45 | v46 ) + v46=0;//TODO FIX puesto por mi + v45=0; + v49=0; + v50=0; + v53=0; + v54=0; + v57=0; + v58=0; + if ( v45 | v46 ) v44 = -v44; if ( v44 < 315.0 ) { @@ -10119,7 +10142,7 @@ int recalculateRaceCarWithOrientation() raceParticipantIngame[v75].unk_4A7E04 = v60 + raceParticipantIngame[v75].unk_4A7E04; } } - }*/ + } v74 = 0; if ( raceParticipant2[currentDriverSelectedIndex_503518].spikes && !raceParticipantIngame[v5].hasFinishedTheRace_4A7E0C ) { @@ -15842,7 +15865,8 @@ if ( isCircuitReversed_456AA8 ) } while ( v56 ); } - // recalculateRaceCarWithOrientation(); + + recalculateRaceCarWithOrientation(); currentDriverSelectedIndex_503518 = 0; if ( v50 > 0 ) { @@ -17930,6 +17954,8 @@ int __cdecl drawMenu(int menuType, int top) v6 += v10; result = dword_4456F0[v3]; ++v5; + if ( v5 >= result ) + return result; v8 = getMenuText(menuType, ++menuEntryIndex); v13 = v11; if ( v5 >= result ) @@ -18273,7 +18299,7 @@ int __cdecl refreshMenuUp(int a1) drawTextWithFont( (int)graphicsGeneral.fbig3aBpk, (int)&bigLetterSpacing_445848, - getMenuText(a1, v9), + getMenuText(a1, v10), 640 * (v11 + dword_4456F8[v1]) + dword_4456F4[v1] + 3232); drawImageWithPosition( @@ -23347,6 +23373,7 @@ int showEndScreen() palette1[v3] = colorToPaletteEntry( (unsigned __int8)(*(byte *)(*(_DWORD *)(**(_DWORD **)(v1 + 4) + 4) + v2) & 0xFC) << 14, + 6553600); palette1[v3+1] = colorToPaletteEntry( (unsigned __int8)(*(byte *)(*(_DWORD *)(**(_DWORD **)(v1 + 4) + 4) + v2 + 1) & 0xFC) << 14, @@ -25702,6 +25729,7 @@ int __cdecl sub_42C7F0(int a1, int a2, int a3, int a4, int a5, int a6) { if ( a4 ) { + //carAnimCurrentFrame_45FBA0 = 0; //TODO he quitado la animacion del coche!!!! drawMenuAnimation(a5 + 416, a6 + 80, carAnimCurrentFrame_45FBA0, getCarBpkById(0), (int)&carAnimFrameSize_45FBA0); @@ -26194,13 +26222,13 @@ bool __cdecl drawYesNoMenu(int a1, int a2, int a3, signed int *a4) v19 = 640 * a2 + a1 - 4450; if ( *a4 == 1 ) { - drawTextWithFont((int)graphicsGeneral.fbig3aBpk, (int)&bigLetterSpacing_445848, "yes", v19); - drawTextWithFont((int)fbig3bBpk, (int)&bigLetterSpacing_445848, "no", 640 * a2 + a1 - 4280); + drawTextWithFont((int)graphicsGeneral.fbig3aBpk, (int)&bigLetterSpacing_445848, getLanguageEntry("yes"), v19); + drawTextWithFont((int)fbig3bBpk, (int)&bigLetterSpacing_445848, getLanguageEntry("no"), 640 * a2 + a1 - 4280); } else { - drawTextWithFont((int)fbig3bBpk, (int)&bigLetterSpacing_445848, "yes", v19); - drawTextWithFont((int)graphicsGeneral.fbig3aBpk, (int)&bigLetterSpacing_445848, "no", 640 * a2 + a1 - 4280); + drawTextWithFont((int)fbig3bBpk, (int)&bigLetterSpacing_445848, getLanguageEntry("yes"), v19); + drawTextWithFont((int)graphicsGeneral.fbig3aBpk, (int)&bigLetterSpacing_445848, getLanguageEntry("no"), 640 * a2 + a1 - 4280); } refreshAllScreen(); while ( 2 ) @@ -26262,8 +26290,8 @@ bool __cdecl drawYesNoMenu(int a1, int a2, int a3, signed int *a4) memset(&v14[v5 - 5], 0xC4u, 0xF0u); } while ( v13 < 16000 ); - drawTextWithFont((int)graphicsGeneral.fbig3aBpk, (int)&bigLetterSpacing_445848, "yes", 640 * a2 + a1 - 4450); - drawTextWithFont((int)fbig3bBpk, (int)&bigLetterSpacing_445848, "no", 640 * a2 + a1 - 4280); + drawTextWithFont((int)graphicsGeneral.fbig3aBpk, (int)&bigLetterSpacing_445848, getLanguageEntry("yes"), 640 * a2 + a1 - 4450); + drawTextWithFont((int)fbig3bBpk, (int)&bigLetterSpacing_445848, getLanguageEntry("no"), 640 * a2 + a1 - 4280); continue; case KEY_RIGHT: case 0xCD: @@ -26278,8 +26306,8 @@ bool __cdecl drawYesNoMenu(int a1, int a2, int a3, signed int *a4) memset(&v16[v5 - 5], 0xC4u, 0xF0u); } while ( v15 < 16000 ); - drawTextWithFont((int)fbig3bBpk, (int)&bigLetterSpacing_445848, "yes", 640 * a2 + a1 - 4450); - drawTextWithFont((int)graphicsGeneral.fbig3aBpk, (int)&bigLetterSpacing_445848, "no", 640 * a2 + a1 - 4280); + drawTextWithFont((int)fbig3bBpk, (int)&bigLetterSpacing_445848, getLanguageEntry("yes"), 640 * a2 + a1 - 4450); + drawTextWithFont((int)graphicsGeneral.fbig3aBpk, (int)&bigLetterSpacing_445848, getLanguageEntry("no"), 640 * a2 + a1 - 4280); continue; case 1: if ( !a3 ) @@ -26456,6 +26484,19 @@ signed int __cdecl readKeyboard(const char *a1, int a2, int a3, int a4, unsigned a++; face = initialFace; + + v68 = *((byte *)graphicsGeneral.copperPal + v65 + 2); + v22 = (double)v68; + v23 = *((byte *)graphicsGeneral.copperPal + v65); + v68 = *((byte *)graphicsGeneral.copperPal + v65 + 1); + v24 = v22; + v25 = (double)v68; + v68 = v23; + v26 = v25; + v27 = (double)v23; + setPaletteValueWithFloats(v27, v26, v24); + + sub_42C7F0(a2, a3, v10, v13, 63, 112); v15 = eventDetected(); v16 = (unsigned __int8)v15; @@ -31003,8 +31044,8 @@ void enterShop() v24[2] = 0; drawTextWithFont(v26, (int)&letterSpacing_4458B0, (const char *)&v99, 110250); } - drawTextWithFont((int)graphicsGeneral.fbig3aBpk, (int)&bigLetterSpacing_445848, "yes", 118640); - drawTextWithFont((int)fbig3bBpk, (int)&bigLetterSpacing_445848, "no", 118810); + drawTextWithFont((int)graphicsGeneral.fbig3aBpk, (int)&bigLetterSpacing_445848, getLanguageEntry("yes"), 118640); + drawTextWithFont((int)fbig3bBpk, (int)&bigLetterSpacing_445848, getLanguageEntry("no"), 118810); refreshAllScreen(); v45 = 0; while ( 2 ) @@ -31063,8 +31104,8 @@ void enterShop() v54[2] = -60; } while ( v53 < 16000 ); - drawTextWithFont((int)graphicsGeneral.fbig3aBpk, (int)&bigLetterSpacing_445848, "yes", 118640); - drawTextWithFont((int)fbig3bBpk, (int)&bigLetterSpacing_445848, "no", 118810); + drawTextWithFont((int)graphicsGeneral.fbig3aBpk, (int)&bigLetterSpacing_445848, getLanguageEntry("yes"), 118640); + drawTextWithFont((int)fbig3bBpk, (int)&bigLetterSpacing_445848, getLanguageEntry("no"), 118810); continue; case KEY_RIGHT: case 0xCD: @@ -31082,8 +31123,8 @@ void enterShop() v56[2] = -60; } while ( v55 < 16000 ); - drawTextWithFont((int)fbig3bBpk, (int)&bigLetterSpacing_445848, "yes", 118640); - drawTextWithFont((int)graphicsGeneral.fbig3aBpk, (int)&bigLetterSpacing_445848, "no", 118810); + drawTextWithFont((int)fbig3bBpk, (int)&bigLetterSpacing_445848, getLanguageEntry("yes"), 118640); + drawTextWithFont((int)graphicsGeneral.fbig3aBpk, (int)&bigLetterSpacing_445848, getLanguageEntry("no"), 118810); continue; case KEY_ENTER: case 0x9C: @@ -32771,7 +32812,7 @@ int mainMenu() //exit to os drawMenu(INITIAL_MENU, 0); createPopup(170, 200, 300, 80, 1); - drawTextWithFont((int)graphicsGeneral.fsma3aBpk, (int)&letterSpacing_4458B0, "Are you sure?", 133373); + drawTextWithFont((int)graphicsGeneral.fsma3aBpk, (int)&letterSpacing_4458B0, getLanguageEntry("Are you sure?"), 133373); drawYesNoMenu(180, 238, 1, &v63); break; default: @@ -32900,6 +32941,7 @@ int sub_43ACE0(double a1, int a2, int a3,char *args) dword_45EA40 = *(_DWORD *)(a3 + 32); dword_45EA44 = *(_DWORD *)(a3 + 36); checkArgs(args); + initI18n(mainArgs.language); inicializeScreen(a1); dword_4A9140 = (int)exitGame_43ACB0; nullsub_1(); @@ -35774,9 +35816,13 @@ int initSystem(double fmodMinVersion, int a1, const char **a2, const char *args int v14; // [sp+0h] [bp-Ch]@7 v3 = *a2; + if(*a2==NULL) + *a2=malloc(sizeof(char*)); v4 = strrchr(*a2, 92); if ( v4 || (v4 = strrchr(*a2, 47)) != 0 ) v3 = v4 + 1; + if(v3==NULL) + v3=malloc(sizeof(char*)); v5 = strrchr(v3, 46); if ( v5 ) v6 = v5 - v3; @@ -35826,8 +35872,8 @@ int outOfMemoryError() void __cdecl generateExitError() { - fclose((FILE *)&iob[0] + 1); - fclose((FILE *)&iob[0] + 2); + // fclose((FILE *)&iob[0] + 1); + //fclose((FILE *)&iob[0] + 2); } diff --git a/i18n/i18n.c b/i18n/i18n.c new file mode 100644 index 0000000..1cf04b7 --- /dev/null +++ b/i18n/i18n.c @@ -0,0 +1,78 @@ + +#include +#include +#include +#include "../config.h" +#include "i18n.h" +#include "../util/hash.h" + + +hash_t *languageEntries; + +char * readline(FILE *fp, char *buffer) +{ + int ch; + int i = 0; + size_t buff_len = 0; + void *tmp; + buffer = malloc(buff_len + 1); + if (!buffer) return NULL; // Out of memory + + while ((ch = fgetc(fp)) != '\n' && ch != EOF) + { + buff_len++; + tmp = realloc(buffer, buff_len + 1); + if (tmp == NULL) + { + free(buffer); + return NULL; // Out of memory + } + buffer = tmp; + + buffer[i] = (char) ch; + i++; + } + buffer[i] = '\0'; + + // Detect end + if (ch == EOF && (i == 0 || ferror(fp))) + { + free(buffer); + return NULL; + } + return buffer; +} + +int initI18n(int language) { + + FILE * fp; + char *s; + char delim[] = "="; + char *key ; + char *value ; + languageEntries = hash_new(150); + if(mainArgs.language) + fp = fopen(strcat(strcat("lang/",mainArgs.language),".txt"), "r"); + else + return; + while ((s = readline(fp, 0)) != NULL) + { + + key = strtok(s, delim); + + if(key != NULL) + { + value = strtok(NULL, delim); + hash_insert(languageEntries, (key), value); + } + //free(s); + } +} + +char * getLanguageEntry(char * languageEntry) { + char * result; + result = (char *)hash_lookup(languageEntries, (languageEntry)); + if(result == NULL) + return languageEntry; + return result ; +} diff --git a/i18n/i18n.h b/i18n/i18n.h new file mode 100644 index 0000000..58c9ff5 --- /dev/null +++ b/i18n/i18n.h @@ -0,0 +1,9 @@ +typedef enum { + LANGUAGE_ENGLISH = 0, + LANGUAGE_SPANISH = 1 + +}Languages; + + +int initI18n(int language); +char * getLanguageEntry(char* languageEntry); \ No newline at end of file diff --git a/lang/langEs.txt b/lang/langEs.txt new file mode 100644 index 0000000..79159da --- /dev/null +++ b/lang/langEs.txt @@ -0,0 +1,39 @@ +#menus +Start Racing=Comenzar Carrera +Multiplayer Race=Multijugador +Configure=Configuracion +See hall of fame=Salon de la fama +Credits=Creditos +Exit to os=Salir al os +yes=si +no=no +Are you sure?=¿Estas seguro? + +Start a new game=Comenzar nuevo juego +End current Game=Finalizar juego +See current Stadistics=Ver estadisticas +Load game=Cargar juego +save game=Guardar partida +Previous menu=Volver + +Music volume=Volumen de la musica +Effect volume=Volumen de los efectos +define Keyboard=Configura teclado +Define Gamepad/Joystick=Configura gamepad/joystick +Gamepad/Joystick Disabled=gamepad/joystick Desactivado + +Empty slot=Slot vacio +Quicksave slot=Guardado rapido + +Accelerate=Acelerar +Brake=Frenar +Steer Left=Giro Izquierda +Steer right=Giro Derecha +Turbo boost=Turbo Boost +Machine Gun=Ametralladora +Drop Mine=Dejar Mina +Horn=Claxon +Select difficulty:=Dificultad: +speed makes me dizzy=la velocidad me marea +i live to ride=vivo para conducir +petrol in my veins=petroleo en mis venas \ No newline at end of file diff --git a/license/licenseScreen.c b/license/licenseScreen.c index 902f44c..5d1a403 100644 --- a/license/licenseScreen.c +++ b/license/licenseScreen.c @@ -16,7 +16,7 @@ #include "../imageUtil.h" #include "../drivers.h" #include "../config.h" - +#include "../i18n/i18n.h" char aSpeedMakesMeDi[21] = "speed makes me dizzy"; // weak char aILiveToRide[15] = "i live to ride"; // weak @@ -95,6 +95,7 @@ int __cdecl licenseScreen(int useWeapons_mal) carAnimCurrentFrame_45FBA0 = 0; v57 = 1; //dword_46086C[27 * driverId] = 0; + drivers[driverId].colour = 0; drawTransparentBlock(0, 371, 639, 109); drawBottomMenuText(); @@ -112,8 +113,8 @@ int __cdecl licenseScreen(int useWeapons_mal) drawImageWithPosition2((int)graphicsGeneral.face01Bpk, 64, 64, (int)((char *)screenBuffer + 122330)); if (useWeapons_mal) { - drawTextWithFont((int)fbig3bBpk, (int)&bigLetterSpacing_445848, "yes", 202463); - drawTextWithFont((int)fbig3bBpk, (int)&bigLetterSpacing_445848, "no", 202633); + drawTextWithFont((int)fbig3bBpk, (int)&bigLetterSpacing_445848, getLanguageEntry("yes"), 202463); + drawTextWithFont((int)fbig3bBpk, (int)&bigLetterSpacing_445848, getLanguageEntry("no"), 202633); v5 = 0; v6 = 186240; do @@ -235,21 +236,21 @@ int __cdecl licenseScreen(int useWeapons_mal) memcpy((char *)screenBuffer + 53760, (char *)graphicsGeneral.menubg5Bpk + 53760, 0x2C380u); drawMenu(INITIAL_MENU, 0); createPopup(93, 142, 440, 186, 1); - drawTextWithFont((int)graphicsGeneral.fbig3aBpk, (int)&bigLetterSpacing_445848, "Select difficulty:", 102573); + drawTextWithFont((int)graphicsGeneral.fbig3aBpk, (int)&bigLetterSpacing_445848, getLanguageEntry("Select difficulty:"), 102573); drawCursor(115, 28 * configuration.difficulty + 221); v28 = configuration.difficulty; if (configuration.difficulty ) { - drawTextWithFont((int)fbig3bBpk, (int)&bigLetterSpacing_445848, aSpeedMakesMeDi, 138379); + drawTextWithFont((int)fbig3bBpk, (int)&bigLetterSpacing_445848, getLanguageEntry(aSpeedMakesMeDi), 138379); if ( v28 == 1 ) { - drawTextWithFont((int)graphicsGeneral.fbig3aBpk, (int)&bigLetterSpacing_445848, aILiveToRide, 156299); + drawTextWithFont((int)graphicsGeneral.fbig3aBpk, (int)&bigLetterSpacing_445848, getLanguageEntry(aILiveToRide), 156299); goto LABEL_37; } } else { - drawTextWithFont((int)graphicsGeneral.fbig3aBpk, (int)&bigLetterSpacing_445848, aSpeedMakesMeDi, 138379); + drawTextWithFont((int)graphicsGeneral.fbig3aBpk, (int)&bigLetterSpacing_445848, getLanguageEntry(aSpeedMakesMeDi), 138379); } drawTextWithFont((int)fbig3bBpk, (int)&bigLetterSpacing_445848, aILiveToRide, 156299); if ( v28 != 2 ) @@ -267,7 +268,7 @@ int __cdecl licenseScreen(int useWeapons_mal) v53 = (int)&bigLetterSpacing_445848; v51 = graphicsGeneral.fbig3aBpk; LABEL_38: - drawTextWithFont((int)v51, v53, aPetrolInMyVein, 174219); + drawTextWithFont((int)v51, v53, getLanguageEntry(aPetrolInMyVein), 174219); refreshAllScreen(); while ( 1 ) { @@ -300,18 +301,18 @@ int __cdecl licenseScreen(int useWeapons_mal) while ( v30 < 144640 ); if ( v28 ) { - drawTextWithFont((int)fbig3bBpk, (int)&bigLetterSpacing_445848, aSpeedMakesMeDi, 138379); + drawTextWithFont((int)fbig3bBpk, (int)&bigLetterSpacing_445848, getLanguageEntry(aSpeedMakesMeDi), 138379); if ( v28 == 1 ) { - drawTextWithFont((int)graphicsGeneral.fbig3aBpk, (int)&bigLetterSpacing_445848, aILiveToRide, 156299); + drawTextWithFont((int)graphicsGeneral.fbig3aBpk, (int)&bigLetterSpacing_445848, getLanguageEntry(aILiveToRide), 156299); goto LABEL_57; } } else { - drawTextWithFont((int)graphicsGeneral.fbig3aBpk, (int)&bigLetterSpacing_445848, aSpeedMakesMeDi, 138379); + drawTextWithFont((int)graphicsGeneral.fbig3aBpk, (int)&bigLetterSpacing_445848,getLanguageEntry( aSpeedMakesMeDi), 138379); } - drawTextWithFont((int)fbig3bBpk, (int)&bigLetterSpacing_445848, aILiveToRide, 156299); + drawTextWithFont((int)fbig3bBpk, (int)&bigLetterSpacing_445848, getLanguageEntry(aILiveToRide), 156299); if ( v28 == 2 ) { // v56 = *((float*)aPetrolInMyVein); @@ -319,7 +320,7 @@ int __cdecl licenseScreen(int useWeapons_mal) v54 = (int)&bigLetterSpacing_445848; v52 = graphicsGeneral.fbig3aBpk; LABEL_58: - drawTextWithFont((int)v52, v54, aPetrolInMyVein, 174219); + drawTextWithFont((int)v52, v54, getLanguageEntry(aPetrolInMyVein), 174219); drawKeyCursor(138355, (char *)screenBuffer + 138355, 0x190u, 84); loadMenuSoundEffect(1u, 25, 0, configuration.effectsVolume, dword_445194); goto LABEL_59; @@ -406,7 +407,7 @@ int __cdecl licenseScreen(int useWeapons_mal) LABEL_86: if ( isMultiplayerGame ) { - drawTextWithFont((int)graphicsGeneral.fsma3bBpk, (int)&letterSpacing_4458B0, "press to enter chat mode", 233635); + drawTextWithFont((int)graphicsGeneral.fsma3bBpk, (int)&letterSpacing_4458B0, getLanguageEntry("press to enter chat mode"), 233635); drawTextWithFont((int)graphicsGeneral.fsma3aBpk, (int)&letterSpacing_4458B0, "F1", 233689); } drawBottomMenuText(); diff --git a/menus.c b/menus.c index 5e51e34..c334334 100644 --- a/menus.c +++ b/menus.c @@ -1,10 +1,11 @@ #include "menus.h" #include "util.h" #include "savegame.h" +#include "i18n/i18n.h" #include -char * menu0[] = { "Start Racing", "Multiplayer Race", "Configure","See hall of fame","Credits","Exit to OS" }; +char * menu0[] = { "Start Racing", "Multiplayer Race", "Configure","See hall of fame","Credits","Exit to os" }; char * menu1[] = { "Start a new game", "End current Game", "See current Stadistics","Load game","save game","Previous menu" }; @@ -34,34 +35,34 @@ char* getMenuText(int menu, int position) { default: break; case INITIAL_MENU://menu principal - return menu0[position]; + return getLanguageEntry(menu0[position]); break; case START_NEW_GAME_MENU:// - return menu1[position]; + return getLanguageEntry(menu1[position]); break; case CONFIGURE_MENU:// - return menu3[position]; + return getLanguageEntry(menu3[position]); break; case LOAD_MENU:// if (position == 8) { - return menu5[position]; + return getLanguageEntry(menu5[position]); } else { if (getSaveGameName(position) != NULL) { return getSaveGameName(position); - }else return menu5[position]; + }else return getLanguageEntry(menu5[position]); } break; case DEFINE_KEYBOARD_MENU:// - return menu6[position]; + return getLanguageEntry(menu6[position]); break; case DEFINE_GAMEPAD_MENU:// - return menu8[position]; + return getLanguageEntry(menu8[position]); break; diff --git a/translation.c b/translation.c new file mode 100644 index 0000000..cb9f0dd --- /dev/null +++ b/translation.c @@ -0,0 +1,15 @@ + +#include +#include "i18n.h" + + +char * languageEntries[100]; + + +int initLanguage() { + languageEntries[EXIT_TO_OS]="SALIR AL OS"; +} + +char * getLanguageEntry(int languageEntry) { + return languageEntries[languageEntry]; +} diff --git a/translation.h b/translation.h new file mode 100644 index 0000000..92b16b4 --- /dev/null +++ b/translation.h @@ -0,0 +1,7 @@ + +typedef enum { + EXIT_TO_OS = 0 + +}LanguageEntries; + +char * getLanguageEntry(int languageEntry); \ No newline at end of file diff --git a/util/hash.c b/util/hash.c new file mode 100644 index 0000000..803b911 --- /dev/null +++ b/util/hash.c @@ -0,0 +1,48 @@ +#include +#include +#include "hash.h" +#include +#include + +hash_t *hash_new (int size) { + hash_t *h = malloc(sizeof (hash_t)); + // h->keys = malloc(size* sizeof (void *)); + // h->values = malloc(size* sizeof (void *)); + h->size = size; + h->filled = 0; + return h; +} + +int hash_index (hash_t *h, char *key) { + int i;// = (int) hash(key) % h->size; + char *orig =""; + char * dest=""; + dest =malloc(strlen(key)); + strcpy(dest,key); + for(i=0;ifilled;i++){ + orig = malloc(strlen(h->keys[i])); + strcpy(orig,h->keys[i]); + + if(strcmp(strupr(orig),strupr(dest))==0){ + return i; + } + } + /* while (h->keys[i] && h->keys[i] != key) + i = (i + 1) % h->size;*/ + return -1; +} + +void hash_insert (hash_t *h, char *key, void *value) { + //int i = hash_index(h, key); + + h->keys[h->filled] = key; + h->values[h->filled] = value; + h->filled = h->filled +1; +} + +void *hash_lookup (hash_t *h, char *key) { + signed int i = hash_index(h, key); + if(i==-1) + return NULL; + return h->values[i]; +} diff --git a/util/hash.h b/util/hash.h new file mode 100644 index 0000000..741f1e1 --- /dev/null +++ b/util/hash.h @@ -0,0 +1,12 @@ +typedef struct { + int size; + char *keys[150]; + char *values[150]; + int filled; +} hash_t; + + +hash_t *hash_new (int size); +int hash_index (hash_t *h, void *key); +void hash_insert (hash_t *h, void *key, void *value); +void *hash_lookup (hash_t *h, void *key); \ No newline at end of file