]> Git repositories of Nishi - reisen.git/commitdiff
it works
authorNishi <nishi@nishi.boats>
Tue, 8 Oct 2024 07:55:46 +0000 (07:55 +0000)
committerNishi <nishi@nishi.boats>
Tue, 8 Oct 2024 07:55:46 +0000 (07:55 +0000)
git-svn-id: file:///raid/svn-personal/reisen/trunk@10 c77b849d-6a5c-934c-a956-7b968ca1e197

Platform/generic.mk
Platform/generic64.mk
SFX/Makefile
SFX/main.c
SFX/sfx.h
Tool/main.c

index 910e1d0c12584b7d1673e8d1248f3ebb32d98f13..8ff2e0828418083b5f976b705b492b83e8673e31 100644 (file)
@@ -6,4 +6,5 @@ WINDRES = i686-w64-mingw32-windres
 CFLAGS = -std=c99 -g
 LDFLAGS =
 LIBS = -lz
-WINLIBS = $(PWD)/libz.a -lgdi32 -lshell32
+BITS = 32
+WINLIBS = $(PWD)/zlib$(BITS)/libz.a -lgdi32 -lshell32 -lcomctl32
index 97eaa8757637c3936fcbd2c949e93a7a7f764268..95393d772f0cbcdfeb2cc2c63d72504c28a06457 100644 (file)
@@ -6,4 +6,5 @@ WINDRES = x86_64-w64-mingw32-windres
 CFLAGS = -std=c99 -g
 LDFLAGS =
 LIBS = -lz
-WINLIBS = $(PWD)/libz.a -lgdi32 -lshell32
+BITS = 64
+WINLIBS = $(PWD)/zlib$(BITS)/libz.a -lgdi32 -lshell32 -lcomctl32
index aaedfb0869d6682e84183a0c22422c47c81352f5..9ab4393e3304ac735441570493e6865f06b8cf29 100644 (file)
@@ -13,7 +13,7 @@ reisen.sfx: $(OBJS)
        $(WINCC) -mwindows -o $@ $(OBJS) $(WINLIBS)
 
 .c.o:
-       $(WINCC) -mwindows -I $(PWD)/zlib-include -c -o $@ $<
+       $(WINCC) -mwindows -I $(PWD)/zlib$(BITS) -c -o $@ $<
 
 .rc.res:
        $(WINDRES) -O coff $< $@
index f42a3b771474dbd691e5f6c7fe054645990bcf8d..e5c4a2224ece149b2ec9f7b891c11ea7030a94ed 100644 (file)
@@ -4,6 +4,7 @@
 #include <shlobj.h>
 #include <stdio.h>
 #include <stdint.h>
+#include <string.h>
 #include <stdlib.h>
 #include <zlib.h>
 
 
 #include "../version.h"
 
+#define COMPRESS 16384
+
 #define StringText(dc,rt,str) DrawText(dc, str, -1, &rt, DT_WORDBREAK)
 
+HWND edit;
+HWND progress;
 HINSTANCE hInst;
 FILE* finst;
 HFONT titlefont;
@@ -22,13 +27,31 @@ HBRUSH graybrush;
 HBRUSH darkgraybrush;
 
 uint32_t bytes = 0;
+uint32_t counts;
 char name[257];
 char setupname[512];
 char welcome[512];
 
+BOOL change = FALSE;
+BOOL err;
 HWND windows[512];
 int window_count = 0;
-int phase = 0;
+int gphase = 0;
+char instpath[MAX_PATH];
+
+struct entry {
+       char* name;
+       uint32_t size;
+       BOOL dir;
+};
+
+struct entry entries[2048];
+
+void RenderPhase(int phase, HWND hWnd);
+
+int CALLBACK BrowseProc(HWND hWnd, UINT msg, LPARAM lp, LPARAM lp2){
+       return 0;
+}
 
 void InitWindowQueue(void){
        int i;
@@ -40,11 +63,116 @@ void InitWindowQueue(void){
 
 enum phases {
        PHASE_WELCOME = 0,
-       PHASE_DIR
+       PHASE_DIR,
+       PHASE_INSTALLING,
+       PHASE_INSTALLED,
+       PHASE_ERROR
 };
 
 void AddWindowQueue(HWND w){
+       SendMessage(w, WM_SETFONT, (WPARAM)normalfont, TRUE);
        windows[window_count++] = w;
+       windows[window_count] = NULL;
+}
+
+void ExtractProc(void* arg){
+       HWND hWnd = (HWND)arg;
+       int i;
+       int incr = 0;
+       BOOL fs = TRUE;
+       char sep[MAX_PATH + 1];
+       int nsep = 0;
+       char cpath[MAX_PATH + 1];
+       cpath[0] = 0;
+       for(i = 0; instpath[i] != 0; i++){
+               if(instpath[i] == '/') instpath[i] = '\\';
+       }
+       for(i = 0;; i++){
+               if(instpath[i] == '\\' || instpath[i] == 0){
+                       if(fs){
+                               fs = FALSE;
+                               strcat(cpath, sep);
+                       }else{
+                               if(nsep > 0){
+                                       strcat(cpath, "\\");
+                                       strcat(cpath, sep);
+                                       sep[0] = 0;
+
+                                       CreateDirectory(cpath, NULL);
+                               }
+                       }
+                       nsep = 0;
+                       if(instpath[i] == 0) break;
+               }else{
+                       sep[nsep++] = instpath[i];
+                       sep[nsep] = 0;
+               }
+       }
+       incr = 0;
+       fseek(finst, 0, SEEK_END);
+       fseek(finst, -4-256-bytes, SEEK_CUR);
+       for(i = 0; i < counts; i++){
+               char destpath[MAX_PATH];
+               sprintf(destpath, "%s%s", instpath, entries[i].name);
+retry:
+               fseek(finst, strlen(entries[i].name), SEEK_CUR);
+               if(entries[i].dir){
+                       fseek(finst, 4, SEEK_CUR);
+                       fseek(finst, 1, SEEK_CUR);
+                       CreateDirectory(destpath, NULL);
+               }else{
+                       FILE* f;
+                       z_stream strm;
+                       unsigned char in[COMPRESS];
+                       unsigned char out[COMPRESS];
+                       int ret;
+                       uint32_t buflen = entries[i].size;
+                       fseek(finst, 1, SEEK_CUR);
+
+                       f = fopen(destpath, "wb");
+                       if(f == NULL){
+                               int ret = MessageBox(hWnd, "Error opening output.\r\nRetry?", "Error", MB_YESNO | MB_ICONERROR | MB_DEFBUTTON2);
+                               if(ret == IDYES){
+                                       goto retry;
+                               }else{
+                                       goto itsover;
+                               }
+                       }
+
+                       strm.zalloc = Z_NULL;
+                       strm.zfree = Z_NULL;
+                       strm.opaque = Z_NULL;
+                       strm.avail_in = 0;
+                       strm.next_in = 0;
+                       ret = inflateInit(&strm);
+                       do {
+                               strm.avail_in = fread(in, 1, buflen < COMPRESS ? buflen : COMPRESS, finst);
+                               if(strm.avail_in == 0) break;
+                               strm.next_in = in;
+                               do {
+                                       int have;
+                                       strm.avail_out = COMPRESS;
+                                       strm.next_out = out;
+                                       inflate(&strm, Z_NO_FLUSH);
+                                       have = COMPRESS - strm.avail_out;
+                                       fwrite(out, 1, have, f);
+                               }while(strm.avail_out == 0);
+                       } while(ret != Z_STREAM_END);
+                       inflateEnd(&strm);
+
+                       fseek(finst, 4, SEEK_CUR);
+                       fseek(finst, 1, SEEK_CUR);
+                       fclose(f);
+               }
+               SendMessage(progress, PBM_SETPOS, (WPARAM)((double)(i + 1) / counts * 100), 0);
+       }
+       gphase = PHASE_INSTALLED;
+       change = TRUE;
+       _endthread();
+itsover:
+       gphase = PHASE_ERROR;
+       change = TRUE;
+       _endthread();
 }
 
 void RenderPhase(int phase, HWND hWnd){
@@ -53,9 +181,20 @@ void RenderPhase(int phase, HWND hWnd){
        GetClientRect(hWnd, &rc);
        InitWindowQueue();
        if(phase == PHASE_WELCOME || phase == PHASE_DIR){
-               AddWindowQueue(CreateWindow("BUTTON", "Next", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, rc.right - 75 - 15 - 75 - 25, rc.bottom - 10 - 25, 75, 25, hWnd, (HMENU)GUI_SFX_NEXT, hInst, NULL));
+               AddWindowQueue(CreateWindow("BUTTON", "&Next", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, rc.right - 75 - 15 - 75 - 25, rc.bottom - 10 - 25, 75, 25, hWnd, (HMENU)GUI_SFX_NEXT, hInst, NULL));
+       }
+       if(phase == PHASE_DIR){
+               edit = CreateWindow("EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, rc.left + 150 + 10, rc.top + 10 + 25 + 10, rc.right - 150 - 10 * 2 - 50 - 10, 15, hWnd, (HMENU)GUI_SFX_DIREDIT, hInst, NULL);
+               SendMessage(edit, WM_SETTEXT, 0, (LPARAM)instpath);
+               AddWindowQueue(edit);
+               AddWindowQueue(CreateWindow("BUTTON", "&Browse", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, rc.right - 10 - 50, rc.top + 10 + 25 + 10, 50, 15, hWnd, (HMENU)GUI_SFX_BROWSE, hInst, NULL));
+       }else if(phase == PHASE_INSTALLING){
+               progress = CreateWindow(PROGRESS_CLASS, NULL, WS_CHILD | WS_VISIBLE | PBS_SMOOTH, rc.left + 150 + 10, rc.top + 10 + 25 + 10, rc.right - 150 - 10 * 2, 15, hWnd, (HMENU)0, hInst, NULL);
+               SendMessage(progress, PBM_SETPOS, (WPARAM)0, 0);
+               AddWindowQueue(progress);
+               _beginthread(ExtractProc, 0, hWnd);
        }
-       AddWindowQueue(CreateWindow("BUTTON", "Cancel", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, rc.right - 75 - 15, rc.bottom - 10 - 25, 75, 25, hWnd, (HMENU)GUI_SFX_CANCEL, hInst, NULL));
+       AddWindowQueue(CreateWindow("BUTTON", (phase == PHASE_INSTALLED || phase == PHASE_ERROR) ? "&Exit" : "&Cancel", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, rc.right - 75 - 15, rc.bottom - 10 - 25, 75, 25, hWnd, (HMENU)GUI_SFX_CANCEL, hInst, NULL));
 }
 
 void ShowBitmapSize(HWND hWnd, HDC hdc, const char* name, int x, int y, int w, int h) {
@@ -92,20 +231,43 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
                int ev = HIWORD(wp);
                if(trig == GUI_SFX_CANCEL){
                        if(ev == BN_CLICKED){
-                               AskQuit(hWnd);
+                               if(gphase == PHASE_ERROR || gphase == PHASE_INSTALLED){
+                                       DestroyWindow(hWnd);
+                               }else{
+                                       AskQuit(hWnd);
+                               }
                        }
                }else if(trig == GUI_SFX_NEXT){
                        if(ev == BN_CLICKED){
-                               phase++;
-                               RenderPhase(phase, hWnd);
+                               if(gphase == PHASE_DIR){
+                                       SendMessage(edit, WM_GETTEXT, MAX_PATH, (LPARAM)instpath);
+                               }
+                               gphase++;
+                               RenderPhase(gphase, hWnd);
                                RedrawWindow(hWnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE);
                        }
+               }else if(trig == GUI_SFX_BROWSE){
+                       if(ev == BN_CLICKED){
+                               BROWSEINFO bi;
+                               ITEMIDLIST* lpid;
+                               memset(&bi, 0, sizeof(bi));
+                               bi.hwndOwner = hWnd;
+                               bi.lpfn = BrowseProc;
+                               bi.ulFlags = BIF_VALIDATE;
+                               bi.lpszTitle = "Select the install directory";
+                               lpid = SHBrowseForFolder(&bi);
+                               if(lpid != NULL){
+                                       SHGetPathFromIDList(lpid, instpath);
+                                       SendMessage(edit, WM_SETTEXT, 0, (LPARAM)instpath);
+                               }
+                       }
                }
        }else if(msg == WM_CREATE){
                RECT rc;
 
                GetClientRect(hWnd, &rc);
 
+               InitCommonControls();
 
                titlefont = CreateFont(25, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0, 0, FF_SWISS, NULL);
                normalfont = CreateFont(15, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0, 0, FF_SWISS, NULL);
@@ -115,6 +277,14 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
 
                RenderPhase(PHASE_WELCOME, hWnd);
 
+               SetTimer(hWnd, 1, 10, NULL);
+
+       }else if(msg == WM_TIMER){
+               if(change){
+                       change = FALSE;
+                       RenderPhase(gphase, hWnd);
+                       RedrawWindow(hWnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE);
+               }
        }else if(msg == WM_DESTROY){
                DeleteObject(titlefont);
                DeleteObject(normalfont);
@@ -139,7 +309,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
                SetTextColor(dc, RGB(0, 0, 0));
                ShowBitmapSize(hWnd, dc, "INSTALLER", 0, 0, 0, 0);
 
-               if(phase == PHASE_WELCOME){
+               if(gphase == PHASE_WELCOME){
                        SelectObject(dc, titlefont);
                        StringText(dc, rt, welcome);
                        rt.top += 25;
@@ -155,10 +325,22 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
                        rt.top += 15;
        
                        StringText(dc, rt, "Click Next to continue.");
-               }else if(phase == PHASE_DIR){
+               }else if(gphase == PHASE_DIR){
                        SelectObject(dc, titlefont);
                        StringText(dc, rt, "Select the folder to be installed in.");
                        rt.top += 25;
+               }else if(gphase == PHASE_INSTALLING){
+                       SelectObject(dc, titlefont);
+                       StringText(dc, rt, "Installing");
+                       rt.top += 25;
+               }else if(gphase == PHASE_ERROR){
+                       SelectObject(dc, titlefont);
+                       StringText(dc, rt, "Error");
+                       rt.top += 25;
+               }else if(gphase == PHASE_INSTALLED){
+                       SelectObject(dc, titlefont);
+                       StringText(dc, rt, "Installation successful");
+                       rt.top += 25;
                }
 
                GetClientRect(hWnd, &rc);
@@ -218,17 +400,25 @@ BOOL InitWindow(int nCmdShow) {
 int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) {
        char path[MAX_PATH + 1];
        int len = GetModuleFileName(hCurInst, path, MAX_PATH);
-       FILE* f;
        MSG msg;
        BOOL bret;
        uint8_t n;
        int i;
-       phase = PHASE_WELCOME;
+       uint32_t bbytes;
+       uint32_t entbytes;
+       uint32_t incr;
+       BOOL first = TRUE;
+       instpath[0] = 'C';
+       instpath[1] = ':';
+       instpath[2] = '\\';
+       instpath[3] = 0;
+       gphase = PHASE_WELCOME;
        hInst = hCurInst;
        name[256] = 0;
        path[len] = 0;
        finst = fopen(path, "rb");
-       if(f == NULL){
+       if(finst == NULL){
+               printf("panic: cannot read %s\n", path);
                return FALSE;
        }
        fseek(finst, 0, SEEK_END);
@@ -239,6 +429,79 @@ int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, in
                bytes <<= 8;
                bytes |= n;
        }
+       strcat(instpath, name);
+       counts = 0;
+loop:
+       bbytes = bytes;
+       fseek(finst, 0, SEEK_END);
+       fseek(finst, -4-256, SEEK_CUR);
+       incr = 0;
+       while(1){
+               uint8_t fnlen;
+               uint8_t attr;
+               char* fnnam;
+               fseek(finst, -1, SEEK_CUR);
+               fread(&attr, 1, 1, finst);
+               fseek(finst, -1-4, SEEK_CUR);
+               for(i = 0; i < 4; i++){
+                       fread(&n, 1, 1, finst);
+                       entbytes <<= 8;
+                       entbytes |= n;
+               }
+               fflush(stdout);
+               if(attr & 1){
+                       fseek(finst, -4-entbytes-1, SEEK_CUR);
+                       fread(&fnlen, 1, 1, finst);
+                       fseek(finst, -1-fnlen, SEEK_CUR);
+                       fnnam = malloc(fnlen + 1);
+                       fnnam[fnlen] = 0;
+                       fread(fnnam, fnlen, 1, finst);
+                       fseek(finst, -fnlen, SEEK_CUR);
+
+                       bytes -= fnlen + 1 + entbytes + 4 + 1;
+
+                       if(first){
+                               free(fnnam);
+                       }else{
+                               int i;
+                               entries[counts - incr - 1].dir = FALSE;
+                               entries[counts - incr - 1].name = fnnam;
+                               entries[counts - incr - 1].size = entbytes;
+                               for(i = 0; fnnam[i] != 0; i++){
+                                       if(fnnam[i] == '/') fnnam[i] = '\\';
+                               }
+                               incr++;
+                       }
+               }else{
+                       fnnam = malloc(entbytes + 1);
+                       fnnam[entbytes] = 0;
+                       fseek(finst, -4-entbytes, SEEK_CUR);
+                       fread(fnnam, 1, entbytes, finst);
+                       fseek(finst, -entbytes, SEEK_CUR);
+                       bytes -= entbytes + 4 + 1;
+
+                       if(first){
+                               free(fnnam);
+                       }else{
+                               entries[counts - incr - 1].dir = TRUE;
+                               entries[counts - incr - 1].name = fnnam;
+                               for(i = 0; fnnam[i] != 0; i++){
+                                       if(fnnam[i] == '/') fnnam[i] = '\\';
+                               }
+                               incr++;
+                       }
+               }
+               if(first){
+                       counts++;
+               }
+               if(bytes == 0) break;
+       }
+       bytes = bbytes;
+       if(first){
+               first = FALSE;
+               goto loop;
+       }
+
        strcpy(setupname, name);
        strcpy(setupname + strlen(name), " Setup");
        setupname[strlen(name) + 6] = 0;
index b56f88197bf24fd600b75c5dbe2009deae0eb368..328b4811452b443259809e410a2c8cdded163bbd 100644 (file)
--- a/SFX/sfx.h
+++ b/SFX/sfx.h
@@ -2,3 +2,5 @@
 
 #define GUI_SFX_NEXT   100
 #define GUI_SFX_CANCEL 101
+#define GUI_SFX_DIREDIT        102
+#define GUI_SFX_BROWSE 103
index 460d18cc58d88270f21dd7db1e1382ee21bfa031..9cd4c4d77bc86936eb10edd73db98497404a5f8c 100644 (file)
@@ -15,7 +15,7 @@ extern unsigned int sfx_len;
 uint32_t total;
 const char* projname;
 
-#define COMPRESS 16384
+#define COMPRESS 65535
 
 FILE* prepare_file(const char* path){
        FILE* f = fopen(path, "wb");
@@ -54,8 +54,8 @@ int scan(FILE* f, const char* base, const char* pref){
                                                strcpy(pt + strlen(pref) + 1, d->d_name);
                                                pt[strlen(pref) + 1 + strlen(d->d_name)] = 0;
 
-                                               fwrite(pt + 1, 1, strlen(pt) - 1, f);
-                                               written = strlen(pt) - 1;
+                                               fwrite(pt, 1, strlen(pt), f);
+                                               written = strlen(pt);
 
                                                total += 5 + written;
 
@@ -107,7 +107,9 @@ int scan(FILE* f, const char* base, const char* pref){
                                                printf("Compressing %s... ", path);
                                                fflush(stdout);
 
-                                               fwrite(pt + 1, 1, strlen(pt), f);
+                                               fwrite(pt, 1, strlen(pt), f);
+                                               byt = strlen(pt);
+                                               fwrite(&byt, 1, 1, f);
 
                                                do{
                                                        strm.avail_in = fread(in, 1, COMPRESS, src);
@@ -126,7 +128,7 @@ int scan(FILE* f, const char* base, const char* pref){
 
                                                printf("done, %lu bytes, %d%%\n", (unsigned long)written, (int)(((double)written / s.st_size) * 100));
 
-                                               total += strlen(pt) + 1 + 5 + written;
+                                               total += strlen(pt) + 1 + written + 4 + 1;
 
                                                for(i = 0; i < 4; i++){
                                                        byt = (written & 0xff000000) >> 24;