mirror of
https://github.com/izzy2lost/vba10.git
synced 2026-03-26 18:15:30 -07:00
316 lines
8.1 KiB
C++
316 lines
8.1 KiB
C++
#include "ROMDatabase.h"
|
|
#include "ppltasks_extra.h"
|
|
#include "stringhelper.h"
|
|
#include <collection.h>
|
|
|
|
using namespace Platform;
|
|
using namespace Platform::Collections;
|
|
using namespace Windows::Foundation;
|
|
using namespace Windows::Foundation::Collections;
|
|
using namespace Windows::Storage;
|
|
using namespace Windows::Storage::Streams;
|
|
using namespace Windows::Storage::AccessCache;
|
|
using namespace Windows::UI::Xaml;
|
|
|
|
using namespace Concurrency;
|
|
using namespace Concurrency::extras;
|
|
using namespace std;
|
|
using namespace VBA10;
|
|
|
|
|
|
#define ROMDB_FILE_NAME "romdb.db"
|
|
|
|
|
|
//ROMDatabase^ ROMDatabase::singleton;
|
|
|
|
|
|
|
|
ROMDatabase::ROMDatabase() : initialized(false)
|
|
{
|
|
}
|
|
|
|
|
|
task<void> ROMDatabase::Initialize(void)
|
|
{
|
|
if (initialized)
|
|
return create_task([] {});
|
|
else
|
|
return create_task(Windows::Storage::ApplicationData::Current->LocalFolder->CreateFileAsync(ROMDB_FILE_NAME, CreationCollisionOption::OpenIfExists))
|
|
.then([this](StorageFile^ file)
|
|
{
|
|
db = ref new SQLiteWinRT::Database(file);
|
|
|
|
//open database
|
|
return db->OpenAsync(SQLiteWinRT::SqliteOpenMode::OpenReadWrite);
|
|
|
|
}).then([this]
|
|
{
|
|
//create table if not exist
|
|
return db->ExecuteStatementAsync("CREATE TABLE IF NOT EXISTS ROMTABLE ( "\
|
|
"LOCATIONTYPE INT NOT NULL,"\
|
|
"DISPLAYNAME TEXT NOT NULL,"\
|
|
"FILENAME TEXT NOT NULL,"\
|
|
"FOLDERPATH TEXT NOT NULL,"\
|
|
"TOKEN TEXT NOT NULL,"\
|
|
"LASTPLAYED INT NOT NULL,"\
|
|
"LASTSAVEINDEX INT NOT NULL, "\
|
|
"AUTOSAVEINDEX INT NOT NULL, "\
|
|
"SNAPSHOTURI TEXT NOT NULL );");
|
|
}).then([this]
|
|
{
|
|
return db->PrepareStatementAsync("SELECT * FROM ROMTABLE ORDER BY DISPLAYNAME ASC;");
|
|
|
|
}).then([this](SQLiteWinRT::Statement^ stmt)
|
|
{
|
|
statement = stmt;
|
|
return RetrieveQuerry();
|
|
|
|
}).then([this] (Vector<ROMDBEntry^>^ ret)
|
|
{
|
|
_allROMDBEntries = ret;
|
|
|
|
//load rom entry
|
|
return LoadSnapshotImage();
|
|
}).then([this](task<void> t)
|
|
{
|
|
//check to see if any entry failed to load (due to deleted folder)
|
|
for (int i = 0; i < _allROMDBEntries->Size; i++)
|
|
{
|
|
auto entry = _allROMDBEntries->GetAt(i);
|
|
if (!entry->Folder)
|
|
{
|
|
_allROMDBEntries->RemoveAt(i);
|
|
i--;
|
|
}
|
|
}
|
|
initialized = true;
|
|
return t.get();
|
|
});
|
|
|
|
|
|
|
|
|
|
//auto items = ref new Vector<String^>();
|
|
|
|
|
|
//__await db->OpenAsync(SQLiteWinRT::SqliteOpenMode::OpenRead);
|
|
//auto stmt = __await db->PrepareStatementAsync("SELECT rowid, CityName FROM Cities;");
|
|
//while (__await stmt->StepAsync())
|
|
// items->Append(stmt->GetIntAt(0) + ": " + stmt->GetTextAt(1));
|
|
}
|
|
|
|
Platform::String^ ROMDatabase::ReplaceSingleQuote(Platform::String^ pstr)
|
|
{
|
|
wstring wstr(pstr->Begin(), pstr->End());
|
|
replaceAll(wstr, L"'", L"''");
|
|
return ref new Platform::String(wstr.c_str());
|
|
}
|
|
|
|
task<void> ROMDatabase::AddAsync(ROMDBEntry^ entry)
|
|
{
|
|
return create_task([this, entry]
|
|
{
|
|
|
|
|
|
|
|
//prepare statement to add to rom table
|
|
Platform::String^ cmd = "INSERT INTO ROMTABLE (LOCATIONTYPE, DISPLAYNAME, FILENAME, FOLDERPATH, TOKEN, LASTPLAYED, LASTSAVEINDEX, AUTOSAVEINDEX, SNAPSHOTURI) VALUES (";
|
|
cmd += entry->LocationType + ",";
|
|
cmd += "'" + ReplaceSingleQuote(entry->DisplayName) + "',";
|
|
cmd += "'" + ReplaceSingleQuote(entry->FileName) + "',";
|
|
cmd += "'" + ReplaceSingleQuote(entry->FolderPath) + "',";
|
|
cmd += "'" + ReplaceSingleQuote(entry->Token) + "',";
|
|
cmd += entry->LastPlayed.UniversalTime + ",";
|
|
cmd += entry->LastSaveIndex + ",";
|
|
cmd += entry->AutoSaveIndex + ",";
|
|
cmd += "'" + ReplaceSingleQuote(entry->SnapshotUri) + "')";
|
|
|
|
#if _DEBUG
|
|
Platform::String ^message = cmd;
|
|
wstring wstr(message->Begin(), message->End());
|
|
OutputDebugStringW(wstr.c_str());
|
|
#endif
|
|
return db->ExecuteStatementAsync(cmd);
|
|
});
|
|
}
|
|
|
|
|
|
//call this after prepare statement async
|
|
task<Vector<ROMDBEntry^>^> ROMDatabase::RetrieveQuerry()
|
|
{
|
|
auto items = ref new Vector<ROMDBEntry^>();
|
|
|
|
|
|
|
|
//now carry out the tasks, start with one StepAsync to see table has any data
|
|
return create_task([this]
|
|
{
|
|
return statement->StepAsync();
|
|
}).then([this, items](bool ret)
|
|
{
|
|
if (ret)
|
|
{
|
|
return create_iterative_task([this, items]
|
|
{
|
|
return create_task([this, items]
|
|
{
|
|
ROMDBEntry^ entry = ref new ROMDBEntry(
|
|
statement->GetIntAt(0), statement->GetTextAt(1), statement->GetTextAt(2), statement->GetTextAt(3),
|
|
statement->GetTextAt(4), DateTime{ statement->GetInt64At(5) }, statement->GetIntAt(6), statement->GetIntAt(7), statement->GetTextAt(8)
|
|
);
|
|
items->Append(entry);
|
|
|
|
return statement->StepAsync();
|
|
});
|
|
});;
|
|
}
|
|
else
|
|
return create_task([] {});
|
|
}).then([items](task<void> t)
|
|
{
|
|
return items; //t.get();
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
task<void> ROMDatabase::LoadSnapshotImage()
|
|
{
|
|
vector<task<void>> tasks;
|
|
|
|
for (int i= 0; i < _allROMDBEntries->Size; i++)
|
|
{
|
|
auto entry = _allROMDBEntries->GetAt(i);
|
|
|
|
|
|
tasks.emplace_back(create_task([entry]
|
|
{
|
|
if (entry->LocationType == 0) //app storage
|
|
{
|
|
|
|
|
|
return create_task([entry]()->StorageFolder^
|
|
{
|
|
return ApplicationData::Current->LocalFolder;
|
|
});
|
|
}
|
|
else // external storage
|
|
{
|
|
//find the folder in futureaccesslist
|
|
|
|
return create_task([entry]
|
|
{
|
|
return StorageApplicationPermissions::FutureAccessList->GetFolderAsync(entry->Token);
|
|
});
|
|
}
|
|
}).then([entry](StorageFolder^ folder)
|
|
{
|
|
if (folder)
|
|
{
|
|
//update folder path (incase user change folder name)
|
|
entry->FolderPath = folder->Path;
|
|
entry->Folder = folder;
|
|
|
|
|
|
|
|
}
|
|
|
|
//get the snapshot file
|
|
return folder->GetFileAsync(entry->SnapshotUri);
|
|
|
|
}).then([entry](StorageFile ^file)
|
|
{
|
|
//open file
|
|
return file->OpenAsync(FileAccessMode::Read);
|
|
}).then([entry](IRandomAccessStream^ stream)
|
|
{
|
|
//load bitmap image for snapshot
|
|
entry->Snapshot = ref new BitmapImage();
|
|
return entry->Snapshot->SetSourceAsync(stream);
|
|
}).then([tasks](task<void> t)
|
|
{
|
|
try
|
|
{
|
|
t.get();
|
|
}
|
|
catch (Exception^ e)
|
|
{
|
|
// We'll handle the specific errors below.
|
|
}
|
|
}));
|
|
}
|
|
|
|
|
|
// When all tasks finish, create a continuation task that observes any exceptions that occurred.
|
|
return when_all(begin(tasks), end(tasks)).then([tasks](task<void> t)
|
|
{
|
|
try
|
|
{
|
|
t.get();
|
|
}
|
|
catch (COMException^ e)
|
|
{
|
|
// We'll handle the specific errors below.
|
|
}
|
|
|
|
});
|
|
}
|
|
|
|
|
|
task<void> ROMDatabase::UpdateAsync(ROMDBEntry^ entry)
|
|
{
|
|
return create_task([this, entry]
|
|
{
|
|
|
|
//prepare statement to update entry
|
|
Platform::String^ cmd = "UPDATE ROMTABLE SET DISPLAYNAME = ";
|
|
cmd += "'" + ReplaceSingleQuote(entry->DisplayName) + "',";
|
|
cmd += " FOLDERPATH = '" + ReplaceSingleQuote(entry->FolderPath) + "',";
|
|
cmd += " LASTPLAYED = " + entry->LastPlayed.UniversalTime + ",";
|
|
cmd += " LASTSAVEINDEX = " + entry->LastSaveIndex + ",";
|
|
cmd += " AUTOSAVEINDEX = " + entry->AutoSaveIndex ;
|
|
cmd += " WHERE FILENAME = '" + ReplaceSingleQuote(entry->FileName) + "' AND TOKEN = '" + ReplaceSingleQuote(entry->Token) + "';";
|
|
|
|
#if _DEBUG
|
|
Platform::String ^message = cmd;
|
|
wstring wstr(message->Begin(), message->End());
|
|
OutputDebugStringW(wstr.c_str());
|
|
#endif
|
|
return db->ExecuteStatementAsync(cmd);
|
|
});
|
|
}
|
|
|
|
|
|
ROMDBEntry^ ROMDatabase::GetEntryFromName(Platform::String^ name)
|
|
{
|
|
for (int i = 0; i < _allROMDBEntries->Size; i++)
|
|
{
|
|
ROMDBEntry^ entry = _allROMDBEntries->GetAt(i);
|
|
if (entry->DisplayName == name)
|
|
return entry;
|
|
}
|
|
|
|
//if come to here, it means we don't find the entry with the correct name
|
|
return nullptr;
|
|
}
|
|
|
|
task<void> ROMDatabase::RemoveAsync(ROMDBEntry ^ entry)
|
|
{
|
|
return create_task([this, entry]
|
|
{
|
|
|
|
//prepare statement to update entry
|
|
Platform::String^ cmd = "DELETE FROM ROMTABLE ";
|
|
cmd += " WHERE FILENAME = '" + ReplaceSingleQuote(entry->FileName) + "' AND TOKEN = '" + ReplaceSingleQuote(entry->Token) + "';";
|
|
|
|
#if _DEBUG
|
|
Platform::String ^message = cmd;
|
|
wstring wstr(message->Begin(), message->End());
|
|
OutputDebugStringW(wstr.c_str());
|
|
#endif
|
|
return db->ExecuteStatementAsync(cmd);
|
|
});
|
|
}
|
|
|