Files
pcsx2-sourceforge/pcsx2v2/windows/McdsDlg.cpp

1749 lines
44 KiB
C++

/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2008 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdio.h>
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <math.h>
#include "libintlmsc.h"
#define _(String) dgettext (PACKAGE, String)
#include "PS2Edefs.h"
#include "resource.h"
#include "Misc.h"
#include "System.h"
#include "McdsDlg.h"
#include <vector>
using namespace std;
u16 SJISTable[0xFFFF];
void IniSJISTable()
{
memset(SJISTable, 0, 0xFFFF);
//Blow me sony for using this retarded sjis to store the savegame name
SJISTable[0x20] = 0x0020;
SJISTable[0x21] = 0x0021;
SJISTable[0x22] = 0x0022;
SJISTable[0x23] = 0x0023;
SJISTable[0x24] = 0x0024;
SJISTable[0x25] = 0x0025;
SJISTable[0x26] = 0x0026;
SJISTable[0x27] = 0x0027;
SJISTable[0x28] = 0x0028;
SJISTable[0x29] = 0x0029;
SJISTable[0x2A] = 0x002A;
SJISTable[0x2B] = 0x002B;
SJISTable[0x2C] = 0x002C;
SJISTable[0x2D] = 0x002D;
SJISTable[0x2E] = 0x002E;
SJISTable[0x2F] = 0x002F;
SJISTable[0x30] = 0x0030;
SJISTable[0x31] = 0x0031;
SJISTable[0x32] = 0x0032;
SJISTable[0x33] = 0x0033;
SJISTable[0x34] = 0x0034;
SJISTable[0x35] = 0x0035;
SJISTable[0x36] = 0x0036;
SJISTable[0x37] = 0x0037;
SJISTable[0x38] = 0x0038;
SJISTable[0x39] = 0x0039;
SJISTable[0x3A] = 0x003A;
SJISTable[0x3B] = 0x003B;
SJISTable[0x3C] = 0x003C;
SJISTable[0x3D] = 0x003D;
SJISTable[0x3E] = 0x003E;
SJISTable[0x3F] = 0x003F;
SJISTable[0x40] = 0x0040;
SJISTable[0x41] = 0x0041;
SJISTable[0x42] = 0x0042;
SJISTable[0x43] = 0x0043;
SJISTable[0x44] = 0x0044;
SJISTable[0x45] = 0x0045;
SJISTable[0x46] = 0x0046;
SJISTable[0x47] = 0x0047;
SJISTable[0x48] = 0x0048;
SJISTable[0x49] = 0x0049;
SJISTable[0x4A] = 0x004A;
SJISTable[0x4B] = 0x004B;
SJISTable[0x4C] = 0x004C;
SJISTable[0x4D] = 0x004D;
SJISTable[0x4E] = 0x004E;
SJISTable[0x4F] = 0x004F;
SJISTable[0x50] = 0x0050;
SJISTable[0x51] = 0x0051;
SJISTable[0x52] = 0x0052;
SJISTable[0x53] = 0x0053;
SJISTable[0x54] = 0x0054;
SJISTable[0x55] = 0x0055;
SJISTable[0x56] = 0x0056;
SJISTable[0x57] = 0x0057;
SJISTable[0x58] = 0x0058;
SJISTable[0x59] = 0x0059;
SJISTable[0x5A] = 0x005A;
SJISTable[0x5B] = 0x005B;
SJISTable[0x5C] = 0x00A5;
SJISTable[0x5D] = 0x005D;
SJISTable[0x5E] = 0x005E;
SJISTable[0x5F] = 0x005F;
SJISTable[0x60] = 0x0060;
SJISTable[0x61] = 0x0061;
SJISTable[0x62] = 0x0062;
SJISTable[0x63] = 0x0063;
SJISTable[0x64] = 0x0064;
SJISTable[0x65] = 0x0065;
SJISTable[0x66] = 0x0066;
SJISTable[0x67] = 0x0067;
SJISTable[0x68] = 0x0068;
SJISTable[0x69] = 0x0069;
SJISTable[0x6A] = 0x006A;
SJISTable[0x6B] = 0x006B;
SJISTable[0x6C] = 0x006C;
SJISTable[0x6D] = 0x006D;
SJISTable[0x6E] = 0x006E;
SJISTable[0x6F] = 0x006F;
SJISTable[0x70] = 0x0070;
SJISTable[0x71] = 0x0071;
SJISTable[0x72] = 0x0072;
SJISTable[0x73] = 0x0073;
SJISTable[0x74] = 0x0074;
SJISTable[0x75] = 0x0075;
SJISTable[0x76] = 0x0076;
SJISTable[0x77] = 0x0077;
SJISTable[0x78] = 0x0078;
SJISTable[0x79] = 0x0079;
SJISTable[0x7A] = 0x007A;
SJISTable[0x7B] = 0x007B;
SJISTable[0x7C] = 0x007C;
SJISTable[0x7D] = 0x007D;
SJISTable[0x7E] = 0x007E;
SJISTable[0x8140] = 0x0020;
SJISTable[0x8149] = 0x0021;
SJISTable[0x22] = 0x0022;
SJISTable[0x8194] = 0x0023;
SJISTable[0x8190] = 0x0024;
SJISTable[0x8193] = 0x0025;
SJISTable[0x8195] = 0x0026;
SJISTable[0x27] = 0x0027;
SJISTable[0x8169] = 0x0028;
SJISTable[0x816A] = 0x0029;
SJISTable[0x8196] = 0x002A;
SJISTable[0x817B] = 0x002B;
SJISTable[0x8143] = 0x002C;
SJISTable[0x815D] = 0x002D;
SJISTable[0x8144] = 0x002E;
SJISTable[0x815E] = 0x002F;
SJISTable[0x824F] = 0x0030;
SJISTable[0x8250] = 0x0031;
SJISTable[0x8251] = 0x0032;
SJISTable[0x8252] = 0x0033;
SJISTable[0x8253] = 0x0034;
SJISTable[0x8254] = 0x0035;
SJISTable[0x8255] = 0x0036;
SJISTable[0x8256] = 0x0037;
SJISTable[0x8257] = 0x0038;
SJISTable[0x8258] = 0x0039;
SJISTable[0x8146] = 0x003A;
SJISTable[0x8147] = 0x003B;
SJISTable[0x8183] = 0x003C;
SJISTable[0x8181] = 0x003D;
SJISTable[0x8184] = 0x003E;
SJISTable[0x8148] = 0x003F;
SJISTable[0x8197] = 0x0040;
SJISTable[0x8260] = 0x0041;
SJISTable[0x8261] = 0x0042;
SJISTable[0x8262] = 0x0043;
SJISTable[0x8263] = 0x0044;
SJISTable[0x8264] = 0x0045;
SJISTable[0x8265] = 0x0046;
SJISTable[0x8266] = 0x0047;
SJISTable[0x8267] = 0x0048;
SJISTable[0x8268] = 0x0049;
SJISTable[0x8269] = 0x004A;
SJISTable[0x826A] = 0x004B;
SJISTable[0x826B] = 0x004C;
SJISTable[0x826C] = 0x004D;
SJISTable[0x826D] = 0x004E;
SJISTable[0x826E] = 0x004F;
SJISTable[0x826F] = 0x0050;
SJISTable[0x8270] = 0x0051;
SJISTable[0x8271] = 0x0052;
SJISTable[0x8272] = 0x0053;
SJISTable[0x8273] = 0x0054;
SJISTable[0x8274] = 0x0055;
SJISTable[0x8275] = 0x0056;
SJISTable[0x8276] = 0x0057;
SJISTable[0x8277] = 0x0058;
SJISTable[0x8278] = 0x0059;
SJISTable[0x8279] = 0x005A;
SJISTable[0x816D] = 0x005B;
SJISTable[0x818F] = 0x00A5;
SJISTable[0x816E] = 0x005D;
SJISTable[0x814F] = 0x005E;
SJISTable[0x8151] = 0x005F;
SJISTable[0x814D] = 0x0060;
SJISTable[0x8281] = 0x0061;
SJISTable[0x8282] = 0x0062;
SJISTable[0x8283] = 0x0063;
SJISTable[0x8284] = 0x0064;
SJISTable[0x8285] = 0x0065;
SJISTable[0x8286] = 0x0066;
SJISTable[0x8287] = 0x0067;
SJISTable[0x8288] = 0x0068;
SJISTable[0x8289] = 0x0069;
SJISTable[0x828A] = 0x006A;
SJISTable[0x828B] = 0x006B;
SJISTable[0x828C] = 0x006C;
SJISTable[0x828D] = 0x006D;
SJISTable[0x828E] = 0x006E;
SJISTable[0x828F] = 0x006F;
SJISTable[0x8290] = 0x0070;
SJISTable[0x8291] = 0x0071;
SJISTable[0x8292] = 0x0072;
SJISTable[0x8293] = 0x0073;
SJISTable[0x8294] = 0x0074;
SJISTable[0x8295] = 0x0075;
SJISTable[0x8296] = 0x0076;
SJISTable[0x8297] = 0x0077;
SJISTable[0x8298] = 0x0078;
SJISTable[0x8299] = 0x0079;
SJISTable[0x829A] = 0x007A;
SJISTable[0x816F] = 0x007B;
SJISTable[0x8162] = 0x007C;
SJISTable[0x8170] = 0x007D;
SJISTable[0x7E] = 0x007E;
}
HWND mcdDlg;
HTREEITEM root;
HWND treewindow;
HTREEITEM AddTreeItem(HWND treeview, HTREEITEM parent, const char *name, LPARAM lp)
{
TVINSERTSTRUCT node={
parent,
0,
{
TVIF_TEXT,
NULL,
TVIS_EXPANDED,
TVIS_EXPANDED,
(LPSTR)name,
0,
0,
0,
0,
lp,
1
}
};
return TreeView_InsertItem(treeview,&node);
}
void ReadDir(int cluster, int rec, HTREEITEM tree);
class Time
{
public:
u8 sec;
u8 min;
u8 hour;
u8 day;
u8 month;
u16 year;
};
class Dir
{
protected:
public:
static const u16 DF_READ = 0x0001;
static const u16 DF_WRITE = 0x0002;
static const u16 DF_EXECUTE = 0x0004;
static const u16 DF_PROTECTED = 0x0008;
static const u16 DF_FILE = 0x0010;
static const u16 DF_DIRECTORY = 0x0020;
static const u16 DF_HIDDEN = 0x2000;
static const u16 DF_EXISTS = 0x8000;
// Directory Attributes
u16 Mode;
s32 Lenght;
Time Created;
s32 Cluster;
u32 DirEntry;
Time Modified;
u32 Attribute;
s8 Name[256]; // just in case some names are longer
// Parent dir and contents of dir
Dir *Parent;
vector<Dir> Sons;
// Used to store the contents of a file
u8 *File;
Dir()
{
File = 0;
}
bool IsHidden()
{
return (Mode & DF_HIDDEN) ? 1 : 0;
}
bool IsFile()
{
return (Mode & DF_FILE) ? 1 : 0;
}
bool IsDirectory()
{
return (Mode & DF_DIRECTORY) ? 1 : 0;
}
bool Exists()
{
return (Mode & DF_EXISTS) ? 1 : 0;
}
void Load(s8 *d)
{
File = 0;
// For the moment we dont need to load more data
Mode = *(u16 *)d;
Lenght = *(u32 *)(d + 0x04);
Cluster = *(u32 *)(d + 0x10);
strncpy(Name, d + 0x40, 255);
}
Dir* AddSon(Dir &d)
{
d.Parent = this;
vector<Dir>::iterator i = Sons.insert(Sons.end(), d);
return &i[0];
}
void Release()
{
for(int i=0;i<Sons.size();i++)
{
Sons[i].Release();
}
Sons.clear();
if(File != 0)
free(File);
}
u32 BuildICO(char *dest)
{
if(IsDirectory() || !Exists())
return 0;
u32 FileID = *(u32 *)File;
u32 AnimationShapes = *(u32 *)(File + 4);
u32 TextureType = *(u32 *)(File + 8);
//u32 ConstantCheck = *(u32 *)(d->File + 12);
u32 NumVertex = *(u32 *)(File + 16);
// Check if it's an ico file
if(FileID != 0x00010000)
{
MessageBox(mcdDlg, "It's not an ICO file.", "Error", 0);
return 0;
}
// Is texture compressed?
if(TextureType != 0x07)
{
//MessageBox(mcdDlg, "Compressed texture, not yet supported.", "Error", 0);
//return;
}
// Calculate the offset to the animation segment
u32 VertexSize = (AnimationShapes * 8) + 8 + 8;
u32 AnimationSegmentOffset = (VertexSize * NumVertex) + 20;
// Check if we really are at the animation header
u32 AnimationID = *(u32 *)(File + AnimationSegmentOffset);
if(AnimationID != 0x00000001)
{
MessageBox(mcdDlg, "Animation header ID is incorrect.", "Error", 0);
return 0;
}
// Get the size of all the animation segment
u32 FrameLenght = *(u32 *)(File + AnimationSegmentOffset + 4);
u32 NumberOfFrames = *(u32 *)(File + AnimationSegmentOffset + 16);
u32 Offset = AnimationSegmentOffset + 20;
for(int i=0;i<NumberOfFrames;i++)
{
u32 KeyNum = *(u32 *)(File + Offset + 4);
Offset += 16 + (KeyNum * 8) - 8; // The -8 is there because the doc with the ico format spec is either wrong or I'm stupid
}
int z, y=0;
u16 ico[0x4000];
//u8 cico[128*128*3];
if(TextureType > 0x07)
{
u32 CompressedDataSize = *(u32 *)(File + Offset);
//RLE compression
Offset += 4;
u32 OffsetEnd = Offset + CompressedDataSize;
u32 WriteCount = 0;
while(WriteCount < 0x8000 && Offset < OffsetEnd)
{
u16 Data = *(u16 *)(File + Offset);
if(Data < 0xFF00) //Replication
{
Offset += 2;
u16 Rep = *(u16 *)(File + Offset);
for(int i=0;i<Data;i++)
{
ico[WriteCount] = Rep;
WriteCount++;
}
Offset += 2;
}
else // Lenght
{
u16 Lenght = 0xFFFF - Data;
Offset += 2;
Lenght++; // doh! This shit made me debug for hours
for(int i=0;i<Lenght;i++)
{
ico[WriteCount] = *(u16 *)(File + Offset);
WriteCount++;
Offset += 2;
}
}
}
}
else
{
// Get the texture from the file
memcpy(ico, &File[/*d->Lenght-0x8000*/Offset], 0x8000);
}
// Convert from TIM to rgb
for(z=0;z<0x4000;z++)
{
dest[y] = 8 * (ico[z] & 0x1F);
dest[y+1] = 8 * ((ico[z] >>5) & 0x1F);
dest[y+2] = 8 * (ico[z] >>10);
y += 3;
}
return 1;
}
};
class SaveGame
{
public:
Dir *D;
char Name1[256];
char Name2[256];
u8 Icon[128*128*3];
SaveGame(Dir *_Dir)
{
char IconName[256];
D = _Dir;
// Find icon.sys
for(int i=0;i<D->Sons.size();i++)
{
if(!strcmp("icon.sys", D->Sons[i].Name))
{
char temp[256];
// Get Name in SJIS format
u16 *p = (u16 *)(D->Sons[i].File + 192);
while(*p != 0x0000)
{
// Switch bytes
u8 *pp = (u8 *)p;
u8 tb = *pp;
*pp = pp[1];
pp[1] = tb;
// Translate char
*p = SJISTable[*p];
p++;
}
// Convert unicode string
wcstombs(temp, (wchar_t *)(D->Sons[i].File + 192), 255);
// Get the second line separator
u16 SecondLine = *(u16 *)(D->Sons[i].File + 6);
SecondLine /= 2;
// Copy the 2 parts of the string to different strings
strncpy(Name1, temp, SecondLine);
Name1[SecondLine] = 0;
strcpy(Name2, &temp[SecondLine]);
if(strlen(Name2) + SecondLine > 68)
Name2[0] = 0;
// Get the icon file name
strcpy(IconName, (char *)D->Sons[i].File + 260);
}
}
// Find the icon now
for(int i=0;i<D->Sons.size();i++)
{
if(!strcmp(IconName, D->Sons[i].Name))
{
D->Sons[i].BuildICO((char*)Icon);
}
}
}
void AddIcoToImageList(HIMAGELIST il)
{
HDC hDC = GetDC(NULL);
HDC memDC = CreateCompatibleDC (hDC);
HBITMAP memBM = CreateCompatibleBitmap ( hDC, 128, 128 );
SelectObject ( memDC, memBM );
int px, py, pc=0;
for(px=0;px<128;px++){
for(py=0;py<128;py++){
SetPixel(memDC, py, px, RGB(Icon[pc], Icon[pc+1], Icon[pc+2]));
pc+=3;
}
}
HDC memDC2 = CreateCompatibleDC (hDC);
HBITMAP memBM2 = CreateCompatibleBitmap ( hDC, 64, 64 );
SelectObject ( memDC2, memBM2 );
SetStretchBltMode(memDC2, HALFTONE);
StretchBlt(memDC2, 0, 0, 64, 64, memDC, 0, 0, 128, 128, SRCCOPY);
DeleteDC(memDC2);
DeleteDC(memDC);
ImageList_Add(il, memBM2, NULL);
DeleteObject(memBM);
DeleteObject(memBM2);
ReleaseDC(NULL, hDC);
}
void DrawICO(HWND hWnd)
{
// int px, py, pc=0;
HDC dc = GetDC(hWnd);
/*
for(px=0;px<128;px++){
for(py=0;py<128;py++){
SetPixel(dc, py, px, RGB(Icon[pc], Icon[pc+1], Icon[pc+2]));
pc+=3;
}
}
*/
/*
HDC hDC = GetDC(NULL);
HDC memDC = CreateCompatibleDC ( hDC );
HBITMAP memBM = CreateCompatibleBitmap ( hDC, 256, 128 );
SelectObject ( memDC, memBM );
for(px=0;px<128;px++){
for(py=0;py<128;py++){
SetPixel(memDC, py, px, RGB(Icon[pc], Icon[pc+1], Icon[pc+2]));
pc+=3;
}
}
RECT rect;
rect.left=132;
rect.right=255;
rect.top=4;
rect.bottom=255;
DrawText(memDC, Name1, strlen(Name1), &rect, 0);
rect.top=20;
DrawText(memDC, Name2, strlen(Name2), &rect, 0);
SetStretchBltMode(dc, HALFTONE);
StretchBlt(dc, 0, 0, 64, 64, memDC, 0, 0, 128, 128, SRCCOPY);
//BitBlt(dc, 0, 0, 256, 128, memDC, 0, 0, SRCCOPY);
*/
}
};
class MemoryCard
{
public:
FILE *fp;
int FAT[256*256];
int indirect_table[256];
char FileName[1024];
Dir Root;
vector<SaveGame> SaveGameList;
HIMAGELIST ImageList;
MemoryCard()
{
fp = 0;
ImageList = 0;
}
int BuildFAT()
{
int IFC;
// indirect table containing the clusters with FAT data
int i, o;
// First read IFC from the superblock (8MB cards only have 1)
fseek(fp, 0x50, SEEK_SET);
fread(&IFC, 4, 1, fp);
if(IFC != 8)
{
MessageBox(mcdDlg, "IFC is not 8. Memory Card is probably corrupt.", "Error", 0);
return 0;
}
#ifdef _DEBUG
SysPrintf("IFC: %d\n\n", IFC);
#endif
// Read the cluster with the indirect data to the FAT.
fseek(fp, 0x420 * IFC, SEEK_SET);
fread(indirect_table, 4, 128, fp);
fseek(fp, (0x420 * IFC) + 0x210, SEEK_SET);
fread(&indirect_table[128], 4, 128, fp);
// Build the FAT table from the indirect_table
o = 0;
i = 0;
while(indirect_table[i] != 0xFFFFFFFF)
{
fseek(fp, 0x420 * indirect_table[i], SEEK_SET);
fread(&FAT[o], 4, 128, fp);
o+=128;
fseek(fp, (0x420 * indirect_table[i]) + 0x210, SEEK_SET);
fread(&FAT[o], 4, 128, fp);
o+=128;
i++;
}
return 1;
}
void ReadFile(Dir *d)
{
int cluster = d->Cluster;
int size = d->Lenght;
int numclusters = (int)ceil((double)size / 1024);
int numpages = (int)ceil((double)size / 512);
int i=0, j=0, c=0, read=0;
d->File = (u8 *) malloc(size);
for(i=0;i<numclusters;i++)
{
read = size - c;
if(read > 512)
read = 512;
fseek(fp, 0xA920 + ((cluster) * 0x420), SEEK_SET);
fread(&d->File[c], 1, read, fp);
c+=read;
j++;
if(j == numpages)
break;
read = size - c;
if(read > 512)
read = 512;
fseek(fp, 0xA920 + (((cluster) * 0x420)+528), SEEK_SET);
fread(&d->File[c], 1, read, fp);
c+=read;
j++;
if(j == numpages)
break;
cluster = FAT[cluster];
cluster = cluster ^ 0x80000000;
if(cluster == 0x7FFFFFFF || cluster == 0xFFFFFFFF)
break;
}
}
void Read(u32 cluster, Dir *d)
{
int i;
s8 file1[512], file2[512];
Dir D1, D2;
for(i = 0; i < 0xffff; i++)
{
// Read first page containing the first dir
fseek(fp, 0xA920 + ((cluster) * 0x420), SEEK_SET);
fread(file1, 1, 512, fp);
// Initialize the temporal dir
D1.Load(file1);
if(D1.Exists() && D1.Lenght >= 0 && D1.Cluster >= 0)
{
// If it exists add the dir to current dir
Dir *td = d->AddSon(D1);
// If it's a directory and not . or .. recursive call
if(D1.IsDirectory() && D1.Name[0]!= '.' )
{
Read(td->Cluster, td);
}
// If it's a file load the file
if(D1.IsFile())
{
ReadFile(td);
}
}
// Read second page with second dir or empty
fseek(fp, 0xA920 + (((cluster) * 0x420) + 528), SEEK_SET);
fread(file2, 1, 512, fp);
// Initialize the temporal dir and add it to current dir
D2.Load(file2);
if(D2.Exists() && D2.Lenght >= 0 && D2.Cluster >= 0)
{
Dir *td = d->AddSon(D2);
if(D2.IsDirectory() && D2.Name[0]!= '.')
{
Read(td->Cluster, td);
}
// If it's a file load the file
if(D2.IsFile() && D2.Name[0]!= '.')
{
ReadFile(td);
}
}
// Get next cluster from the FAT table
cluster = FAT[cluster];
cluster = cluster ^ 0x80000000;
if(cluster == 0x7FFFFFFF || cluster == 0xFFFFFFFF)
break;
}
}
void Load(char *filename)
{
strcpy(FileName, filename);
// Clear previous data
if(fp != 0)
{
fclose(fp);
}
memset(FAT, 0, 256*256*4);
Root.Release();
SaveGameList.clear();
ImageList_Destroy(ImageList);
// Open memory card file
fp = fopen(FileName, "rb");
// Check if we opened the file
if(fp == NULL)
{
MessageBox(mcdDlg, "Unable to open memory card file.", "Error", 0);
return;
}
// Build the FAT table for the card
if(BuildFAT() == 1)
{
// Read the root dir
Read(0, &Root);
}
fclose(fp);
ReadSaveGames();
}
void AddDirToTreeView(HWND hWnd, HTREEITEM tree, Dir *d)
{
for(int i=0;i<d->Sons.size();i++)
{
HTREEITEM temptree = AddTreeItem(hWnd, tree, d->Sons[i].Name, 0);
if(d->Sons[i].IsDirectory())
{
TreeView_SetItemState(hWnd, temptree, TVIS_EXPANDED|TVIS_BOLD, 0x00F0);
AddDirToTreeView(hWnd, temptree, &d->Sons[i]);
}
}
}
void AddToListView(HWND hWnd)
{
ListView_SetIconSpacing(hWnd, 128, 128);
ListView_DeleteAllItems(hWnd);
ListView_SetImageList(hWnd, ImageList, LVSIL_NORMAL);
LVITEM item;
char temp[2560];
item.mask = LVIF_IMAGE | LVIF_TEXT;
item.iItem = 0;
item.iSubItem = 0;
item.state = 0;
item.stateMask = 0;
item.pszText = temp;
item.cchTextMax = 255;
item.iImage = 1;
item.iIndent = 0;
item.lParam = 0;
for(int i=0;i<SaveGameList.size();i++)
{
strcpy(item.pszText, SaveGameList[i].Name1);
if(SaveGameList[i].Name2[0] != 0)
{
strcat(item.pszText, "\n");
strcat(item.pszText, SaveGameList[i].Name2);
}
item.iImage = i;
ListView_InsertItem(hWnd, &item);
}
}
void AddCardToTreeView(HWND hWnd)
{
TreeView_DeleteAllItems(hWnd);
AddDirToTreeView(hWnd, 0, &Root);
}
// In theory all the games use a folder and then put files inside it, so for the moment this will be enough
Dir *FindFile(char *dir, char *file)
{
//Find the dir first
int i;
for(i=0;i<Root.Sons.size();i++)
{
if(!strcmp(dir, Root.Sons[i].Name))
break;
}
if(i == Root.Sons.size())
{
MessageBox(mcdDlg, "Unable to find the directory.", "Error", 0);
return NULL;
}
// Find the file now
Dir *d = &Root.Sons[i];
for(i=0;i<d->Sons.size();i++)
{
if(!strcmp(file, d->Sons[i].Name))
break;
}
if(i == d->Sons.size())
{
MessageBox(mcdDlg, "Unable to find the file.", "Error", 0);
return NULL;
}
return &d->Sons[i];
}
void PaintICOFile(HWND hWnd, char *dir, char *name)
{
// First find the file
Dir *d = FindFile(dir, name);
if(d == NULL)
return;
u32 FileID = *(u32 *)d->File;
u32 AnimationShapes = *(u32 *)(d->File + 4);
u32 TextureType = *(u32 *)(d->File + 8);
//u32 ConstantCheck = *(u32 *)(d->File + 12);
u32 NumVertex = *(u32 *)(d->File + 16);
// Check if it's an ico file
if(FileID != 0x00010000)
{
MessageBox(mcdDlg, "It's not an ICO file.", "Error", 0);
return;
}
// Is texture compressed?
if(TextureType != 0x07)
{
//MessageBox(mcdDlg, "Compressed texture, not yet supported.", "Error", 0);
//return;
}
// Calculate the offset to the animation segment
u32 VertexSize = (AnimationShapes * 8) + 8 + 8;
u32 AnimationSegmentOffset = (VertexSize * NumVertex) + 20;
// Check if we really are at the animation header
u32 AnimationID = *(u32 *)(d->File + AnimationSegmentOffset);
if(AnimationID != 0x00000001)
{
MessageBox(mcdDlg, "Animation header ID is incorrect.", "Error", 0);
return;
}
// Get the size of all the animation segment
u32 FrameLenght = *(u32 *)(d->File + AnimationSegmentOffset + 4);
u32 NumberOfFrames = *(u32 *)(d->File + AnimationSegmentOffset + 16);
u32 Offset = AnimationSegmentOffset + 20;
for(int i=0;i<NumberOfFrames;i++)
{
u32 KeyNum = *(u32 *)(d->File + Offset + 4);
Offset += 16 + (KeyNum * 8) - 8; // The -8 is there because the doc with the ico format spec is either wrong or I'm stupid
}
int z, y=0;
u16 ico[0x4000];
u8 cico[128*128*3];
if(TextureType > 0x07)
{
u32 CompressedDataSize = *(u32 *)(d->File + Offset);
//RLE compression
Offset += 4;
u32 OffsetEnd = Offset + CompressedDataSize;
u32 WriteCount = 0;
while(WriteCount < 0x8000 && Offset < OffsetEnd)
{
u16 Data = *(u16 *)(d->File + Offset);
if(Data < 0xFF00) //Replication
{
Offset += 2;
u16 Rep = *(u16 *)(d->File + Offset);
for(int i=0;i<Data;i++)
{
ico[WriteCount] = Rep;
WriteCount++;
}
Offset += 2;
}
else // Lenght
{
u16 Lenght = 0xFFFF - Data;
Offset += 2;
Lenght++; // doh! This shit made me debug for hours
for(int i=0;i<Lenght;i++)
{
ico[WriteCount] = *(u16 *)(d->File + Offset);
WriteCount++;
Offset += 2;
}
}
}
}
else
{
// Get the texture from the file
memcpy(ico, &d->File[/*d->Lenght-0x8000*/Offset], 0x8000);
}
// Convert from TIM to rgb
for(z=0;z<0x4000;z++)
{
cico[y] = 8 * (ico[z] & 0x1F);
cico[y+1] = 8 * ((ico[z] >>5) & 0x1F);
cico[y+2] = 8 * (ico[z] >>10);
y += 3;
}
// Draw
int px, py, pc=0;
HDC dc = GetDC(hWnd);
for(px=0;px<128;px++){
for(py=0;py<128;py++){
SetPixel(dc, py, px, RGB(cico[pc], cico[pc+1], cico[pc+2]));
pc+=3;
}
}
}
void ReadSaveGames()
{
// Initialize the conversion table for SJIS strings
IniSJISTable();
// Create the image list
ImageList = ImageList_Create(64, 64, ILC_COLOR32, 10, 256);
for(int i=0;i<Root.Sons.size();i++)
{
if(Root.Sons[i].Name[0] != '.')
{
SaveGame SG(&Root.Sons[i]);
SaveGameList.push_back(SG);
SG.AddIcoToImageList(ImageList);
}
}
}
int FindEmptyCluster()
{
// Read fat until free is found 0x7FFFFFFF
for(int i=0;i<256*256;i++)
{
if(FAT[i] == 0x7FFFFFFF)
return i;
}
// if we dont find it, memcard is full
return -1;
}
void SaveRootDir(Dir *Di)
{
// Open memcard
int i;
fclose(fp);
fp = fopen(FileName, "rb+");
if(fp == NULL)
{
MessageBox(mcdDlg, "Unable to open memcard.", "Error", 0);
return;
}
//walk the root dir fat chain
int cluster = 0, oldcluster = 0;
//s8 file1[256], file2[256];
int Lenght = Root.Sons[0].Lenght;
for(i = 0; i < 0xffff; i++)
{
// Get next cluster from the FAT table
oldcluster = cluster;
cluster = FAT[cluster];
cluster = cluster ^ 0x80000000;
if(cluster == 0x7FFFFFFF || cluster == 0xFFFFFFFF)
break;
}
// oldcluster has in theory the last cluster
// if lenght is even, there is empty space in cluster
// if lenght is odd we'll need a new cluster.
int dircluster = FindEmptyCluster();
char dir[512];
memset(dir, 0, 512);
*(u16 *)&dir[0] = Dir::DF_EXISTS | Dir::DF_DIRECTORY | Dir::DF_READ; // mode flag
*(u32 *)&dir[4] = Di->Sons.size(); // number of files inside the dir
*(u8 *)&dir[8] = 0; // creation time seconds
*(u8 *)&dir[9] = 0; // creation time minuts
*(u8 *)&dir[10] = 0; // creation time hours
*(u8 *)&dir[11] = 1; // creation time day
*(u8 *)&dir[12] = 1; // creation time month
*(u16 *)&dir[13] = 2008; // creation time year
*(u32 *)&dir[16] = dircluster; // cluster with the contents of the dir
*(u32 *)&dir[20] = 0; // dir entry for '.'
*(u8 *)&dir[24] = 0; // modification time seconds
*(u8 *)&dir[25] = 0; // modification time minuts
*(u8 *)&dir[26] = 0; // modification time hours
*(u8 *)&dir[27] = 1; // modification time day
*(u8 *)&dir[28] = 1; // modification time month
*(u16 *)&dir[29] = 2008; // modification time year
*(u32 *)&dir[32] = 0; // user attribute unused
strcpy(&dir[64], Di->Name); // DIRECTORY NAME
if(Lenght % 2)
{
// Find empty cluster...
int c = FindEmptyCluster();
// THIS MAY BE WRONG...TEST
FAT[oldcluster] = c;
FAT[c] = 0xFFFFFFFF;
// Add dir to first page of new cluster
fseek(fp, 0xA920 + (((c) * 0x420) + 0), SEEK_SET);
fwrite(dir, 512, 1, fp);
}
else
{
// Add dir to second page of cluster
fseek(fp, 0xA920 + (((oldcluster) * 0x420) + 528), SEEK_SET);
fwrite(dir, 512, 1, fp);
}
// CALCULATE CRCS OF CLUSTER
// INCREASE ROOT DIR SIZE BY 1
fseek(fp, 0xA920 + (((0) * 0x420) + 4), SEEK_SET);
int nl = Lenght + 1;
fwrite(&nl, 4, 1, fp);
int numfiles = 5;
// ADD FILE ENTRIES TO DIR ., ..
memset(dir, 0, 512);
*(u16 *)&dir[0] = Dir::DF_EXISTS | Dir::DF_DIRECTORY | Dir::DF_READ; // mode flag
*(u32 *)&dir[4] = numfiles; // number of files inside the dir
*(u8 *)&dir[8] = 0; // creation time seconds
*(u8 *)&dir[9] = 0; // creation time minuts
*(u8 *)&dir[10] = 0; // creation time hours
*(u8 *)&dir[11] = 1; // creation time day
*(u8 *)&dir[12] = 1; // creation time month
*(u16 *)&dir[13] = 2008; // creation time year
*(u32 *)&dir[16] = 0; // cluster with the contents of the dir
*(u32 *)&dir[20] = 0; // dir entry for '.'
*(u8 *)&dir[24] = 0; // modification time seconds
*(u8 *)&dir[25] = 0; // modification time minuts
*(u8 *)&dir[26] = 0; // modification time hours
*(u8 *)&dir[27] = 1; // modification time day
*(u8 *)&dir[28] = 1; // modification time month
*(u16 *)&dir[29] = 2008; // modification time year
*(u32 *)&dir[32] = 0; // user attribute unused
strcpy(&dir[64], "."); // DIRECTORY NAME
fseek(fp, 0xA920 + (((dircluster) * 0x420) + 0), SEEK_SET);
fwrite(dir, 512, 1, fp);
memset(dir, 0, 512);
*(u16 *)&dir[0] = Dir::DF_EXISTS | Dir::DF_DIRECTORY | Dir::DF_READ; // mode flag
*(u32 *)&dir[4] = 2; // number of files inside the dir
*(u8 *)&dir[8] = 0; // creation time seconds
*(u8 *)&dir[9] = 0; // creation time minuts
*(u8 *)&dir[10] = 0; // creation time hours
*(u8 *)&dir[11] = 1; // creation time day
*(u8 *)&dir[12] = 1; // creation time month
*(u16 *)&dir[13] = 2008; // creation time year
*(u32 *)&dir[16] = 0; // cluster with the contents of the dir
*(u32 *)&dir[20] = 0; // dir entry for '.'
*(u8 *)&dir[24] = 0; // modification time seconds
*(u8 *)&dir[25] = 0; // modification time minuts
*(u8 *)&dir[26] = 0; // modification time hours
*(u8 *)&dir[27] = 1; // modification time day
*(u8 *)&dir[28] = 1; // modification time month
*(u16 *)&dir[29] = 2008; // modification time year
*(u32 *)&dir[32] = 0; // user attribute unused
strcpy(&dir[64], ".."); // DIRECTORY NAME
fseek(fp, 0xA920 + (((dircluster) * 0x420) + 528), SEEK_SET);
fwrite(dir, 512, 1, fp);
FAT[dircluster] = 0xFFFFFFFF;
// ADD REST OF FILES
for(int i=2;i<numfiles;i+=2)
{
// Find a new cluster to store files and updata FAT table
int newcluster = FindEmptyCluster();
FAT[dircluster] = newcluster;
FAT[newcluster] = 0xFFFFFFFF;
dircluster = newcluster;
// Add first file
memset(dir, 0, 512);
*(u16 *)&dir[0] = Dir::DF_EXISTS | Dir::DF_FILE | Dir::DF_READ; // mode flag
*(u32 *)&dir[4] = 0; // SIZE OF FILE
*(u8 *)&dir[8] = 0; // creation time seconds
*(u8 *)&dir[9] = 0; // creation time minuts
*(u8 *)&dir[10] = 0; // creation time hours
*(u8 *)&dir[11] = 1; // creation time day
*(u8 *)&dir[12] = 1; // creation time month
*(u16 *)&dir[13] = 2008; // creation time year
*(u32 *)&dir[16] = 0; // cluster with the contents of the file
*(u32 *)&dir[20] = 0; // dir entry for '.'
*(u8 *)&dir[24] = 0; // modification time seconds
*(u8 *)&dir[25] = 0; // modification time minuts
*(u8 *)&dir[26] = 0; // modification time hours
*(u8 *)&dir[27] = 1; // modification time day
*(u8 *)&dir[28] = 1; // modification time month
*(u16 *)&dir[29] = 2008; // modification time year
*(u32 *)&dir[32] = 0; // user attribute unused
strcpy(&dir[64], "Kaka1"); // DIRECTORY NAME
fseek(fp, 0xA920 + (((dircluster) * 0x420) + 0), SEEK_SET);
fwrite(dir, 512, 1, fp);
// Add first file contents
// Add second file
// Add second file contents
}
// SAVE FAT HERE
for(int i=0;i<8;i++)
{
fseek(fp, 0x420 * indirect_table[i], SEEK_SET);
fwrite(&FAT[i*256], 512, 1, fp);
fseek(fp, 16, SEEK_CUR);
fwrite(&FAT[(i*256)+128], 512, 1, fp);
}
// Close the file
fclose(fp);
}
void SaveRootDir(char *name)
{
int i;
// Open memcard
fclose(fp);
fp = fopen(FileName, "rb+");
if(fp == NULL)
{
MessageBox(mcdDlg, "Unable to open memcard.", "Error", 0);
return;
}
//walk the root dir fat chain
int cluster = 0, oldcluster = 0;
//s8 file1[256], file2[256];
int Lenght = Root.Sons[0].Lenght;
for(i = 0; i < 0xffff; i++)
{
// Get next cluster from the FAT table
oldcluster = cluster;
cluster = FAT[cluster];
cluster = cluster ^ 0x80000000;
if(cluster == 0x7FFFFFFF || cluster == 0xFFFFFFFF)
break;
}
// oldcluster has in theory the last cluster
// if lenght is even, there is empty space in cluster
// if lenght is odd we'll need a new cluster.
int dircluster = FindEmptyCluster();
char dir[512];
memset(dir, 0, 512);
*(u16 *)&dir[0] = Dir::DF_EXISTS | Dir::DF_DIRECTORY | Dir::DF_READ; // mode flag
*(u32 *)&dir[4] = 2; // number of files inside the dir
*(u8 *)&dir[8] = 0; // creation time seconds
*(u8 *)&dir[9] = 0; // creation time minuts
*(u8 *)&dir[10] = 0; // creation time hours
*(u8 *)&dir[11] = 1; // creation time day
*(u8 *)&dir[12] = 1; // creation time month
*(u16 *)&dir[13] = 2008; // creation time year
*(u32 *)&dir[16] = dircluster; // cluster with the contents of the dir
*(u32 *)&dir[20] = 0; // dir entry for '.'
*(u8 *)&dir[24] = 0; // modification time seconds
*(u8 *)&dir[25] = 0; // modification time minuts
*(u8 *)&dir[26] = 0; // modification time hours
*(u8 *)&dir[27] = 1; // modification time day
*(u8 *)&dir[28] = 1; // modification time month
*(u16 *)&dir[29] = 2008; // modification time year
*(u32 *)&dir[32] = 0; // user attribute unused
strcpy(&dir[64], "DirName"); // DIRECTORY NAME
if(Lenght % 2)
{
// Find empty cluster...
int c = FindEmptyCluster();
// THIS MAY BE WRONG...TEST
FAT[oldcluster] = c;
FAT[c] = 0xFFFFFFFF;
// Add dir to first page of new cluster
fseek(fp, 0xA920 + (((c) * 0x420) + 0), SEEK_SET);
fwrite(dir, 512, 1, fp);
}
else
{
// Add dir to second page of cluster
fseek(fp, 0xA920 + (((oldcluster) * 0x420) + 528), SEEK_SET);
fwrite(dir, 512, 1, fp);
}
// CALCULATE CRCS OF CLUSTER
// INCREASE ROOT DIR SIZE BY 1
fseek(fp, 0xA920 + (((0) * 0x420) + 4), SEEK_SET);
int nl = Lenght + 1;
fwrite(&nl, 4, 1, fp);
int numfiles = 5;
// ADD FILE ENTRIES TO DIR ., ..
memset(dir, 0, 512);
*(u16 *)&dir[0] = Dir::DF_EXISTS | Dir::DF_DIRECTORY | Dir::DF_READ; // mode flag
*(u32 *)&dir[4] = numfiles; // number of files inside the dir
*(u8 *)&dir[8] = 0; // creation time seconds
*(u8 *)&dir[9] = 0; // creation time minuts
*(u8 *)&dir[10] = 0; // creation time hours
*(u8 *)&dir[11] = 1; // creation time day
*(u8 *)&dir[12] = 1; // creation time month
*(u16 *)&dir[13] = 2008; // creation time year
*(u32 *)&dir[16] = 0; // cluster with the contents of the dir
*(u32 *)&dir[20] = 0; // dir entry for '.'
*(u8 *)&dir[24] = 0; // modification time seconds
*(u8 *)&dir[25] = 0; // modification time minuts
*(u8 *)&dir[26] = 0; // modification time hours
*(u8 *)&dir[27] = 1; // modification time day
*(u8 *)&dir[28] = 1; // modification time month
*(u16 *)&dir[29] = 2008; // modification time year
*(u32 *)&dir[32] = 0; // user attribute unused
strcpy(&dir[64], "."); // DIRECTORY NAME
fseek(fp, 0xA920 + (((dircluster) * 0x420) + 0), SEEK_SET);
fwrite(dir, 512, 1, fp);
memset(dir, 0, 512);
*(u16 *)&dir[0] = Dir::DF_EXISTS | Dir::DF_DIRECTORY | Dir::DF_READ; // mode flag
*(u32 *)&dir[4] = 2; // number of files inside the dir
*(u8 *)&dir[8] = 0; // creation time seconds
*(u8 *)&dir[9] = 0; // creation time minuts
*(u8 *)&dir[10] = 0; // creation time hours
*(u8 *)&dir[11] = 1; // creation time day
*(u8 *)&dir[12] = 1; // creation time month
*(u16 *)&dir[13] = 2008; // creation time year
*(u32 *)&dir[16] = 0; // cluster with the contents of the dir
*(u32 *)&dir[20] = 0; // dir entry for '.'
*(u8 *)&dir[24] = 0; // modification time seconds
*(u8 *)&dir[25] = 0; // modification time minuts
*(u8 *)&dir[26] = 0; // modification time hours
*(u8 *)&dir[27] = 1; // modification time day
*(u8 *)&dir[28] = 1; // modification time month
*(u16 *)&dir[29] = 2008; // modification time year
*(u32 *)&dir[32] = 0; // user attribute unused
strcpy(&dir[64], ".."); // DIRECTORY NAME
fseek(fp, 0xA920 + (((dircluster) * 0x420) + 528), SEEK_SET);
fwrite(dir, 512, 1, fp);
FAT[dircluster] = 0xFFFFFFFF;
// ADD REST OF FILES
for(int i=2;i<numfiles;i+=2)
{
// Find a new cluster to store files and updata FAT table
int newcluster = FindEmptyCluster();
FAT[dircluster] = newcluster;
FAT[newcluster] = 0xFFFFFFFF;
dircluster = newcluster;
// Add first file
memset(dir, 0, 512);
*(u16 *)&dir[0] = Dir::DF_EXISTS | Dir::DF_FILE | Dir::DF_READ; // mode flag
*(u32 *)&dir[4] = 2; // number of files inside the dir
*(u8 *)&dir[8] = 0; // creation time seconds
*(u8 *)&dir[9] = 0; // creation time minuts
*(u8 *)&dir[10] = 0; // creation time hours
*(u8 *)&dir[11] = 1; // creation time day
*(u8 *)&dir[12] = 1; // creation time month
*(u16 *)&dir[13] = 2008; // creation time year
*(u32 *)&dir[16] = 0; // cluster with the contents of the file
*(u32 *)&dir[20] = 0; // dir entry for '.'
*(u8 *)&dir[24] = 0; // modification time seconds
*(u8 *)&dir[25] = 0; // modification time minuts
*(u8 *)&dir[26] = 0; // modification time hours
*(u8 *)&dir[27] = 1; // modification time day
*(u8 *)&dir[28] = 1; // modification time month
*(u16 *)&dir[29] = 2008; // modification time year
*(u32 *)&dir[32] = 0; // user attribute unused
strcpy(&dir[64], "Kaka1"); // DIRECTORY NAME
fseek(fp, 0xA920 + (((dircluster) * 0x420) + 0), SEEK_SET);
fwrite(dir, 512, 1, fp);
// Add first file contents
// Add second file
// Add second file contents
}
// SAVE FAT HERE
for(int i=0;i<8;i++)
{
fseek(fp, 0x420 * indirect_table[i], SEEK_SET);
fwrite(&FAT[i*256], 512, 1, fp);
fseek(fp, 16, SEEK_CUR);
fwrite(&FAT[(i*256)+128], 512, 1, fp);
}
// Close the file
fclose(fp);
}
};
MemoryCard MC1, MC2;
BOOL GetTreeViewSelection(HWND hWnd, char *d, char *n)
{
HTREEITEM sel = TreeView_GetSelection(hWnd);
TVITEMEX file, dir;
file.hItem = sel;
file.mask = TVIF_HANDLE|TVIF_TEXT;
file.pszText = n;
file.cchTextMax = 255;
BOOL r = TreeView_GetItem(GetDlgItem(mcdDlg, IDC_TREE1), &file);
if(r == FALSE)
{
return r;
}
HTREEITEM parentsel = TreeView_GetParent(hWnd, sel);
dir.hItem = parentsel;
dir.mask = TVIF_HANDLE|TVIF_TEXT;
dir.pszText = d;
dir.cchTextMax = 255;
r = TreeView_GetItem(GetDlgItem(mcdDlg, IDC_TREE1), &dir);
return r;
}
void Open_Mcd_Proc(HWND hW, int mcd) {
OPENFILENAME ofn;
char szFileName[256];
char szFileTitle[256];
char szFilter[1024];
char *str;
memset(szFileName, 0, sizeof(szFileName));
memset(szFileTitle, 0, sizeof(szFileTitle));
memset(szFilter, 0, sizeof(szFilter));
strcpy(szFilter, _("Ps2 Memory Card (*.ps2)"));
str = szFilter + strlen(szFilter) + 1;
strcpy(str, "*.ps2");
str+= strlen(str) + 1;
strcpy(str, _("All Files"));
str+= strlen(str) + 1;
strcpy(str, "*.*");
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hW;
ofn.lpstrFilter = szFilter;
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 1;
ofn.lpstrFile = szFileName;
ofn.nMaxFile = 256;
ofn.lpstrInitialDir = "memcards";
ofn.lpstrFileTitle = szFileTitle;
ofn.nMaxFileTitle = 256;
ofn.lpstrTitle = NULL;
ofn.lpstrDefExt = "MC2";
ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR;
if (GetOpenFileName ((LPOPENFILENAME)&ofn)) {
Edit_SetText(GetDlgItem(hW,mcd == 1 ? IDC_MCD1 : IDC_MCD2), szFileName);
}
}
void SaveFileDialog(HWND hW, int MC, char *dir, char *name) {
OPENFILENAME ofn;
char szFileName[256];
char szFileTitle[256];
char szFilter[1024];
// char *str; (unused for now)
memset(szFileName, 0, sizeof(szFileName));
memset(szFileTitle, 0, sizeof(szFileTitle));
memset(szFilter, 0, sizeof(szFilter));
strcpy(szFilter, "All Files (*.*)");
strcpy(szFileName, name);
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hW;
ofn.lpstrFilter = szFilter;
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 1;
ofn.lpstrFile = szFileName;
ofn.nMaxFile = 256;
ofn.lpstrInitialDir = "memcards";
ofn.lpstrFileTitle = szFileTitle;
ofn.nMaxFileTitle = 256;
ofn.lpstrTitle = NULL;
ofn.lpstrDefExt = "MC2";
ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_OVERWRITEPROMPT | OFN_EXTENSIONDIFFERENT;
if (GetSaveFileName ((LPOPENFILENAME)&ofn))
{
Dir *d;
if(MC == 1)
d = MC1.FindFile(dir, name);
else
d = MC2.FindFile(dir, name);
if(d != NULL)
{
FILE *fp = fopen(ofn.lpstrFile, "wb");
fwrite(d->File, d->Lenght, 1, fp);
fclose(fp);
}
}
}
FILE *fp;
BOOL CALLBACK ConfigureMcdsDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch(uMsg) {
case WM_INITDIALOG:
mcdDlg = hW;
SetWindowText(hW, _("Memcard Manager"));
Button_SetText(GetDlgItem(hW, IDOK), _("OK"));
Button_SetText(GetDlgItem(hW, IDCANCEL), _("Cancel"));
Button_SetText(GetDlgItem(hW, IDC_MCDSEL1), _("Select Mcd"));
Button_SetText(GetDlgItem(hW, IDC_MCDSEL2), _("Select Mcd"));
Static_SetText(GetDlgItem(hW, IDC_FRAMEMCD1), _("Memory Card 1"));
Static_SetText(GetDlgItem(hW, IDC_FRAMEMCD2), _("Memory Card 2"));
if (!strlen(Config.Mcd1)) strcpy(Config.Mcd1, "memcards\\Mcd001.ps2");
if (!strlen(Config.Mcd2)) strcpy(Config.Mcd2, "memcards\\Mcd002.ps2");
Edit_SetText(GetDlgItem(hW,IDC_MCD1), Config.Mcd1);
Edit_SetText(GetDlgItem(hW,IDC_MCD2), Config.Mcd2);
//MC1.Load(Config.Mcd1);
//MC2.Load(Config.Mcd2);
//MC1.AddCardToTreeView(GetDlgItem(hW, IDC_TREE1));
//MC2.AddCardToTreeView(GetDlgItem(hW, IDC_TREE2));
//MC1.AddToListView(GetDlgItem(hW,IDC_LIST1));
//MC2.AddToListView(GetDlgItem(hW,IDC_LIST2));
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDC_MCDSEL1:
Open_Mcd_Proc(hW, 1);
return TRUE;
case IDC_MCDSEL2:
Open_Mcd_Proc(hW, 2);
return TRUE;
case IDCANCEL:
{
EndDialog(hW,FALSE);
return TRUE;
}
case IDOK:
Edit_GetText(GetDlgItem(hW,IDC_MCD1), Config.Mcd1, 256);
Edit_GetText(GetDlgItem(hW,IDC_MCD2), Config.Mcd2, 256);
// SaveConfig();
EndDialog(hW,TRUE);
return TRUE;
case IDC_RELOAD1:
{
char cardname[1024];
Edit_GetText(GetDlgItem(hW, IDC_MCD1), cardname, 1024);
MC1.Load(cardname);
MC1.AddToListView(GetDlgItem(hW,IDC_LIST1));
//MC1.AddCardToTreeView(GetDlgItem(hW,IDC_TREE1));
break;
}
case IDC_RELOAD2:
{
char cardname[1024];
Edit_GetText(GetDlgItem(hW, IDC_MCD2), cardname, 1024);
MC2.Load(cardname);
MC2.AddToListView(GetDlgItem(hW,IDC_LIST2));
//MC2.AddCardToTreeView(GetDlgItem(hW,IDC_TREE2));
break;
}
case IDC_LOADICO1:
{
char cardname[1024];
MC1.SaveRootDir("test");
Edit_GetText(GetDlgItem(hW, IDC_MCD1), cardname, 1024);
MC1.Load(cardname);
MC1.AddToListView(GetDlgItem(hW,IDC_LIST1));
/*
char dir[256], name[256];
if(GetTreeViewSelection(GetDlgItem(mcdDlg, IDC_TREE1), dir, name))
MC1.PaintICOFile(GetDlgItem(mcdDlg, IDC_ICON1), dir, name);
else
MessageBox(mcdDlg, "Please select a file.", "Error", 0);
*/
break;
}
case IDC_LOADICO2:
{
/*
char dir[256], name[256];
if(GetTreeViewSelection(GetDlgItem(mcdDlg, IDC_TREE2), dir, name))
MC1.PaintICOFile(GetDlgItem(mcdDlg, IDC_ICON2), dir, name);
else
MessageBox(mcdDlg, "Please select a file.", "Error", 0);
*/
break;
}
case IDC_SAVE1:
{
/*
char dir[256], name[256];
if(GetTreeViewSelection(GetDlgItem(mcdDlg, IDC_TREE1), dir, name))
SaveFileDialog(mcdDlg, 1, dir, name);
else
MessageBox(mcdDlg, "Please select a file.", "Error", 0);
*/
break;
}
case IDC_SAVE2:
{
/*
char dir[256], name[256];
if(GetTreeViewSelection(GetDlgItem(mcdDlg, IDC_TREE2), dir, name))
SaveFileDialog(mcdDlg, 2, dir, name);
else
MessageBox(mcdDlg, "Please select a file.", "Error", 0);
*/
break;
}
}
case WM_DESTROY:
return TRUE;
}
return FALSE;
}