public int sceUtilitySavedataInitStart(ref SceUtilitySavedataParam Params)
        {
            Console.WriteLine(Params.Mode);
            Console.WriteLine(Params.ToStringDefault());
            //Params.DataBufPointer
            Params.Base.Result = 0;

            var SavePathFolder = "ms0:/PSP/SAVEDATA/" + Params.GameName + Params.SaveName;
            var SaveDataBin    = SavePathFolder + "/DATA.BIN";
            var SaveIcon0      = SavePathFolder + "/ICON0.PNG";
            var SavePic1       = SavePathFolder + "/PIC1.PNG";

            Action <PspUtilitySavedataFileData, string> Save =
                (PspUtilitySavedataFileData PspUtilitySavedataFileData, string FileName) =>
            {
                if (PspUtilitySavedataFileData.Used)
                {
                    HleIoManager.HleIoWrapper.WriteBytes(
                        FileName,
                        Memory.ReadBytes(PspUtilitySavedataFileData.BufferPointer, PspUtilitySavedataFileData.Size)
                        );
                }
            };

            try
            {
                switch (Params.Mode)
                {
                case PspUtilitySavedataMode.Autoload:
                case PspUtilitySavedataMode.Load:
                case PspUtilitySavedataMode.ListLoad:
                {
                    try
                    {
                        Memory.WriteBytes(
                            Params.DataBufPointer,
                            HleIoManager.HleIoWrapper.ReadBytes(SaveDataBin)
                            );
                    }
                    catch (IOException)
                    {
                        throw (new SceKernelException(SceKernelErrors.ERROR_SAVEDATA_LOAD_NO_DATA));
                    }
                    catch (Exception Exception)
                    {
                        Console.WriteLine(Exception);
                        throw (new SceKernelException(SceKernelErrors.ERROR_SAVEDATA_LOAD_ACCESS_ERROR));
                    }
                }
                break;

                case PspUtilitySavedataMode.Autosave:
                case PspUtilitySavedataMode.Save:
                case PspUtilitySavedataMode.ListSave:
                {
                    try
                    {
                        HleIoManager.HleIoWrapper.Mkdir(SavePathFolder, SceMode.All);

                        HleIoManager.HleIoWrapper.WriteBytes(
                            SaveDataBin,
                            Memory.ReadBytes(Params.DataBufPointer, Params.DataSize)
                            );

                        Save(Params.Icon0FileData, SaveIcon0);
                        Save(Params.Pic1FileData, SavePic1);
                        //Save(Params.SfoParam, SavePic1);
                    }
                    catch (Exception Exception)
                    {
                        Console.Error.WriteLine(Exception);
                        throw (new SceKernelException(SceKernelErrors.ERROR_SAVEDATA_SAVE_ACCESS_ERROR));
                    }
                }
                break;

                // "METAL SLUG XX" outputs the following on stdout after calling mode 8 (PspUtilitySavedataMode.Sizes):
                //
                // ------ SIZES ------
                // ---------- savedata result ----------
                // result = 0x801103c7
                //
                // bind : un used(0x0).
                //
                // -- dir name --
                // title id : ULUS10495
                // user  id : METALSLUGXX
                //
                // ms free size
                //   cluster size(byte) : 32768 byte
                //   free cluster num   : 32768
                //   free size(KB)      : 1048576 KB
                //   free size(string)  : "1 GB"
                //
                // ms data size(titleId=ULUS10495, userId=METALSLUGXX)
                //   cluster num        : 0
                //   size (KB)          : 0 KB
                //   size (string)      : "0 KB"
                //   size (32KB)        : 0 KB
                //   size (32KB string) : "0 KB"
                //
                // utility data size
                //   cluster num        : 13
                //   size (KB)          : 416 KB
                //   size (string)      : "416 KB"
                //   size (32KB)        : 416 KB
                //   size (32KB string) : "416 KB"
                // error: SCE_UTILITY_SAVEDATA_TYPE_SIZES return 801103c7
                case PspUtilitySavedataMode.Sizes:
                {
                    SceKernelErrors SceKernelError = SceKernelErrors.ERROR_OK;

                    //Console.Error.WriteLine("Not Implemented: sceUtilitySavedataInitStart.Sizes");

                    uint SectorSize = 1024;
                    uint FreeSize   = 32 * 1024 * 1024;   // 32 MB
                    uint UsedSize   = 0;

                    // MS free size.
                    // Gets the ammount of free space in the Memory Stick. If null,
                    // the size is ignored and no error is returned.
                    {
                        var SizeFreeInfo = (SizeFreeInfo *)Params.msFreeAddr.GetPointer <SizeFreeInfo>(Memory);
                        SizeFreeInfo->SectorSize  = SectorSize;
                        SizeFreeInfo->FreeSectors = FreeSize / SectorSize;
                        SizeFreeInfo->FreeKb      = FreeSize / 1024;

                        SizeFreeInfo->FreeKbString = (SizeFreeInfo->FreeKb) + "KB";
                    }

                    // MS data size.
                    // Gets the size of the data already saved in the Memory Stick.
                    // If null, the size is ignored and no error is returned.
                    {
                        var SizeUsedInfo = (SizeUsedInfo *)Params.msDataAddr.GetPointer <SizeUsedInfo>(Memory);

                        if (SizeUsedInfo != null)
                        {
#if true
                            if (true)
                            {
                                Console.WriteLine(SizeUsedInfo->saveName);
                                Console.WriteLine(SizeUsedInfo->gameName);

                                SizeUsedInfo->UsedKb   = UsedSize / 1024;
                                SizeUsedInfo->UsedKb32 = UsedSize / (32 * 1024);

                                SizeUsedInfo->UsedKbString   = (SizeUsedInfo->UsedKb) + "KB";
                                SizeUsedInfo->UsedKb32String = (SizeUsedInfo->UsedKb32) + "KB";
                            }
                            else
                            {
                                SceKernelError = SceKernelErrors.ERROR_SAVEDATA_SIZES_NO_DATA;
                            }
#else
                            SceKernelError = SceKernelErrors.ERROR_SAVEDATA_SIZES_NO_DATA;
#endif
                        }
                    }

                    // Utility data size.
                    // Gets the size of the data to be saved in the Memory Stick.
                    // If null, the size is ignored and no error is returned.
                    {
                        var SizeRequiredSpaceInfo =
                            (SizeRequiredSpaceInfo *)Params.utilityDataAddr.GetPointer <SizeRequiredSpaceInfo>(
                                Memory);
                        if (SizeRequiredSpaceInfo != null)
                        {
                            long RequiredSize = 0;
                            RequiredSize += Params.Icon0FileData.Size;
                            RequiredSize += Params.Icon1FileData.Size;
                            RequiredSize += Params.Pic1FileData.Size;
                            RequiredSize += Params.Snd0FileData.Size;
                            RequiredSize += Params.DataSize;

                            SizeRequiredSpaceInfo->RequiredSpaceSectors =
                                (uint)MathUtils.RequiredBlocks(RequiredSize, SectorSize);
                            SizeRequiredSpaceInfo->RequiredSpaceKb =
                                (uint)MathUtils.RequiredBlocks(RequiredSize, 1024);
                            SizeRequiredSpaceInfo->RequiredSpace32KB =
                                (uint)MathUtils.RequiredBlocks(RequiredSize, 32 * 1024);

                            SizeRequiredSpaceInfo->RequiredSpaceString =
                                (SizeRequiredSpaceInfo->RequiredSpaceKb) + "KB";
                            SizeRequiredSpaceInfo->RequiredSpace32KBString =
                                (SizeRequiredSpaceInfo->RequiredSpace32KB) + "KB";
                        }
                    }

                    if (SceKernelError != SceKernelErrors.ERROR_OK)
                    {
                        throw (new SceKernelException(SceKernelError));
                    }
                }
                break;

                case PspUtilitySavedataMode.List:
                {
                    var ListRequest = (ListRequest *)Params.idListAddr.GetPointer <ListRequest>(Memory);
                    ListRequest->NumEntriesReaded = 0;
                }
                break;

                case PspUtilitySavedataMode.GetSize:
                {
                    //Params.DataSize
                    //throw (new SceKernelException(SceKernelErrors.ERROR_SAVEDATA_RW_NO_MEMSTICK));
                    //throw (new SceKernelException(SceKernelErrors.ERROR_SAVEDATA_RW_NO_DATA));
                    Console.Error.WriteLine("Not Implemented: sceUtilitySavedataInitStart.GetSize");
                }
                break;

                case PspUtilitySavedataMode.Read:
                case PspUtilitySavedataMode.ReadSecure:
                {
                    //throw (new SceKernelException(SceKernelErrors.ERROR_SAVEDATA_RW_NO_DATA));
                    Console.Error.WriteLine("Not Implemented: sceUtilitySavedataInitStart.Read");
                }
                break;

                default:
                    Console.Error.WriteLine("sceUtilitySavedataInitStart: Unsupported mode: " + Params.Mode);
                    Debug.Fail("sceUtilitySavedataInitStart: Unsupported mode: " + Params.Mode);
                    throw (new SceKernelException((SceKernelErrors)(-1)));
                    //break;
                }
                //throw(new NotImplementedException());

                Params.Base.Result = SceKernelErrors.ERROR_OK;
            }
            catch (SceKernelException SceKernelException)
            {
                Params.Base.Result = SceKernelException.SceKernelError;
            }
            finally
            {
                CurrentDialogStep = DialogStepEnum.SUCCESS;
            }


            return(0);
        }
        public int sceUtilitySavedataInitStart(SceUtilitySavedataParam* Params)
        {
            //Params->DataBufPointer
            Params->Base.Result = 0;

            var SavePathFolder = "ms0:/PSP/SAVEDATA/" + Params->GameName + Params->SaveName;
            var SaveDataBin = SavePathFolder + "/DATA.BIN";
            var SaveIcon0 = SavePathFolder + "/ICON0.PNG";
            var SavePic1 = SavePathFolder + "/PIC1.PNG";

            Action<PspUtilitySavedataFileData, String> Save = (PspUtilitySavedataFileData PspUtilitySavedataFileData, String FileName) =>
            {
                if (PspUtilitySavedataFileData.Used)
                {
                    HleIoManager.HleIoWrapper.WriteBytes(
                        FileName,
                        PspMemory.ReadBytes(PspUtilitySavedataFileData.BufferPointer, PspUtilitySavedataFileData.Size)
                    );
                }
            };

            try
            {
                switch (Params->Mode)
                {
                    case PspUtilitySavedataMode.Autoload:
                    case PspUtilitySavedataMode.Load:
                    case PspUtilitySavedataMode.ListLoad:
                        {
                            try
                            {
                                PspMemory.WriteBytes(
                                    Params->DataBufPointer,
                                    HleIoManager.HleIoWrapper.ReadBytes(SaveDataBin)
                                );
                            }
                            catch (IOException)
                            {
                                throw (new SceKernelException(SceKernelErrors.ERROR_SAVEDATA_LOAD_NO_DATA));
                            }
                            catch (Exception)
                            {
                                throw (new SceKernelException(SceKernelErrors.ERROR_SAVEDATA_LOAD_ACCESS_ERROR));
                            }
                        }
                        break;
                    case PspUtilitySavedataMode.Autosave:
                    case PspUtilitySavedataMode.Save:
                    case PspUtilitySavedataMode.ListSave:
                        {
                            try
                            {
                                HleIoManager.HleIoWrapper.Mkdir(SavePathFolder, SceMode.All);

                                HleIoManager.HleIoWrapper.WriteBytes(
                                    SaveDataBin,
                                    PspMemory.ReadBytes(Params->DataBufPointer, Params->DataSize)
                                );

                                Save(Params->Icon0FileData, SaveIcon0);
                                Save(Params->Pic1FileData, SavePic1);
                                //Save(Params->SfoParam, SavePic1);
                            }
                            catch (Exception Exception)
                            {
                                Console.Error.WriteLine(Exception);
                                throw (new SceKernelException(SceKernelErrors.ERROR_SAVEDATA_SAVE_ACCESS_ERROR));
                            }
                        }
                        break;

                    // "METAL SLUG XX" outputs the following on stdout after calling mode 8 (PspUtilitySavedataMode.Sizes):
                    //
                    // ------ SIZES ------
                    // ---------- savedata result ----------
                    // result = 0x801103c7
                    //
                    // bind : un used(0x0).
                    //
                    // -- dir name --
                    // title id : ULUS10495
                    // user  id : METALSLUGXX
                    //
                    // ms free size
                    //   cluster size(byte) : 32768 byte
                    //   free cluster num   : 32768
                    //   free size(KB)      : 1048576 KB
                    //   free size(string)  : "1 GB"
                    //
                    // ms data size(titleId=ULUS10495, userId=METALSLUGXX)
                    //   cluster num        : 0
                    //   size (KB)          : 0 KB
                    //   size (string)      : "0 KB"
                    //   size (32KB)        : 0 KB
                    //   size (32KB string) : "0 KB"
                    //
                    // utility data size
                    //   cluster num        : 13
                    //   size (KB)          : 416 KB
                    //   size (string)      : "416 KB"
                    //   size (32KB)        : 416 KB
                    //   size (32KB string) : "416 KB"
                    // error: SCE_UTILITY_SAVEDATA_TYPE_SIZES return 801103c7
                    case PspUtilitySavedataMode.Sizes:
                        {
                            SceKernelErrors SceKernelError = SceKernelErrors.ERROR_OK;

                            //Console.Error.WriteLine("Not Implemented: sceUtilitySavedataInitStart.Sizes");

                            uint SectorSize = 1024;
                            uint FreeSize = 32 * 1024 * 1024; // 32 MB
                            uint UsedSize = 0;

                            // MS free size.
                            // Gets the ammount of free space in the Memory Stick. If null,
                            // the size is ignored and no error is returned.
                            {
                                var SizeFreeInfo = (SizeFreeInfo*)Params->msFreeAddr.GetPointer<SizeFreeInfo>(PspMemory);
                                SizeFreeInfo->SectorSize = SectorSize;
                                SizeFreeInfo->FreeSectors = FreeSize / SectorSize;
                                SizeFreeInfo->FreeKb = FreeSize / 1024;

                                SizeFreeInfo->FreeKbString = (SizeFreeInfo->FreeKb) + "KB";
                            }

                            // MS data size.
                            // Gets the size of the data already saved in the Memory Stick.
                            // If null, the size is ignored and no error is returned.
                            {
                                var SizeUsedInfo = (SizeUsedInfo*)Params->msDataAddr.GetPointer<SizeUsedInfo>(PspMemory);

                                if (SizeUsedInfo != null)
                                {
                                    if (false)
                                    {
                                        Console.WriteLine(SizeUsedInfo->saveName);
                                        Console.WriteLine(SizeUsedInfo->gameName);

                                        SizeUsedInfo->UsedKb = UsedSize / 1024;
                                        SizeUsedInfo->UsedKb32 = UsedSize / (32 * 1024);

                                        SizeUsedInfo->UsedKbString = (SizeUsedInfo->UsedKb) + "KB";
                                        SizeUsedInfo->UsedKb32String = (SizeUsedInfo->UsedKb32) + "KB";
                                    }
                                    else
                                    {
                                        SceKernelError = SceKernelErrors.ERROR_SAVEDATA_SIZES_NO_DATA;
                                    }
                                }
                            }

                            // Utility data size.
                            // Gets the size of the data to be saved in the Memory Stick.
                            // If null, the size is ignored and no error is returned.
                            {
                                var SizeRequiredSpaceInfo = (SizeRequiredSpaceInfo*)Params->utilityDataAddr.GetPointer<SizeRequiredSpaceInfo>(PspMemory);
                                if (SizeRequiredSpaceInfo != null)
                                {
                                    long RequiredSize = 0;
                                    RequiredSize += Params->Icon0FileData.Size;
                                    RequiredSize += Params->Icon1FileData.Size;
                                    RequiredSize += Params->Pic1FileData.Size;
                                    RequiredSize += Params->Snd0FileData.Size;
                                    RequiredSize += Params->DataSize;

                                    SizeRequiredSpaceInfo->RequiredSpaceSectors = (uint)MathUtils.RequiredBlocks(RequiredSize, SectorSize);
                                    SizeRequiredSpaceInfo->RequiredSpaceKb = (uint)MathUtils.RequiredBlocks(RequiredSize, 1024);
                                    SizeRequiredSpaceInfo->RequiredSpace32KB = (uint)MathUtils.RequiredBlocks(RequiredSize, 32 * 1024);

                                    SizeRequiredSpaceInfo->RequiredSpaceString = (SizeRequiredSpaceInfo->RequiredSpaceKb) + "KB";
                                    SizeRequiredSpaceInfo->RequiredSpace32KBString = (SizeRequiredSpaceInfo->RequiredSpace32KB) + "KB";
                                }
                            }

                            if (SceKernelError != SceKernelErrors.ERROR_OK) throw (new SceKernelException(SceKernelErrors.ERROR_SAVEDATA_SIZES_NO_DATA));
                        }
                        break;
                    case PspUtilitySavedataMode.List:
                        {
                            var ListRequest = (ListRequest*)Params->idListAddr.GetPointer<ListRequest>(PspMemory);
                            ListRequest->NumEntriesReaded = 0;
                        }
                        break;
                    case PspUtilitySavedataMode.GetSize:
                        {
                            //Params->DataSize
                            //throw (new SceKernelException(SceKernelErrors.ERROR_SAVEDATA_RW_NO_MEMSTICK));
                            //throw (new SceKernelException(SceKernelErrors.ERROR_SAVEDATA_RW_NO_DATA));
                            Console.Error.WriteLine("Not Implemented: sceUtilitySavedataInitStart.GetSize");
                        }
                        break;
                    case PspUtilitySavedataMode.Read:
                    case PspUtilitySavedataMode.ReadSecure:
                        {
                            //throw (new SceKernelException(SceKernelErrors.ERROR_SAVEDATA_RW_NO_DATA));
                            Console.Error.WriteLine("Not Implemented: sceUtilitySavedataInitStart.Read");
                        }
                        break;
                    default:
                        Console.Error.WriteLine("sceUtilitySavedataInitStart: Unsupported mode: " + Params->Mode);
                        Debug.Fail("sceUtilitySavedataInitStart: Unsupported mode: " + Params->Mode);
                        throw (new SceKernelException((SceKernelErrors)(-1)));
                        //break;
                }
                //throw(new NotImplementedException());

                Params->Base.Result = SceKernelErrors.ERROR_OK;
            }
            catch (SceKernelException SceKernelException)
            {
                Params->Base.Result = SceKernelException.SceKernelError;
            }
            finally
            {
                CurrentDialogStep = DialogStepEnum.SUCCESS;
            }

            return 0;
        }
 public int sceUtilitySavedataInitStart(SceUtilitySavedataParam* Params)
 {
     //throw(new NotImplementedException());
     CurrentDialogStep = DialogStepEnum.SUCCESS;
     return 0;
 }