mirror of
https://github.com/0ldsk00l/nestopia.git
synced 2025-04-02 10:31:51 -04:00
370 lines
13 KiB
C++
370 lines
13 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
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "NstWindowParam.hpp"
|
|
#include "NstResourceString.hpp"
|
|
#include "NstManagerEmulator.hpp"
|
|
#include "NstDialogImageInfo.hpp"
|
|
#include "../core/api/NstApiCartridge.hpp"
|
|
#include "../core/api/NstApiFds.hpp"
|
|
#include "../core/api/NstApiNsf.hpp"
|
|
|
|
namespace Nestopia
|
|
{
|
|
namespace Window
|
|
{
|
|
ImageInfo::ImageInfo(Managers::Emulator& e)
|
|
:
|
|
dialog (IDD_IMAGE_INFO,WM_INITDIALOG,this,&ImageInfo::OnInitDialog),
|
|
emulator (e)
|
|
{
|
|
}
|
|
|
|
ibool ImageInfo::OnInitDialog(Param&)
|
|
{
|
|
struct Table
|
|
{
|
|
static void Tab(HeapString* const strings,const uint count,const bool fixed)
|
|
{
|
|
if (fixed)
|
|
{
|
|
uint maxTab = 0;
|
|
|
|
for (uint i=0; i < count; ++i)
|
|
maxTab = NST_MAX(maxTab,strings[i].Length());
|
|
|
|
maxTab += 2;
|
|
|
|
for (uint i=0; i < count; ++i)
|
|
{
|
|
if (uint pos = strings[i].Length())
|
|
{
|
|
strings[i].Resize( maxTab );
|
|
strings[i][pos] = ':';
|
|
|
|
while (++pos < maxTab)
|
|
strings[i][pos] = ' ';
|
|
}
|
|
}
|
|
}
|
|
else for (uint i=0; i < count; ++i)
|
|
{
|
|
if (strings[i].Length())
|
|
strings[i] << ": ";
|
|
}
|
|
}
|
|
|
|
static void Output(HeapString& output,HeapString* const strings,const uint count)
|
|
{
|
|
for (uint i=0; i < count; ++i)
|
|
{
|
|
if (strings[i].Length())
|
|
{
|
|
output << strings[i];
|
|
|
|
if (i < count-1)
|
|
output << "\r\n";
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
HeapString text;
|
|
|
|
const bool fixedFont = dialog.Edit(IDC_IMAGE_INFO_EDIT).FixedFont();
|
|
|
|
if (emulator.IsCart())
|
|
{
|
|
typedef Nes::Cartridge::Profile Profile;
|
|
|
|
enum
|
|
{
|
|
SP_H = Profile::Board::SOLDERPAD_H,
|
|
SP_V = Profile::Board::SOLDERPAD_V
|
|
};
|
|
|
|
const Profile& profile = *Nes::Cartridge(emulator).GetProfile();
|
|
|
|
HeapString types[] =
|
|
{
|
|
!profile.game.title.empty() ? Resource::String( IDS_TEXT_NAME ) : HeapString(),
|
|
!profile.game.altTitle.empty() ? Resource::String( IDS_TEXT_ALTNAME ) : HeapString(),
|
|
!profile.game.publisher.empty() ? Resource::String( IDS_TEXT_PUBLISHER ) : HeapString(),
|
|
!profile.game.developer.empty() ? Resource::String( IDS_TEXT_DEVELOPER ) : HeapString(),
|
|
!profile.game.region.empty() ? Resource::String( IDS_TEXT_REGION ) : HeapString(),
|
|
profile.game.players ? Resource::String( IDS_TEXT_PLAYERS ) : HeapString(),
|
|
Resource::String( IDS_TEXT_FILE ),
|
|
Resource::String( IDS_TEXT_DIRECTORY ),
|
|
Resource::String( IDS_TEXT_SOFTPATCHED ),
|
|
"CRC",
|
|
"SHA-1",
|
|
Resource::String( IDS_TEXT_SYSTEM ),
|
|
Resource::String( IDS_TEXT_BOARD ),
|
|
profile.board.GetPrg() ? "PRG-ROM" : HeapString(),
|
|
profile.board.GetChr() ? "CHR-ROM" : HeapString(),
|
|
profile.board.GetVram() ? "V-RAM" : HeapString(),
|
|
profile.board.GetWram() ? "W-RAM" : HeapString(),
|
|
!profile.board.chips.empty() ? Resource::String( IDS_TEXT_CHIPS ) : HeapString(),
|
|
profile.board.solderPads & (SP_H|SP_V) ? Resource::String( IDS_TEXT_SOLDERPAD ) : HeapString(),
|
|
Resource::String( IDS_TEXT_BATTERY ),
|
|
profile.board.HasBattery() ? Resource::String( IDS_TEXT_FILE ) : HeapString(),
|
|
profile.board.HasBattery() ? Resource::String( IDS_TEXT_DIRECTORY ) : HeapString(),
|
|
Resource::String( IDS_TEXT_DUMP )
|
|
};
|
|
|
|
Table::Tab( types, sizeof(array(types)), fixedFont );
|
|
|
|
if (!profile.game.title.empty())
|
|
types[0] << profile.game.title.c_str();
|
|
|
|
if (!profile.game.altTitle.empty())
|
|
types[1] << profile.game.altTitle.c_str();
|
|
|
|
if (!profile.game.publisher.empty())
|
|
types[2] << profile.game.publisher.c_str();
|
|
|
|
if (!profile.game.developer.empty())
|
|
types[3] << profile.game.developer.c_str();
|
|
|
|
if (!profile.game.region.empty())
|
|
types[4] << profile.game.region.c_str();
|
|
|
|
if (profile.game.players)
|
|
types[5] << profile.game.players;
|
|
|
|
types[6] << emulator.GetImagePath().File();
|
|
types[7] << emulator.GetImagePath().Directory();
|
|
|
|
types[8] << Resource::String( profile.patched ? IDS_TEXT_YES : IDS_TEXT_NO );;
|
|
|
|
{
|
|
char sha1[41] = {0};
|
|
char crc32[9] = {0};
|
|
|
|
profile.hash.Get( sha1, crc32 );
|
|
|
|
types[9] << crc32;
|
|
types[10] << sha1;
|
|
}
|
|
|
|
types[11] << Resource::String
|
|
(
|
|
profile.system.type == Profile::System::VS_UNISYSTEM ? IDS_TEXT_VSUNISYSTEM :
|
|
profile.system.type == Profile::System::VS_DUALSYSTEM ? IDS_TEXT_VSDUALSYSTEM :
|
|
profile.system.type == Profile::System::PLAYCHOICE_10 ? IDS_TEXT_PLAYCHOICE10 :
|
|
profile.system.type == Profile::System::NES_PAL ? IDS_TEXT_NES_PAL :
|
|
profile.system.type == Profile::System::NES_PAL_A ? IDS_TEXT_NES_PAL_A :
|
|
profile.system.type == Profile::System::NES_PAL_B ? IDS_TEXT_NES_PAL_B :
|
|
profile.system.type == Profile::System::FAMICOM ? IDS_TEXT_FAMICOM :
|
|
profile.system.type == Profile::System::DENDY ? IDS_TEXT_DENDY :
|
|
IDS_TEXT_NES_NTSC
|
|
);
|
|
|
|
types[12] << profile.board.type.c_str();
|
|
|
|
if (profile.board.mapper && profile.board.mapper != Profile::Board::NO_MAPPER)
|
|
types[12] << ", " << Resource::String( IDS_TEXT_MAPPER ) << ' ' << profile.board.mapper;
|
|
|
|
if (const uint prg = profile.board.GetPrg())
|
|
types[13] << (prg % 1024 ? prg : prg / 1024) << (prg % 1024 ? " bytes" : "k");
|
|
|
|
if (const uint chr = profile.board.GetChr())
|
|
types[14] << (chr % 1024 ? chr : chr / 1024) << (chr % 1024 ? " bytes" : "k");
|
|
|
|
if (const uint vram = profile.board.GetVram())
|
|
types[15] << (vram % 1024 ? vram : vram / 1024) << (vram % 1024 ? " bytes" : "k");
|
|
|
|
if (const uint wram = profile.board.GetWram())
|
|
types[16] << (wram % 1024 ? wram : wram / 1024) << (wram % 1024 ? " bytes" : "k");
|
|
|
|
for (uint i=0, n=profile.board.chips.size(); i < n; ++i)
|
|
{
|
|
if (i)
|
|
types[17] << ", ";
|
|
|
|
types[17] << profile.board.chips[i].type.c_str();
|
|
}
|
|
|
|
if (profile.board.solderPads & (SP_H|SP_V))
|
|
{
|
|
types[18] << "H:" << ((profile.board.solderPads & SP_H) ? '1' : '0')
|
|
<< " V:" << ((profile.board.solderPads & SP_V) ? '1' : '0');
|
|
}
|
|
|
|
types[19] << Resource::String( profile.board.HasBattery() ? IDS_TEXT_YES : IDS_TEXT_NO );
|
|
|
|
if (profile.board.HasBattery())
|
|
{
|
|
types[20] << emulator.GetSavePath().File();
|
|
types[21] << emulator.GetSavePath().Directory();
|
|
}
|
|
|
|
types[22] << Resource::String
|
|
(
|
|
profile.dump.state == Profile::Dump::OK ? IDS_TEXT_OK :
|
|
profile.dump.state == Profile::Dump::BAD ? IDS_TEXT_BAD :
|
|
IDS_TEXT_UNKNOWN
|
|
);
|
|
|
|
Table::Output( text, types, sizeof(array(types)) );
|
|
}
|
|
else if (emulator.IsFds())
|
|
{
|
|
const Nes::Fds fds(emulator);
|
|
|
|
std::vector<HeapString> types( 3 + NST_MAX(fds.GetNumSides()/2,1) );
|
|
|
|
types[0] = Resource::String( IDS_TEXT_FILE );
|
|
types[1] = Resource::String( IDS_TEXT_DIRECTORY );
|
|
types[2] = Resource::String( IDS_TEXT_HEADER );
|
|
|
|
for (uint i=3, n=types.size(); i < n; ++i)
|
|
types[i] = Resource::String( IDS_TEXT_DISK ).Invoke( i-3+1 );
|
|
|
|
Table::Tab( &types.front(), types.size(), fixedFont );
|
|
|
|
types[0] << emulator.GetImagePath().File();
|
|
types[1] << emulator.GetImagePath().Directory();
|
|
types[2] << Resource::String( fds.HasHeader() ? IDS_TEXT_YES : IDS_TEXT_NO );
|
|
|
|
for (uint i=0, n=fds.GetNumSides(); i < n; ++i)
|
|
{
|
|
Nes::Fds::DiskData data;
|
|
fds.GetDiskData( i, data );
|
|
|
|
uint size = 0;
|
|
|
|
for (Nes::Fds::DiskData::Files::const_iterator it(data.files.begin()), end(data.files.end()); it != end; ++it)
|
|
size += it->data.size();
|
|
|
|
types[3+i/2] << (i % 2 ? ", B: " : "A: ")
|
|
<< (size / 1024)
|
|
<< "k "
|
|
<< Resource::String( IDS_TEXT_IN_FILES ).Invoke( data.files.size() );
|
|
|
|
if (!data.raw.empty())
|
|
types[3+i/2] << ", " << Resource::String( IDS_TEXT_TRAILING_DATA ).Invoke( data.raw.size() );
|
|
}
|
|
|
|
Table::Output( text, &types.front(), types.size() );
|
|
}
|
|
else if (emulator.IsNsf())
|
|
{
|
|
const Nes::Nsf nsf(emulator);
|
|
|
|
HeapString types[] =
|
|
{
|
|
Resource::String( IDS_TEXT_FILE ),
|
|
Resource::String( IDS_TEXT_DIRECTORY ),
|
|
*nsf.GetName() ? Resource::String( IDS_TEXT_NAME ) : HeapString(),
|
|
*nsf.GetArtist() ? Resource::String( IDS_TEXT_ARTIST ) : HeapString(),
|
|
*nsf.GetCopyright() ? Resource::String( IDS_TEXT_COPYRIGHT ) : HeapString(),
|
|
Resource::String( IDS_TEXT_REGION ),
|
|
Resource::String( IDS_TEXT_SONGS ),
|
|
nsf.GetNumSongs() > 1 ? Resource::String( IDS_TEXT_STARTINGSONG ) : HeapString(),
|
|
Resource::String( IDS_TEXT_EXTRACHIPS ),
|
|
Resource::String( IDS_TEXT_BANKSWITCHING ),
|
|
Resource::String( IDS_TEXT_LOADADDRESS ),
|
|
Resource::String( IDS_TEXT_INITADDRESS ),
|
|
Resource::String( IDS_TEXT_PLAYADDRESS )
|
|
};
|
|
|
|
Table::Tab( types, sizeof(array(types)), fixedFont );
|
|
|
|
types[0] << emulator.GetImagePath().File();
|
|
types[1] << emulator.GetImagePath().Directory();
|
|
|
|
if (*nsf.GetName())
|
|
types[2].Import( nsf.GetName() );
|
|
|
|
if (*nsf.GetArtist())
|
|
types[3].Import( nsf.GetArtist() );
|
|
|
|
if (*nsf.GetCopyright())
|
|
types[4].Import( nsf.GetCopyright() );
|
|
|
|
types[5] <<
|
|
(
|
|
nsf.GetMode() == Nes::Nsf::TUNE_MODE_NTSC ? "NTSC" :
|
|
nsf.GetMode() == Nes::Nsf::TUNE_MODE_PAL ? "PAL" :
|
|
"NTSC/PAL"
|
|
);
|
|
|
|
types[6] << nsf.GetNumSongs();
|
|
|
|
if (nsf.GetNumSongs() > 1)
|
|
types[7] << (nsf.GetStartingSong() + 1);
|
|
|
|
if (const uint chips = nsf.GetChips())
|
|
{
|
|
cstring c = "";
|
|
|
|
if ( chips & Nes::Nsf::CHIP_MMC5 ) { types[8] << "MMC5"; c = "+"; }
|
|
if ( chips & Nes::Nsf::CHIP_VRC6 ) { types[8] << c << "VRC6"; c = "+"; }
|
|
if ( chips & Nes::Nsf::CHIP_VRC7 ) { types[8] << c << "VRC7"; c = "+"; }
|
|
if ( chips & Nes::Nsf::CHIP_N163 ) { types[8] << c << "N163"; c = "+"; }
|
|
if ( chips & Nes::Nsf::CHIP_S5B ) { types[8] << c << "Sunsoft5B"; c = "+"; }
|
|
if ( chips & Nes::Nsf::CHIP_FDS ) { types[8] << c << "FDS"; c = "+"; }
|
|
}
|
|
else
|
|
{
|
|
types[8] << Resource::String( IDS_TEXT_NO );
|
|
}
|
|
|
|
types[9] << Resource::String( nsf.UsesBankSwitching() ? IDS_TEXT_YES : IDS_TEXT_NO );
|
|
|
|
types[10] << HexString( 16, nsf.GetLoadAddress() );
|
|
types[11] << HexString( 16, nsf.GetInitAddress() );
|
|
types[12] << HexString( 16, nsf.GetPlayAddress() );
|
|
|
|
Table::Output( text, types, sizeof(array(types)) );
|
|
}
|
|
|
|
if (text.Length())
|
|
{
|
|
dialog.Edit(IDC_IMAGE_INFO_EDIT) << text.Ptr();
|
|
|
|
Point size( dialog.Edit(IDC_IMAGE_INFO_EDIT).GetMaxTextSize() );
|
|
Point delta( dialog.Edit(IDC_IMAGE_INFO_EDIT).GetWindow().Size() );
|
|
|
|
if (size.x > delta.x)
|
|
{
|
|
size.x = delta.x;
|
|
size.y += ::GetSystemMetrics(SM_CXVSCROLL);
|
|
::ShowScrollBar( dialog.Control(IDC_IMAGE_INFO_EDIT).GetWindow(), SB_HORZ, true );
|
|
}
|
|
|
|
if (size != delta)
|
|
{
|
|
dialog.Edit(IDC_IMAGE_INFO_EDIT).GetWindow().Size() = size;
|
|
delta -= size;
|
|
dialog.Control(IDOK).GetWindow().Position() -= delta;
|
|
dialog.Size() -= delta;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|