mirror of
https://github.com/0ldsk00l/nestopia.git
synced 2025-04-02 10:31:51 -04:00
811 lines
16 KiB
C++
811 lines
16 KiB
C++
////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Nestopia - NES/Famicom emulator written in C++
|
|
//
|
|
// Copyright (C) 2003-2008 Martin Freij
|
|
//
|
|
// This file is part of Nestopia.
|
|
//
|
|
// Nestopia 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.
|
|
//
|
|
// Nestopia 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 Nestopia; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef NST_DIALOG_LAUNCHER_H
|
|
#define NST_DIALOG_LAUNCHER_H
|
|
|
|
#pragma once
|
|
|
|
#include <vector>
|
|
#include <map>
|
|
#include "NstCollectionBitSet.hpp"
|
|
#include "NstWindowMenu.hpp"
|
|
#include "NstWindowStatusBar.hpp"
|
|
#include "NstWindowDialog.hpp"
|
|
#include "NstDialogFind.hpp"
|
|
#include "../core/api/NstApiCartridge.hpp"
|
|
#include <CommCtrl.h>
|
|
|
|
namespace Nes
|
|
{
|
|
using namespace Api;
|
|
}
|
|
|
|
namespace Nestopia
|
|
{
|
|
namespace Io
|
|
{
|
|
class File;
|
|
}
|
|
|
|
namespace Managers
|
|
{
|
|
class Paths;
|
|
}
|
|
|
|
namespace Window
|
|
{
|
|
class Launcher
|
|
{
|
|
public:
|
|
|
|
Launcher(const Nes::Cartridge::Database&,const Managers::Paths&,const Configuration&);
|
|
~Launcher();
|
|
|
|
void Save(Configuration&,bool,bool);
|
|
void Open(bool);
|
|
void Synchronize(HWND) const;
|
|
void Close();
|
|
|
|
private:
|
|
|
|
struct Handlers;
|
|
|
|
enum
|
|
{
|
|
STATUSBAR_SECOND_FIELD_WIDTH = 14,
|
|
CMD_ENTER = 1
|
|
};
|
|
|
|
void UpdateItemCount(uint) const;
|
|
void OnNoSelection() const;
|
|
|
|
ibool OnInitDialog (Param&);
|
|
ibool OnDropFiles (Param&);
|
|
ibool OnSize (Param&);
|
|
ibool OnCmdEnter (Param&);
|
|
ibool OnClose (Param&);
|
|
ibool OnDestroy (Param&);
|
|
|
|
void OnCmdFileRun (uint=0);
|
|
void OnCmdFileRefresh (uint);
|
|
void OnCmdEditHeader (uint);
|
|
void OnCmdViewShowGrids (uint);
|
|
void OnCmdViewShowDatabaseCorrected (uint);
|
|
void OnCmdViewShowOnTop (uint);
|
|
void OnCmdOptionsPaths (uint);
|
|
void OnCmdOptionsColors (uint);
|
|
|
|
void OnListGetDisplayInfo (const NMHDR&);
|
|
void OnListKeyDown (const NMHDR&);
|
|
void OnListColumnClick (const NMHDR&);
|
|
void OnListItemActivate (const NMHDR&);
|
|
void OnListItemChanged (const NMHDR&);
|
|
void OnListInsertItem (const NMHDR&);
|
|
void OnListDeleteItem (const NMHDR&);
|
|
void OnListDeleteAllItems (const NMHDR&);
|
|
void OnTreeSelectionChanging (const NMHDR&);
|
|
|
|
class List
|
|
{
|
|
public:
|
|
|
|
List
|
|
(
|
|
Dialog&,
|
|
Menu::CmdHandler&,
|
|
const Managers::Paths&,
|
|
const Configuration&,
|
|
const Nes::Cartridge::Database&
|
|
);
|
|
|
|
~List();
|
|
|
|
void operator = (const Control::ListView&);
|
|
|
|
enum Updater
|
|
{
|
|
DONT_REPAINT,
|
|
REPAINT
|
|
};
|
|
|
|
void Add(wcstring);
|
|
void Close();
|
|
void Save(Configuration&,bool);
|
|
void Sort(uint=0);
|
|
bool CanRefresh() const;
|
|
void Refresh();
|
|
void Insert(const Param&);
|
|
void SetColors(uint,uint,Updater=DONT_REPAINT) const;
|
|
void OnGetDisplayInfo(LPARAM);
|
|
|
|
class Paths
|
|
{
|
|
public:
|
|
|
|
explicit Paths(const Configuration&);
|
|
|
|
void Save(Configuration&) const;
|
|
|
|
struct Settings
|
|
{
|
|
struct Folder
|
|
{
|
|
Path path;
|
|
bool incSubDir;
|
|
};
|
|
|
|
typedef std::vector<Folder> Folders;
|
|
|
|
struct Include : Collection::BitSet
|
|
{
|
|
enum
|
|
{
|
|
NES,UNF,XML,FDS,NSF,PATCH,ARCHIVE,ANY,UNIQUE
|
|
};
|
|
|
|
enum
|
|
{
|
|
TYPES = NES|UNF|XML|FDS|NSF|PATCH,
|
|
FILES = TYPES|ARCHIVE
|
|
};
|
|
|
|
explicit Include(bool a=false)
|
|
: Collection::BitSet( (0xFF^0x40) | uint(a) << 6 ) {}
|
|
};
|
|
|
|
Include include;
|
|
Folders folders;
|
|
};
|
|
|
|
private:
|
|
|
|
struct Handlers;
|
|
|
|
enum
|
|
{
|
|
LIMIT = 999
|
|
};
|
|
|
|
ibool OnInitDialog (Param&);
|
|
ibool OnCmdAdd (Param&);
|
|
ibool OnCmdRemove (Param&);
|
|
ibool OnCmdClear (Param&);
|
|
ibool OnCmdOk (Param&);
|
|
|
|
void OnKeyDown (const NMHDR&);
|
|
void OnItemChanged (const NMHDR&);
|
|
void OnInsertItem (const NMHDR&);
|
|
void OnDeleteItem (const NMHDR&);
|
|
|
|
Settings settings;
|
|
Dialog dialog;
|
|
const Control::NotificationHandler notifications;
|
|
|
|
public:
|
|
|
|
void Open()
|
|
{
|
|
dialog.Open();
|
|
}
|
|
|
|
const Settings& GetSettings() const
|
|
{
|
|
return settings;
|
|
}
|
|
};
|
|
|
|
class Files
|
|
{
|
|
class Inserter;
|
|
class Searcher;
|
|
|
|
public:
|
|
|
|
class Strings
|
|
{
|
|
HeapString container;
|
|
|
|
public:
|
|
|
|
explicit Strings(uint=0);
|
|
|
|
typedef uint Index;
|
|
|
|
enum
|
|
{
|
|
NONE = -1
|
|
};
|
|
|
|
int Find(GenericString) const;
|
|
void Clear();
|
|
|
|
template<typename T>
|
|
Index operator << (const T& t)
|
|
{
|
|
uint pos = container.Length();
|
|
container << t << '\0';
|
|
return pos;
|
|
}
|
|
|
|
Index Import(cstring t)
|
|
{
|
|
uint pos = container.Length();
|
|
container.Import( t );
|
|
container << '\0';
|
|
return pos;
|
|
}
|
|
|
|
wcstring operator [] (uint i) const
|
|
{
|
|
return container.Ptr() + i;
|
|
}
|
|
|
|
uint Size() const
|
|
{
|
|
return container.Length() * (container.Wide() ? 2 : 1);
|
|
}
|
|
};
|
|
|
|
Files();
|
|
|
|
void Load();
|
|
void Save();
|
|
void Refresh(const Paths::Settings&,const Nes::Cartridge::Database&);
|
|
bool Insert(const Nes::Cartridge::Database&,GenericString);
|
|
void Clear();
|
|
bool ShouldDefrag() const;
|
|
void Defrag();
|
|
|
|
class Entry
|
|
{
|
|
friend class Files;
|
|
friend class Inserter;
|
|
friend class Searcher;
|
|
|
|
public:
|
|
|
|
typedef Nes::Cartridge::Database Db;
|
|
|
|
enum Type
|
|
{
|
|
NES = 0x01,
|
|
UNF = 0x02,
|
|
XML = 0x04,
|
|
FDS = 0x08,
|
|
NSF = 0x10,
|
|
PATCH = 0x20,
|
|
ARCHIVE = 0x80,
|
|
ALL = NES|UNF|XML|FDS|NSF|PATCH
|
|
};
|
|
|
|
enum
|
|
{
|
|
SYSTEM_UNKNOWN,
|
|
SYSTEM_PC10,
|
|
SYSTEM_VS,
|
|
SYSTEM_PAL,
|
|
SYSTEM_NTSC,
|
|
SYSTEM_NTSC_PAL
|
|
};
|
|
|
|
uint GetSystem(const Db*) const;
|
|
|
|
private:
|
|
|
|
explicit Entry(uint=0);
|
|
|
|
Db::Entry SearchDb(const Db*) const;
|
|
|
|
enum
|
|
{
|
|
ATR_BATTERY = 0x08,
|
|
ATR_PC10 = 0x10,
|
|
ATR_VS = 0x20,
|
|
ATR_PAL = 0x40,
|
|
ATR_NTSC = 0x80,
|
|
ATR_NTSC_PAL = ATR_PAL|ATR_NTSC,
|
|
ATR_DEFAULT_FDS = ATR_NTSC
|
|
};
|
|
|
|
Strings::Index file;
|
|
Strings::Index path;
|
|
Strings::Index name;
|
|
|
|
typedef Nes::Cartridge::Profile::Hash Hash;
|
|
|
|
Hash hash;
|
|
|
|
ushort pRom;
|
|
ushort cRom;
|
|
ushort wRam;
|
|
ushort vRam;
|
|
ushort mapper;
|
|
uchar type;
|
|
uchar attributes;
|
|
|
|
public:
|
|
|
|
uint GetType() const
|
|
{
|
|
return type;
|
|
}
|
|
|
|
wcstring GetPath(const Strings& strings) const
|
|
{
|
|
return strings[path];
|
|
}
|
|
|
|
wcstring GetFile(const Strings& strings) const
|
|
{
|
|
return strings[file];
|
|
}
|
|
|
|
wcstring GetName(const Strings& strings,const Db* db) const
|
|
{
|
|
if (const Db::Entry entry = SearchDb( db ))
|
|
{
|
|
wcstring title = entry.GetTitle();
|
|
|
|
if (*title)
|
|
return title;
|
|
}
|
|
|
|
return name ? strings[name] : L"-";
|
|
}
|
|
|
|
uint GetPRom(const Db* db=NULL) const
|
|
{
|
|
if (const Db::Entry entry = SearchDb( db ))
|
|
return entry.GetPrgRom() / Nes::Core::SIZE_1K;
|
|
else
|
|
return pRom;
|
|
}
|
|
|
|
uint GetCRom(const Db* db=NULL) const
|
|
{
|
|
if (const Db::Entry entry = SearchDb( db ))
|
|
return entry.GetChrRom() / Nes::Core::SIZE_1K;
|
|
else
|
|
return cRom;
|
|
}
|
|
|
|
uint GetWRam(const Db* db=NULL) const
|
|
{
|
|
if (const Db::Entry entry = SearchDb( db ))
|
|
return entry.GetWram() / Nes::Core::SIZE_1K;
|
|
else
|
|
return wRam;
|
|
}
|
|
|
|
uint GetVRam(const Db* db=NULL) const
|
|
{
|
|
if (const Db::Entry entry = SearchDb( db ))
|
|
return entry.GetVram() / Nes::Core::SIZE_1K;
|
|
else
|
|
return vRam;
|
|
}
|
|
|
|
bool GetBattery(const Db* db=NULL) const
|
|
{
|
|
if (const Db::Entry entry = SearchDb( db ))
|
|
return entry.HasBattery();
|
|
else
|
|
return (attributes & ATR_BATTERY);
|
|
}
|
|
|
|
uint GetMapper(const Db* db=NULL) const
|
|
{
|
|
if (const Db::Entry entry = SearchDb( db ))
|
|
return entry.GetMapper();
|
|
else
|
|
return mapper;
|
|
}
|
|
|
|
Nes::Cartridge::Profile::Dump::State GetDump(const Db* db=NULL) const
|
|
{
|
|
if (const Db::Entry entry = SearchDb( db ))
|
|
return entry.GetDumpState();
|
|
else
|
|
return Nes::Cartridge::Profile::Dump::UNKNOWN;
|
|
}
|
|
};
|
|
|
|
typedef Collection::Vector<Entry> Entries;
|
|
|
|
private:
|
|
|
|
enum Exception
|
|
{
|
|
ERR_CORRUPT_DATA
|
|
};
|
|
|
|
enum
|
|
{
|
|
MAX_ENTRIES = 0xFFFFF,
|
|
GARBAGE_THRESHOLD = 127
|
|
};
|
|
|
|
ushort dirty;
|
|
ushort loaded;
|
|
Strings strings;
|
|
Entries entries;
|
|
|
|
public:
|
|
|
|
uint Count() const
|
|
{
|
|
return entries.Size();
|
|
}
|
|
|
|
const Entry& operator [] (uint i) const
|
|
{
|
|
return entries[i];
|
|
}
|
|
|
|
void Disable(Entry* entry)
|
|
{
|
|
if (entry->type)
|
|
{
|
|
entry->type = 0;
|
|
dirty = true;
|
|
}
|
|
}
|
|
|
|
const Strings& GetStrings() const
|
|
{
|
|
return strings;
|
|
}
|
|
};
|
|
|
|
class Columns
|
|
{
|
|
public:
|
|
|
|
explicit Columns(const Configuration&);
|
|
|
|
void Update(const uchar*);
|
|
void Save(Configuration&) const;
|
|
|
|
enum Type
|
|
{
|
|
TYPE_FILE,
|
|
TYPE_SYSTEM,
|
|
TYPE_MAPPER,
|
|
TYPE_PROM,
|
|
TYPE_CROM,
|
|
TYPE_WRAM,
|
|
TYPE_VRAM,
|
|
TYPE_BATTERY,
|
|
TYPE_DUMP,
|
|
TYPE_NAME,
|
|
TYPE_FOLDER,
|
|
NUM_TYPES,
|
|
NUM_DEFAULT_SELECTED_TYPES = 9,
|
|
NUM_DEFAULT_AVAILABLE_TYPES = NUM_TYPES - NUM_DEFAULT_SELECTED_TYPES
|
|
};
|
|
|
|
private:
|
|
|
|
struct Handlers;
|
|
|
|
void Reset();
|
|
void Add(uint,uint);
|
|
void UpdateButtonRemove();
|
|
void UpdateButtonAdd();
|
|
|
|
ibool OnInitDialog (Param&);
|
|
ibool OnCmdSelected (Param&);
|
|
ibool OnCmdAvailable (Param&);
|
|
ibool OnCmdAdd (Param&);
|
|
ibool OnCmdRemove (Param&);
|
|
ibool OnCmdDefault (Param&);
|
|
ibool OnCmdOk (Param&);
|
|
|
|
typedef Collection::Vector<uchar> Types;
|
|
|
|
Types available;
|
|
Types selected;
|
|
Dialog dialog;
|
|
|
|
static wcstring const cfgStrings[NUM_TYPES];
|
|
|
|
public:
|
|
|
|
uint Count() const
|
|
{
|
|
return selected.Size();
|
|
}
|
|
|
|
Type GetType(uint i) const
|
|
{
|
|
return Type(selected[i]);
|
|
}
|
|
|
|
uint GetStringId(uint i) const
|
|
{
|
|
return IDS_LAUNCHER_COLUMN_FILE + selected[i];
|
|
}
|
|
|
|
void Open()
|
|
{
|
|
dialog.Open();
|
|
}
|
|
};
|
|
|
|
private:
|
|
|
|
class Strings
|
|
{
|
|
public:
|
|
|
|
wcstring GetMapper(uint);
|
|
wcstring GetSize(uint);
|
|
void Flush();
|
|
|
|
private:
|
|
|
|
struct ValueString
|
|
{
|
|
wchar_t string[5];
|
|
};
|
|
|
|
typedef String::Stack<10+1> SizeString;
|
|
typedef std::map<uint,SizeString> Sizes;
|
|
typedef Collection::Vector<ValueString> Mappers;
|
|
|
|
Sizes sizes;
|
|
Mappers mappers;
|
|
};
|
|
|
|
enum
|
|
{
|
|
STYLE =
|
|
(
|
|
LVS_EX_FULLROWSELECT |
|
|
LVS_EX_TWOCLICKACTIVATE |
|
|
LVS_EX_HEADERDRAGDROP
|
|
)
|
|
};
|
|
|
|
void ReloadListColumns() const;
|
|
void UpdateColumnOrder();
|
|
void UpdateSortColumnOrder(uint);
|
|
void Redraw();
|
|
int Sorter(const void*,const void*);
|
|
void OnFind(GenericString,uint);
|
|
bool Optimize();
|
|
|
|
void OnCmdEditFind (uint);
|
|
void OnCmdEditInsert (uint);
|
|
void OnCmdEditDelete (uint);
|
|
void OnCmdEditClear (uint);
|
|
void OnCmdViewAlignColumns (uint);
|
|
void OnCmdOptionsColumns (uint);
|
|
|
|
Control::ListView ctrl;
|
|
|
|
const Nes::Cartridge::Database imageDatabase;
|
|
const Nes::Cartridge::Database* useImageDatabase;
|
|
|
|
uchar order[Columns::NUM_TYPES];
|
|
|
|
uint typeFilter;
|
|
uint style;
|
|
|
|
Finder finder;
|
|
Paths paths;
|
|
Files files;
|
|
Columns columns;
|
|
Strings strings;
|
|
const Managers::Paths& pathManager;
|
|
|
|
public:
|
|
|
|
Generic GetWindow() const
|
|
{
|
|
return ctrl.GetWindow();
|
|
}
|
|
|
|
void OpenPathDialog()
|
|
{
|
|
paths.Open();
|
|
}
|
|
|
|
void Draw(uint type)
|
|
{
|
|
typeFilter = type;
|
|
Redraw();
|
|
}
|
|
|
|
bool DatabaseCorrectionEnabled() const
|
|
{
|
|
return useImageDatabase;
|
|
}
|
|
|
|
bool ToggleDatabase()
|
|
{
|
|
useImageDatabase = (useImageDatabase ? NULL : &imageDatabase);
|
|
ctrl.Redraw();
|
|
return useImageDatabase;
|
|
}
|
|
|
|
bool ToggleGrids()
|
|
{
|
|
style ^= LVS_EX_GRIDLINES;
|
|
ctrl.StyleEx() = style;
|
|
return style & LVS_EX_GRIDLINES;
|
|
}
|
|
|
|
bool HitTest(const Point& point) const
|
|
{
|
|
return ctrl.HitTest( point.x, point.y );
|
|
}
|
|
|
|
uint GetStyle() const
|
|
{
|
|
return ctrl.StyleEx();
|
|
}
|
|
|
|
HWND GetHandle() const
|
|
{
|
|
return ctrl.GetHandle();
|
|
}
|
|
|
|
uint NumPaths() const
|
|
{
|
|
return paths.GetSettings().folders.size();
|
|
}
|
|
|
|
uint Size() const
|
|
{
|
|
return ctrl.Size();
|
|
}
|
|
|
|
const Files::Entry* operator [] (uint i) const
|
|
{
|
|
return static_cast<const Files::Entry*>(static_cast<const void*>( ctrl[i].Data() ));
|
|
}
|
|
|
|
const Files::Entry* GetSelection() const
|
|
{
|
|
int index = ctrl.Selection().GetIndex();
|
|
return index >= 0 ? (*this)[index] : NULL;
|
|
}
|
|
|
|
const Files::Strings& GetStrings() const
|
|
{
|
|
return files.GetStrings();
|
|
}
|
|
|
|
const Managers::Paths& GetPaths() const
|
|
{
|
|
return pathManager;
|
|
}
|
|
};
|
|
|
|
class Tree
|
|
{
|
|
public:
|
|
|
|
Tree();
|
|
|
|
void operator = (const Control::TreeView&);
|
|
|
|
enum Updater {DONT_REPAINT,REPAINT};
|
|
|
|
void SetColors(uint,uint,Updater=DONT_REPAINT) const;
|
|
uint GetType(HTREEITEM) const;
|
|
void Close();
|
|
|
|
private:
|
|
|
|
Control::TreeView ctrl;
|
|
uint selection;
|
|
const Control::TreeView::ImageList imageList;
|
|
|
|
public:
|
|
|
|
Generic GetWindow() const
|
|
{
|
|
return ctrl.GetWindow();
|
|
}
|
|
};
|
|
|
|
class Colors
|
|
{
|
|
public:
|
|
|
|
explicit Colors(const Configuration&);
|
|
|
|
void Save(Configuration&) const;
|
|
|
|
private:
|
|
|
|
struct Handlers;
|
|
|
|
enum
|
|
{
|
|
DEF_BACKGROUND_COLOR = RGB(0xFF,0xFF,0xFF),
|
|
DEF_FOREGROUND_COLOR = RGB(0x00,0x00,0x00)
|
|
};
|
|
|
|
struct Type
|
|
{
|
|
inline Type(int,int,int,int);
|
|
|
|
COLORREF color;
|
|
const Rect rect;
|
|
};
|
|
|
|
void UpdateColor(const Type&) const;
|
|
void UpdateColors() const;
|
|
void ChangeColor(COLORREF&);
|
|
|
|
ibool OnInitDialog (Param&);
|
|
ibool OnPaint (Param&);
|
|
ibool OnCmdChangeBackground (Param&);
|
|
ibool OnCmdChangeForeground (Param&);
|
|
ibool OnCmdDefault (Param&);
|
|
|
|
Type background;
|
|
Type foreground;
|
|
|
|
COLORREF customColors[16];
|
|
|
|
Dialog dialog;
|
|
|
|
public:
|
|
|
|
COLORREF GetBackgroundColor() const
|
|
{
|
|
return background.color;
|
|
}
|
|
|
|
COLORREF GetForegroundColor() const
|
|
{
|
|
return foreground.color;
|
|
}
|
|
|
|
void Open()
|
|
{
|
|
dialog.Open();
|
|
}
|
|
};
|
|
|
|
Dialog dialog;
|
|
Menu menu;
|
|
Control::NotificationHandler listNotifications;
|
|
Control::NotificationHandler treeNotifications;
|
|
StatusBar statusBar;
|
|
Tree tree;
|
|
List list;
|
|
Point margin;
|
|
Colors colors;
|
|
Point initialSize;
|
|
};
|
|
}
|
|
}
|
|
|
|
#endif
|