diff --git a/src/ClassicalSharp.sln b/src/ClassicalSharp.sln index d77789ca7..daafd912c 100644 --- a/src/ClassicalSharp.sln +++ b/src/ClassicalSharp.sln @@ -1,28 +1,28 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Client", "Client\Client.vcxproj", "{8A7D82BD-178A-4785-B41B-70EDE998920A}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8A7D82BD-178A-4785-B41B-70EDE998920A}.Debug|x64.ActiveCfg = Debug|x64 - {8A7D82BD-178A-4785-B41B-70EDE998920A}.Debug|x64.Build.0 = Debug|x64 - {8A7D82BD-178A-4785-B41B-70EDE998920A}.Debug|x86.ActiveCfg = Debug|Win32 - {8A7D82BD-178A-4785-B41B-70EDE998920A}.Debug|x86.Build.0 = Debug|Win32 - {8A7D82BD-178A-4785-B41B-70EDE998920A}.Release|x64.ActiveCfg = Release|x64 - {8A7D82BD-178A-4785-B41B-70EDE998920A}.Release|x64.Build.0 = Release|x64 - {8A7D82BD-178A-4785-B41B-70EDE998920A}.Release|x86.ActiveCfg = Release|Win32 - {8A7D82BD-178A-4785-B41B-70EDE998920A}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Client", "Client\Client.vcxproj", "{8A7D82BD-178A-4785-B41B-70EDE998920A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8A7D82BD-178A-4785-B41B-70EDE998920A}.Debug|x64.ActiveCfg = Debug|x64 + {8A7D82BD-178A-4785-B41B-70EDE998920A}.Debug|x64.Build.0 = Debug|x64 + {8A7D82BD-178A-4785-B41B-70EDE998920A}.Debug|x86.ActiveCfg = Debug|Win32 + {8A7D82BD-178A-4785-B41B-70EDE998920A}.Debug|x86.Build.0 = Debug|Win32 + {8A7D82BD-178A-4785-B41B-70EDE998920A}.Release|x64.ActiveCfg = Release|x64 + {8A7D82BD-178A-4785-B41B-70EDE998920A}.Release|x64.Build.0 = Release|x64 + {8A7D82BD-178A-4785-B41B-70EDE998920A}.Release|x86.ActiveCfg = Release|Win32 + {8A7D82BD-178A-4785-B41B-70EDE998920A}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/Client/Bitmap.c b/src/Client/Bitmap.c index 131f91eb5..2a1fb328e 100644 --- a/src/Client/Bitmap.c +++ b/src/Client/Bitmap.c @@ -11,6 +11,7 @@ void Bitmap_Create(Bitmap* bmp, Int32 width, Int32 height, UInt8* scan0) { bmp->Stride = width * BITMAP_SIZEOF_PIXEL; bmp->Scan0 = scan0; } + void Bitmap_CopyBlock(Int32 srcX, Int32 srcY, Int32 dstX, Int32 dstY, Bitmap* src, Bitmap* dst, Int32 size) { Int32 x, y; for (y = 0; y < size; y++) { @@ -40,7 +41,7 @@ void Bitmap_AllocateClearedPow2(Bitmap* bmp, Int32 width, Int32 height) { } -#define PNG_HEADER 8 +#define PNG_SIG_SIZE 8 #define PNG_RGB_MASK 0xFFFFFFUL #define PNG_PALETTE 256 #define PNG_FourCC(a, b, c, d) ((UInt32)a << 24) | ((UInt32)b << 16) | ((UInt32)c << 8) | (UInt32)d @@ -58,15 +59,14 @@ void Bitmap_AllocateClearedPow2(Bitmap* bmp, Int32 width, Int32 height) { #define PNG_FILTER_PAETH 4 typedef void(*Png_RowExpander)(UInt8 bpp, Int32 width, UInt32* palette, UInt8* src, UInt32* dst); +UInt8 png_sig[PNG_SIG_SIZE] = { 137, 80, 78, 71, 13, 10, 26, 10 }; void Png_CheckHeader(Stream* stream) { - UInt8 header[PNG_HEADER]; - static UInt8 sig[PNG_HEADER] = { 137, 80, 78, 71, 13, 10, 26, 10 }; - Stream_Read(stream, header, PNG_HEADER); - + UInt8 header[PNG_SIG_SIZE]; + Stream_Read(stream, header, PNG_SIG_SIZE); Int32 i; - for (i = 0; i < PNG_HEADER; i++) { - if (header[i] != sig[i]) ErrorHandler_Fail("Invalid PNG header"); + for (i = 0; i < PNG_SIG_SIZE; i++) { + if (header[i] != png_sig[i]) ErrorHandler_Fail("Invalid PNG header"); } } @@ -311,14 +311,14 @@ void Bitmap_DecodePng(Bitmap* bmp, Stream* stream) { while (readingChunks) { UInt32 dataSize = Stream_ReadU32_BE(stream); - UInt32 fourCC = Stream_ReadU32_BE(stream); + UInt32 fourCC = Stream_ReadU32_BE(stream); switch (fourCC) { case PNG_FourCC('I', 'H', 'D', 'R'): { if (dataSize != 13) ErrorHandler_Fail("PNG header chunk has invalid size"); gotHeader = true; - bmp->Width = Stream_ReadI32_BE(stream); + bmp->Width = Stream_ReadI32_BE(stream); bmp->Height = Stream_ReadI32_BE(stream); if (bmp->Width < 0 || bmp->Width > PNG_MAX_DIMS) ErrorHandler_Fail("PNG image too wide"); if (bmp->Height < 0 || bmp->Height > PNG_MAX_DIMS) ErrorHandler_Fail("PNG image too tall"); @@ -461,4 +461,26 @@ void Bitmap_DecodePng(Bitmap* bmp, Stream* stream) { Png_ComputeTransparency(bmp, transparentCol); } if (bmp->Scan0 == NULL) ErrorHandler_Fail("Invalid PNG image"); +} + +void Bitmap_EncodePng(Bitmap* bmp, Stream* stream) { + Stream_Write(stream, png_sig, PNG_SIG_SIZE); + + /* Write header chunk */ + Stream_WriteU32_BE(stream, 13); + Stream_WriteU32_BE(stream, PNG_FourCC('I', 'H', 'D', 'R')); + Stream_WriteU32_BE(stream, bmp->Width); + Stream_WriteU32_BE(stream, bmp->Height); + Stream_WriteU8(stream, 8); /* bits per sample */ + Stream_WriteU8(stream, PNG_COL_RGB); /* TODO: RGBA but mask all alpha to 255? */ + Stream_WriteU8(stream, 0); /* DEFLATE compression method */ + Stream_WriteU8(stream, 0); /* ADAPTIVE filter method */ + Stream_WriteU8(stream, 0); /* Not using interlacing */ + + /* Write PNG body */ + // do stuff here ???? + + /* Write end chunk */ + Stream_WriteU32_BE(stream, 0); + Stream_WriteU32_BE(stream, PNG_FourCC('I', 'E', 'N', 'D')); } \ No newline at end of file diff --git a/src/Client/Game.c b/src/Client/Game.c index 51bf0fce4..2a8df6107 100644 --- a/src/Client/Game.c +++ b/src/Client/Game.c @@ -784,8 +784,6 @@ bool AsyncDownloader_GetCurrent(AsyncRequest* request, Int32* progress) { return void AsyncDownloader_PurgeOldEntriesTask(ScheduledTask* task) { } DateTime DateTime_FromTotalMs(Int64 ms) { DateTime time; return time; } -void Bitmap_EncodePng(Bitmap* bmp, Stream* stream) { } - void Gfx_MakeApiInfo(void) { } void AdvLightingBuilder_SetActive(void) { } diff --git a/src/Client/Platform.h b/src/Client/Platform.h index 4b881b628..6cc5b54fb 100644 --- a/src/Client/Platform.h +++ b/src/Client/Platform.h @@ -17,6 +17,7 @@ extern ReturnCode ReturnCode_FileNotFound; void Platform_Init(void); void Platform_Free(void); void Platform_Exit(ReturnCode code); +STRING_PURE String Platform_GetCommandLineArgs(void); void* Platform_MemAlloc(UInt32 numElems, UInt32 elemsSize); void* Platform_MemRealloc(void* mem, UInt32 numElems, UInt32 elemsSize); diff --git a/src/Client/Program.c b/src/Client/Program.c index 9db4d0165..94f81f1eb 100644 --- a/src/Client/Program.c +++ b/src/Client/Program.c @@ -9,8 +9,9 @@ #include "Bitmap.h" #include "Constants.h" #include "Game.h" +#include "Funcs.h" -int main(int argc, char* argv[]) { +int main(void) { ErrorHandler_Init("client.log"); Platform_Init(); @@ -46,28 +47,29 @@ int main(int argc, char* argv[]) { if (device.Bounds.Width < 854) width = 640; } - String title = String_FromConst(PROGRAM_APP_NAME); - //argc = 5; - //char* default_argv[5] = { "path", "UnknownShadow200", "fff", "127.0.0.1", "25566" }; - argc = 2; - char* default_argv[2] = { "path", "UnknownShadow200" }; - argv = default_argv; + String title = String_FromConst(PROGRAM_APP_NAME); + String rawArgs = Platform_GetCommandLineArgs(); + //rawArgs = String_FromReadonly("UnknownShadow200 fff 127.0.0.1 25566"); + //rawArgs = String_FromReadonly("UnknownShadow200"); - if (argc == 1 || argc == 2) { - String_AppendConst(&Game_Username, argc > 1 ? argv[1] : "Singleplayer"); - //String_AppendConst(&Game_Username, "Singleplayer"); - } else if (argc < 5) { + String args[5]; UInt32 argsCount = Array_Elems(args); + String_UNSAFE_Split(&rawArgs, ' ', args, &argsCount); + + if (argsCount == 1) { + String name = args[0]; + if (name.length == 0) name = String_FromReadonly("Singleplayer"); + String_Set(&Game_Username, &name); + } else if (argsCount < 4) { Platform_LogConst("ClassicalSharp.exe is only the raw client. You must either use the launcher or provide command line arguments to start the client."); return; } else { - String_AppendConst(&Game_Username, argv[1]); - String_AppendConst(&Game_Mppass, argv[2]); - String ipRaw = String_FromReadonly(argv[3]); - String portRaw = String_FromReadonly(argv[4]); + String_Set(&Game_Username, &args[0]); + String_Set(&Game_Mppass, &args[1]); + String_Set(&Game_IPAddress, &args[2]); - String bits[4]; UInt32 bitsCount = 4; - String_UNSAFE_Split(&ipRaw, '.', bits, &bitsCount); - if (bitsCount != 4) { + String bits[4]; UInt32 bitsCount = Array_Elems(bits); + String_UNSAFE_Split(&args[2], '.', bits, &bitsCount); + if (bitsCount != Array_Elems(bits)) { Platform_LogConst("Invalid IP"); return; } @@ -78,11 +80,9 @@ int main(int argc, char* argv[]) { } UInt16 portTmp; - if (!Convert_TryParseUInt16(&portRaw, &portTmp)) { + if (!Convert_TryParseUInt16(&args[3], &portTmp)) { Platform_LogConst("Invalid port"); return; } - - String_Set(&Game_IPAddress, &ipRaw); Game_Port = portTmp; } diff --git a/src/Client/WinPlatform.c b/src/Client/WinPlatform.c index 17c3f57ac..61b9d1450 100644 --- a/src/Client/WinPlatform.c +++ b/src/Client/WinPlatform.c @@ -80,6 +80,27 @@ void Platform_Exit(ReturnCode code) { ExitProcess(code); } +STRING_PURE String Platform_GetCommandLineArgs(void) { + String args = String_FromReadonly(GetCommandLineA()); + + Int32 argsStart; + if (args.buffer[0] == '"') { + /* Handle path argument in full "path" form, which can include spaces */ + argsStart = String_IndexOf(&args, '"', 1) + 1; + } else { + argsStart = String_IndexOf(&args, ' ', 0) + 1; + } + + if (argsStart == 0) argsStart = args.length; + args = String_UNSAFE_SubstringAt(&args, argsStart); + + /* get rid of duplicate leading spaces before first arg */ + while (args.length > 0 && args.buffer[0] == ' ') { + args = String_UNSAFE_SubstringAt(&args, 1); + } + return args; +} + void* Platform_MemAlloc(UInt32 numElems, UInt32 elemsSize) { UInt32 numBytes = numElems * elemsSize; /* TODO: avoid overflow here */ return malloc(numBytes);