UIG製のコードを追加

git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_Repair@651 385bec56-5757-e545-9c3a-d8741f4650f1
This commit is contained in:
N2614 2012-02-22 02:25:50 +00:00
parent f33ba28561
commit 0d5bf9a14e
17 changed files with 7661 additions and 0 deletions

View File

@ -0,0 +1,645 @@
/*---------------------------------------------------------------------------*
Project: Horizon
File: CTR_LgyData.h
Copyright (C)2010 Nintendo Co., Ltd. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Rev$
*---------------------------------------------------------------------------*/
#ifndef CTR_LGYDATA_H_
#define CTR_LGYDATA_H_
#ifdef __cplusplus
extern "C" {
#endif
namespace nn { namespace CTR {
#define NN_CTR_ROMHEADER_CORP_ID "NINTENDO "
#define NN_CTR_TITLE_NAME_MAX 12
#define NN_CTR_GAME_CODE_MAX 4
#define NN_CTR_MAKER_CODE_MAX 2
#define NN_CTR_DIGEST_SIZE_SHA1 20
#define NN_CTR_NINTENDO_LOGO_DATA_LENGTH 0x9c
#define NN_CTR_PARENTAL_CONTROL_INFO_SIZE 0x10
/*===========================================================================*
* ROM FORMAT
*===========================================================================*/
// ROM access control info
typedef struct LegacyRomAccessControl {
u32 common_client_key :1; // launcher deliver common client Key
u32 hw_aes_slot_B :1; // launcher deliver HW AES slot B setting for ES
u32 hw_aes_slot_C :1; // launcher deliver HW AES slot C setting for NAM
u32 sd_card_access :1; // sd card access control
u32 nand_access :1; // NAND access control
u32 game_card_on :1; // NANDアプリでゲームカード電源ONーマルモード
u32 shared2_file :1; // shared file in "nand:/shared2"
u32 hw_aes_slot_B_SignJPEGForLauncher :1; // launcher deliver HW AES slot B setting for Sign JPEG for Launcher
u32 game_card_nitro_mode :1; // NANDアプリでゲームカードNTR互換領域へアクセス
u32 hw_aes_slot_A_SSLClientCert :1; // launcher deliver HW AES slot A setting for SSL Client Certificate
u32 hw_aes_slot_B_SignJPEGForUser :1; // launcher deliver HW AES slot B setting for Sign JPEG for User
u32 photo_access_read :1; // "photo:" archive read-access control
u32 photo_access_write :1; // "photo:" archive write-access control
u32 sdmc_access_read :1; // "sdmc:" archive read-access control
u32 sdmc_access_write :1; // "sdmc:" archive write-access control
u32 backup_access_read :1; // CARD-backup read-access control
u32 backup_access_write :1; // CARD-backup write-access control
u32: 14;
u32 common_client_key_for_debugger_sysmenu :1; // launcher deliver common client Key
} LegacyRomAccessControl;
// ROM expansion flags
typedef struct LegacyRomExpansionFlags {
u8 codec_mode:1; // 0:NTR mode, 1:TWL mode // undeveloped
u8 agree_EULA:1; // 1: necessary agree EULA
u8 availableSubBannerFile:1; // 1: Available SubBannerFile
u8 WiFiConnectionIcon :1; // 1: WiFiConnectionをランチャーで表示
u8 DSWirelessIcon :1; // 1: DSWirelessIconをランチャーで表示
u8 rsv_d5:1;
u8 enable_nitro_whitelist_signature :1; // 1: NITROホワイトリスト署名有効フラグ
u8 developer_encrypt:1; // 1: 開発用セキュリティがかかっている場合に"1"。製品版では"0" (※TwlSDK UIG_branch/RC2以降はこちらが有効
} LegacyRomExpansionFlags;
//---------------------------------------------------------------------------
// Section A ROM HEADER
//---------------------------------------------------------------------------
typedef struct LegacyRomHeader
{
//==========================================================
//
// NTR/TWL common
//
//==========================================================
//
// 0x000 System Reserved
//
char title_name[NN_CTR_TITLE_NAME_MAX]; // Soft title name
char game_code[NN_CTR_GAME_CODE_MAX]; // Game code
char maker_code[NN_CTR_MAKER_CODE_MAX]; // Maker code
char platform_code; // Platform code bit0: not support NTR, bit1: support TWL ( NTR_only=0x00, NTR/TWL=0x03, TWL_only=0x02 )
u8 rom_type; // Rom type
u8 rom_size; // Rom size (2のrom_size乗 Mbit: ex. 128Mbitのときrom_size = 7)
u8 reserved_A[7]; // System Reserved A ( Set ALL 0 )
u8 enable_signature:1; // enable ROM Header signature
u8 enable_aes:1; // enable AES encryption
u8 developer_encrypt_old:1; // 開発用セキュリティがかかっている場合に"1"。製品版では"0" (※TwlSDK RC plusまではこちらが有効
u8 disable_debug:1; // デバッグ禁止フラグ
u8: 4;
u8 permit_landing_normal_jump:1; // アプリジャンプのノーマルジャンプで呼び出されることを許可する( for TWL Application Jump )
u8 permit_landing_tmp_jump:1; // アプリジャンプのTMPジャンプで呼び出されることを許可する( for TWL Application Jump )
// ※NTR体験版アプリはDSダウンロードプレイの署名しかついていないので、このフラグはNTR-ROMヘッダの0x160bytes内の領域に格納する必要がある。
u8: 4;
u8 for_korea:1; // For Korea
u8 for_china:1; // For China
u8 rom_version; // Rom version
u8 comp_arm9_boot_area:1; // Compress arm9 boot area
u8 comp_arm7_boot_area:1; // Compress arm7 boot area
u8 inspect_card:1; // Show inspect card
u8 disable_clear_memory_pad:1; // for Debugger
u8 enable_twl_rom_cache_read:1; // Enable TWL ROM cacheRead command
u8 :1; // reserved.
u8 warning_no_spec_rom_speed:1;// Warning not to specify rom speed
u8 disable_detect_pull_out:1; // Decect CARD removal by checking ROM-ID
//
// 0x020 for Static modules (Section:B)
//
// ARM9
u32 main_rom_offset; // ROM offset
void *main_entry_address; // Entry point
void *main_ram_address; // RAM address
u32 main_size; // Module size
// ARM7
u32 sub_rom_offset; // ROM offset
void *sub_entry_address; // Entry point
void *sub_ram_address; // RAM address
u32 sub_size; // Module size
//
// 0x040 for File Name Table[FNT] (Section:C)
//
struct ROM_FNT *fnt_offset; // ROM offset
u32 fnt_size; // Table size
//
// 0x048 for File Allocation Table[FAT] (Section:E)
//
struct ROM_FAT *fat_offset; // ROM offset
u32 fat_size; // Table size
//
// 0x050 for Overlay Tables[OVT] (Section:D)
//
// ARM9
struct ROM_OVT *main_ovt_offset; // ROM offset
u32 main_ovt_size; // Table size
// ARM7
struct ROM_OVT *sub_ovt_offset; // ROM offset
u32 sub_ovt_size; // Table size
// 0x060 for ROM control parameter (Section:F)
u32 game_cmd_param; // Game command parameter
u32 secure_cmd_param; // Secure command parameter
u32 banner_offset; // Banner ROM offset
u16 secure_area_crc16; // Secure area CRC-16
u16 secure_cmd_latency; // Secure command latency ((param+2)*256 system cycles)
// since NITRO-SDK 2.0PR4
void *main_autoload_done; // ARM9 autoload done callback address (debug purpose)
void *sub_autoload_done; // ARM7 autoload done callback address (debug purpose)
u8 ctrl_reserved_B[8]; // Ctrl Reserved B (Set 0)
// since NITRO-SDK 2.0PR6
u32 rom_valid_size; // ROM Original Size
u32 rom_header_size; // ROM Header size
u32 main_module_param_offset; // Offset for table of ARM9 module parameters
u32 sub_module_param_offset; // Offset for table of ARM7 module parameters
// 0x090 - 0x0C0 System Reserved
u16 twl_card_normal_area_rom_offset; // undeveloped
u16 twl_card_keytable_area_rom_offset; // undeveloped
u16 nand_card_dl_area_rom_offset; // undeveloped
u16 nand_card_bk_area_rom_offset; // undeveloped
u8 nand_card_flag; // undeveloped
u8 reserved_B[39];
// 0x0C0 for NINTENDO logo data
u8 nintendo_logo[ NN_CTR_NINTENDO_LOGO_DATA_LENGTH ]; // NINTENDO logo data
u16 nintendo_logo_crc16; // CRC-16
// 0x15E ROM header CRC-16
u16 header_crc16; // ROM header CRC-16
// 0x160 - 0x180 Debugger Reserved
u8 reserved_C[32]; // Debugger Reserved (Set ALL 0)
//==========================================================
//
// TWL only
//
//==========================================================
// 0x180 - 0x190 TWL-WRAM A/B/C ARM9 configuration data
u32 main_wram_config_data[8]; // developing...
// 0x1A0 - 0x1B0 TWL-WRAM A/B/C ARM7 configuration data
u32 sub_wram_config_data[4]; // developing...
// 0x1B0 - Card Region bitmap
u32 card_region_bitmap;
// 0x1B4 - AccessControl
LegacyRomAccessControl access_control;
/* 注意: fatfs_command.c 内で 0x01b4 のアドレスを
*/
// 0x1B8 - ARM7-SCFG
u32 arm7_scfg_ext; // SCFG-EXT
// padding(3byte)
u8 reserved_ltd_A2[ 3 ];
// 0x1BF - TWL expansion flags
LegacyRomExpansionFlags exFlags;
// 0x1C0 for EX Static modules
//
// ARM9
u32 main_ltd_rom_offset; // ROM offset // undeveloped
u8 reserved_ltd_B[ 4 ];
void *main_ltd_ram_address; // RAM address // undeveloped //
u32 main_ltd_size; // Module size // undeveloped //
// ARM7
u32 sub_ltd_rom_offset; // ROM offset // undeveloped
void *sub_mount_info_ram_address; // ARM7 MountInfo RAM address.
void *sub_ltd_ram_address; // RAM address // undeveloped //
u32 sub_ltd_size; // Module size // undeveloped //
/* 注意: os_reset.c / crt0.HYB.c / crt0.LTD.c 内で 0x01c0 0x01e0 のアドレスを
*/
// 0x01E0 - 0x01E8 for NITRO digest area offset & size
u32 nitro_digest_area_rom_offset;
u32 nitro_digest_area_size;
// 0x01E8 - 0x01F0 for TWL digest area offset & size
u32 twl_digest_area_rom_offset;
u32 twl_digest_area_size;
// 0x01F0 - 0x01F8 for FS digest table1 offset & size
u32 digest1_table_offset;
u32 digest1_table_size;
// 0x01F8 - 0x0200 for FS digest table2 offset & size
u32 digest2_table_offset;
u32 digest2_table_size;
// 0x0200 - 0x0208 for FS digest config parameters
u32 digest1_block_size;
u32 digest2_covered_digest1_num;
// 0x0208 - 0x020C for TWL banner size.
u32 banner_size;
// 0x020C - 0x020E for shared2 files size
u8 shared2_file0_size; // shared2 file [0]
u8 shared2_file1_size; // shared2 file [1]
/* 注意: fatfs_command.c 内で 0x020C-0x020D のアドレスを
*/
// 0x020E for Agree EULA version
u8 agree_EULA_version;
// 0x020F TWL Administration flags
u8 unnecessary_rating_display:1; // レーティング表記がいらないROMのときに立てる(管理用:ランチャーでは不使用)
u8: 7;
// 0x0210 - 0x0214 for TWL rom valid size
u32 twl_rom_valid_size; // ROM Original Size
// 0x0214 - 0x0218 for shared2 files size
u8 shared2_file2_size; // shared2 file [2]
u8 shared2_file3_size; // shared2 file [3]
u8 shared2_file4_size; // shared2 file [4]
u8 shared2_file5_size; // shared2 file [5]
/* 注意: fatfs_command.c 内で 0x0214 - 0x0217 のアドレスを
*/
// 0x0218 - 0x0220 for TWL ltd module param offset
u32 main_ltd_module_param_offset; // Offset for table of ARM9 ltd module parameters
u32 sub_ltd_module_param_offset; // Offset for table of ARM7 ltd module parameters
// 0x0220 - 0x0230 for AES target offset & size
u32 aes_target_rom_offset;
u32 aes_target_size;
u32 aes_target2_rom_offset; // 予約
u32 aes_target2_size; // 予約
// 0x0230 - 0x0238 for TitleID
union {
u64 titleID;
// struct {
u8 titleID_Lo[ 4 ];
// u32 titleID_Hi;
// };
};
/* 注意: os_reset.c / crt0.HYB.c / crt0.LTD.c / fatfs_command.c 内で 0x0234 をハードコーディングしています。
titleID_Hi */
// 0x0238 - 0x0240 for Public & Private Save Data Size
u32 public_save_data_size;
u32 private_save_data_size;
// 0x0240 - 0x02f0 reserved.
u8 reserved_ltd_F[ 0x2f0 - 0x240 ];
// 0x02f0 - 0x0300 Parental Controls Rating Info
u8 parental_control_rating_info[ NN_CTR_PARENTAL_CONTROL_INFO_SIZE ];
// 0x0300 - 0x0378 Rom Segment Digest
u8 main_static_digest[ NN_CTR_DIGEST_SIZE_SHA1 ];
u8 sub_static_digest[ NN_CTR_DIGEST_SIZE_SHA1 ];
u8 digest2_table_digest[ NN_CTR_DIGEST_SIZE_SHA1 ];
u8 banner_digest[ NN_CTR_DIGEST_SIZE_SHA1 ];
u8 main_ltd_static_digest[ NN_CTR_DIGEST_SIZE_SHA1 ];
u8 sub_ltd_static_digest[ NN_CTR_DIGEST_SIZE_SHA1 ];
} LegacyRomHeader;
// include\nn\drivers\card\CTR\ARM946ES\extra.h を移植 ---------------------------------------------------
#define NN_CTR_SDK_128M
/* MC1 */
#define NN_CTR_REG_MI_MC1_CC_SHIFT 16
#define NN_CTR_REG_MI_MC1_CC_SIZE 16
#define NN_CTR_REG_MI_MC1_CC_MASK 0xffff0000
#define NN_CTR_REG_MI_MC1_SWP_SHIFT 15
#define NN_CTR_REG_MI_MC1_SWP_SIZE 1
#define NN_CTR_REG_MI_MC1_SWP_MASK 0x00008000
#define NN_CTR_REG_MI_MC1_SL2_STATUS_SHIFT 4
#define NN_CTR_REG_MI_MC1_SL2_STATUS_SIZE 4
#define NN_CTR_REG_MI_MC1_SL2_STATUS_MASK 0x000000f0
#define NN_CTR_REG_MI_MC1_SL2_M1_SHIFT 7
#define NN_CTR_REG_MI_MC1_SL2_M1_SIZE 1
#define NN_CTR_REG_MI_MC1_SL2_M1_MASK 0x00000080
#define NN_CTR_REG_MI_MC1_SL2_M0_SHIFT 6
#define NN_CTR_REG_MI_MC1_SL2_M0_SIZE 1
#define NN_CTR_REG_MI_MC1_SL2_M0_MASK 0x00000040
#define NN_CTR_REG_MI_MC1_SL2_CDET_SHIFT 4
#define NN_CTR_REG_MI_MC1_SL2_CDET_SIZE 1
#define NN_CTR_REG_MI_MC1_SL2_CDET_MASK 0x00000010
#define NN_CTR_REG_MI_MC1_SL1_STATUS_SHIFT 0
#define NN_CTR_REG_MI_MC1_SL1_STATUS_SIZE 4
#define NN_CTR_REG_MI_MC1_SL1_STATUS_MASK 0x0000000f
#define NN_CTR_REG_MI_MC1_SL1_M1_SHIFT 3
#define NN_CTR_REG_MI_MC1_SL1_M1_SIZE 1
#define NN_CTR_REG_MI_MC1_SL1_M1_MASK 0x00000008
#define NN_CTR_REG_MI_MC1_SL1_M0_SHIFT 2
#define NN_CTR_REG_MI_MC1_SL1_M0_SIZE 1
#define NN_CTR_REG_MI_MC1_SL1_M0_MASK 0x00000004
#define NN_CTR_REG_MI_MC1_SL1_CDET_SHIFT 0
#define NN_CTR_REG_MI_MC1_SL1_CDET_SIZE 1
#define NN_CTR_REG_MI_MC1_SL1_CDET_MASK 0x00000001
#ifndef SDK_ASM
#define NN_CTR_REG_MI_MC1_FIELD( cc, swp, sl2_status, sl2_m1, sl2_m0, sl2_cdet, sl1_status, sl1_m1, sl1_m0, sl1_cdet ) \
(u32)( \
((u32)(cc) << NN_CTR_REG_MI_MC1_CC_SHIFT) | \
((u32)(swp) << NN_CTR_REG_MI_MC1_SWP_SHIFT) | \
((u32)(sl2_status) << NN_CTR_REG_MI_MC1_SL2_STATUS_SHIFT) | \
((u32)(sl2_m1) << NN_CTR_REG_MI_MC1_SL2_M1_SHIFT) | \
((u32)(sl2_m0) << NN_CTR_REG_MI_MC1_SL2_M0_SHIFT) | \
((u32)(sl2_cdet) << NN_CTR_REG_MI_MC1_SL2_CDET_SHIFT) | \
((u32)(sl1_status) << NN_CTR_REG_MI_MC1_SL1_STATUS_SHIFT) | \
((u32)(sl1_m1) << NN_CTR_REG_MI_MC1_SL1_M1_SHIFT) | \
((u32)(sl1_m0) << NN_CTR_REG_MI_MC1_SL1_M0_SHIFT) | \
((u32)(sl1_cdet) << NN_CTR_REG_MI_MC1_SL1_CDET_SHIFT))
#endif
/* MC */
#define NN_CTR_REG_MI_MC_SWP_SHIFT 15
#define NN_CTR_REG_MI_MC_SWP_SIZE 1
#define NN_CTR_REG_MI_MC_SWP_MASK 0x8000
#define NN_CTR_REG_MI_MC_SL2_MODE_SHIFT 6
#define NN_CTR_REG_MI_MC_SL2_MODE_SIZE 2
#define NN_CTR_REG_MI_MC_SL2_MODE_MASK 0x00c0
#define NN_CTR_REG_MI_MC_SL2_CDET_SHIFT 4
#define NN_CTR_REG_MI_MC_SL2_CDET_SIZE 1
#define NN_CTR_REG_MI_MC_SL2_CDET_MASK 0x0010
#define NN_CTR_REG_MI_MC_SL1_MODE_SHIFT 2
#define NN_CTR_REG_MI_MC_SL1_MODE_SIZE 2
#define NN_CTR_REG_MI_MC_SL1_MODE_MASK 0x000c
#define NN_CTR_REG_MI_MC_SL1_CDET_SHIFT 0
#define NN_CTR_REG_MI_MC_SL1_CDET_SIZE 1
#define NN_CTR_REG_MI_MC_SL1_CDET_MASK 0x0001
#ifndef SDK_ASM
#define NN_CTR_REG_MI_MC_FIELD( swp, sl2_mode, sl2_cdet, sl1_mode, sl1_cdet ) \
(u16)( \
((u32)(swp) << NN_CTR_REG_MI_MC_SWP_SHIFT) | \
((u32)(sl2_mode) << NN_CTR_REG_MI_MC_SL2_MODE_SHIFT) | \
((u32)(sl2_cdet) << NN_CTR_REG_MI_MC_SL2_CDET_SHIFT) | \
((u32)(sl1_mode) << NN_CTR_REG_MI_MC_SL1_MODE_SHIFT) | \
((u32)(sl1_cdet) << NN_CTR_REG_MI_MC_SL1_CDET_SHIFT))
#endif
/* EXMEMCNT_L */
#define NN_CTR_REG_MI_EXMEMCNT_L_EP_SHIFT 15
#define NN_CTR_REG_MI_EXMEMCNT_L_EP_SIZE 1
#define NN_CTR_REG_MI_EXMEMCNT_L_EP_MASK 0x8000
#define NN_CTR_REG_MI_EXMEMCNT_L_EMODE_SHIFT 14
#define NN_CTR_REG_MI_EXMEMCNT_L_EMODE_SIZE 1
#define NN_CTR_REG_MI_EXMEMCNT_L_EMODE_MASK 0x4000
#define NN_CTR_REG_MI_EXMEMCNT_L_ECE2_SHIFT 13
#define NN_CTR_REG_MI_EXMEMCNT_L_ECE2_SIZE 1
#define NN_CTR_REG_MI_EXMEMCNT_L_ECE2_MASK 0x2000
#define NN_CTR_REG_MI_EXMEMCNT_L_MP_SHIFT 11
#define NN_CTR_REG_MI_EXMEMCNT_L_MP_SIZE 1
#define NN_CTR_REG_MI_EXMEMCNT_L_MP_MASK 0x0800
#define NN_CTR_REG_MI_EXMEMCNT_L_MP_A_SHIFT 11
#define NN_CTR_REG_MI_EXMEMCNT_L_MP_A_SIZE 1
#define NN_CTR_REG_MI_EXMEMCNT_L_MP_A_MASK 0x0800
#define NN_CTR_REG_MI_EXMEMCNT_L_MP_B_SHIFT 10
#define NN_CTR_REG_MI_EXMEMCNT_L_MP_B_SIZE 1
#define NN_CTR_REG_MI_EXMEMCNT_L_MP_B_MASK 0x0400
#define NN_CTR_REG_MI_EXMEMCNT_L_CP_SHIFT 7
#define NN_CTR_REG_MI_EXMEMCNT_L_CP_SIZE 1
#define NN_CTR_REG_MI_EXMEMCNT_L_CP_MASK 0x0080
#define NN_CTR_REG_MI_EXMEMCNT_L_PHI_SHIFT 5
#define NN_CTR_REG_MI_EXMEMCNT_L_PHI_SIZE 2
#define NN_CTR_REG_MI_EXMEMCNT_L_PHI_MASK 0x0060
#define NN_CTR_REG_MI_EXMEMCNT_L_ROM2nd_SHIFT 4
#define NN_CTR_REG_MI_EXMEMCNT_L_ROM2nd_SIZE 1
#define NN_CTR_REG_MI_EXMEMCNT_L_ROM2nd_MASK 0x0010
#define NN_CTR_REG_MI_EXMEMCNT_L_ROM1st_SHIFT 2
#define NN_CTR_REG_MI_EXMEMCNT_L_ROM1st_SIZE 2
#define NN_CTR_REG_MI_EXMEMCNT_L_ROM1st_MASK 0x000c
#define NN_CTR_REG_MI_EXMEMCNT_L_RAM_SHIFT 0
#define NN_CTR_REG_MI_EXMEMCNT_L_RAM_SIZE 2
#define NN_CTR_REG_MI_EXMEMCNT_L_RAM_MASK 0x0003
#ifndef SDK_ASM
#define NN_CTR_REG_MI_EXMEMCNT_L_FIELD( ep, emode, ece2, mp, mp_a, mp_b, cp, phi, rom2nd, rom1st, ram ) \
(u16)( \
((u32)(ep) << NN_CTR_REG_MI_EXMEMCNT_L_EP_SHIFT) | \
((u32)(emode) << NN_CTR_REG_MI_EXMEMCNT_L_EMODE_SHIFT) | \
((u32)(ece2) << NN_CTR_REG_MI_EXMEMCNT_L_ECE2_SHIFT) | \
((u32)(mp) << NN_CTR_REG_MI_EXMEMCNT_L_MP_SHIFT) | \
((u32)(mp_a) << NN_CTR_REG_MI_EXMEMCNT_L_MP_A_SHIFT) | \
((u32)(mp_b) << NN_CTR_REG_MI_EXMEMCNT_L_MP_B_SHIFT) | \
((u32)(cp) << NN_CTR_REG_MI_EXMEMCNT_L_CP_SHIFT) | \
((u32)(phi) << NN_CTR_REG_MI_EXMEMCNT_L_PHI_SHIFT) | \
((u32)(rom2nd) << NN_CTR_REG_MI_EXMEMCNT_L_ROM2nd_SHIFT) | \
((u32)(rom1st) << NN_CTR_REG_MI_EXMEMCNT_L_ROM1st_SHIFT) | \
((u32)(ram) << NN_CTR_REG_MI_EXMEMCNT_L_RAM_SHIFT))
#endif
/* EXMEMCNT_H */
#define NN_CTR_REG_MI_EXMEMCNT_H_PHI33M_SHIFT 7
#define NN_CTR_REG_MI_EXMEMCNT_H_PHI33M_SIZE 1
#define NN_CTR_REG_MI_EXMEMCNT_H_PHI33M_MASK 0x0080
#define NN_CTR_REG_MI_EXMEMCNT_H_WW1_2nd_SHIFT 5
#define NN_CTR_REG_MI_EXMEMCNT_H_WW1_2nd_SIZE 1
#define NN_CTR_REG_MI_EXMEMCNT_H_WW1_2nd_MASK 0x0020
#define NN_CTR_REG_MI_EXMEMCNT_H_WW1_1st_SHIFT 3
#define NN_CTR_REG_MI_EXMEMCNT_H_WW1_1st_SIZE 2
#define NN_CTR_REG_MI_EXMEMCNT_H_WW1_1st_MASK 0x0018
#define NN_CTR_REG_MI_EXMEMCNT_H_WW0_2nd_SHIFT 2
#define NN_CTR_REG_MI_EXMEMCNT_H_WW0_2nd_SIZE 1
#define NN_CTR_REG_MI_EXMEMCNT_H_WW0_2nd_MASK 0x0004
#define NN_CTR_REG_MI_EXMEMCNT_H_WW0_1st_SHIFT 0
#define NN_CTR_REG_MI_EXMEMCNT_H_WW0_1st_SIZE 2
#define NN_CTR_REG_MI_EXMEMCNT_H_WW0_1st_MASK 0x0003
#ifndef SDK_ASM
#define NN_CTR_REG_MI_EXMEMCNT_H_FIELD( phi33m, ww1_2nd, ww1_1st, ww0_2nd, ww0_1st ) \
(u16)( \
((u32)(phi33m) << NN_CTR_REG_MI_EXMEMCNT_H_PHI33M_SHIFT) | \
((u32)(ww1_2nd) << NN_CTR_REG_MI_EXMEMCNT_H_WW1_2nd_SHIFT) | \
((u32)(ww1_1st) << NN_CTR_REG_MI_EXMEMCNT_H_WW1_1st_SHIFT) | \
((u32)(ww0_2nd) << NN_CTR_REG_MI_EXMEMCNT_H_WW0_2nd_SHIFT) | \
((u32)(ww0_1st) << NN_CTR_REG_MI_EXMEMCNT_H_WW0_1st_SHIFT))
#endif
#define NN_CTR_AES_KEY_SIZE 16 // 128 bit
#define NN_CTR_GAME_CODE_MAX 4
#define NN_CTR_AES_BLOCK_SIZE 16
// define NN_CTR_data---------------------------------------------
#define NN_CTR_BANNER_IMAGE_SIZE (32 * 32 / (8/4))
#define NN_CTR_BANNER_PLTT_SIZE (16 * 2)
#define NN_CTR_BANNER_LANG_LENGTH 128
#define NN_CTR_BANNER_LANG_SIZE (BANNER_LANG_LENGTH * 2)
#define NN_CTR_BANNER_VER_NTR_MIN 1 // NTRバナーver.MIN.
#define NN_CTR_BANNER_VER_NTR_MAX 3 // NTRバナーver.MAX.(smaller than UCHAR_MAX)
#define NN_CTR_BANNER_VER_TWL_MIN 3 // TWLバナーver.MIN.
#define NN_CTR_BANNER_VER_TWL_MAX 3 // TWLバナーver.MAX.(smaller than UCHAR_MAX)
#define NN_CTR_BANNER_CHINESE_SUPPORT_VER 2 // 中国語サポートver.
#define NN_CTR_BANNER_KOREAN_SUPPORT_VER 3 // 韓国語サポートver.
#define NN_CTR_BANNER_LANG_NUM_RSV 8 // 言語予約領域数
#define NN_CTR_BANNER_ANIME_PATTERN_NUM 8 // バナーアニメパターン数
#define NN_CTR_BANNER_ANIME_CONTROL_INFO_NUM 64 // バナーアニメコントロール情報数
// バナーファイル上の言語配置順序
typedef enum {
NN_CTR_BANNER_PRIO_JAPANESE = 0,
NN_CTR_BANNER_PRIO_ENGLISH,
NN_CTR_BANNER_PRIO_FRENCH,
NN_CTR_BANNER_PRIO_GERMAN,
NN_CTR_BANNER_PRIO_ITALIAN,
NN_CTR_BANNER_PRIO_SPANISH,
NN_CTR_BANNER_PRIO_CHINESE,
NN_CTR_BANNER_PRIO_KOREAN,
NN_CTR_BANNER_LANG_NUM,
NN_CTR_BANNER_LANG_NUM_V1 = NN_CTR_BANNER_PRIO_CHINESE,
NN_CTR_BANNER_LANG_NUM_V2 = NN_CTR_BANNER_PRIO_KOREAN - NN_CTR_BANNER_PRIO_CHINESE,
NN_CTR_BANNER_LANG_NUM_V3 = NN_CTR_BANNER_LANG_NUM - NN_CTR_BANNER_PRIO_KOREAN
} LegacyBannerLanguagePriorityIdx;
// プラットフォームコード
typedef enum {
NN_CTR_BANNER_PLATFORM_NTR = 0,
NN_CTR_BANNER_PLATFORM_TWL = 1,
NN_CTR_BANNER_PLATFORM_MAX = 2
} LegacyBannerPlatformCode;
// バナーアニメデータ構造体(bannercvtr.exeが出力するデータ)
typedef struct {
u8 image [ NN_CTR_BANNER_ANIME_PATTERN_NUM ][ NN_CTR_BANNER_IMAGE_SIZE ];
u8 pltt [ NN_CTR_BANNER_ANIME_PATTERN_NUM ][ NN_CTR_BANNER_PLTT_SIZE ];
struct {
u8 frameCount : 8;
union {
struct {
u8 cellNo : 3;
u8 plttNo : 3;
u8 flipType : 2;
}normal;
u8 animeType;
};
} control[ NN_CTR_BANNER_ANIME_CONTROL_INFO_NUM ];
} LegacyBannerAnime;
// バナーヘッダ
typedef struct {
u8 version;
u8 platform; // 上記BannerPlatformCodeで指定
u16 crc16_v1;
u16 crc16_v2;
u16 crc16_v3;
u16 crc16_anime;
u8 reserved_B[ 22 ];
} LegacyBannerHeader;
// バナーver.1 ボディ
typedef struct {
u8 image[ NN_CTR_BANNER_IMAGE_SIZE ];
u8 pltt[ NN_CTR_BANNER_PLTT_SIZE ];
u16 gameName[ NN_CTR_BANNER_LANG_NUM_V1 ][ NN_CTR_BANNER_LANG_LENGTH ];
} LegacyBannerFileV1;
// バナーver.2 ボディ追加分
typedef struct {
u16 gameName[ NN_CTR_BANNER_LANG_NUM_V2 ][ NN_CTR_BANNER_LANG_LENGTH ];
} LegacyBannerFileV2;
// バナーver.3 ボディ追加分
typedef struct {
u16 gameName[ NN_CTR_BANNER_LANG_NUM_V3 ][ NN_CTR_BANNER_LANG_LENGTH ];
} LegacyBannerFileV3;
// バナーgameName 言語拡張予約領域
typedef struct {
u16 gameName[ NN_CTR_BANNER_LANG_NUM_RSV ][ NN_CTR_BANNER_LANG_LENGTH ];
} LegacyBannerFileRsv;
// TWLバナーファイル構造体
typedef struct {
LegacyBannerHeader h;
LegacyBannerFileV1 v1;
LegacyBannerFileV2 v2;
LegacyBannerFileV3 v3; // <--- ここまではNTRバナーと共通
LegacyBannerFileRsv rsv;
LegacyBannerAnime anime;
} LegacyTwlBannerFile;
}
}
#ifdef __cplusplus
}
#endif
#endif //CTR_LGYDATA_H_

View File

@ -0,0 +1,55 @@
// CtrIcon.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//
#ifndef __IDB_CTR_ICON_H_
#define __IDB_CTR_ICON_H_
#include <nn/types.h>
#include <nn/CTR/CTR_SystemMenuData.h>
#define BIG_TEXTURE_WIDTH 64 // 通常アイコンのテクスチャサイズ
#define BIG_TEXTURE_HEIGHT 64
#define SMALL_TEXTURE_WIDTH 32 // 小さなアイコンのテクスチャサイズ
#define SMALL_TEXTURE_HEIGHT 32
#define BIG_ICON_WIDTH nn::CTR::SYSTEMMENUDATA_BIG_ICON_WIDTH
#define BIG_ICON_HEIGHT nn::CTR::SYSTEMMENUDATA_BIG_ICON_HEIGHT
#define SMALL_ICON_WIDTH nn::CTR::SYSTEMMENUDATA_SMALL_ICON_HEIGHT // 小さなアイコンの使用領域&アイコンデータのサイズ
#define SMALL_ICON_HEIGHT nn::CTR::SYSTEMMENUDATA_SMALL_ICON_HEIGHT
#define TWL_ICON_WIDTH 32
#define TWL_ICON_HEIGHT 32
#define PIXEL_SIZE sizeof(u16) // 1ピクセルのビット深度
#define DATA_BLOCK_WIDTH 8 // ブロックサイズ
#define DATA_BLOCK_HEIGHT 8
#define DATA_BLOCK_LENGTH (DATA_BLOCK_WIDTH * DATA_BLOCK_HEIGHT)
#define DATA_BLOCK_SIZE (DATA_BLOCK_LENGTH* PIXEL_SIZE)
// ブロック単位での大きさ
#define BIG_ICON_BLOCK_WIDTH (BIG_ICON_WIDTH / DATA_BLOCK_WIDTH)
#define BIG_ICON_BLOCK_HEIGHT (BIG_ICON_HEIGHT/ DATA_BLOCK_HEIGHT)
#define SMALL_ICON_BLOCK_WIDTH (SMALL_ICON_WIDTH / DATA_BLOCK_WIDTH)
#define SMALL_ICON_BLOCK_HEIGHT (SMALL_ICON_HEIGHT/ DATA_BLOCK_HEIGHT)
#define TWL_ICON_BLOCK_WIDTH (TWL_ICON_WIDTH / DATA_BLOCK_WIDTH)
#define TWL_ICON_BLOCK_HEIGHT (TWL_ICON_HEIGHT/ DATA_BLOCK_HEIGHT)
#define BIG_TEXTURE_BLOCK_WIDTH (BIG_TEXTURE_WIDTH / DATA_BLOCK_WIDTH)
#define BIG_TEXTURE_BLOCK_HEIGHT (BIG_TEXTURE_HEIGHT/ DATA_BLOCK_HEIGHT)
#define SMALL_TEXTURE_BLOCK_WIDTH (SMALL_TEXTURE_WIDTH / DATA_BLOCK_WIDTH)
#define SMALL_TEXTURE_BLOCK_HEIGHT (SMALL_TEXTURE_HEIGHT/ DATA_BLOCK_HEIGHT)
// アイコン画像をテクスチャに変換したデータ(2の乗数にするためのパディングつき)
typedef struct
{
u16 little[SMALL_TEXTURE_HEIGHT*SMALL_TEXTURE_WIDTH];
u16 big[BIG_TEXTURE_HEIGHT*BIG_TEXTURE_WIDTH];
} IDB_TextureData;
typedef nn::CTR::SystemMenuDataIcon IDB_IconData;
#endif // ifndef __IDB_IDB_H_

View File

@ -0,0 +1,227 @@
// IDB.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//
#ifndef __IDB_IDB_H_
#define __IDB_IDB_H_
#include <nn/types.h>
#include <nn/CTR/CTR_SystemMenuData.h>
#include <nn/CTR/CTR_LegacyData.h>
#include "CtrIcon.h"
#include <nn/assert.h>
#ifndef BOOL
typedef int BOOL;
#endif //BOOL
#ifndef TRUE
// Any non zero value is considered TRUE
#define TRUE 1
#endif //TRUE
#ifndef FALSE
#define FALSE 0
#endif // FALSE
#define IDB_VERSION 9 // アイコンデータベースのバージョン
#define IDB_ICON_DATA_MAX 512 // アイコンデータの最大件数
#define IDB_OWNER_ICON_DATA_MAX 256 // オーナーアイコンデータの最大件数
#define IDB_PICTURE_DATA_WIDTH 48 // アイコンテクスチャの幅
#define IDB_PICTURE_DATA_HEIGHT 48 // アイコンテクスチャの高さ
#define IDB_PICTURE_DATA_DEPTH 2 // アイコンテクスチャのbit深度
#define IDB_PICTURE_DATA_SIZE (IDB_PICTURE_DATA_WIDTH*IDB_PICTURE_DATA_HEIGHT*IDB_PICTURE_DATA_DEPTH)
#define IDB_APP_INFO_SHORT_TITLE_LENGTH 64 // 短いソフトタイトル(1行)
#define IDB_APP_INFO_LONG_TITLE_LENGTH 128 // 長いソフトタイトル(2行)
#define IDB_APP_INFO_PUBLISHER_LENGTH 64 // 発売元
#define IDB_RATING_MAX 16 // 1つのROMに設定できる最大レーティング数
#define IDB_LANGUAGE_MAX 16 // 1つのアイコン情報に入る最大言語数
enum IDB_IconFormat
{
IDB_ICON_FORMAT_CTR,
IDB_ICON_FORMAT_TWL,
IDB_ICON_FORMAT_NTR,
IDB_ICON_FORMAT_MAX,
IDB_ICON_FORMAT_INVALID = 0x7fffffff // 問合せ時にIDB_ICON_FORMAT_INVALIDを
};
// データベースを取得するためのキーとなるユニークなID
struct IDB_Key
{
nn::ProgramId programID; // プログラムID
s32 remasterVersion; // リマスターバージョン()
u8 padding[4]; // パディング常に0
};
#define IDB_KEY_LATEST_VERSION (-1) // IDB_Key.remasterVersionにこれを指定するとオーナー枠、フレンド枠問わず最新のバージョンを取得する
#define IDB_KEY_LATEST_VERSION_OWNER (-2) // IDB_Key.remasterVersionにこれを指定するとオーナー枠を優先して最新のバージョンを取得する
// アプリ情報
struct IDB_SoftwareInfo
{
wchar_t shortTitle[IDB_APP_INFO_SHORT_TITLE_LENGTH]; // 短いタイトル
wchar_t longTitle[IDB_APP_INFO_LONG_TITLE_LENGTH]; // 長いタイトル
wchar_t publisher[IDB_APP_INFO_PUBLISHER_LENGTH]; // 発売元
} ;
// NTR互換アイコン本体
struct IDB_NTRIconDataRaw
{
u8 image[ NN_CTR_BANNER_IMAGE_SIZE ];
u8 pltt[ NN_CTR_BANNER_PLTT_SIZE ];
};
// NTR互換アイコン
struct IDB_NTRIconData
{
IDB_NTRIconDataRaw data;
// このパディングは無効な領域を参照している事があるのでアクセスしてはならない
u8 padding[sizeof(nn::CTR::SystemMenuDataIcon)-sizeof(IDB_NTRIconDataRaw)];
};
// TWL互換アイコン
struct IDB_TWLIconData
{
nn::CTR::LegacyBannerAnime data;
// このパディングは無効な領域を参照している事があるのでアクセスしてはならない
u8 padding[sizeof(nn::CTR::SystemMenuDataIcon)-sizeof(nn::CTR::LegacyBannerAnime)];
};
// 1つのアイコンの全データ
struct IDB_Icon
{
IDB_Key key;
nn::CTR::SystemMenuDataRegion region; // リージョン情報(リージョン違いのアイコンは区別するが、gameCodeに含まれているため)
u8 rating[IDB_RATING_MAX]; // レーティング情報
u32 matchMakeGameCode; // 合流ゲームID
u64 matchMakeGameCodeBit; // 合流ゲームモードビット
nn::CTR::SystemMenuDataTitle info[IDB_LANGUAGE_MAX]; // タイトル名などのソフト情報
IDB_IconFormat format;
union
{ // それぞれIDB_IconFormatが
nn::CTR::SystemMenuDataIcon *data; // ≒ IDB_IconPicture *data; IDB_ICON_FORMAT_CTRのとき
IDB_TWLIconData *twlData; // IDB_ICON_FORMAT_TWLのとき
IDB_NTRIconData *ntrData; // IDB_ICON_FORMAT_NTRのとき
};
};
/////////////////////////////////////////////////////////////////////////////////
// コンパイル時アサート(静的アサート)
/////////////////////////////////////////////////////////////////////////////////
// NW_COMPILER_ASSERT( sizeof(char)==1 ); // 8bit
// NW_COMPILER_ASSERT( sizeof(u8)==1 ); // 8bit
// NW_COMPILER_ASSERT( sizeof(u16)==2 ); // 16bit
// NW_COMPILER_ASSERT( sizeof(u32)==4 ); // 32bit
// NW_COMPILER_ASSERT( sizeof(IDB_FormatType)==sizeof(s32) ); // enumは32bit
// NW_COMPILER_ASSERT( sizeof(IDB_Region)==sizeof(s32) ); // enumは32bit
// NW_COMPILER_ASSERT( IDB_ICON_DATA_MAX>IDB_OWNER_ICON_DATA_MAX ); // オーナー枠はアイコンデータの最大個数以下
/////////////////////////////////////////////////////////////////////////////////
// 関数宣言
/////////////////////////////////////////////////////////////////////////////////
/*!
@brief
IDB_GetBufferSize()IDB_IsInitialized()
@param[in] buffer IDBが使用するバッファを指定します
onMemory引数を指定したIDB_GetBufferSize()
IDB_Finalize()
@param[in] onMemory (7M前後)
IDB_Finalizeが低速になります
@param[in] readOnly trueの時ReadOnlyモードで動作するようになります
ReadOnlyモードの時はIDB_Update()
falseの時はIDBの整合性を保つためHOMEメニューをはじめとする
Finalizeを呼ぶ必要があります
ReadOnlyモードでもIDBのファイルが存在しないなどの時には
IDB_Initialize()
IDB_Initialize()HOME等のアプレットへは遷移しないで下さい
*/
void IDB_Initialize( u8 *buffer, bool onMemory, bool readOnly );
/*!
@brief
IDB_Initilize()bufferを返します
使IDB_Initilize()
IDBへのライトバックが行われますが
ReadOnlyモードで動作しているときは行われません
ReadOnlyモードで動作していないときは
*/
u8 * IDB_Finalize( void );
/*!
@brief IDBが使用するバッファのサイズを返します
IDB_Initilize()
onMemoryがfalseの時は12kbyte前後のバッファを使用します
onmemoryをtrueにした場合IDB_Initilizeのonmemory
trueに指定した時に要求されるサイズを返します(7M前後)
@param[in] onMemory IDB_Initialize()onMemoryと同じ値を与えてください
*/
u32 IDB_GetBufferSize( bool onMemory = false );
/*!
@brief IDBを使用する準備が出来たかどうかを返します
IDB_Initilize()
*/
BOOL IDB_IsInitialized( void );
/*!
@brief IDB_Index型の変数を返します
FALSEを返します
(inIcon)
@param[in] inIcon
*/
BOOL IDB_Update( IDB_Icon *inIcon );
/*!
@brief
TRUEをFALSEを返します
FALSEを返したとき*outIconの中身は更新されません
IDB_Updateでアイコンを登録した直後でも存在しないことがあります
@param[in] outIcon
outIcon->dataだけは有効なIDB_IconPicture型を指している必要があります
@param[key] outIcon
@return TRUE
*/
BOOL IDB_Select( IDB_Icon *outIcon, IDB_Key *key );
BOOL IDB_IsContains( IDB_Key *key );
u32 IDB_GetDataNum();
#endif // ifndef __IDB_IDB_H_

View File

@ -0,0 +1,76 @@
/*!
@file IDBUT.h
@brief
*/
#ifndef __IDB_IDBUT_H_
#define __IDB_IDBUT_H_
#include <nn/types.h>
#include <nn/cfg/CTR/cfg_RegionCode.h>
#include <nn/cfg/CTR/cfg_LanguageCode.h>
#include "IDB.h"
namespace nn
{
namespace CTR
{
struct SystemMenuDataTitle;
}
}
/////////////////////////////////////////////////////////////////////////////////
// 関数宣言
/////////////////////////////////////////////////////////////////////////////////
// SystemMenuDataTitleを初期化します
void IDBUT_InitSoftwareInfo( nn::CTR::SystemMenuDataTitle *info );
void IDBUT_InitIcon( IDB_Icon *icon );
// アイコンデータから適切な言語のインデックスを返します
int IDBUT_GetLanguageIndex( IDB_Icon *icon, nn::cfg::CTR::CfgRegionCode region, nn::cfg::CTR::CfgLanguageCode language );
int IDBUT_GetLanguageIndexReceiverSide( IDB_Icon *icon, nn::cfg::CTR::CfgRegionCode receiverRegion, nn::cfg::CTR::CfgLanguageCode receiverLanguage );
void IDBUT_GetTextureFromIcon( IDB_TextureData* dstTex, const IDB_IconData* srcIcon );
void IDBUT_GetIconFromTexture( IDB_IconData* dstIcon, const IDB_TextureData* srcTex );
s32 IDBUT_GetIconDataSize(void);
// CTRのROMアイコンヘッダのnn::CTR::SystemMenuDataから、IDBで使用する形式のデータに変換します。
void IDBUT_GetIconFromSystemMenuData( IDB_Icon* idbIcon, const IDB_Key *key, nn::CTR::SystemMenuData* sysMenuData );
// TWL/NTRのバナーファイルのnn::CTR::LegacyTwlBannerFileから、IDBで使用する形式のデータに変換します。
void IDBUT_GetIconFromLegacyBannerData( IDB_Icon* idbIcon, const IDB_Key *key, nn::CTR::LegacyTwlBannerFile* legacyBannerData );
// TWL のアニメ情報とアニメのコマ数を指定すると
// そのコマにおけるアイコンのテクスチャを取得できます。
void IDBUT_GetTwlIconTextureByControlInfoNo( u16* dstTwlIconTexture,
const nn::CTR::LegacyBannerAnime* bannerAnm,
const u8 controlInfoNo, u8* workBuffer );
// TWL のアニメ情報のインデックス通りのアイコンのテクスチャを取得できます。
void IDBUT_GetTwlIconTextureByCellNo( u16* dstTwlIconTexture,
const nn::CTR::LegacyBannerAnime* bannerAnm,
const u8 cellNo, u8* workBuffer );
// GetTwlIconTexture に必要なバッファのサイズを取得します
s32 IDBUT_GetWorkBufferSizeForConvertTwlIcon(void);
// GetTwlIconTexture の dstTwlIconTexture のサイズを取得します。
s32 IDBUT_GetTwlIconTextureSize(void);
// NTR のアイコンをテクスチャへ変換します。
void IDBUT_GetNtrIconTexture( u16* dstNtrIconTexture,
const IDB_NTRIconDataRaw* ntrIconDataRaw,
u8* workBuffer );
// NTR のアイコンを変換するのに必要なバッファのサイズを取得します。
s32 IDBUT_GetWorkBufferSizeForConvertNtrIcon(void);
// NTR のアイコンを変換後のサイズを取得します。
s32 IDBUT_GetNtrIconTextureSize(void);
#endif // ifndef __IDB_IDBUT_H_

View File

@ -0,0 +1,117 @@
// IDBi.h : コンソール アプリケーションのエントリ ポイントを定義します。
//
#ifndef __IDB_IDBi_H_
#define __IDB_IDBi_H_
#include <nn/types.h>
#include "IDB.h"
#include <nn/assert.h>
#ifdef __cplusplus
extern "C" {
#endif // ifdef __cplusplus
// IDBi_Time型
// 2000年1月1日 UTCの真夜中からの閏秒を考慮しない経過秒数
// 最大で2133年前後まで記録できる
typedef u32 IDBi_Time;
// データベースを取得するためのキーとなるインデックス
typedef u16 IDBi_Index;
#define IDBi_INDEX_INVALID 0xffff // 無効なインデックス
// アプレットをマスクするときのID
static const nn::ProgramId IDBi_MASK_PROGRAM_ID = 0xffffffffffffff00ull;
// データ比較用のテーブル
typedef struct
{
bit64 programID;
u32 lastAccess; // IDBi_Time lastAccess : 最終アクセス日時
u16 remasterVersion; // リマスターバージョン
u8 reserved0; // 予約領域(必ず0で埋める)
u8 reserved1; // 予約領域(必ず0で埋める)
} IDBi_IconTable;
// 1つのアイコンのデータ本体
typedef struct
{
u16 region; // IDB_Region region : リージョン
u8 format; // IDB_IconFormat format : フォーマット
u8 padding[1]; // パディング
u8 rating[IDB_RATING_MAX]; // レーティング情報
u32 matchMakeGameCode; // マッチメイクゲームコード
u64 matchMakeGameCodeBit; // マッチメイクゲームコードビット
IDB_SoftwareInfo info[IDB_LANGUAGE_MAX];
IDB_IconData data; // アイコン画像
} IDBi_IconData;
// アイコンのデータベース、テーブルファイルフォーマット
typedef struct
{
u16 ownerDataCount; // 保存されているオーナーデータ数
u8 padding[6]; // パディング
IDBi_IconTable iconTable[IDB_ICON_DATA_MAX]; // 比較用のテーブル
} IDBi_TableFile;
// アイコンのデータベース、アイコンファイルフォーマット
typedef struct
{
IDBi_IconData iconData[IDB_ICON_DATA_MAX]; // データ本体
} IDBi_DataFile;
// データ区分
typedef enum
{
IDBi_DIVISION_OWNER, // オーナー枠
IDBi_DIVISION_FRIEND, // フレンド枠
IDBi_DIVISION_NONE, // 区分に無い
IDBi_DIVISION_INVALID = 0x7fffffff
} IDBi_Division;
/////////////////////////////////////////////////////////////////////////////////
// コンパイル時アサート(静的アサート)
/////////////////////////////////////////////////////////////////////////////////
// NW_COMPILER_ASSERT( sizeof(u8)==1 ); // 8bit
// NW_COMPILER_ASSERT( sizeof(u16)==2 ); // 16bit
// NW_COMPILER_ASSERT( sizeof(u32)==4 ); // 32bit
// NW_COMPILER_ASSERT( sizeof(int)>=4 ); // intは32bit以上
// NW_COMPILER_ASSERT( (1ULL<<(8*sizeof(s8)-1)) > IDB_FORMAT_MAX ); // IDB_FORMAT_MAXはs8で表せる最大サイズ以下
// NW_COMPILER_ASSERT( (1ULL<<(8*sizeof(IDBi_Index))) > IDB_ICON_DATA_MAX ); // IDBi_IndexはIDB_ICON_DATA_MAX分のindexを表現できる
// NW_COMPILER_ASSERT( (1ULL<<(8*sizeof(IDBi_Time ))) > 60ULL*60*24*(365+1)*100 ); // IDBi_Timeは秒単位で100年以上表現できる
// // 秒 分 時 日 年
/////////////////////////////////////////////////////////////////////////////////
// 関数宣言
/////////////////////////////////////////////////////////////////////////////////
void IDBi_Initialize( u8 * buffer, bool onMemory, bool readOnly );
u8 * IDBi_Finalize( void );
u32 IDBi_GetBufferSize( bool onMemory );
BOOL IDBi_IsInitialized( void );
IDBi_Index IDBi_Update( IDB_Icon * inIcon, IDBi_Division division );
BOOL IDBi_Select( IDB_Icon * outIcon, IDB_Key * key, BOOL updateLastAccess = TRUE );
BOOL IDBi_SelectFromIndex( IDB_Icon * outIcon, IDBi_Index index, BOOL updateLastAccess = TRUE );
BOOL IDBi_IsContains( IDB_Key * key );
void IDBi_MaskProgramID( nn::ProgramId* programID );
IDBi_Index IDBi_GetIndex( const IDB_Key * restrict inKey );
nn::ProgramId IDBi_GetProgramID( const int index );
void IDBi_Save(void);
void IDBi_Load(void);
#ifdef __cplusplus
}
#endif // ifdef __cplusplus
#endif // ifndef __IDB_IDB_H_

View File

@ -0,0 +1,82 @@
// IDB.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//
#include "IDB.h"
#include "IDBi.h"
#include <nn/assert.h>
/////////////////////////////////////////////////////////////////////////////////
// 関数定義
/////////////////////////////////////////////////////////////////////////////////
// 初期化
void IDB_Initialize( u8 *buffer, bool onMemory, bool readOnly )
{
NN_NULL_ASSERT( buffer );
if ( buffer==NULL ) return;
IDBi_Initialize( buffer, onMemory, readOnly);
}
// 開放
u8 * IDB_Finalize( void )
{
return IDBi_Finalize();
}
// 必要なバッファサイズを返す
u32 IDB_GetBufferSize( bool onMemory )
{
return IDBi_GetBufferSize(onMemory);
}
BOOL IDB_IsInitialized( void )
{
return IDBi_IsInitialized();
}
// 指定したアイコン情報をフレンド枠に追加する
// 追加したindexを返す
// データが追加できなかったときはFALSEを返す
BOOL IDB_Update( IDB_Icon *inIcon )
{
NN_NULL_ASSERT( inIcon );
if ( inIcon==NULL ) return FALSE;
return IDBi_Update( inIcon, IDBi_DIVISION_FRIEND ) != IDBi_INDEX_INVALID;
}
// 指定したキーを持つアイコンデータをロードする
// データが存在しない場合はfalseを返す
BOOL IDB_Select( IDB_Icon *outIcon, IDB_Key *key )
{
NN_NULL_ASSERT( outIcon );
NN_NULL_ASSERT( key );
if ( outIcon==NULL ) return FALSE;
if ( key==NULL ) return FALSE;
return IDBi_Select(outIcon, key, TRUE);
}
// 指定したインデックスを持つアイコンデータをロードする
// データが存在しない場合はfalseを返す
BOOL IDB_SelectFromIndex( IDB_Icon *outIcon, IDBi_Index index )
{
NN_NULL_ASSERT( outIcon );
if ( outIcon==NULL ) return FALSE;
return IDBi_SelectFromIndex(outIcon, index, TRUE);
}
// 指定したキーのデータが存在するかどうかを返す
// データが存在したらtrue、存在しない場合はfalseを返す
BOOL IDB_IsContains( IDB_Key *key )
{
NN_NULL_ASSERT( key );
if ( key==NULL ) return FALSE;
return IDBi_IsContains( key );
}

View File

@ -0,0 +1,724 @@
// IDBUT.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//
#include "IDBUT.h"
//#include "IDBi.h"
#include <nn/assert.h>
#include <string.h>
#include <wchar.h>
#include <nn/CTR/ctr_ProgramId.h>
// TWL アイコンの変換のためのバッファ
typedef struct
{
u8 tmpBuf[ TWL_ICON_WIDTH * TWL_ICON_HEIGHT * 3 ];
u8 nativeBuf[ TWL_ICON_WIDTH * TWL_ICON_HEIGHT * 3 ];
}SConvertBuf;
enum IDB_TwlAlphaColor
{
IDB_TWL_ALPHA_COLOR_R = 235,
IDB_TWL_ALPHA_COLOR_G = 235,
IDB_TWL_ALPHA_COLOR_B = 235
};
// 内部関数
void IDBUT_ConvertTwl555To888( u8* pDst, const u8* pSrc, const u8* pPltt );
void IDBUT_Convert888To565( u16* pDst, const u8* pSrc, int width, int height );
void IDBUT_ConvertLineToNative( u8* pDst, const u8* pSrc, int width, int height );
void IDBUT_GetLegacyIconTexture( u16* pDst, const u8* pImage, const u8* pPltt, u8* workBuffer );
void IDBUT_SetBlock8( u8* pDst, const u8* pSrc, int width, int height, int posX, int posY );
void IDBUT_SetBlock4( u8* pDst, const u8* pSrc, int width, int height, int posX, int posY );
void IDBUT_SetBlock2( u8* pDst, const u8* pSrc, int width, int height, int posX, int posY );
int IDBUT_GetCtrLanguageIndex( IDB_Icon *icon, nn::cfg::CTR::CfgRegionCode region, nn::cfg::CTR::CfgLanguageCode language );
int IDBUT_GetCtrLanguageIndexReceiverSide( IDB_Icon *icon, nn::cfg::CTR::CfgLanguageCode receiverLanguage );
int IDBUT_GetTwlLanguageIndex( IDB_Icon *icon, nn::cfg::CTR::CfgRegionCode region, nn::cfg::CTR::CfgLanguageCode language );
/////////////////////////////////////////////////////////////////////////////////
// 関数定義
/////////////////////////////////////////////////////////////////////////////////
/*!
@brief SystemMenuDataTitleを初期化します<BR><BR>
@param[in/out] info
*/
void IDBUT_InitSoftwareInfo( nn::CTR::SystemMenuDataTitle *info )
{
memset( info->shortName, 0, sizeof(info->shortName) );
memset( info->longName, 0, sizeof(info->longName) );
memset( info->publisher, 0, sizeof(info->publisher) );
}
/*!
@brief <BR><BR>
icon->dataはNULLに初期化されますので<BR>
@param[in/out] icon
*/
void IDBUT_InitIcon( IDB_Icon *icon )
{
int i;
icon->key.programID = nn::CTR::INVALID_PROGRAM_ID;
icon->key.remasterVersion = 0;
memset( icon->key.padding, 0, sizeof( icon->key.padding ) );
icon->region = nn::CTR::BNR_REGION_JAPAN;
memset( icon->rating, 0, sizeof(icon->rating) );
icon->matchMakeGameCode = 0;
icon->matchMakeGameCodeBit= 0;
icon->format = IDB_ICON_FORMAT_INVALID;
for ( i=0; i<IDB_LANGUAGE_MAX; i++ )
{
IDBUT_InitSoftwareInfo( icon->info );
}
icon->data = NULL;
}
/*!
@brief <BR><BR>
<BR>
<BR>
<BR>
@param[in] icon IDB_Icon
@param[in] region
@param[in] language
@return (nn::cfg::CTR::CfgLanguageCodeと同じ値です)
*/
int IDBUT_GetLanguageIndex( IDB_Icon *icon, nn::cfg::CTR::CfgRegionCode region, nn::cfg::CTR::CfgLanguageCode language )
{
// これが返ることはないはず
int ret = nn::cfg::CTR::CFG_LANGUAGE_ENGLISH;
if( icon->format == IDB_ICON_FORMAT_CTR )
{
ret = IDBUT_GetCtrLanguageIndex( icon, region, language );
}
else if( icon->format == IDB_ICON_FORMAT_TWL || icon->format == IDB_ICON_FORMAT_NTR )
{
ret = IDBUT_GetTwlLanguageIndex( icon, region, language );
}
return ret;
}
/*!
@brief 使<BR><BR>
<BR>
<BR>
<BR>
@param[in] icon IDB_Icon
@param[in] region
@param[in] language
@return (nn::cfg::CTR::CfgLanguageCodeと同じ値です)
*/
int IDBUT_GetLanguageIndexReceiverSide( IDB_Icon *icon, nn::cfg::CTR::CfgRegionCode region, nn::cfg::CTR::CfgLanguageCode language )
{
// これが返ることはないはず
int ret = nn::cfg::CTR::CFG_LANGUAGE_ENGLISH;
if( icon->format == IDB_ICON_FORMAT_CTR )
{
ret = IDBUT_GetCtrLanguageIndexReceiverSide( icon, language );
}
else if( icon->format == IDB_ICON_FORMAT_TWL || icon->format == IDB_ICON_FORMAT_NTR )
{
ret = IDBUT_GetTwlLanguageIndex( icon, region, language );
}
return ret;
}
int IDBUT_GetCtrLanguageIndex( IDB_Icon *icon, nn::cfg::CTR::CfgRegionCode region, nn::cfg::CTR::CfgLanguageCode language )
{
switch ( region )
{
case nn::cfg::CTR::CFG_REGION_JAPAN:
return nn::cfg::CTR::CFG_LANGUAGE_JAPANESE;
case nn::cfg::CTR::CFG_REGION_AMERICA:
case nn::cfg::CTR::CFG_REGION_EUROPE: // CFG_REGION_AUSTRALIA
case nn::cfg::CTR::CFG_REGION_TAIWAN:
if ( icon->info[language].longName[0] != L'\0' &&
icon->info[language].shortName[0] != L'\0' ) return language;
return nn::cfg::CTR::CFG_LANGUAGE_ENGLISH;
case nn::cfg::CTR::CFG_REGION_CHINA:
return nn::cfg::CTR::CFG_LANGUAGE_SIMP_CHINESE;
case nn::cfg::CTR::CFG_REGION_KOREA:
return nn::cfg::CTR::CFG_LANGUAGE_KOREAN;
}
return nn::cfg::CTR::CFG_LANGUAGE_ENGLISH; // ここに来る事は無いはず
}
int IDBUT_GetCtrLanguageIndexReceiverSide( IDB_Icon *icon, nn::cfg::CTR::CfgLanguageCode language )
{
if ( icon->info[language].longName[0] != L'\0' &&
icon->info[language].shortName[0] != L'\0' ) return language;
return nn::cfg::CTR::CFG_LANGUAGE_ENGLISH;
}
int IDBUT_GetTwlLanguageIndex( IDB_Icon *icon, nn::cfg::CTR::CfgRegionCode region, nn::cfg::CTR::CfgLanguageCode language )
{
// これがそのまま返ることはない
int ret = nn::cfg::CTR::CFG_LANGUAGE_ENGLISH;
if ( icon->info[ language ].longName[ 0 ] != L'\0' )
{
ret = language;
}
else
{
const int TWL_LANGUAGE_PRIORITY_JUET_NUM = 6;
const int TWL_LANGUAGE_PRIORITY_CK_NUM = 8;
int languagePriority[ TWL_LANGUAGE_PRIORITY_CK_NUM ];
int priorityMaxNum = TWL_LANGUAGE_PRIORITY_JUET_NUM;
memset( languagePriority, 0, sizeof( languagePriority ) );
switch( region )
{
case nn::cfg::CTR::CFG_REGION_JAPAN:
case nn::cfg::CTR::CFG_REGION_TAIWAN:
priorityMaxNum = TWL_LANGUAGE_PRIORITY_JUET_NUM;
languagePriority[ 0 ] = nn::cfg::CTR::CFG_LANGUAGE_JAPANESE;
languagePriority[ 1 ] = nn::cfg::CTR::CFG_LANGUAGE_ENGLISH;
languagePriority[ 2 ] = nn::cfg::CTR::CFG_LANGUAGE_GERMAN;
languagePriority[ 3 ] = nn::cfg::CTR::CFG_LANGUAGE_FRENCH;
languagePriority[ 4 ] = nn::cfg::CTR::CFG_LANGUAGE_SPANISH;
languagePriority[ 5 ] = nn::cfg::CTR::CFG_LANGUAGE_ITALIAN;
break;
case nn::cfg::CTR::CFG_REGION_AMERICA:
priorityMaxNum = TWL_LANGUAGE_PRIORITY_JUET_NUM;
languagePriority[ 0 ] = nn::cfg::CTR::CFG_LANGUAGE_ENGLISH;
languagePriority[ 1 ] = nn::cfg::CTR::CFG_LANGUAGE_FRENCH;
languagePriority[ 2 ] = nn::cfg::CTR::CFG_LANGUAGE_SPANISH;
languagePriority[ 3 ] = nn::cfg::CTR::CFG_LANGUAGE_GERMAN;
languagePriority[ 4 ] = nn::cfg::CTR::CFG_LANGUAGE_ITALIAN;
languagePriority[ 5 ] = nn::cfg::CTR::CFG_LANGUAGE_JAPANESE;
break;
case nn::cfg::CTR::CFG_REGION_EUROPE:
case nn::cfg::CTR::CFG_REGION_AUSTRALIA:
priorityMaxNum = TWL_LANGUAGE_PRIORITY_JUET_NUM;
languagePriority[ 0 ] = nn::cfg::CTR::CFG_LANGUAGE_ENGLISH;
languagePriority[ 1 ] = nn::cfg::CTR::CFG_LANGUAGE_GERMAN;
languagePriority[ 2 ] = nn::cfg::CTR::CFG_LANGUAGE_FRENCH;
languagePriority[ 3 ] = nn::cfg::CTR::CFG_LANGUAGE_SPANISH;
languagePriority[ 4 ] = nn::cfg::CTR::CFG_LANGUAGE_ITALIAN;
languagePriority[ 5 ] = nn::cfg::CTR::CFG_LANGUAGE_JAPANESE;
break;
case nn::cfg::CTR::CFG_REGION_CHINA:
priorityMaxNum = TWL_LANGUAGE_PRIORITY_CK_NUM;
languagePriority[ 0 ] = nn::cfg::CTR::CFG_LANGUAGE_SIMP_CHINESE;
languagePriority[ 1 ] = nn::cfg::CTR::CFG_LANGUAGE_ENGLISH;
languagePriority[ 2 ] = nn::cfg::CTR::CFG_LANGUAGE_GERMAN;
languagePriority[ 3 ] = nn::cfg::CTR::CFG_LANGUAGE_FRENCH;
languagePriority[ 4 ] = nn::cfg::CTR::CFG_LANGUAGE_SPANISH;
languagePriority[ 5 ] = nn::cfg::CTR::CFG_LANGUAGE_ITALIAN;
languagePriority[ 6 ] = nn::cfg::CTR::CFG_LANGUAGE_JAPANESE;
languagePriority[ 7 ] = nn::cfg::CTR::CFG_LANGUAGE_KOREAN;
break;
case nn::cfg::CTR::CFG_REGION_KOREA:
priorityMaxNum = TWL_LANGUAGE_PRIORITY_CK_NUM;
languagePriority[ 0 ] = nn::cfg::CTR::CFG_LANGUAGE_KOREAN;
languagePriority[ 1 ] = nn::cfg::CTR::CFG_LANGUAGE_ENGLISH;
languagePriority[ 2 ] = nn::cfg::CTR::CFG_LANGUAGE_JAPANESE;
languagePriority[ 3 ] = nn::cfg::CTR::CFG_LANGUAGE_GERMAN;
languagePriority[ 4 ] = nn::cfg::CTR::CFG_LANGUAGE_FRENCH;
languagePriority[ 5 ] = nn::cfg::CTR::CFG_LANGUAGE_SPANISH;
languagePriority[ 6 ] = nn::cfg::CTR::CFG_LANGUAGE_ITALIAN;
languagePriority[ 7 ] = nn::cfg::CTR::CFG_LANGUAGE_SIMP_CHINESE;
break;
default: break;
}
// 優先順位順にタイトルが存在する言語を探す
for( int i = 0; i < priorityMaxNum; ++i )
{
int languageID = languagePriority[ i ];
if( icon->info[ languageID ].longName[ 0 ] != L'\0' )
{
ret = languageID;
break;
}
}
}
return ret;
}
int IDBUTi_GetLastIndexOfReturn( const wchar_t * const str, size_t len )
{
for ( int i = len - 1; i>=0; i-- )
{
if ( str[i]==L'\n' ) return i;
}
return -1;
}
/*!
@brief IDB_IconDataからIDB_TextureDataへデータ形式を変換します<BR><BR>
IDBで保存しているIDB_IconDataは48*4824*24<BR>
GPUの制約上64*6432*32<BR>
IDB_TextureDataです
@param[in] srcIcon IDB_IconData
@param[out] dstTex IDB_TextureData
*/
void IDBUT_GetTextureFromIcon( IDB_TextureData* dstTex, const IDB_IconData* srcIcon )
{
const IDB_IconData *src =(IDB_IconData *)srcIcon;
for ( int y=0; y<BIG_ICON_BLOCK_HEIGHT; y++ )
{
memcpy(
&dstTex->big[ y * DATA_BLOCK_LENGTH * BIG_TEXTURE_BLOCK_WIDTH ],
&src->big[ y * DATA_BLOCK_LENGTH * BIG_ICON_BLOCK_WIDTH ],
DATA_BLOCK_SIZE * BIG_ICON_BLOCK_WIDTH );
// 鯣芧듣芽闣芣蛤벜뫧릧黣莻鯦몷꜊
memset( &dstTex->big[ y * DATA_BLOCK_LENGTH * BIG_TEXTURE_BLOCK_WIDTH + DATA_BLOCK_LENGTH * BIG_ICON_BLOCK_WIDTH ],
0xff,
((BIG_TEXTURE_WIDTH-BIG_ICON_WIDTH)/DATA_BLOCK_WIDTH)*DATA_BLOCK_SIZE );
}
for ( int y=0; y<SMALL_ICON_BLOCK_HEIGHT; y++ )
{
memcpy(
&dstTex->little[ y * DATA_BLOCK_LENGTH * SMALL_TEXTURE_BLOCK_WIDTH ],
&src->little[ y * DATA_BLOCK_LENGTH * SMALL_ICON_BLOCK_WIDTH ],
DATA_BLOCK_SIZE * SMALL_ICON_BLOCK_WIDTH );
// 鯣芧듣芽闣芣蛤벜뫧릧黣莻鯦몷꜊
memset( &dstTex->little[ y * DATA_BLOCK_LENGTH * SMALL_TEXTURE_BLOCK_WIDTH + DATA_BLOCK_LENGTH * SMALL_ICON_BLOCK_WIDTH ],
0xff,
((SMALL_TEXTURE_WIDTH-SMALL_ICON_WIDTH)/DATA_BLOCK_WIDTH)*DATA_BLOCK_SIZE );
}
// テクスチャフィルタ対策に一ドット縁取りをする
const int rightEdgeIndex[8] = { 21, 23, 29, 31, 53, 55, 61, 63 }; // 8*8のブロックの右端のインデックス
const int bottomEdgeIndex[8] = { 42, 43, 46, 47, 58, 59, 62, 63 }; // 8*8のブロックの下端のインデックス
const int nextBlockOffsetX = 21; // ブロックを跨いだときの隣のドットのオフセット
const int nextBlockOffsetY = 42; // ブロックを跨いだときの隣のドットのオフセット
const int rightBBlockIndex[ BIG_ICON_BLOCK_HEIGHT] = { 5, 11, 17, 23, 29, 35 }; // ブロック単位での右端のインデックス(アイコン大)
const int bottomBBlockIndex[BIG_ICON_BLOCK_WIDTH] = { 30, 31, 32, 33, 34, 35 }; // ブロック単位での下端のインデックス(アイコン大)
const int rightSBlockIndex[ SMALL_ICON_BLOCK_HEIGHT] = { 2, 5, 8 }; // ブロック単位での右端のインデックス(アイコン小)
const int bottomSBlockIndex[SMALL_ICON_BLOCK_WIDTH] = { 6, 7, 8 }; // ブロック単位での下端のインデックス(アイコン小)
const int rightBBlockTexIndex[ BIG_ICON_BLOCK_HEIGHT] = { 6, 14, 22, 30, 38, 46 }; // ブロック単位での右端の隣のインデックス(テクスチャ大)
const int bottomBBlockTexIndex[BIG_ICON_BLOCK_WIDTH] = { 48, 49, 50, 51, 52, 53 }; // ブロック単位での下端の隣のインデックス(テクスチャ大)
const int rightSBlockTexIndex[ SMALL_ICON_BLOCK_HEIGHT] = { 3, 7, 11 }; // ブロック単位での右端の隣のインデックス(テクスチャ小)
const int bottomSBlockTexIndex[SMALL_ICON_BLOCK_WIDTH] = { 12, 13, 14 }; // ブロック単位での下端の隣のインデックス(テクスチャ小)
// 下
for ( int bx=0; bx<BIG_ICON_BLOCK_WIDTH; bx++ )
{
for ( int x=0; x<DATA_BLOCK_WIDTH; x++ )
{
dstTex->big[ bottomBBlockTexIndex[bx] *DATA_BLOCK_LENGTH + bottomEdgeIndex[x] - nextBlockOffsetY ] =
src->big[ bottomBBlockIndex[bx] *DATA_BLOCK_LENGTH + bottomEdgeIndex[x] ];
}
}
for ( int sx=0; sx<SMALL_ICON_BLOCK_WIDTH; sx++ )
{
for ( int x=0; x<DATA_BLOCK_WIDTH; x++ )
{
dstTex->little[ bottomSBlockTexIndex[sx] *DATA_BLOCK_LENGTH + bottomEdgeIndex[x] - nextBlockOffsetY ] =
src->little[ bottomSBlockIndex[sx] *DATA_BLOCK_LENGTH + bottomEdgeIndex[x] ];
}
}
// 右
for ( int by=0; by<BIG_ICON_BLOCK_HEIGHT; by++ )
{
for ( int y=0; y<DATA_BLOCK_HEIGHT; y++ )
{
dstTex->big[ rightBBlockTexIndex[by] *DATA_BLOCK_LENGTH + rightEdgeIndex[y] - nextBlockOffsetX ] =
src->big[ rightBBlockIndex[by] *DATA_BLOCK_LENGTH + rightEdgeIndex[y] ];
}
}
for ( int sy=0; sy<SMALL_ICON_BLOCK_HEIGHT; sy++ )
{
for ( int y=0; y<DATA_BLOCK_HEIGHT; y++ )
{
dstTex->little[ rightSBlockTexIndex[sy] *DATA_BLOCK_LENGTH + rightEdgeIndex[y] - nextBlockOffsetX ] =
src->little[ rightSBlockIndex[sy] *DATA_BLOCK_LENGTH + rightEdgeIndex[y] ];
}
}
}
/*!
@brief IDB_TextureDataからIDB_IconDataへデータ形式を変換します<BR><BR>
IDBで保存しているIDB_IconDataは48*4824*24<BR>
GPUの制約上64*6432*32<BR>
IDB_TextureDataです
@param[in] srcTex IDB_TextureData
@param[out] dstIcon IDB_IconData
*/
void IDBUT_GetIconFromTexture( IDB_IconData* dstIcon, const IDB_TextureData* srcTex )
{
int y;
IDB_IconData *dst =(IDB_IconData *)dstIcon;
for ( y=0; y<BIG_ICON_BLOCK_HEIGHT; y++ )
{
memcpy(
&dst->big[y * DATA_BLOCK_LENGTH * BIG_ICON_BLOCK_WIDTH ],
&srcTex->big[y * DATA_BLOCK_LENGTH * BIG_TEXTURE_BLOCK_WIDTH ],
DATA_BLOCK_SIZE*BIG_ICON_BLOCK_WIDTH );
}
for ( y=0; y<SMALL_ICON_BLOCK_HEIGHT; y++ )
{
memcpy(
&dst->little[y * DATA_BLOCK_LENGTH * SMALL_ICON_BLOCK_WIDTH ],
&srcTex->little[y * DATA_BLOCK_LENGTH * SMALL_TEXTURE_BLOCK_WIDTH ],
DATA_BLOCK_SIZE*SMALL_ICON_BLOCK_WIDTH );
}
}
/*!
@brief IDB_IconDataのサイズを取得します<BR><BR>
@return IDB_IconDataのサイズを返します
*/
s32 IDBUT_GetIDB_IconDataSize(void)
{
return sizeof(IDB_IconData);
}
/*!
@brief CTRのROMアイコンヘッダのnn::CTR::SystemMenuDataからIDBで使用する形式のデータに変換します<BR><BR>
      idbIconの中でsysMenuData内のデータを参照しますのでidbIconを使用している間はsysMenuDataを破棄する事はできません
@param[out] idbIcon IDB_Icon
@param[in] key IDB_Key
@param[in] sysMenuData SystemMenuData
*/
void IDBUT_GetIconFromSystemMenuData( IDB_Icon* idbIcon, const IDB_Key *key, nn::CTR::SystemMenuData* sysMenuData )
{
const nn::CTR::SystemMenuDataHeader *header = &sysMenuData->header;
if ( key!=NULL )
{
memcpy( &idbIcon->key, key, sizeof(idbIcon->key) );
}else{
idbIcon->key.programID = nn::CTR::INVALID_PROGRAM_ID;
idbIcon->key.remasterVersion = 0;
}
memset( idbIcon->key.padding, 0, sizeof( idbIcon->key.padding ) );
idbIcon->region = header->region;
memcpy( idbIcon->rating, header->rating, sizeof( idbIcon->rating ) );
idbIcon->matchMakeGameCode = header->matchMakeGameCode;
idbIcon->matchMakeGameCodeBit = header->matchMakeGameCodeBit;
memcpy( idbIcon->info, header->title, sizeof(idbIcon->info) );
idbIcon->format = IDB_ICON_FORMAT_CTR;
idbIcon->data = &sysMenuData->raw;
}
/*!
@brief TWL/NTRのバナーファイルのnn::CTR::LegacyTwlBannerFileからIDBで使用する形式のデータに変換します
      idbIconの中でlegacyBannerData内のデータを参照しますのでidbIconを使用している間はlegacyBannerDataを破棄する事はできません
@param[out] idbIcon IDB_Icon
@param[in] key IDB_Key
@param[in] legacyBannerData LegacyTwlBannerFile
*/
void IDBUT_GetIconFromLegacyBannerData( IDB_Icon* idbIcon, const IDB_Key *key, nn::CTR::LegacyTwlBannerFile* legacyBannerData )
{
if ( key!=NULL )
{
idbIcon->key = *key;
}else{
idbIcon->key.programID = nn::CTR::INVALID_PROGRAM_ID;
idbIcon->key.remasterVersion = 0;
}
memset( idbIcon->key.padding, 0, sizeof( idbIcon->key.padding ) );
idbIcon->region = nn::CTR::BNR_REGION_ALL; // TODO : NTRではいいとして、TWLのリージョンは
memset( idbIcon->rating, 0x80, sizeof( idbIcon->rating ) ); // TODO : レーティングは全部?
idbIcon->matchMakeGameCode = 0;
idbIcon->matchMakeGameCodeBit = 0;
if ( legacyBannerData->h.platform == nn::CTR::NN_CTR_BANNER_PLATFORM_NTR )
{
// NN_LOG("IDB_ICON_FORMAT_NTR\n");
idbIcon->format = IDB_ICON_FORMAT_NTR;
idbIcon->ntrData = (IDB_NTRIconData *)&legacyBannerData->v1.image;
// TODO: NTRのバナーデータはバージョン違いがありますが未対応です。
}else{
// NN_LOG("IDB_ICON_FORMAT_TWL\n");
idbIcon->format = IDB_ICON_FORMAT_TWL;
idbIcon->twlData = (IDB_TWLIconData *)&legacyBannerData->anime;
// TODO: TWLのバナーデータはバージョン違いがありますが未対応です。
}
for ( int i=0; i<nn::CTR::NN_CTR_BANNER_LANG_NUM_V1; i++ )
{
memset( idbIcon->info[i].longName, 0, sizeof(idbIcon->info[i].longName) );
memset( idbIcon->info[i].shortName, 0, sizeof(idbIcon->info[i].shortName) );
memset( idbIcon->info[i].publisher, 0, sizeof(idbIcon->info[i].publisher) );
wcsncpy( idbIcon->info[i].longName, (wchar_t *)legacyBannerData->v1.gameName[i], NN_CTR_BANNER_LANG_LENGTH);
}
int langNum = nn::CTR::NN_CTR_BANNER_LANG_NUM_V1;
// 中国語のサポートがあるバージョンか?
if( legacyBannerData->h.version >= NN_CTR_BANNER_CHINESE_SUPPORT_VER )
{
// 中国語のタイトルを埋め込み
for( int i = 0; i < nn::CTR::NN_CTR_BANNER_LANG_NUM_V2; ++i )
{
int ofs = langNum + i;
memset( idbIcon->info[ofs].longName, 0, sizeof(idbIcon->info[ofs].longName) );
memset( idbIcon->info[ofs].shortName, 0, sizeof(idbIcon->info[ofs].shortName) );
memset( idbIcon->info[ofs].publisher, 0, sizeof(idbIcon->info[ofs].publisher) );
wcsncpy( idbIcon->info[ofs].longName, (wchar_t *)legacyBannerData->v2.gameName[i], NN_CTR_BANNER_LANG_LENGTH);
}
langNum += nn::CTR::NN_CTR_BANNER_LANG_NUM_V2;
if( legacyBannerData->h.version >= NN_CTR_BANNER_KOREAN_SUPPORT_VER )
{
// 韓国語のタイトルを埋め込み
for( int i = 0; i < nn::CTR::NN_CTR_BANNER_LANG_NUM_V3; ++i )
{
int ofs = langNum + i;
memset( idbIcon->info[ofs].longName, 0, sizeof(idbIcon->info[ofs].longName) );
memset( idbIcon->info[ofs].shortName, 0, sizeof(idbIcon->info[ofs].shortName) );
memset( idbIcon->info[ofs].publisher, 0, sizeof(idbIcon->info[ofs].publisher) );
wcsncpy( idbIcon->info[ofs].longName, (wchar_t *)legacyBannerData->v3.gameName[i], NN_CTR_BANNER_LANG_LENGTH);
}
langNum += nn::CTR::NN_CTR_BANNER_LANG_NUM_V3;
}
}
// 残りの言語は全て0埋め
for ( int i=langNum; i<IDB_LANGUAGE_MAX; i++ )
{
memset( idbIcon->info[i].longName, 0, sizeof(idbIcon->info[i].longName) );
memset( idbIcon->info[i].shortName, 0, sizeof(idbIcon->info[i].shortName) );
memset( idbIcon->info[i].publisher, 0, sizeof(idbIcon->info[i].publisher) );
}
}
void IDBUT_GetTwlIconTextureByControlInfoNo( u16* dstTwlIconTexture,
const nn::CTR::LegacyBannerAnime* bannerAnm,
const u8 controlInfoNo, u8* workBuffer )
{
u8 cellNo = bannerAnm->control[ controlInfoNo ].normal.cellNo;
IDBUT_GetTwlIconTextureByCellNo( dstTwlIconTexture, bannerAnm, cellNo, workBuffer );
}
void IDBUT_GetTwlIconTextureByCellNo( u16* dstTwlIconTexture,
const nn::CTR::LegacyBannerAnime* bannerAnm,
const u8 cellNo, u8* workBuffer )
{
u8 plttNo = 0;
IDBUT_GetLegacyIconTexture( dstTwlIconTexture,
bannerAnm->image[ cellNo ], bannerAnm->pltt[ plttNo ],
workBuffer );
}
s32 IDBUT_GetWorkBufferSizeForConvertTwlIcon(void)
{
return 3 * TWL_ICON_WIDTH * TWL_ICON_HEIGHT * 2;
}
s32 IDBUT_GetTwlIconTextureSize(void)
{
return sizeof( u16 ) * TWL_ICON_WIDTH * TWL_ICON_HEIGHT;
}
void IDBUT_GetNtrIconTexture( u16* dstNtrIconTexture,
const IDB_NTRIconDataRaw* ntrIconDataRaw,
u8* workBuffer )
{
IDBUT_GetLegacyIconTexture( dstNtrIconTexture,
ntrIconDataRaw->image, ntrIconDataRaw->pltt,
workBuffer );
}
s32 IDBUT_GetWorkBufferSizeForConvertNtrIcon(void)
{
return IDBUT_GetWorkBufferSizeForConvertTwlIcon();
}
s32 IDBUT_GetNtrIconTextureSize(void)
{
return IDBUT_GetTwlIconTextureSize();
}
void IDBUT_GetLegacyIconTexture( u16* dstIconTexture,
const u8* pImage, const u8* pPltt, u8* workBuffer )
{
SConvertBuf* convBuf = reinterpret_cast<SConvertBuf*>(workBuffer);
memset( convBuf->tmpBuf, 0, sizeof(convBuf->tmpBuf) );
memset( convBuf->nativeBuf, 0, sizeof(convBuf->nativeBuf) );
// NTR の bgr555 のバッファを bgr888 へ変換
IDBUT_ConvertTwl555To888( convBuf->tmpBuf, pImage, pPltt );
// bgr888 のバッファをネイティブフォーマットへ変換
IDBUT_ConvertLineToNative( convBuf->nativeBuf, convBuf->tmpBuf,
TWL_ICON_WIDTH, TWL_ICON_HEIGHT );
// bgr888 のバッファを bgr565 のバッファへ変換
IDBUT_Convert888To565( dstIconTexture, convBuf->nativeBuf,
TWL_ICON_WIDTH, TWL_ICON_HEIGHT );
}
void IDBUT_ConvertTwl555To888( u8* pDst, const u8* pSrc, const u8* pPltt )
{
// パレットを変換
u8 dstPltt[ NN_CTR_BANNER_PLTT_SIZE / 2 ][ 3 ];
memset( dstPltt, 0, sizeof( dstPltt ) );
// パレットは抜きの色で、CTR 全体で統一されている
dstPltt[ 0 ][ 0 ] = IDB_TWL_ALPHA_COLOR_B;
dstPltt[ 0 ][ 1 ] = IDB_TWL_ALPHA_COLOR_G;
dstPltt[ 0 ][ 2 ] = IDB_TWL_ALPHA_COLOR_R;
for( int i = 1; i < NN_CTR_BANNER_PLTT_SIZE / 2; ++i )
{
u16 color = *( (u16*)pPltt + i );
dstPltt[ i ][ 0 ] = (u8)( (u16)( (f64)( ( color >> 10 ) & 0x1f ) / 31.0 * 255.0 ) );
dstPltt[ i ][ 1 ] = (u8)( (u16)( (f64)( ( color >> 5 ) & 0x1f ) / 31.0 * 255.0 ) );
dstPltt[ i ][ 2 ] = (u8)( (u16)( (f64)( ( color >> 0 ) & 0x1f ) / 31.0 * 255.0 ) );
//NN_LOG("[%02x] %04x\n", i, color);
}
// 画像を変換
for( int i = 0; i < TWL_ICON_WIDTH * TWL_ICON_HEIGHT / 2; ++i )
{
// ブロック単位(×)でどの位置か
int blockX = ( i / 4 ) % 4;
int blockY = i / 128;
// ブロックの始めの数字
int start = 128 * blockY + 32 * blockX;
// ブロックの始めからどの位置かで id を決定する
int id = start + ( ( i % 32 ) % 4 ) + 4 * ( ( i / 16 ) % 8 );
int prev = 2 * i * 3;
int next = ( 2 * i + 1 ) * 3;
u8 plttPrev = ( pSrc[ id ] & 0x0f );
u8 plttNext = ( pSrc[ id ] & 0xf0 ) >> 4;
//NN_LOG("[%d] %02x [%d] %02x\n", prev, plttPrev, next, plttNext);
for( int j = 0; j < 3; ++ j )
{
pDst[ prev + j ] = dstPltt[ plttPrev ][ j ];
pDst[ next + j ] = dstPltt[ plttNext ][ j ];
}
}
}
void IDBUT_Convert888To565( u16* pDst, const u8* pSrc, int width, int height )
{
for( int h = 0; h < height; ++h )
{
for( int w = 0; w < width; ++w )
{
u16 r = pSrc[3 * (h * width + w) + 0] >> 3;
u16 g = pSrc[3 * (h * width + w) + 1] >> 2;
u16 b = pSrc[3 * (h * width + w) + 2] >> 3;
pDst[h * width + w] = ( ( r & 0x1f ) << 0 ) | ( ( g & 0x3f ) << 5 ) | ( ( b & 0x1f ) << 11 );
}
}
}
void IDBUT_ConvertLineToNative( u8* pDst, const u8* pSrc, int width, int height )
{
for( int h = 0; h < height; h += DATA_BLOCK_HEIGHT )
{
for( int w = 0; w < width; w += DATA_BLOCK_WIDTH )
{
IDBUT_SetBlock8( pDst, pSrc, width, height, w, h );
}
}
}
void IDBUT_SetBlock8( u8* pDst, const u8* pSrc, int width, int height, int posX, int posY )
{
for( int h = 0; h < 8; h += 4 )
{
for( int w = 0; w < 8; w += 4 )
{
IDBUT_SetBlock4( pDst, pSrc, width, height, posX + w, posY + h );
}
}
}
void IDBUT_SetBlock4( u8* pDst, const u8* pSrc, int width, int height, int posX, int posY )
{
for( int h = 0; h < 4; h += 2 )
{
for( int w = 0; w < 4; w += 2 )
{
IDBUT_SetBlock2( pDst, pSrc, width, height, posX + w, posY + h );
}
}
}
void IDBUT_SetBlock2( u8* pDst, const u8* pSrc, int width, int height, int posX, int posY )
{
NN_UNUSED_VAR( height );
static int dstW = 0;
static int dstH = 0;
if( posX == 0 && posY == 0)
{
dstW = 0;
dstH = 0;
}
for( int h = 0; h < 2; ++h )
{
for( int w = 0; w < 2; ++w )
{
int dstPos = 3 * ( dstH * width + dstW );
int srcPos = 3 * ( ( posY + h ) * width + ( posX + w ) );
pDst[ dstPos + 0 ] = pSrc[ srcPos + 0 ];
pDst[ dstPos + 1 ] = pSrc[ srcPos + 1 ];
pDst[ dstPos + 2 ] = pSrc[ srcPos + 2 ];
++dstW;
if( dstW >= width )
{
dstW = 0;
++dstH;
}
}
}
}

View File

@ -0,0 +1,926 @@
// IDBi.c : コンソール アプリケーションのエントリ ポイントを定義します。
//
#include "IDBi.h"
//#define DEBUG_SD 1 // この定義を有効にするとSDカード版になります(デバッグ用)
#include <nn/assert.h>
#include <string.h>
#include <nn/fs/fs_Api.h>
#include <nn/fs/fs_ApiSharedExtSaveData.h>
#include <nn/fs/fs_Parameters.h>
#include <nn/fs/CTR/MPCore/fs_FileSystemBase.h>
#include <nn/fs/fs_FileSystemBase.h>
#include <nn/fs/fs_FileSystem.h>
#include <nn/fs/fs_FileOutputStream.h>
#include <nn/fs/fs_FileInputStream.h>
#include <nn/fnd/fnd_DateTime.h>
#include <nn/fnd/fnd_TimeSpan.h>
#include <nn/CTR/CTR_ProgramId.h>
static bool sReadOnly = false; // ReadOnlyモードのときはtrue
static IDBi_TableFile * restrict spTable = NULL;
static IDBi_IconData * restrict spIconBuf = NULL; // データ読み書き用の一時的なアイコンバッファ。
static IDBi_IconData * restrict spTmpIconBuf = NULL; // 交換用の一時的なアイコンバッファ
// 使用頻度が高いので、未使用でもアロケートは常にしておく
static IDBi_DataFile * restrict spDataBuf = NULL; // オンメモリバージョンのバッファ、こちらを使用しているときは
// spIconBufはNULLになる。
static const char * const sArchiveName = "IDB";
#ifndef DEBUG_SD
static const bit32 sShardExtID = 0xF000000B; // アイコンデータベースID
#endif
static const bit64 sInvalidProgramID = 0xffffffffffffffff;
static const wchar_t * const sTableFileName= L"IDB:/idbt.dat";
static const wchar_t * const sDataFileName = L"IDB:/idb.dat";
// ファイル外部非公開関数宣言
static void IDBi_InitTable( void );
static IDBi_Index IDBi_Append( const IDB_Icon * restrict inIcon, IDBi_Division division );
static IDBi_Index IDBi_AppendCore( const IDB_Icon * restrict inIcon, IDBi_Division division );
static void IDBi_SetFromIndex( const IDB_Icon * restrict inIcon, IDBi_Index index );
static IDBi_Index IDBi_ExpandOwner( void );
static IDBi_Index IDBi_MoveToOwner( IDBi_Index index );
static IDBi_Index IDBi_UpdateLastAccess( const IDB_Key * restrict inKey ); // アクセス日時を上書き
static IDBi_Index IDBi_GetOldestIndex(IDBi_Division division );
static IDBi_Time IDBi_GetCurrentTime( void );
static IDBi_Division IDBi_GetDivision( const IDB_Key * restrict key );
static IDBi_Division IDBi_GetDivisionFromIndex( IDBi_Index index );
static IDBi_Index IDBi_GetEmptyIndex(IDBi_Division division);
static BOOL IDBi_IsOwnerDivisionFull( void );
static BOOL IDBi_IsFriendDivisionFull( void );
static void IDBi_Move( IDBi_Index dest, IDBi_Index src );
static void IDBi_Exchange( IDBi_Index dest, IDBi_Index src );
static void IDBi_ReadData(IDBi_Index index);
static void IDBi_WriteData(IDBi_Index index);
/////////////////////////////////////////////////////////////////////////////////
// 関数定義
/////////////////////////////////////////////////////////////////////////////////
// 初期化
void IDBi_Initialize( u8 * buffer, bool onMemory, bool readOnly )
{
NN_NULL_ASSERT( buffer );
NN_ASSERT( spTable == NULL );
NN_ASSERT( spIconBuf == NULL );
NN_ASSERT( spTmpIconBuf == NULL );
if ( buffer==NULL ) return;
if ( spTable != NULL ) return;
if ( spIconBuf != NULL ) return;
if( spTmpIconBuf != NULL ) return;
sReadOnly = readOnly;
spTable = (IDBi_TableFile *)buffer; // reinterpret_cast
spTmpIconBuf = (IDBi_IconData *)(buffer+sizeof(IDBi_TableFile)); // reinterpret_cast
if ( onMemory )
{
spDataBuf = (IDBi_DataFile *)(buffer+sizeof(IDBi_TableFile)+sizeof(IDBi_IconData) ); // reinterpret_cast
spIconBuf = NULL;
}else{
spIconBuf = (IDBi_IconData *)(buffer+sizeof(IDBi_TableFile)+sizeof(IDBi_IconData) ); // reinterpret_cast
spDataBuf = NULL;
}
nn::Result res;
#ifndef DEBUG_SD
NN_LOG("IDB::MountSharedExtSaveData start\n");
res = nn::fs::MountSharedExtSaveData( sArchiveName, sShardExtID );
NN_LOG("IDB::MountSharedExtSaveData done\n");
NN_ASSERT_RESULT( res );
#else
NN_LOG("IDB::MountSdmc start\n");
nn::fs::MountSdmc( sArchiveName );
NN_LOG("IDB::MountSdmc done\n");
#endif
// ファイルが存在しなかった場合は作成
nn::fs::FileOutputStream os;
bool fileCreated = false;
res = os.TryInitialize( sDataFileName, false );
if ( res.IsFailure() )
{
NN_LOG( "res = os.TryInitialize( sDataFileName, false ); failure\n" );
fileCreated = true;
NN_LOG("IDB::CreateFile start\n");
res = nn::fs::TryCreateFile( sDataFileName, sizeof(IDBi_DataFile) );
NN_LOG("IDB::CreateFile done\n");
if ( res.IsSuccess() )
{
res = os.TryInitialize( sDataFileName, false );
NN_ASSERT_RESULT( res );
}
}
if ( res.IsSuccess() )
{
s64 size = 0;
res = os.TryGetSize(&size);
if ( res.IsFailure() || fileCreated )
{
if ( spDataBuf )
{
NN_LOG("IDB::Format start (on memory)\n");
memset(spDataBuf, 0x0, sizeof(IDBi_DataFile ) );
s32 len;
res = os.TryWrite( &len, spDataBuf, sizeof(IDBi_DataFile ), false );
NN_LOG("IDB::Format done (on memory)\n");
}else{ // オンメモリでは無い場合のフォーマットはかなり遅い
NN_LOG("IDB::Format start (small memory) %d\n", IDBi_GetBufferSize(false) );
const s32 max = IDB_ICON_DATA_MAX * sizeof(IDBi_IconData );
const s32 chunk = IDBi_GetBufferSize(false);
s32 current = 0;
s32 len;
int i=0;
memset(buffer, 0x0, chunk );
while( current+chunk<max )
{
res = os.TryWrite( &len, buffer, chunk, false );
if ( (i++)%16==0 ) NN_LOG(".");
current+=chunk;
}
res = os.TryWrite( &len, buffer, max-current, false );
/* 本当にやりたいのはこっちです
// memset(spIconBuf, 0x0, sizeof(IDBi_IconData ) );
for ( int i=0; i<IDB_ICON_DATA_MAX; i++ )
{
s32 len;
res = os.TryWrite( &len, spIconBuf, sizeof(IDBi_IconData ), false );
if ( i%16==0 ) NN_LOG(".");
}
*/
NN_LOG("\nIDB::Format done (on memory)\n");
}
}
res = os.TryFlush();
os.Finalize();
}else{ // ここに来るのはありえないはず。あるとすればアプレットとアプリの競合(どちらかのバグ)
NN_ASSERT_RESULT( res );
}
IDBi_Load();
}
u8 * IDBi_Finalize( void )
{
NN_NULL_ASSERT( spTable );
NN_ASSERT( spIconBuf!=NULL || spDataBuf!=NULL );
if ( spTable==NULL ) return NULL;
if ( spIconBuf==NULL && spDataBuf==NULL ) return NULL;
if ( spTmpIconBuf == NULL ) return NULL;
u8 * ret = (u8 *)spTable; // reinterpret_cast
if ( !sReadOnly )
{
IDBi_Save();
}
nn::fs::Unmount(sArchiveName);
spTable = NULL;
spIconBuf = NULL;
spTmpIconBuf = NULL;
spDataBuf = NULL;
return ret;
}
u32 IDBi_GetBufferSize( bool onMemory )
{
if ( onMemory )
{
return sizeof( IDBi_TableFile ) + sizeof( IDBi_DataFile ) + sizeof( IDBi_IconData ); // テーブル + 全アイコンデータ + 交換用のアイコンバッファ
}else{
return sizeof( IDBi_TableFile ) + sizeof( IDBi_IconData ) + sizeof( IDBi_IconData ); // テーブル + アイコン1つ分の編集用バッファ + 交換用のアイコンバッファ
}
}
BOOL IDBi_IsInitialized( void )
{
return spTable!=NULL;
}
// 指定したアイコンを指定した場所に更新する、データが存在しない場合は追加する)
IDBi_Index IDBi_Update( IDB_Icon * inIcon, IDBi_Division division )
{
NN_NULL_ASSERT( spTable ); // Initialize済
NN_NULL_ASSERT( inIcon );
NN_ASSERT( !sReadOnly ); // ReadOnlyモードのときは呼べない
NN_ASSERT( inIcon->key.programID != 0 ); // 0は登録できません。
NN_ASSERT( inIcon->key.programID != nn::CTR::INVALID_PROGRAM_ID ); // nn::CTR::INVALID_PROGRAM_IDは登録できません。
if ( spTable==NULL ) return IDBi_INDEX_INVALID;
if ( inIcon==NULL ) return IDBi_INDEX_INVALID;
if ( sReadOnly ) return IDBi_INDEX_INVALID;
if ( inIcon->key.programID == 0 ) return IDBi_INDEX_INVALID; // 無効なIDが指定された時は何もしない
if ( inIcon->key.programID == nn::CTR::INVALID_PROGRAM_ID ) return IDBi_INDEX_INVALID;
if ( nn::CTR::IsTwlSystemApp( inIcon->key.programID ) ) return IDBi_INDEX_INVALID; // TwlSystemアプリの場合は登録しない
// アプレットのプログラムIDに対して下位ビットを無視するようにする
IDBi_MaskProgramID( &inIcon->key.programID );
IDBi_Division origDivision = IDBi_GetDivision( &inIcon->key );
NN_ASSERT( division!=IDBi_DIVISION_NONE ); // divisionが有効な値である
if ( division==IDBi_DIVISION_NONE ) return IDBi_INDEX_INVALID;
NN_LOG( "update time %d\n" , IDBi_GetCurrentTime() );
IDBi_Index ret = IDBi_INDEX_INVALID;
switch ( origDivision )
{
case IDBi_DIVISION_OWNER:
ret = IDBi_UpdateLastAccess( &inIcon->key );
break;
case IDBi_DIVISION_FRIEND:
if ( division== IDBi_DIVISION_FRIEND )
{
ret = IDBi_UpdateLastAccess( &inIcon->key );
}
else
{
ret = IDBi_MoveToOwner( IDBi_GetIndex( &inIcon->key ) );
}
break;
case IDBi_DIVISION_NONE:
ret = IDBi_Append( inIcon, division );
break;
}
return ret;
}
// データを取得する
// データが存在しなかった場合はFALSEを返す
BOOL IDBi_Select( IDB_Icon * outIcon, IDB_Key * key, BOOL updateLastAccess )
{
NN_NULL_ASSERT( spTable ); // Initialize済
NN_NULL_ASSERT( outIcon );
NN_NULL_ASSERT( key );
if ( spTable==NULL ) return FALSE;
if ( outIcon==NULL ) return FALSE;
if ( key ==NULL ) return FALSE;
if( key->programID == sInvalidProgramID ){ return FALSE; }
// アプレットのプログラムIDに対して下位ビットを無視するようにする
IDBi_MaskProgramID( &key->programID );
IDBi_Index index = IDBi_GetIndex( key );
if ( index == IDBi_INDEX_INVALID ) return FALSE;
return IDBi_SelectFromIndex( outIcon, index, updateLastAccess );
}
// データを取得する
// データが存在しなかった場合はFALSEを返す
BOOL IDBi_SelectFromIndex( IDB_Icon * outIcon, IDBi_Index index, BOOL updateLastAccess )
{
NN_NULL_ASSERT( spTable ); // Initialize済
NN_NULL_ASSERT( outIcon );
NN_ASSERT( 0<=index && index<IDB_ICON_DATA_MAX ); // indexは有効な値である
if ( spTable==NULL ) return FALSE;
if ( outIcon==NULL ) return FALSE;
if (!( 0<=index && index<IDB_ICON_DATA_MAX )) return FALSE;
if ( index == IDBi_INDEX_INVALID ) return FALSE;
IDBi_IconTable * const restrict pTable = &spTable->iconTable[index];
IDBi_IconData * restrict pData;
if ( spDataBuf )
{
pData = &spDataBuf->iconData[index];
}else{
IDBi_ReadData( index );
pData = spIconBuf;
}
if ( pTable->programID == sInvalidProgramID ) return FALSE;
if ( updateLastAccess )
{
pTable->lastAccess = IDBi_GetCurrentTime();
}
outIcon->key.programID = pTable->programID;
outIcon->key.remasterVersion = pTable->remasterVersion;
memset( outIcon->key.padding, 0, sizeof(outIcon->key.padding) );
memcpy( outIcon->info, pData->info, sizeof( pData->info ) );
memcpy( outIcon->rating, pData->rating, sizeof( pData->rating ) );
outIcon->region = (nn::CTR::SystemMenuDataRegion)pData->region;
outIcon->format = (IDB_IconFormat)pData->format;
// フォーマットが違っていても(TWL等)、あまりの部分は0で埋めているので問題ない
memcpy( outIcon->data, &pData->data, sizeof( IDB_IconData ) );
return TRUE;
}
// 指定したキーのデータが存在するかどうかを返す
// データが存在したらtrue、存在しない場合はfalseを返す
BOOL IDBi_IsContains( IDB_Key *key )
{
NN_NULL_ASSERT( spTable ); // Initialize済
if ( spTable==NULL ) return FALSE;
if ( key->programID == sInvalidProgramID ){ return FALSE; }
// アプレットのプログラムIDに対して下位ビットを無視するようにする
IDBi_MaskProgramID( &key->programID );
return IDBi_GetIndex( key ) != IDBi_INDEX_INVALID;
}
// データが存在する区分を返す
// 存在しなかった場合はIDBi_DIVISION_NONEを返す
IDBi_Division IDBi_GetDivision( const IDB_Key * restrict key )
{
NN_NULL_ASSERT( key );
if ( key==NULL ) return IDBi_DIVISION_NONE;
IDBi_Index index = IDBi_GetIndex( key );
return IDBi_GetDivisionFromIndex( index );
}
// データが存在する区分を返す
// 存在しなかった場合はIDBi_DIVISION_NONEを返す
IDBi_Division IDBi_GetDivisionFromIndex( IDBi_Index index )
{
if ( index == IDBi_INDEX_INVALID ) return IDBi_DIVISION_NONE;
NN_ASSERT( 0<=index && index<IDB_ICON_DATA_MAX ); // indexは有効な値である
if (!( 0<=index && index<IDB_ICON_DATA_MAX )) return IDBi_DIVISION_NONE;
if ( index<spTable->ownerDataCount ) return IDBi_DIVISION_OWNER;
else return IDBi_DIVISION_FRIEND;
}
// 空のインデックスを返す
// 空きが存在しなかった時はIDBi_INDEX_INVALIDを返す
IDBi_Index IDBi_GetEmptyIndex(IDBi_Division division)
{
int from = division == IDBi_DIVISION_OWNER ? 0 : spTable->ownerDataCount;
int to = division == IDBi_DIVISION_OWNER ? spTable->ownerDataCount : IDB_ICON_DATA_MAX;
int i;
for ( i=from; i<to; i++ )
{
if ( spTable->iconTable[i].programID == sInvalidProgramID ) return (IDBi_Index)i;
}
return IDBi_INDEX_INVALID;
}
// オーナー枠が満タンならTrueを返す
// (拡張すれば空きが存在する可能性もある)
BOOL IDBi_IsOwnerDivisionFull( void )
{
int i;
for ( i=0; i<spTable->ownerDataCount; i++ )
{
if ( spTable->iconTable[i].programID == sInvalidProgramID ) return FALSE;
}
return TRUE;
}
// フレンド枠が満タンならTrueを返す
BOOL IDBi_IsFriendDivisionFull( void )
{
int i;
for ( i=IDB_ICON_DATA_MAX-1; i>=spTable->ownerDataCount; i-- )
{
if ( spTable->iconTable[i].programID == sInvalidProgramID ) return FALSE;
}
return TRUE;
}
// 内部データを移動する
void IDBi_Move( IDBi_Index dest, IDBi_Index src )
{
NN_ASSERT( 0<=dest && dest<IDB_ICON_DATA_MAX ); // indexは有効な値である
NN_ASSERT( 0<= src && src<IDB_ICON_DATA_MAX ); // indexは有効な値である
if (!( 0<=dest && dest<IDB_ICON_DATA_MAX )) return;
if (!( 0<= src && src<IDB_ICON_DATA_MAX )) return;
if ( dest == IDBi_INDEX_INVALID ) return;
if ( src == IDBi_INDEX_INVALID ) return;
spTable->iconTable[dest] = spTable->iconTable[src];
//spTable->iconTable[dest].lastAccess = IDBi_GetCurrentTime();
if( spDataBuf == NULL )
{
IDBi_ReadData( src );
}else{
memcpy( &spDataBuf->iconData[ dest ], &spDataBuf->iconData[ src ], sizeof( IDBi_IconData ) );
}
IDBi_WriteData( dest );
spTable->iconTable[src].programID = sInvalidProgramID;
}
// 内部データを交換する
void IDBi_Exchange( IDBi_Index dest, IDBi_Index src )
{
NN_ASSERT( 0<=dest && dest<IDB_ICON_DATA_MAX ); // indexは有効な値である
NN_ASSERT( 0<= src && src<IDB_ICON_DATA_MAX ); // indexは有効な値である
NN_ASSERT( spTmpIconBuf != NULL );
if (!( 0<=dest && dest<IDB_ICON_DATA_MAX )) return;
if (!( 0<= src && src<IDB_ICON_DATA_MAX )) return;
if( spTmpIconBuf == NULL ) return;
if ( dest == IDBi_INDEX_INVALID ) return;
if ( src == IDBi_INDEX_INVALID ) return;
IDBi_IconTable tmpTable;
tmpTable = spTable->iconTable[dest];
spTable->iconTable[dest] = spTable->iconTable[src];
spTable->iconTable[src] = tmpTable;
spTable->iconTable[dest].lastAccess = IDBi_GetCurrentTime();
if( spDataBuf != NULL )
{
memcpy( spTmpIconBuf, &spDataBuf->iconData[ dest ], sizeof( IDBi_IconData ) );
memcpy( &spDataBuf->iconData[ dest ], &spDataBuf->iconData[ src ], sizeof( IDBi_IconData ) );
memcpy( &spDataBuf->iconData[ src ], spTmpIconBuf, sizeof( IDBi_IconData ) );
}
else if( spIconBuf != NULL )
{
IDBi_ReadData( dest );
memcpy( spTmpIconBuf, spIconBuf, sizeof( IDBi_IconData ) );
// src を dest へ
IDBi_ReadData( src );
IDBi_WriteData( dest );
// dest を src へ
memcpy( spIconBuf, spTmpIconBuf, sizeof( IDBi_IconData ) );
IDBi_WriteData( src );
}
}
///////////////////////////////////////////////////////////////////
// ファイル外部非公開関数
///////////////////////////////////////////////////////////////////
// テーブルのデータを初期化する
void IDBi_InitTable( void )
{
int i;
spTable->ownerDataCount = 0;
memset( spTable->padding, 0, sizeof(spTable->padding) );
for ( i=0; i<IDB_ICON_DATA_MAX; i++ )
{
IDBi_IconTable * restrict table = &spTable->iconTable[i];
table->programID = sInvalidProgramID; // 無効ID
table->lastAccess = 0; // IDBi_Time lastAccess : 最終アクセス日時
table->remasterVersion = 0; // ソフトバージョン
table->reserved0 = 0; // 予約(必ず0で埋める)
table->reserved1 = 0; // 予約(必ず0で埋める)
}
IDBi_Save();
}
// データを追加する場合の処理
// 可能であるのならオーナー枠の拡張などを行う
IDBi_Index IDBi_Append( const IDB_Icon * restrict inIcon, IDBi_Division division )
{
NN_NULL_ASSERT( inIcon );
if ( inIcon==NULL ) return IDBi_INDEX_INVALID;
switch ( division )
{
case IDBi_DIVISION_OWNER:
if ( !IDBi_IsOwnerDivisionFull() )
{
}else if ( spTable->ownerDataCount<IDB_OWNER_ICON_DATA_MAX )
{
IDBi_ExpandOwner();
}
break;
case IDBi_DIVISION_FRIEND:
break;
}
return IDBi_AppendCore( inIcon, division );
}
// オーナー枠にデータを追加する
// データが満タンの時は最も古いデータを削除する
// divisionがIDBi_DIVISION_FRIENDの時、
// moveToFriendによって追い出されたデータをフレンド枠に移動するか削除するかを指定できる
// それ以外のときはFALSE
IDBi_Index IDBi_AppendCore( const IDB_Icon * restrict inIcon, IDBi_Division division )
{
IDBi_Index index = IDBi_GetEmptyIndex(division);
if ( index!=IDBi_INDEX_INVALID )
{ // 空きがあったとき
IDBi_SetFromIndex( inIcon, index );
return index;
}else{ // 空きが無かった時
index = IDBi_GetOldestIndex( division );
if ( index==IDBi_INDEX_INVALID ) return index; // ここでIDBi_GetOldestIndexが返ることは無いはずだが、念のため
if ( division==IDBi_DIVISION_OWNER && !IDBi_IsFriendDivisionFull() )
{
// 追い出されたデータをフレンド枠に移動する
IDBi_Index fIndex = IDBi_GetEmptyIndex( IDBi_DIVISION_FRIEND );
IDBi_Move( fIndex, index );
IDBi_SetFromIndex( inIcon, index );
}else{
IDBi_SetFromIndex( inIcon, index );
}
return index;
}
}
// データを指定したindexに追加する
void IDBi_SetFromIndex( const IDB_Icon * restrict inIcon, IDBi_Index index )
{
NN_NULL_ASSERT( inIcon );
NN_ASSERT( 0<=index && index<IDB_ICON_DATA_MAX ); // indexは有効な値である
if ( inIcon==NULL ) return;
if (!( 0<=index && index<IDB_ICON_DATA_MAX )) return;
if ( index == IDBi_INDEX_INVALID ) return;
IDBi_IconTable * const restrict pTable = &spTable->iconTable[index];
pTable->programID = inIcon->key.programID;
pTable->remasterVersion = inIcon->key.remasterVersion;
pTable->reserved0 = 0;
pTable->reserved1 = 0;
pTable->lastAccess = IDBi_GetCurrentTime();
IDBi_IconData * restrict pData;
if ( spDataBuf )
{
pData = &spDataBuf->iconData[index];
}else{
pData = spIconBuf;
}
memcpy( pData->info, inIcon->info, sizeof( pData->info ) );
memcpy( pData->rating, inIcon->rating, sizeof( pData->rating ) );
pData->region = (u16)inIcon->region;
pData->format = (u8)inIcon->format;
switch ( pData->format )
{
case IDB_ICON_FORMAT_CTR:
memcpy( &pData->data, inIcon->data, sizeof( IDB_IconData ) );
break;
case IDB_ICON_FORMAT_TWL:
memcpy( &pData->data, inIcon->twlData, sizeof( nn::CTR::LegacyBannerAnime ) );
memset( ((u8*)&pData->data) + sizeof( nn::CTR::LegacyBannerAnime ), 0, sizeof( IDB_IconData )-sizeof( nn::CTR::LegacyBannerAnime ) );
break;
case IDB_ICON_FORMAT_NTR:
memcpy( &pData->data, inIcon->ntrData, sizeof( IDB_NTRIconDataRaw ) );
memset( ((u8*)&pData->data) + sizeof( IDB_NTRIconDataRaw ), 0, sizeof( IDB_IconData )-sizeof( IDB_NTRIconDataRaw ) );
break;
default:
NN_ASSERT(false);
return;
}
IDBi_WriteData( index );
}
// オーナー枠を拡張する
// 拡張したオーナー枠を返す
IDBi_Index IDBi_ExpandOwner( void )
{
// 拡張した際にフレンド枠のデータを破壊してしまう場合は追い出されたデータを移動する
if ( spTable->iconTable[spTable->ownerDataCount].programID != sInvalidProgramID )
{
//NN_LOG("%llx %llx\n", spTable->iconTable[spTable->ownerDataCount].programID, sInvalidProgramID );
IDBi_Index dropped = spTable->ownerDataCount;
IDBi_Index change;
change = IDBi_GetEmptyIndex( IDBi_DIVISION_FRIEND );
if( change != IDBi_INDEX_INVALID )
{
// 空きがあったのでそこに入れる
IDBi_Move( change, dropped );
}
else
{
// 空きがないのもっとも古い更新時刻のインデックを探す
change = IDBi_GetOldestIndex( IDBi_DIVISION_FRIEND );
if ( change!=IDBi_INDEX_INVALID ) // このルーチンでInvalidが返ってくる事は無いが、念のため
{
if ( spTable->iconTable[change].lastAccess < spTable->iconTable[dropped].lastAccess )
{
IDBi_Move( change, dropped );
}
else
{
// 追い出されたところを空きにする
spTable->iconTable[ dropped ].programID = sInvalidProgramID;
}
}
}
spTable->ownerDataCount++;
// NN_LOG("change:%d dropped:%d\n", change, dropped);
}else{
spTable->ownerDataCount++;
}
return spTable->ownerDataCount;
}
// フレンド枠のデータをオーナー枠に移動する
IDBi_Index IDBi_MoveToOwner( IDBi_Index src )
{
IDBi_Index dest = IDBi_GetEmptyIndex( IDBi_DIVISION_OWNER );
NN_ASSERT( spTable->ownerDataCount <= src && src < IDB_ICON_DATA_MAX ); // indexのデータはフレンド枠にある
if ( dest == IDBi_INDEX_INVALID )
{
// フレンド枠にあるものを移したいときなので、移動先の要素と交換する
if ( spTable->ownerDataCount<IDB_OWNER_ICON_DATA_MAX )
{
dest = spTable->ownerDataCount;
spTable->ownerDataCount++;
}
else
{
// 最も古いデータを交換
dest = IDBi_GetOldestIndex( IDBi_DIVISION_OWNER );
}
// NN_LOG("move to owner exchange src:%d dest:%d ownerDataCount:%d\n", src, dest, spTable->ownerDataCount);
IDBi_Exchange( dest, src );
}
else
{
// NN_LOG("move to owner copy src:%d dest:%d ownerDataCount:%d\n", src, dest, spTable->ownerDataCount);
IDBi_Move( dest, src );
spTable->iconTable[dest].lastAccess = IDBi_GetCurrentTime();
}
return dest;
}
// 最終アクセス日時を更新する
IDBi_Index IDBi_UpdateLastAccess( const IDB_Key * restrict inKey )
{
IDBi_Index index = IDBi_GetIndex( inKey );
if ( index == IDBi_INDEX_INVALID ) return IDBi_INDEX_INVALID;
NN_NULL_ASSERT( inKey );
if ( inKey==NULL ) return IDBi_INDEX_INVALID;
spTable->iconTable[index].lastAccess = IDBi_GetCurrentTime();
return index;
}
// 該当キーのインデックスを返す
// 存在しない時にはIDBi_INDEX_INVALIDを返す
IDBi_Index IDBi_GetIndex( const IDB_Key * restrict inKey )
{
int i;
NN_NULL_ASSERT( inKey );
if ( inKey==NULL ) return IDBi_INDEX_INVALID;
if ( inKey->remasterVersion == IDB_KEY_LATEST_VERSION )
{ // 最新バージョンモード
int latestVer = -1;
IDBi_Index latestIndex = IDBi_INDEX_INVALID;
for ( i=0; i<IDB_ICON_DATA_MAX; i++ )
{
if ( spTable->iconTable[i].programID ==inKey->programID )
{
if ( latestVer < spTable->iconTable[i].remasterVersion )
{
latestVer = spTable->iconTable[i].remasterVersion;
latestIndex = (IDBi_Index)i;
}
}
}
return latestIndex;
}else if ( inKey->remasterVersion == IDB_KEY_LATEST_VERSION_OWNER )
{ // オーナー枠優先モード
int latestScore = -1; // 多いほうを優先
IDBi_Index latestIndex = IDBi_INDEX_INVALID;
for ( i=0; i<IDB_ICON_DATA_MAX; i++ )
{
if ( spTable->iconTable[i].programID ==inKey->programID )
{
const int U16_MAX = 0xffff;
int iVer = spTable->iconTable[i].remasterVersion;
int iScore = IDBi_GetDivisionFromIndex(i)==IDBi_DIVISION_OWNER ? iVer+U16_MAX : iVer;
if ( latestScore < iScore )
{
latestScore = iScore;
latestIndex = (IDBi_Index)i;
}
}
}
return latestIndex;
}else{ // 完全一致モード
for ( i=0; i<IDB_ICON_DATA_MAX; i++ )
{
if ( spTable->iconTable[i].programID ==inKey->programID &&
spTable->iconTable[i].remasterVersion ==inKey->remasterVersion )
{
return (IDBi_Index)i;
}
}
return IDBi_INDEX_INVALID;
}
}
// 最もアクセス日時が遅いインデックスを返す
// データベースが空の時はIDBi_INDEX_INVALIDを返す
IDBi_Index IDBi_GetOldestIndex(IDBi_Division division )
{
int from = division == IDBi_DIVISION_OWNER ? 0 : spTable->ownerDataCount;
int to = division == IDBi_DIVISION_OWNER ? spTable->ownerDataCount : IDB_ICON_DATA_MAX;
int i;
u32 oldestTime = std::numeric_limits<u32>::max(); // U32_MAX;
int oldestIndex= IDBi_INDEX_INVALID;
NN_ASSERT( division!=IDBi_DIVISION_NONE );
if ( division==IDBi_DIVISION_NONE ) return IDBi_INDEX_INVALID;
for ( i=from; i<to; i++ )
{
if ( spTable->iconTable[i].programID==sInvalidProgramID ) continue;
if ( spTable->iconTable[i].lastAccess<oldestTime )
{
oldestIndex = i;
oldestTime =spTable->iconTable[i].lastAccess;
}
}
NN_LOG("IDBi_GetOldestIndex %d from %d to %d\n", oldestIndex, from, to );
return (IDBi_Index)oldestIndex;
}
// IDB形式の現在時間を取得する
IDBi_Time IDBi_GetCurrentTime( void )
{
nn::fnd::TimeSpan now = nn::fnd::DateTime::GetNow() - nn::fnd::DateTime();
return (IDBi_Time)now.GetSeconds();
}
// データをバッファにロードする
void IDBi_ReadData(IDBi_Index index)
{
if ( spIconBuf==NULL ) return; // オンメモリ版は常時ロード
if ( index == IDBi_INDEX_INVALID ) return;
nn::fs::FileInputStream is(sDataFileName);
is.Seek( index * sizeof(IDBi_IconData) ,nn::fs::POSITION_BASE_BEGIN );
is.Read( spIconBuf, sizeof(IDBi_IconData) );
is.Finalize();
}
// バッファのデータをファイルに書き込む
void IDBi_WriteData(IDBi_Index index)
{
NN_ASSERT( 0<=index && index<IDB_ICON_DATA_MAX ); // indexは有効な値である
if (!( 0<=index && index<IDB_ICON_DATA_MAX )) return;
if ( index == IDBi_INDEX_INVALID ) return;
nn::fs::FileOutputStream os(sDataFileName, false);
os.Seek( index * sizeof(IDBi_IconData) ,nn::fs::POSITION_BASE_BEGIN );
if ( spDataBuf )
{
os.Write( &spDataBuf->iconData[index], sizeof(IDBi_IconData) );
}else{
os.Write( spIconBuf, sizeof(IDBi_IconData) );
}
os.Finalize();
}
// 指定したインデックスのプログラムIDを取得する
nn::ProgramId IDBi_GetProgramID( const int index )
{
NN_ASSERT( 0<=index && index<IDB_ICON_DATA_MAX ); // indexは有効な値である
if (!( 0<=index && index<IDB_ICON_DATA_MAX )) return nn::CTR::INVALID_PROGRAM_ID;
if ( index == IDBi_INDEX_INVALID ) return nn::CTR::INVALID_PROGRAM_ID;
return spTable->iconTable[index].programID;
}
// IDBを保存する
void IDBi_Save(void)
{
nn::fs::FileOutputStream os;
nn::Result res = os.TryInitialize( sTableFileName, false );
if ( res.IsFailure() )
{
nn::fs::CreateFile( sTableFileName, sizeof(*spTable) );
res = os.TryInitialize( sTableFileName, false );
NN_RESULT_ASSERT(res);
if ( res.IsFailure() )
{
os.Finalize();
return;
}
}
s32 size;
res = os.TryWrite( &size, spTable, sizeof(*spTable) );
os.Finalize();
}
// IDBをロードする
void IDBi_Load(void)
{
nn::Result res;
nn::fs::FileInputStream is;
res = is.TryInitialize( sTableFileName );
if ( res.IsSuccess() )
{
s32 size;
res = is.TryRead( &size, spTable, sizeof(*spTable) );
is.Finalize();
}else{
NN_LOG("idb reset start\n");
IDBi_InitTable();
}
// オンメモリ版は全てをロードしておく
if ( spDataBuf )
{
nn::fs::FileInputStream dis;
res = dis.TryInitialize(sDataFileName);
if ( res.IsSuccess() )
{
s32 size;
res = dis.TryRead( &size, spDataBuf, sizeof(IDBi_DataFile) );
}
dis.Finalize();
}
}
// アプレットのプログラムID に対して下位8ビットにマスクをかける
void IDBi_MaskProgramID( nn::ProgramId* programID )
{
NN_NULL_ASSERT(programID);
if ( programID==NULL ) return;
if( !nn::CTR::IsTwlApp( *programID ) )
{
if( nn::CTR::GetCategoryOf( *programID ) == nn::CTR::PROGRAM_ID_CATEGORY_APPLET )
{
nn::ProgramId pid = *programID & IDBi_MASK_PROGRAM_ID;
*programID = pid;
}
}
}

View File

@ -0,0 +1,96 @@

//==========================================================================
// 初回起動時処理
//==========================================================================
void OtherFnc::fnc_1st_setting()
{
sys::SharedExtSaveData::deleteData();
sys::SharedExtSaveData::createData();
// IDBの初期化
{
u32 size = IDB_GetBufferSize();
u8* buf = new( sys::Mem::getMainHeap() ) u8[size];
IDB_Initialize( buf, false, false );
// MSETとPNOTEのアイコンを特別にIDBに登録
{
nn::Result result;
IDB_Icon idbIcon;
IDB_Key idbKey;
nn::CTR::SystemMenuData sysMenuData; // これが4KB弱でIDBも喰うのでスレッドスタック16KBでは不足
nn::am::ProgramInfo pinfo;
nn::ProgramId pids[2] =
{
nn::CTR::MakeProgramId( nn::CTR::PROGRAM_ID_CATEGORY_SYSTEM_APPLICATION,
get_programid_mset_with_region_(),
nn::CTR::PROGRAM_ID_VERSION_APP ), // MSETのプログラムID
nn::CTR::MakeProgramId( nn::CTR::PROGRAM_ID_CATEGORY_SYSTEM_APPLICATION,
get_programid_pnote_with_region_(),
nn::CTR::PROGRAM_ID_VERSION_APP ), // PNOTEのプログラムID
};
for( int i = 0; i < 2; i++ )
{
BOOL bret;
// アイコンバナーヘッダ取得
result = nn::fs::CTR::GetSystemMenuData( &sysMenuData, nn::fs::MEDIA_TYPE_NAND, pids[i] );
NN_DBG_PRINT_RESULT( result );
if( result.IsFailure() )
{
continue; // 開発中のみciaを入れていなかったら失敗
}
// アイコンバナーヘッダが取れたらROMヘッダ情報も取れるバージョン情報取得
result = nn::am::GetProgramInfos( &pinfo, nn::fs::MEDIA_TYPE_NAND, &pids[i], 1 );
//NN_DBG_PRINT_RESULT( result );
IDBUT_InitIcon( &idbIcon );
idbKey.programID = pids[i];
idbKey.remasterVersion = static_cast<s32>( pinfo.version );
IDBUT_GetIconFromSystemMenuData( &idbIcon, &idbKey, &sysMenuData );
bret = IDBi_Update( &idbIcon, IDBi_DIVISION_OWNER ); // アイコンをIDBに登録
if( bret )
{
NN_LOG( "IDB Registration : PID=%llx, VERSION=%04x\n", idbKey.programID, idbKey.remasterVersion );
}
else
{
NN_LOG( "IDB registration failed!\n" );
}
}
}
IDB_Finalize();
delete []buf;
}
}
//==========================================================================
// 初回起動時処理2
//==========================================================================
void OtherFnc::fnc_starting_set()
{
// プレイ履歴クリア
nn::pl::CTR::ClearPlayHistory();
// 歩数クリア
nn::pl::CTR::ClearStepHistory();
sys::UserInfoAccessor::setFirstAll( true );
sys::UserInfoAccessor::setBossTask();
sys::UserInfoAccessor::saveFirstInfo( 1, net );
// cfg 情報送信のタスク登録
sys::UserInfoAccessor::setBossSendInfoTaskFirst();
}

View File

@ -0,0 +1,927 @@
/*!
@file sysFile.cpp
@brief
*/
#include "sys.h"
#include "sysFile.h"
#include <nn/fs/CTR/MPCore/fs_FileSystemBasePrivate.h>
#include <nn/fs/fs_ApiSysSaveData.h>
#include <nn/CTR/CTR_ProgramId.h>
namespace sys
{
const char* File::mMmenSysArcName = "SYS:";
const wchar_t* File::mMmenSysSaveDataPath = L"SYS:/Launcher.dat";
const char* File::mMsetSysArcName = "MSETSYS:";
const wchar_t* File::mMsetSysSaveDataPath[ File::eSysSaveDataTypeNum ] =
{ L"MSETSYS:/Mset.dat", L"MSETSYS:/MsetForBoss.dat", };
const char* File::mMsetExtArcName = "MSETEXT:";
const wchar_t* File::mMsetExtSaveDataPath[ File::eExtSaveDataTypeNum ] =
{ L"MSETEXT:/MsetExt.dat", };
#ifndef NW_RELEASE
bool File::smDebugPrintFlag = true;
#endif
/*
char型でのファイルの読み込み
@param device
@param prefix
*/
u8* File::read( const char* fileName, u32* size, bool device, bool prefix )
{
wchar_t name[128];
memset( name, 0, sizeof( name ) );
int i = 0;
while( fileName[i] != '\0' )
{
name[i] = fileName[i];
if( ++i > 128 ) break;
}
return read( name, size, device, prefix );
}
/*
wchar_t型でのファイルの読み込み
@param device
@param prefix
*/
u8* File::read( const wchar_t* fileName, u32* size, bool device, bool prefix )
{
nn::Result result;
nn::fs::FileReader fileReader;
u8* buffer = NULL;
s64 fileSize = 0;
s32 readSize = 0;
wchar_t name[128];
memset( name, 0, sizeof( name ) );
if( prefix )
{
// ファイルシステム内にこれを書くのは正直どうかと思う
// resLoader側に移動するかも
#ifdef NW_PLATFORM_CTR
swprintf( name, 128, L"rom:/%ls", (wchar_t*)fileName );
#else
swprintf( name, 128, L"data/%s", fileName );
#endif
}
else
{
swprintf( name, 128, fileName );
}
result = fileReader.TryInitialize( name );
if( !result.IsSuccess() )
{
debug_print_();
return NULL;
}
result = fileReader.TryGetSize( &fileSize );
if( !result.IsSuccess() || fileSize <= 0 )
{
debug_print_();
fileReader.Finalize();
return NULL;
}
*size = static_cast<u32>( fileSize );
if( device ) buffer = new( Mem::getDeviceHeap(), sys::cDefaultDeviceAlignment ) u8[ *size ];
else buffer = new( Mem::getMainHeap() ) u8[ *size ];
if( buffer == NULL )
{
debug_print_();
fileReader.Finalize();
return NULL;
}
result = fileReader.TryRead( &readSize, buffer, *size );
if( !result.IsSuccess() )
{
debug_print_();
fileReader.Finalize();
delete buffer;
return NULL;
}
fileReader.Finalize();
return buffer;
}
/*!
*/
u8* File::readLZ( const char* fileName, u32* size )
{
u8* comp_buf = read( fileName, size, false, false );
u32 arc_size = nn::cx::GetUncompressedSize( comp_buf );
u8* arc_buf = new( Mem::getDeviceHeap() ) u8[arc_size];
nn::cx::UncompressLZ( comp_buf, arc_buf );
*size = arc_size;
delete []comp_buf;
return arc_buf;
}
/*!
*/
u8* File::mountShare( const char* name, nn::ProgramId tit_id, int data_num, int files, int dirs )
{
int size = nn::fs::GetContentRequiredMemorySize( nn::fs::MEDIA_TYPE_NAND,
tit_id, data_num, files, dirs );
u8* buf = new( Mem::getMainHeap() ) u8[size];
nn::Result result = nn::fs::MountContent( name, nn::fs::MEDIA_TYPE_NAND,
tit_id, data_num, files, dirs, buf, size );
if( result.IsFailure() )
{
delete []buf;
return NULL;
}
return buf;
}
/*!
MSET
*/
void File::initializeMsetSys()
{
nn::Result result = nn::fs::MountSystemSaveData( mMsetSysArcName, getMsetSaveDataId() );
NN_DBG_PRINT_RESULT( result );
if( result.IsFailure() )
{
nn::fs::SystemSaveDataId saveDataId = getMsetSaveDataId();
// ファイルの最大数とディレクトリの最大数は念のため多めにとっておきます。
size_t maxFiles = 2;
size_t maxDirectories = 1;
bool isDuplicateAll = true;
if( result <= nn::fs::ResultNotFound() )
{
// 存在していないため、作成する必要があります。
result = nn::fs::CreateSystemSaveData( saveDataId,
maxFiles, maxDirectories,
eMsetSaveDataSize, isDuplicateAll );
NN_LOG("create mset system save data\n");
}
else if( result <= nn::fs::ResultOperationDenied() )
{
// 指定した ID のシステムセーブデータは、他のプロセスによってマウントされている可能性があります。
// それ以外の理由で、このエラーが発生することは、まずありません。
NN_ASSERT_RESULT( result );
}
else if( result <= nn::fs::ResultNotFormatted() )
{
// フォーマットを行なう必要があります。
result = nn::fs::DeleteSystemSaveData( saveDataId );
if( result.IsSuccess() )
{
result = nn::fs::CreateSystemSaveData( saveDataId,
maxFiles, maxDirectories,
eMsetSaveDataSize, isDuplicateAll );
NN_LOG("create mset system save data\n");
}
}
else if( result <= nn::fs::ResultBadFormat() )
{
// フォーマットを行なう必要があります。
result = nn::fs::DeleteSystemSaveData( saveDataId );
if( result.IsSuccess() )
{
result = nn::fs::CreateSystemSaveData( saveDataId,
maxFiles, maxDirectories,
eMsetSaveDataSize, isDuplicateAll );
NN_LOG("create mset system save data\n");
}
}
else if( result <= nn::fs::ResultVerificationFailed() )
{
// フォーマットを行なう必要があります。
result = nn::fs::DeleteSystemSaveData( saveDataId );
if( result.IsSuccess() )
{
result = nn::fs::CreateSystemSaveData( saveDataId,
maxFiles, maxDirectories,
eMsetSaveDataSize, isDuplicateAll );
NN_LOG("create mset system save data\n");
}
}
else if( result <= nn::fs::ResultOperationDenied() )
{
// このエラーが発生することは、まずありません。
// ただ、発生した場合にカードの挿し直しや本体の再起動で復帰する可能性があります。
nn::dbg::Panic();
}
else
{
// 上記以外のエラーは発生しません。
nn::dbg::Panic();
}
NN_DBG_PRINT_RESULT( result );
// フォーマット後の判定
if( result.IsFailure() )
{
// セーブデータのフォーマットが失敗することはまずありません。
nn::dbg::Panic();
}
else
{
// 再マウント
result = nn::fs::MountSystemSaveData( mMsetSysArcName, saveDataId );
if( result.IsFailure() )
{
// フォーマットに成功した後に、マウントが失敗することはまずありません。
nn::dbg::Panic();
}
else
{
NN_LOG("mset system savedata mount\n");
}
}
}
else
{
NN_LOG("mset system savedata mount\n");
}
}
/*!
MSET
*/
void File::finalizeMsetSys()
{
nn::fs::Unmount( mMsetSysArcName );
}
/*!
MSET
*/
int File::checkMsetExt()
{
nn::Result result = nn::fs::MountExtSaveData( mMsetExtArcName, getMsetExtSaveDataId() );
int ret = eExtResultSuccess;
NN_LOG( "check ext save data\n" );
NN_DBG_PRINT_RESULT( result );
if( result.IsFailure() )
{
if( result <= nn::fs::ResultNotFound() )
{
if( result <= nn::fs::ResultMediaNotFound() )
{
ret = eExtResultDefaultError;
}
else
{
ret = eExtResultNeedCreate;
}
}
else if( result <= nn::fs::ResultNotFormatted() )
{
ret = eExtResultNeedCreate;
}
else if( result <= nn::fs::ResultBadFormat() )
{
ret = eExtResultDefaultError;
}
else if( result <= nn::fs::ResultVerificationFailed() )
{
ret = eExtResultNeedCreate;
}
else if( result <= nn::fs::ResultOperationDenied() )
{
ret = eExtResultDefaultError;
}
else
{
ret = eExtResultDefaultError;
}
}
nn::fs::Unmount( mMsetExtArcName );
return ret;
}
/*!
MSET
*/
int File::initializeMsetExt()
{
nn::Result result = nn::fs::MountExtSaveData( mMsetExtArcName, getMsetExtSaveDataId() );
int ret = eExtResultSuccess;
NN_LOG( "mount ext save data\n" );
NN_DBG_PRINT_RESULT( result );
if( result.IsFailure() )
{
nn::fs::ExtSaveDataId saveDataId = getMsetExtSaveDataId();
u32 iconData = 0;
size_t iconDataSize = sizeof( iconData );
// ファイルの最大数とディレクトリの最大数は念のため多めにとっておきます。
u32 maxDirectories = 1;
u32 maxFiles = 2;
if( result <= nn::fs::ResultNotFound() )
{
if( result <= nn::fs::ResultMediaNotFound() )
{
// SD カードが挿さっていません。
// (補足) 壊れた SD カードや SD カードではないメディアが挿されているときにも、このエラーが返ります。
// 但し、その場合は RegisterSdmcInsertedEvent で登録した挿入イベントはシグナルされます。
ret = eExtResultDefaultError;
}
else
{
// 指定した拡張セーブデータは存在していないので、作成する必要があります。
// (補足) 開発中は、指定した ID が正しいか確認をしてください。
result = nn::fs::CreateExtSaveData( saveDataId,
&iconData, iconDataSize,
maxDirectories, maxFiles);
ret = eExtResultNeedCreate;
}
}
else if( result <= nn::fs::ResultNotFormatted() )
{
// 拡張セーブデータを作り直す必要があります。
// (理由) 拡張セーブデータの作成に失敗した状態です。
result = nn::fs::DeleteExtSaveData( saveDataId );
if( result.IsSuccess() )
{
result = nn::fs::CreateExtSaveData( saveDataId,
&iconData, iconDataSize,
maxDirectories, maxFiles);
}
ret = eExtResultNeedCreate;
}
else if( result <= nn::fs::ResultBadFormat() )
{
// SD カードをフォーマットする必要があります。
ret = eExtResultDefaultError;
}
else if( result <= nn::fs::ResultVerificationFailed() )
{
// 拡張セーブデータを作り直す必要があります。
// (理由) セーブデータが壊れているか、改竄されています。
result = nn::fs::DeleteExtSaveData( saveDataId );
if( result.IsSuccess() )
{
result = nn::fs::CreateExtSaveData( saveDataId,
&iconData, iconDataSize,
maxDirectories, maxFiles);
}
ret = eExtResultNeedCreate;
}
else if( result <= nn::fs::ResultOperationDenied() )
{
if( result <= nn::fs::ResultWriteProtected() )
{
// SD カードが書き込み禁止にされています。
// (補足) マウント時にデータの復旧シーケンスが実行されることがあり、そのときに発生します。
}
else if( result <= nn::fs::ResultMediaAccessError() )
{
// 接触不良等によるハードウェエア的な要因のときのみ、このエラーが返ります。
// そのときは、SD カードの挿し直し、本体の再起動などで復帰する可能性があります。
}
else
{
// SD カード上のファイル、もしくはディレクトリが読み取り専用にされている可能性があります。
// (補足) マウント時にデータの復旧シーケンスが実行されることがあり、そのときに発生します。
}
ret = eExtResultDefaultError;
}
else
{
// 上記以外は、想定外のエラーです。
// 但し、拡張セーブデータへのアクセスで、FATAL エラーは発生させないようにしてください。
ret = eExtResultDefaultError;
}
// 作成後の判定
if( result.IsFailure() )
{
if( result <= nn::fs::ResultNotEnoughSpace() )
{
// SD カードに必要な空き容量がありません。
ret = eExtResultNotFreeError;
}
else if( result <= nn::fs::ResultNotFormatted() )
{
// エラーが発生し、作成が途中で中断されました。
ret = eExtResultDefaultError;
}
else if( result <= nn::fs::ResultOperationDenied() )
{
if( result <= nn::fs::ResultWriteProtected() )
{
// SD カードが書き込み禁止にされています。
}
else if( result <= nn::fs::ResultMediaAccessError() )
{
// 接触不良等によるハードウェエア的な要因のときのみ、このエラーが返ります。
// そのときは、リトライ処理、ゲームカードの挿し直し、本体の再起動などで復帰する可能性があります。
}
else
{
// SD カード上のディレクトリが読み取り専用にされている可能性があります。
// (補足) マウント時にデータの復旧シーケンスが実行されることがあり、そのときに発生します。
}
ret = eExtResultDefaultError;
}
else
{
// 上記以外は、想定外のエラーです。
// 但し、拡張セーブデータへのアクセスで、FATAL エラーは発生させないようにしてください。
// (補足) 開発中は、iconData, iconDataSize に不正な値を渡していないか確かめてください。
ret = eExtResultDefaultError;
}
}
else
{
// 再マウント
result = nn::fs::MountExtSaveData( mMsetExtArcName, getMsetExtSaveDataId() );
if( result.IsFailure() )
{
// 始めの呼び出し時と同様。
// (補足) SD カードが抜かれない限り、作成直後にマウントが失敗することは、まずありません。
ret = eExtResultDefaultError;
}
}
}
return ret;
}
/*!
MSET
*/
void File::finalizeMsetExt()
{
nn::fs::Unmount( mMsetExtArcName );
}
/*!
MSET
*/
void File::readMsetFile( u8* pSaveData, const size_t size, int type )
{
u32 readSize = 0;
u8* pTmp = NULL;
pTmp = sys::File::read( mMsetSysSaveDataPath[ type ], &readSize, false, false );
if( pTmp == NULL )
{
switch( type )
{
case eSysSaveDataTypeDsi:
// ファイルがないので初期化
// 無効な programID で埋める
memset( pSaveData, 0xFF, size );
break;
case eSysSaveDataTypeBoss:
memset( pSaveData, 0, size );
break;
}
}
else
{
// 管理ファイルが読み込めた
memcpy( pSaveData, pTmp, size );
delete[] pTmp;
}
}
/*!
MSET
*/
void File::readMsetExtFile( u8* pSaveData, const size_t size, int type )
{
u32 readSize = 0;
u8* pTmp = NULL;
pTmp = sys::File::read( mMsetExtSaveDataPath[ type ], &readSize, false, false );
if( pTmp == NULL )
{
// ファイルがないので初期化
// 無効な programID で埋める
memset( pSaveData, 0xFF, size );
}
else
{
// 管理ファイルが読み込めた
memcpy( pSaveData, pTmp, size );
delete[] pTmp;
}
}
/*!
*/
void File::saveMmenSys( const u8* saveData, const size_t size )
{
nn::Result result;
nn::fs::FileWriter fileWriter;
// 自分で他のセーブデータへファイルをつくることはしない
result = fileWriter.TryInitialize( mMmenSysSaveDataPath, false );
NN_LOG("mmen sys try initialize\n");
NN_DBG_PRINT_RESULT( result );
if( result.IsSuccess() )
{
s32 out = 0;
result = fileWriter.TryWrite( &out, saveData, size );
if( result.IsSuccess() )
{
result = nn::fs::CommitSystemSaveData( mMmenSysArcName );
if( result.IsFailure() )
{
// これがエラーになってたらパニックだ
nn::dbg::Panic();
}
else
{
NN_LOG( "save to %ls\n", mMmenSysSaveDataPath );
}
}
fileWriter.Finalize();
}
}
void File::saveMsetSys( const u8* saveData, const size_t size, int type )
{
nn::Result result;
nn::fs::FileOutputStream fileWriter;
// なかった場合はファイル作成
result = fileWriter.TryInitialize( mMsetSysSaveDataPath[ type ], false );
if( result.IsFailure() )
{
if( result <= nn::fs::ResultNotFound() )
{
result = nn::fs::TryCreateFile( mMsetSysSaveDataPath[ type ], size );
if( result.IsFailure() )
{
return;
}
else
{
result = fileWriter.TryInitialize( mMsetSysSaveDataPath[ type ], false );
if( result.IsFailure() )
{
return;
}
}
}
else if(result <= nn::fs::ResultVerificationFailed())
{
// 作り直し
result = nn::fs::TryDeleteFile( mMsetSysSaveDataPath[ type ] );
if( result.IsFailure() )
{
return;
}
else
{
result = nn::fs::TryCreateFile( mMsetSysSaveDataPath[ type ], size );
if( result.IsFailure() )
{
return;
}
else
{
result = fileWriter.TryInitialize( mMsetSysSaveDataPath[ type ], false );
if( result.IsFailure() )
{
return;
}
}
}
}
else
{
return;
}
}
s64 fSize = 0;
result = fileWriter.TryGetSize( &fSize );
if( result.IsFailure() )
{
fileWriter.Finalize();
return;
}
if( fSize != size )
{
result = fileWriter.TrySetSize( size );
if( result.IsFailure() )
{
fileWriter.Finalize();
return;
}
}
s32 out = 0;
result = fileWriter.TryWrite( &out, saveData, size );
if( result.IsFailure() )
{
// このときどうしようもない
fileWriter.Finalize();
return;
}
else
{
fileWriter.Finalize();
// コミットしなければ反映されない
result = nn::fs::CommitSystemSaveData( mMsetSysArcName );
if( result.IsFailure() )
{
// これがエラーになってたらパニックだ
nn::dbg::Panic();
}
NN_LOG( "save to %ls\n", mMsetSysSaveDataPath[ type ] );
}
}
/*!
*/
void File::saveMsetExt( const u8* saveData, const size_t size, int type )
{
nn::Result result;
nn::fs::FileOutputStream fileWriter;
// なかった場合はファイル作成
result = fileWriter.TryInitialize( mMsetExtSaveDataPath[ type ], false );
NN_LOG("try save mset ext\n");
NN_DBG_PRINT_RESULT( result );
if( result.IsFailure() )
{
if( result <= nn::fs::ResultNotFound() )
{
if( result <= nn::fs::ResultMediaNotFound() )
{
return;
}
else
{
NN_LOG("try create mset ext\n");
result = nn::fs::TryCreateFile( mMsetExtSaveDataPath[ type ], size );
NN_DBG_PRINT_RESULT( result );
if( result.IsFailure() )
{
if(result <= nn::fs::ResultNotFound())
{
return;
}
else if(result <= nn::fs::ResultAlreadyExists())
{
NN_LOG("try delete mset ext\n");
result = nn::fs::TryDeleteFile( mMsetExtSaveDataPath[ type ] );
NN_DBG_PRINT_RESULT( result );
if( result.IsFailure() )
{
return;
}
else
{
NN_LOG("try create mset ext\n");
result = nn::fs::TryCreateFile( mMsetExtSaveDataPath[ type ], size );
NN_DBG_PRINT_RESULT( result );
if( result.IsFailure() )
{
return;
}
else
{
result = fileWriter.TryInitialize( mMsetExtSaveDataPath[ type ], false );
if( result.IsFailure() )
{
return;
}
}
}
}
}
}
}
else if(result <= nn::fs::ResultVerificationFailed())
{
NN_LOG("try delete mset ext\n");
result = nn::fs::TryDeleteFile( mMsetExtSaveDataPath[ type ] );
NN_DBG_PRINT_RESULT( result );
if( result.IsFailure() )
{
return;
}
else
{
NN_LOG("try create mset ext\n");
result = nn::fs::TryCreateFile( mMsetExtSaveDataPath[ type ], size );
NN_DBG_PRINT_RESULT( result );
if( result.IsFailure() )
{
return;
}
else
{
result = fileWriter.TryInitialize( mMsetExtSaveDataPath[ type ], false );
if( result.IsFailure() )
{
return;
}
}
}
}
else
{
return;
}
}
s64 fSize = 0;
result = fileWriter.TryGetSize( &fSize );
if( result.IsFailure() )
{
fileWriter.Finalize();
return;
}
if( fSize != size )
{
result = fileWriter.TrySetSize( size );
if( result.IsFailure() )
{
fileWriter.Finalize();
return;
}
}
s32 out = 0;
result = fileWriter.TryWrite( &out, saveData, size );
if( result.IsFailure() )
{
// このときどうしようもない
fileWriter.Finalize();
return;
}
else
{
fileWriter.Finalize();
NN_LOG( "save to %ls\n", mMsetExtSaveDataPath[ type ] );
}
}
/*!
*/
void File::debug_print_()
{
#ifndef NW_RELEASE
if( smDebugPrintFlag )
{
NN_LOG("Fail fileRead ");
/*
int i = 0;
while( name[i] != L'\0' )
{
NN_LOG("%c", name[i]);
if( ++i == 128 ) break;
}
*/
NN_LOG("\n");
}
#endif
}
//==========================================================================
// システムセーブデータのID取得
//==========================================================================
nn::fs::SystemSaveDataId File::getMmenSaveDataId()
{
nn::fs::SystemSaveDataId ret;
switch( nn::cfg::CTR::GetRegion() )
{
case nn::cfg::CTR::CFG_REGION_JAPAN:
ret = 0x00020082;
break;
case nn::cfg::CTR::CFG_REGION_EUROPE:
case nn::cfg::CTR::CFG_REGION_AUSTRALIA:
ret = 0x00020098;
break;
case nn::cfg::CTR::CFG_REGION_CHINA:
ret = 0x000200A1;
break;
case nn::cfg::CTR::CFG_REGION_KOREA:
ret = 0x000200A9;
break;
case nn::cfg::CTR::CFG_REGION_TAIWAN:
ret = 0x000200B1;
break;
case nn::cfg::CTR::CFG_REGION_AMERICA:
default:
ret = 0x0002008f;
break;
}
return ret;
}
nn::fs::SystemSaveDataId File::getMsetSaveDataId()
{
nn::fs::SystemSaveDataId ret;
switch( nn::cfg::CTR::GetRegion() )
{
case nn::cfg::CTR::CFG_REGION_JAPAN:
ret = 0x00020200;
break;
case nn::cfg::CTR::CFG_REGION_EUROPE:
case nn::cfg::CTR::CFG_REGION_AUSTRALIA:
ret = 0x00020220;
break;
case nn::cfg::CTR::CFG_REGION_CHINA:
ret = 0x00020260;
break;
case nn::cfg::CTR::CFG_REGION_KOREA:
ret = 0x00020270;
break;
case nn::cfg::CTR::CFG_REGION_TAIWAN:
ret = 0x00020280;
break;
case nn::cfg::CTR::CFG_REGION_AMERICA:
default:
ret = 0x00020210;
break;
}
return ret;
}
nn::fs::ExtSaveDataId File::getMsetExtSaveDataId()
{
nn::fs::ExtSaveDataId ret;
switch( nn::cfg::CTR::GetRegion() )
{
case nn::cfg::CTR::CFG_REGION_JAPAN:
ret = nn::CTR::PROGRAM_ID_UNIQUE_ID_MSET;
break;
case nn::cfg::CTR::CFG_REGION_EUROPE:
case nn::cfg::CTR::CFG_REGION_AUSTRALIA:
ret = nn::CTR::PROGRAM_ID_UNIQUE_ID_MSET_EU;
break;
case nn::cfg::CTR::CFG_REGION_CHINA:
ret = nn::CTR::PROGRAM_ID_UNIQUE_ID_MSET_CN;
break;
case nn::cfg::CTR::CFG_REGION_KOREA:
ret = nn::CTR::PROGRAM_ID_UNIQUE_ID_MSET_KR;
break;
case nn::cfg::CTR::CFG_REGION_TAIWAN:
ret = nn::CTR::PROGRAM_ID_UNIQUE_ID_MSET_TW;
break;
case nn::cfg::CTR::CFG_REGION_AMERICA:
default:
ret = nn::CTR::PROGRAM_ID_UNIQUE_ID_MSET_US;
break;
}
return ret;
}
}

View File

@ -0,0 +1,102 @@
/*!
@file sysFile.h
@brief
*/
#ifndef SYS_FILE_H_
#define SYS_FILE_H_
#include <nn/fs/fs_ApiSysSaveData.h>
namespace sys
{
class File
{
public:
File(){}
~File(){}
static u8* read( const char* fileName, u32* size, bool device = false, bool prefix = true );
static u8* read( const wchar_t* fileName, u32* size, bool device = false, bool prefix = true );
static void readMsetFile( u8* pSaveData, const size_t size, int type );
static void readMsetExtFile( u8* pSaveData, const size_t size, int type );
#ifndef NW_RELEASE
static void setDebugPrintFlag( bool flag ){ smDebugPrintFlag = flag; }
#endif
static u8* readLZ( const char* fileName, u32* size );
static u8* mountShare( const char* name, nn::ProgramId tit_id, int data_num, int files, int dirs );
static void initializeMsetSys();
static void finalizeMsetSys();
enum
{
eSysSaveDataTypeDsi = 0,
eSysSaveDataTypeBoss,
eSysSaveDataTypeNum
};
enum
{
eExtSaveDataTypeDsi = 0,
eExtSaveDataTypeNum
};
enum
{
eExtResultSuccess,
eExtResultNeedCreate,
// これ以降は失敗
eExtResultNotFreeError, // 空き容量が足りない
eExtResultDefaultError
};
static int checkMsetExt(); // マウントできるかどうか
static int initializeMsetExt();
static void finalizeMsetExt();
static void saveMmenSys( const u8* saveData, const size_t size );
static void saveMsetSys( const u8* saveData, const size_t size, int type );
static void saveMsetExt( const u8* saveData, const size_t size, int type );
static nn::fs::SystemSaveDataId getMmenSaveDataId();
static nn::fs::SystemSaveDataId getMsetSaveDataId();
static nn::fs::ExtSaveDataId getMsetExtSaveDataId();
// ---------------------------------------------------------------------------
static const char* getMmenSysArcName() { return mMmenSysArcName; }
static const char* getMsetSysArcName() { return mMsetSysArcName; }
static const char* getMsetExtArcName() { return mMsetExtArcName; }
static const wchar_t* getMmenSysSaveDataPath() { return mMmenSysSaveDataPath; }
static const wchar_t* getMsetSysSaveDataPath( int type ) { return mMsetSysSaveDataPath[ type ]; }
static const wchar_t* getMsetExtSaveDataPath( int type ) { return mMsetExtSaveDataPath[ type ]; }
enum
{
eMsetSaveDataSize = 64 * 1024,
eMsetExtSaveDataSize = 120 * 1024
};
private:
static void debug_print_();
#ifndef NW_RELEASE
static bool smDebugPrintFlag;
#endif
static const char* mMmenSysArcName;
static const wchar_t* mMmenSysSaveDataPath;
static const char* mMsetSysArcName;
static const wchar_t* mMsetSysSaveDataPath[ eSysSaveDataTypeNum ];
static const char* mMsetExtArcName;
static const wchar_t* mMsetExtSaveDataPath[ eExtSaveDataTypeNum ];
};
}
#endif

View File

@ -0,0 +1,212 @@
/*!
@file sysInput.cpp
@brief
*/
#include "sys.h"
#include "sysInput.h"
#ifndef NW_RELEASE
#include "utScreenCapture.h"
#endif
#ifdef DEBUG_TEXT
#include "lytManager.h"
#endif
namespace sys
{
u16 Input::msPad; // 現在の入力
u16 Input::msPadPrev; // 1フレーム前の入力
u16 Input::msPadTrig; // 現在のトリガ
bool Input::msTP;
bool Input::msTPTouch;
nw::math::VEC2 Input::msTPPos;
nw::math::VEC2 Input::msTPFloatPos;
nn::hid::CTR::PadReader* Input::mspPadReader;
nn::hid::CTR::PadStatus* Input::mspPadStatus;
nn::hid::CTR::TouchPanelReader* Input::mspTpReader;
nn::hid::CTR::TouchPanelStatus* Input::mspTpStatus;
nn::hid::CTR::PadReaderWithSvr2* Input::smpPadReaderWithSvr2;
/*!
*/
void Input::init()
{
msPad = 0;
msPadPrev = 0;
msPadTrig = 0;
//nn::Result result;
// nn::hid::Initialize();
//NN_UTIL_PANIC_IF_FAILED(result);
mspPadReader = new( sys::Mem::getMainHeap() ) nn::hid::CTR::PadReader();
mspPadStatus = new( sys::Mem::getMainHeap() ) nn::hid::CTR::PadStatus();
mspPadReader->SetStickClampMode( nn::hid::CTR::PadReader::STICK_CLAMP_MODE_CROSS );
mspTpReader = new( sys::Mem::getMainHeap() ) nn::hid::CTR::TouchPanelReader();
mspTpStatus = new( sys::Mem::getMainHeap() ) nn::hid::CTR::TouchPanelStatus();
smpPadReaderWithSvr2 = new( sys::Mem::getMainHeap() ) nn::hid::CTR::PadReaderWithSvr2();
}
/*!
*/
void Input::update( int system_stt )
{
// ステートが通常以外になったときは更新を止めつつ、処理をリセットさせる
if( system_stt != sys::eSystemStt_Normal )
{
return;
}
msTPTouch = msTP;
// 入力取得
bool pad_ret = mspPadReader->ReadLatest( mspPadStatus );
bool tp_ret = mspTpReader->ReadLatest( mspTpStatus );
if( tp_ret && mspTpStatus->touch == 1 )
{
// タッチパネル座標系をレイアウト座標系に変換します.
nw::math::VEC2 tpStatus;
tpStatus.x = (f32)( mspTpStatus->x - cDown_Width / 2 );
tpStatus.y = -(f32)( mspTpStatus->y - cDown_Height / 2 );
// 遊び範囲内での動作は,
// チャタリング対策のため非常に遅い追従率で追従させます.
// 遊び範囲を超えたときは完全に一致させます.
static const f32 cPlayRadius = 1.5f; // 遊び半径.
static const f32 cSensitivity = 0.1f; // 遊び半径内での追従係数.
if( msTP && nn::math::VEC2DistSq( msTPFloatPos, tpStatus ) < cPlayRadius * cPlayRadius )
{
msTPFloatPos += ( tpStatus - msTPFloatPos ) * cSensitivity;
}
else
{
msTPFloatPos = tpStatus;
}
// 小数のまま使用すると,スライダーバーやタッチスライダーで,
// 終端判定以降にじりじり動いてしまう問題が発生したため,
// 整数に丸めて使用します.
msTPPos.x = (int)msTPFloatPos.x;
msTPPos.y = (int)msTPFloatPos.y;
msTP = true;
}
else msTP = false;
if( pad_ret )
{
msPadTrig = (u16)( msPad & ~msPadPrev );
msPadPrev = msPad;
}
#ifndef NW_RELEASE
// キャプチャー用テストコード
if( isButtonHold( BUTTON_R | BUTTON_L ) )
{
if( isButtonHold( KEY_UP ) ) ut::SaveDisplayBufferSD( eDisp_Up );
else if( isButtonHold( KEY_DOWN ) ) ut::SaveDisplayBufferSD( eDisp_Down );
}
#endif
#ifdef DEBUG_TEXT
if( isButtonHold( BUTTON_R | BUTTON_L ) &&
isTouched() )
{
static bool visible = false;
visible = !visible;
lyt::Manager::setDebugVisible( visible );
}
#endif
}
/*!
*/
void Input::finish()
{
// nn::hid::Finalize();
}
/*!
*/
u16 Input::isTouched()
{
return msTP && !msTPTouch;
}
/*!
*/
u16 Input::isReleased()
{
return !msTP && msTPTouch;
}
/*!
*/
u16 Input::isTouching()
{
return msTP;
}
/*!
PADのトリガ入力を取得
*/
u16 Input::getPadTrig()
{
return mspPadStatus->trigger;
}
/*!
*/
bool Input::isButtonTrig( u16 button )
{
return ( mspPadStatus->trigger & button ) ? true: false;
}
/*!
*/
bool Input::isButtonHold( u16 button )
{
return ( mspPadStatus->hold & button )? true: false;
}
/*!
3D視差ボリューム取得
0.0f1.0f
*/
f32 Input::getSvr2Volume()
{
return smpPadReaderWithSvr2->GetSvr2Volume();
}
/*
*/
f32 Input::getNormalizeX()
{
return mspPadReader->NormalizeStick( mspPadStatus->stick.x );
}
f32 Input::getNormalizeY()
{
return mspPadReader->NormalizeStick( mspPadStatus->stick.y );
}
}

View File

@ -0,0 +1,159 @@
/*!
@file sysInput.h
@brief
*/
#ifndef SYS_INPUT_H_
#define SYS_INPUT_H_
#ifdef NW_PLATFORM_CTR
#include <nn/hid.h>
#include <nn/hid/CTR/hid_PadReaderWithSvr2.h>
#else
#include <windows.h>
#endif
#include "guiManager.h"
#include "guiButton.h"
#include "guiRadioButton.h"
#include "guiRepeatButton.h"
#include "guiSliderBar.h"
#include "guiMayaButton.h"
#include "guiTouchSlider.h"
#include "utUtil.h"
#include "sysDialogManager.h"
#include "sceneCalibrationLayout.h"
#include "sceneCalibrationGuiOperator.h"
#include "sceneStartLayout.h"
#include "sceneCoppaLayout.h"
#ifndef NW_RELEASE
#include "sceneSceneController.h"
#include "sceneDebugLayout.h"
#include "sceneDialogScene.h"
#include "sceneDataMngLayout.h"
#include "sceneDataCmmLayout.h"
#ifdef NW_PLATFORM_CTR
#include "sceneInternetThread.h"
#include "sceneDataMngThread.h"
#include "sceneCoppaThread.h"
#include "sceneCheckScene.h"
#endif
#endif
namespace sys
{
class Input
{
public:
#ifdef NW_PLATFORM_CTRWIN
static const int BUTTON_A = nn::hw::pad::BUTTON_A;
static const int BUTTON_B = nn::hw::pad::BUTTON_B;
static const int BUTTON_SELECT = nn::hw::pad::BUTTON_SELECT;
static const int BUTTON_START = nn::hw::pad::BUTTON_START;
static const int KEY_RIGHT = nn::hw::pad::KEY_RIGHT;
static const int KEY_LEFT = nn::hw::pad::KEY_LEFT;
static const int KEY_UP = nn::hw::pad::KEY_UP;
static const int KEY_DOWN = nn::hw::pad::KEY_DOWN;
static const int BUTTON_R = nn::hw::pad::BUTTON_R;
static const int BUTTON_L = nn::hw::pad::BUTTON_L;
static const int BUTTON_X = nn::hw::pad::BUTTON_X;
static const int BUTTON_Y = nn::hw::pad::BUTTON_Y;
static const int BUTTON_DEBUG = nn::hw::pad::BUTTON_DEBUG;
#endif
#ifdef NW_PLATFORM_CTR
static const int BUTTON_A = nn::hid::CTR::BUTTON_A;
static const int BUTTON_B = nn::hid::CTR::BUTTON_B;
static const int BUTTON_SELECT = nn::hid::CTR::PSEUDO_BUTTON_SELECT;
static const int BUTTON_START = nn::hid::CTR::BUTTON_START;
static const int KEY_RIGHT = nn::hid::CTR::BUTTON_RIGHT;
static const int KEY_LEFT = nn::hid::CTR::BUTTON_LEFT;
static const int KEY_UP = nn::hid::CTR::BUTTON_UP;
static const int KEY_DOWN = nn::hid::CTR::BUTTON_DOWN;
static const int BUTTON_R = nn::hid::CTR::BUTTON_R;
static const int BUTTON_L = nn::hid::CTR::BUTTON_L;
static const int BUTTON_X = nn::hid::CTR::BUTTON_X;
static const int BUTTON_Y = nn::hid::CTR::BUTTON_Y;
static const int BUTTON_DEBUG = nn::hid::CTR::BUTTON_DEBUG;
#endif
static void init();
static void update( int system_stt );
static void finish();
static f32 getSvr2Volume();
static f32 getNormalizeX();
static f32 getNormalizeY();
static const f32 c3dVolume = 0.85f;
private:
static u16 isTouched();
static u16 isReleased();
static u16 isTouching();
static const nw::math::VEC2& getPos(){ return msTPPos; }
static u16 getPadTrig();
static bool isButtonTrig( u16 button );
static bool isButtonHold( u16 button );
static u16 msPad;
static u16 msPadPrev;
static u16 msPadTrig;
static bool msTP; // タッチしているときtrue.
static bool msTPTouch; // 1フレーム前にタッチしていたときtrue.
static nw::math::VEC2 msTPPos; // タッチしているときのタッチ位置の整数値.
static nw::math::VEC2 msTPFloatPos; // タッチしているときのタッチ位置.
#ifdef NW_PLATFORM_CTR
static nn::hid::CTR::PadReader* mspPadReader;
static nn::hid::CTR::PadStatus* mspPadStatus;
static nn::hid::CTR::TouchPanelReader* mspTpReader;
static nn::hid::CTR::TouchPanelStatus* mspTpStatus;
static nn::hid::CTR::PadReaderWithSvr2* smpPadReaderWithSvr2;
#else
static LRESULT Callback( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, BOOL *handled );
#endif
friend class gui::Manager;
friend class gui::Button;
friend class gui::RepeatButton;
friend class gui::RadioButton;
friend class gui::SliderBar;
friend class gui::MayaButton;
friend class gui::TouchSlider;
friend class DialogManager;
friend class DialogButton;
friend int ut::IsInBoundPane( lyt::Object* lyt_obj, const char* group_name );
friend class scene::CalibrationLayout;
friend class scene::CalibrationGuiOperator;
friend class scene::StartLayout;
friend class scene::CoppaLayout;
#ifndef NW_RELEASE
friend class scene::SceneController;
friend class scene::DebugLayout;
friend class scene::DialogScene;
friend class scene::DataMngLayout;
friend class scene::DataCmmLayout;
friend class scene::CheckScene;
friend class scene::InternetFnc;
friend class scene::DataMngFnc;
friend class scene::CoppaFnc;
#endif
};
}
#endif

View File

@ -0,0 +1,286 @@
// sysFirmware.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//
#include "sysSharedExtSaveData.h"
#include <nn/fs.h>
#include <nn/fs/fs_Api.h>
#include <nn/fs/fs_Parameters.h>
#include <nn/fs/fs_FileSystem.h>
#include <nn/fs/fs_ApiSharedExtSaveData.h>
#include <nn/fs/CTR/MPCore/fs_FileSystemBase.h>
//#include <nn/fs/fs_IpcFileSystem.h>
#include <stdio.h>
namespace sys
{
namespace
{
struct Parameter
{
size_t defaultLimitSize;
size_t limitSize;
u32 entryFile;
u32 entryDirectory;
};
#if 0
// refreshLimitSize を呼ぶ場合の初期値
Parameter cPnoteMPPotoParam = { 64 * 1024 * 1024 , 0 , 501 , 505 };
Parameter cSnoteSoundParam = { 1232 * 1024 , 0 , 20 , 1 };
Parameter cNewsBossDataParam = { 0 , 0 , 100 , 1 };
Parameter cCommonDataParam = { 0 , 0 , 8 , 0 };
Parameter cBashotoryaDataParam = { 0 , 0 , 6 , 1 };
#else
// 直で呼ぶ場合の初期値 今はこっち
Parameter cPnoteMPPotoParam = { 0 , 64 * 1024 * 1024 , 511 , 511 };
Parameter cSnoteSoundParam = { 0 , 1232 * 1024 , 32 , 16 };
Parameter cNewsBossDataParam = { 0 , 4354048 , 127 , 16 };
Parameter cCommonDataParam = { 0 , 9277440 , 16 , 16 };
Parameter cBashotoryaDataParam = { 0 , 2785280 , 16 , 16 };
// = 2719744(データ5件+キャッシュ) + 64kb
// = 2498560(データ4件+おしらせ1件+キャッシュ) + 32kb + 220kb(データ-おしらせ) + 28kb
#endif
Parameter* cParams[SharedExtSaveData::cIDCount] = {
&cPnoteMPPotoParam,
&cSnoteSoundParam,
&cNewsBossDataParam,
&cCommonDataParam,
&cBashotoryaDataParam,
};
const char *cParamsString[SharedExtSaveData::cIDCount] = {
"PnoteMPPoto ",
"SnoteSound ",
"NewsBossData ",
"CommonData ",
"BashotoryaData ",
};
}
const bit32 SharedExtSaveData::cIDs[SharedExtSaveData::cIDCount] = {
SharedExtSaveData::cPnoteMPPoto,
SharedExtSaveData::cSnoteSound,
SharedExtSaveData::cNewsBossData,
SharedExtSaveData::cCommonData,
SharedExtSaveData::cBashotorya,
};
void SharedExtSaveData::refreshLimitSize()
{
for ( int i = 0; i < cIDCount; ++ i )
{
switch ( i )
{
// ファイルが 100 作れて、ファイル自体の合計は 4M になるように
case eType_BossData:
{
s64 size = 0;
const s64 filesize_table[ 1 ] = { 4 * 1024 * 1024 };
nn::Result result = nn::fs::QueryTotalQuotaSize( &size ,
cParams[ i ]->entryDirectory ,
cParams[ i ]->entryFile ,
filesize_table ,
1 );
if ( result.IsSuccess() )
{
cParams[ i ]->limitSize = static_cast< size_t > ( size );
NN_LOG( "%s dir: %d file: %d size: %d\n" , cParamsString[ i ] ,
cParams[ i ]->entryDirectory ,
cParams[ i ]->entryFile ,
cParams[ i ]->limitSize );
}
}
break;
// 汎用データ→IDB+GameCoin+LBL+GBL+BindingFolder+Mii
case eType_Common:
{
s64 size = 0;
const s64 filesize_table[ 8 ] =
{
7159808 , // idb
8200 , // idbt
20 , // gamecoin
12000 , // LBL
97328 , // GBL
4 , // BindingFolder
310560 , // Mii1
310560 , // Mii2
};
nn::Result result = nn::fs::QueryTotalQuotaSize( &size ,
cParams[ i ]->entryDirectory ,
cParams[ i ]->entryFile ,
filesize_table ,
8 );
if ( result.IsSuccess() )
{
cParams[ i ]->limitSize = static_cast< size_t > ( size );
NN_LOG( "%s dir: %d file: %d size: %d\n" , cParamsString[ i ] ,
cParams[ i ]->entryDirectory ,
cParams[ i ]->entryFile ,
cParams[ i ]->limitSize );
}
}
break;
// バショトリャー
case eType_Bashotorya:
{
s64 size = 0;
const s64 filesize_table[ 6 ] =
{
274 * 1024 + 52 ,
274 * 1024 + 52 ,
274 * 1024 + 52 ,
274 * 1024 + 52 ,
274 * 1024 + 52 ,
1096 * 1024 ,
};
nn::Result result = nn::fs::QueryTotalQuotaSize( &size ,
cParams[ i ]->entryDirectory ,
cParams[ i ]->entryFile ,
filesize_table ,
sizeof( filesize_table ) / sizeof( *filesize_table ) );
if ( result.IsSuccess() )
{
cParams[ i ]->limitSize = static_cast< size_t > ( size );
NN_LOG( "%s dir: %d file: %d size: %d\n" , cParamsString[ i ] ,
cParams[ i ]->entryDirectory ,
cParams[ i ]->entryFile ,
cParams[ i ]->limitSize );
}
}
break;
// 初期値をコピーする
default:
cParams[ i ]->limitSize = cParams[ i ]->defaultLimitSize;
NN_LOG( "%s dir: %d file: %d size: %d\n" , cParamsString[ i ] ,
cParams[ i ]->entryDirectory ,
cParams[ i ]->entryFile ,
cParams[ i ]->limitSize );
break;
}
}
}
void SharedExtSaveData::createData()
{
//refreshLimitSize(); // QueryTotalQuotaSize を計算する
nn::Result res;
for ( int i=0; i<cIDCount; i++ )
{
res = nn::fs::CreateSharedExtSaveData( cIDs[i],
cParams[i]->entryDirectory, cParams[i]->entryFile, cParams[i]->limitSize );
NN_LOG( "%d size -> %d %d\n" , i , cParams[ i ]->limitSize , res.IsSuccess() );
NN_ASSERT_RESULT( res );
if ( res.IsFailure() )
{
NN_LOG( "result = %d %d %d\n" , res.GetLevel() , res.GetSummary() , res.GetModule() );
}
}
}
void SharedExtSaveData::deleteData()
{
nn::Result res;
for ( int i=0; i<cIDCount; i++ )
{
res = nn::fs::DeleteSharedExtSaveData( cIDs[i] );
}
}
void SharedExtSaveData::checkData()
{
//refreshLimitSize(); // QueryTotalQuotaSize を計算する
nn::Result res;
for ( int i=0; i<cIDCount; i++ )
{
char volume[ 8 ] = { 0 };
sprintf( volume , "ex%02d" , i );
res = nn::fs::MountSharedExtSaveData( volume, cIDs[i] );
if(res.IsFailure())
{
//NN_RESULT_ASSERT( res );
if(res <= nn::fs::ResultNotFound())
{
// 存在していない。作成する。
res = nn::fs::CreateSharedExtSaveData(cIDs[i],
cParams[i]->entryDirectory, cParams[i]->entryFile, cParams[i]->limitSize);
}
else if(res <= nn::fs::ResultNotFormatted())
{
// フォーマットされていない。フォーマットを行なう。
// - まず発生しないはず。
//res = nn::fs::DeleteSharedExtSaveData( cIDs[i] );
//NN_ASSERT_RESULT( res );
res = nn::fs::CreateSharedExtSaveData(cIDs[i],
cParams[i]->entryDirectory, cParams[i]->entryFile, cParams[i]->limitSize);
}
else if(res <= nn::fs::ResultBadFormat())
{
// 不正なフォーマット。フォーマットを行なう。
// - ノイズ等の可能性もあるので、リトライしてもよい?
res = nn::fs::CreateSharedExtSaveData(cIDs[i],
cParams[i]->entryDirectory, cParams[i]->entryFile, cParams[i]->limitSize);
}
else if(res <= nn::fs::ResultVerificationFailed())
{
// 検証に失敗。フォーマットを行なう。
res = nn::fs::CreateSharedExtSaveData(cIDs[i],
cParams[i]->entryDirectory, cParams[i]->entryFile, cParams[i]->limitSize);
}
else
{
// それ以外は、発生しないはず。FATALへ。
// - ノイズ等の可能性もあるので、リトライしてもよい?
}
if(res.IsFailure())
{
// ここで失敗した場合は、さすがに FATAL へ。
}
else
{
// 再マウント
// - ここで失敗した場合は、さすがに FATAL へ。
res = nn::fs::MountSharedExtSaveData(volume, cIDs[i] );
if ( res.IsFailure() )
{
// ここも FATAL?(河野)
}else{
nn::fs::Unmount(volume);
}
}
}else{
nn::fs::Unmount(volume);
}
NN_ASSERT_RESULT( res );
}
}
// 領域の説明を返す
const char *SharedExtSaveData::getInfoString( bit32 id )
{
for ( int i = 0; i<cIDCount; i++ )
{
if ( cIDs[i]==id ) return cParamsString[i];
}
return "unknown ";
}
}

View File

@ -0,0 +1,43 @@
// IDB.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//
#ifndef __SYS_SHARED_EXT_SAVE_DATA_H_
#define __SYS_SHARED_EXT_SAVE_DATA_H_
#include <nn/types.h>
namespace sys
{
class SharedExtSaveData
{
public:
enum SharedExtSaveDataType
{
eType_Photo = 0 ,
eType_Sound ,
eType_BossData ,
eType_Common ,
eType_Bashotorya ,
eType_Max
};
static const int cIDCount = eType_Max;
static const bit32 cIDs[cIDCount];
static const bit32 cPnoteMPPoto = 0xF0000001; // PNOTEのMP画像写真
static const bit32 cSnoteSound = 0xF0000002; // SNOTEのAACデータ音声
static const bit32 cNewsBossData = 0xF0000009; // おしらせBOSSデータ 7168KB 128 8 拡張セーブデータでした
static const bit32 cCommonData = 0xF000000B; // 汎用データ
static const bit32 cBashotorya = 0xF000000C; // バショトリャー
static void createData();
static void deleteData();
static void checkData();
static void refreshLimitSize();
// 領域の説明を返す
static const char *getInfoString( bit32 id );
};
}
#endif // ifndef __SYS_SHARED_EXT_SAVE_DATA_H_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,522 @@
/*!
@file sysUserInfoAccessor.h
@brief
*/
#ifndef SYS_USER_INFO_ACCESSOR_H_
#define SYS_USER_INFO_ACCESSOR_H_
#include <nn/ac.h>
#include <nn/ac/private/ac.h>
#include <nn/cfg.h>
#include <nn/cfg/CTR/detail/cfg_Keys.h>
#include <nn/cfg/CTR/detail/cfg_DataStructures.h>
#include <nn/cfg/CTR/cfg_ParentalControl.h>
#include <nn/cfg/CTR/cfg_Api.h>
#include <nn/cfg/CTR/cfg_NtrSettings.h>
#include <nn/cfg/CTR/cfg_Coppacs.h>
#include "sysProcessManager.h"
namespace sys
{
//==========================================================================
// 初回起動、どこまで終わったかをチェックする
// 全て終わるとendをセット
//==========================================================================
struct FirstInfo
{
u32 end : 1;
u32 langage : 1;
u32 date : 1;
u32 time : 1;
u32 name : 1;
u32 birthday : 1;
u32 country : 1;
u32 area : 1;
u32 view : 1; // 3D確認
u32 eula : 1; // EULA確認
u32 rsv : 22;
};
struct EulaDef
{
u8 id; // 国ID
u8 numLanguage; // 言語数
u8 minorVersion; // EULAマイナーバージョン
u8 majorVersion; // EULAメジャーバージョン
u8 language[4]; // EULA用の言語定数本体設定より多い。言語名表示のため
u8 fileNo[4]; // EULAファイル番号EULAファイル名を <fileNo>.bin にしておく)
};
//==========================================================================
// 一般設定でセーブされる情報
//==========================================================================
struct UserInfo
{
nn::cfg::CTR::detail::UserNameCfgData usr_name; // ユーザーネーム
nn::cfg::CTR::SimpleAddress usr_address; // アドレス
nn::cfg::CTR::detail::BirthdayCfgData usr_birthday; // 誕生日
nn::cfg::CTR::detail::LanguageCfgData usr_language; // 言語
nn::cfg::CTR::detail::SoundSettingCfgData usr_sound; // サウンド
};
//==========================================================================
// TWL用にセーブされる情報
//==========================================================================
struct TwlInfo
{
nn::cfg::CTR::NtrSettingData ds_data;
nn::cfg::CTR::NtrSettingDataEx ds_data_ex;
};
struct TwlInfo2
{
nn::cfg::CTR::detail::TwlCountryCodeCfgData ds_country;
nn::cfg::CTR::detail::TwlParentalControlInfoCfgData ds_pare;
nn::cfg::CTR::detail::TwlEulaInfoCfgData ds_eula;
};
//==========================================================================
// インターネット設定でセーブされる情報
//==========================================================================
struct NetInfo
{
enum
{
eInfoMax = 3
};
nn::ac::CTR::NetworkSetting setting[eInfoMax]; // 接続設定
nn::cfg::CTR::detail::EulaInfoCfgData net_eula; // EULA
nn::cfg::CTR::detail::BossSettingCfgData net_boss; // BOSS
};
//==========================================================================
// 国・地域情報(セーブ不要)
//==========================================================================
enum
{
eAddrLangageNum = nn::cfg::CTR::CFG_SIMPLE_ADDRESS_NUM_LANGUAGES,
eAddrNameLength = nn::cfg::CTR::CFG_SIMPLE_ADDRESS_NAME_LENGTH
};
struct CountryInfo
{
u32 id; // 国ID
u32 numRegion; // 地域数
bool newEntry; // CTRで新たに追加された国はtrue
u8 pad[3];
u16 countryName[eAddrLangageNum][eAddrNameLength];
u8 order[eAddrLangageNum]; // 言語ごとの国名並び順最初の国は0
u8 rsv[32];
};
struct AreaInfo
{
u32 id; // 国IDと地域IDの組み合わせ
u16 regionName[eAddrLangageNum][eAddrNameLength];
u8 order[eAddrLangageNum]; // 言語ごとの国名並び順最初の国は0
u16 latitude; // 緯度
u16 longitude; // 経度
};
//==========================================================================
// その他、セーブ不要の情報
//==========================================================================
struct WorkInfo
{
// 地域
int country_id; // 選んでいる国のID
int country; // 国設定のスライダーバーでの位置
int area; // 地域設定のスライダーバーでの位置
int area_num; // 選んでいる国の地域数
int language;
// 日付、時刻
int time[2]; // 0:時 1:分
int date[3]; // 0:年 1:月 2:日
u8 eula_minor;
u8 eula_major;
u8 padding[2];
};
//==========================================================================
// BOSS で送信する情報
//==========================================================================
// -------------------------------------------------------------------
// cfg の情報
// -------------------------------------------------------------------
struct BossSendCfgInfo
{
nn::cfg::CTR::detail::TouchPanelCfgData touchPanel; // タッチパネル
nn::cfg::CTR::detail::AnalogStickCfgData analogStick; // アナログスティック
nn::cfg::CTR::detail::GyroscopeCfgData gyro; // ジャイロ
nn::cfg::CTR::detail::AccelCfgData accel; // 加速度センサ
nn::cfg::CTR::detail::BackLightCfgData backLight; // バックライト
nn::cfg::CTR::detail::CameraCfgData camera; // カメラ
nn::cfg::CTR::detail::SoundSettingCfgData sound; // サウンド
nn::cfg::CTR::detail::LanguageCfgData language; // 言語
nn::cfg::CTR::detail::SimpleAddressIdCfgData simpleAddress; // 簡易アドレス
nn::cfg::CTR::detail::ParentalControlInfoCfgData parental; // ペアレンタルコントロール
nn::cfg::CTR::detail::EulaInfoCfgData eula; // EULA
nn::cfg::CTR::detail::BossSettingCfgData boss; // BOSS
f32 svr2Vol; // 3D ボリューム
u8 sndVol; // サウンドボリューム
};
// -------------------------------------------------------------------
// インターネット設定の情報
// -------------------------------------------------------------------
struct BossSendNetInfo
{
u8 networkVersion; // NetworkSetting の version
bool wirelessEnable; // WirelessSetting の enable
bool wirelessEditableEssidSecrity; // WirelessSetting の editableEssidSecurity
bool multiSsidEnable; // MultiSsidSetting の enable
bool ipEnableDHCP; // IpSetting の enableDHCP
bool ipAutoDNSSetting; // IpSetting の autoDNSSetting
bool proxyEnable; // ProxySetting の enable
bool otherEnableUPnP; // OtherSetting の enableUPnP
nn::ac::CTR::SecurityMode essidSecurityMode; // EssidSecurity の securityMode
nn::ac::CTR::MultiSsidType multiSsidType; // MultiSsidType の multiSsidType
nn::ac::CTR::ProxyAuthType proxyAuthType; // ProxySetting の authType
u8 padding; // パディング
};
// -------------------------------------------------------------------
// 工場出荷時のキャリブレーションの情報
// -------------------------------------------------------------------
struct FactoryCalInfo
{
nn::cfg::CTR::detail::CameraCfgData camera; // カメラ
nn::cfg::CTR::detail::AnalogStickCfgData analogStick; // アナログスティック
};
struct BossSendInfo
{
BossSendCfgInfo cfgInfo;
BossSendNetInfo netInfo[NetInfo::eInfoMax];
FactoryCalInfo factoryCalInfo;
nn::cfg::CTR::detail::CoppacsCfgData coppacsInfo;
};
//******************************************************************************
// 各種情報にアクセスするためのクラス
//******************************************************************************
//==========================================================================
//
//==========================================================================
class UserInfoAccessor
{
public:
UserInfoAccessor(){}
~UserInfoAccessor(){}
static void init( int flg = 0 );
static void eventProc( int info_event );
static void destroy();
static int checkEula(); // EULAの情報を調べる
static void loadEula();
static void setBossTask();
static void setBossSendInfoTask();
static void setBossSendInfoTaskFirst();
static void saveBossSendInfoTaskOptoutFlag( bool optout );
static bool checkUpdateBossSendInfo( BossSendInfo* pSaveData );
static void getAnalogData( nn::cfg::CTR::detail::AnalogStickCfgData* para, int flg = 0 );
//==========================================================================
// 初回起動設定用
static void saveFirstInfo( int mmen, u8 net ); // 初回起動のセーブ
static bool isFirst(){ return ( msFirst.end == 0 ); }
static const FirstInfo& getFirst(){ return msFirst; }
static void setFirst( FirstInfo& first ){ msFirst = first; }
static void setFirstParam(); // 初回起動用パラメータ
static void setFirstAll( bool set );
static void getSharedArea();
//==========================================================================
// ユーザー情報設定アクセス用
static void setUserInfo( UserInfo& user_info );
static const UserInfo& getUserInfo(){ return msUserInfo; }
static const UserInfo* getUserInfoPtr(){ return &msUserInfo; }
//==========================================================================
// Twlユーザー情報設定アクセス用
static void setTwlInfo( TwlInfo& twl_info );
static const TwlInfo& getTwlInfo(){ return msTwlInfo; }
static const TwlInfo* getTwlInfoPtr(){ return &msTwlInfo; }
static void setTwlInfo2( TwlInfo2& twl_info );
static const TwlInfo2& getTwlInfo2(){ return msTwlInfo2; }
static const TwlInfo2* getTwlInfo2Ptr(){ return &msTwlInfo2; }
//TWLで入力不可能な文字を'?'に置換する
static void replaceUnusableString( wchar_t* buffer, int len );
//TWLで入力不可能な文字を'?'に置換する(TWLで入力可能な文字テーブルを使用する方法)
static void replaceUnusableStringWithTwlUserInfoFontTable(wchar_t* buffer, int len);
static bool binarySearchFromTwlUserInfoFontTable(u16 wc);
//==========================================================================
// ネットワーク設定アクセス用
static bool isCheckNetworkInfo(); // オリジナルとバックアップの比較setting単位
static int getAccNum(){ return msAccNum; } // 接続先の番号取得
static void setAccNum( int num ){ msAccNum = num; } // 接続先のセット
static int getTmpNum(){ return msTmpNum; }
static void setTmpNum( int num ){ msTmpNum = num; }
static void setNetInfo( NetInfo& net_info );
static const NetInfo& getNetInfo(){ return msNetInfo; }
static const NetInfo* getNetInfoPtr(){ return &msNetInfo; }
static const nn::ac::CTR::WirelessSetting& getNetWireInfo( int num ){ return msNetInfo.setting[num].wireless; }
static const nn::ac::CTR::IpSetting& getNetIpInfo( int num ){ return msNetInfo.setting[num].ip; }
static const nn::ac::CTR::ProxySetting& getNetProxyInfo( int num ){ return msNetInfo.setting[num].proxy; }
static const nn::ac::CTR::OtherSetting& getNetOtherInfo( int num ){ return msNetInfo.setting[num].other; }
static const nn::ac::CTR::MultiSsidSetting& getNetMultiInfo( int num ){ return msNetInfo.setting[num].wireless.multiSsid; }
static const nn::ac::CTR::NetworkSetting* getNetSettingPtr( int num ){ return &msNetInfo.setting[num]; }
static void setNetNewParam( int num ); // TODO:アクセスポイント初期設定(仮)
static void setNetWireless( int num, nn::ac::CTR::WirelessSetting& wireless );
static void setNetIp( int num, nn::ac::CTR::IpSetting& ip );
static void setNetProxy( int num, nn::ac::CTR::ProxySetting& proxy );
static void setNetOther( int num, nn::ac::CTR::OtherSetting& other );
static void delNetSetInfo( int num );
static u8* readCountryData( int flg ); // 国地域情報の読み込み
#ifdef MAKE_ACCTEST
#ifndef NW_RELEASE
static void print_net_save_();
#endif
#endif
#ifndef NW_RELEASE
static void getLastDsData();
#endif
static bool isNetSet(){ return msFirstInfo.internet; }
static bool isEula(){ return ( msNetInfo.net_eula.agreeVersion.version > 0 ); }
static bool isEulaCoppa(){ return ( msNetInfo.net_eula.agreeVersion.version >= 0x0101 ); }
static void setNetInit( bool used );
static void setNetBg24Get( bool used );
static void setNetBg24Send( bool used );
static void clrNetBg24();
static nn::ProgramId getHomePid();
static nn::ProgramId getMsetPid();
static nn::ProgramId getPnotePid();
static const char* getMsetBossCode();
static void clrNet2();
static void prepareBossSendInfo();
//==========================================================================
// ペアレンタルコントロール設定アクセス用
static void setParentInfo( nn::cfg::CTR::ParentalControlInfo& parent_info );
static const nn::cfg::CTR::ParentalControlInfo& getParentInfo(){ return msParentInfo; }
static const nn::cfg::CTR::ParentalControlInfo* getParentInfoPtr(){ return &msParentInfo; }
static void clrParentInfo( bool eula );
static bool isCheckParentInfo();
static bool isParentalLock(){ return msParentInfo.flags.isSetParentalControl != 0; }
static bool is3dLock(){ return msParentInfo.flags.ulcd != 0; }
//==========================================================================
// COPPACS設定アクセス用
static void setCoppaInfo( nn::cfg::CTR::detail::CoppacsCfgData& coppa_info );
static const nn::cfg::CTR::detail::CoppacsCfgData& getCoppaInfo(){ return msCoppaInfo; }
static const nn::cfg::CTR::detail::CoppacsCfgData* getCoppaInfoPtr(){ return &msCoppaInfo; }
static bool isCheckCoppaInfo();
static void saveCoppaInfo( nn::cfg::CTR::detail::CoppacsCfgData& coppa_info );
static bool isCoppa(){ return msIsCoppa; }
static void setCoppacs();
//==========================================================================
// WorkInfoアクセス用
static void setWorkInfo( WorkInfo& work_info );
static const WorkInfo& getWorkInfo(){ return msWorkInfo; }
static const WorkInfo* getWorkInfoPtr(){ return &msWorkInfo; }
//==========================================================================
// スライダーバーで使用する要素
static void setSlideWord( int i, int j, wchar_t w ){ msSlideStr[i][j] = w; }
static wchar_t* getSlideStr( int i ){ return msSlideStr[i]; }
static const wchar_t** getSlideFact(){ return mspSlideFact; }
//==========================================================================
// 現リージョンで存在する国数の取得
static u16 getCountryNum(){ return msCountryNum; }
//==========================================================================
private:
static void check_first_set_();
static void set_country_info_();
static void flush_net_setting_();
static void set_boss_send_info_task_();
static bool save_boss_send_info_();
static void prepare_boss_send_cfg_info_();
static void prepare_boss_send_net_info_();
static void prepare_boss_send_factory_cal_info_();
#ifndef NW_RELEASE
//二分探索するため、テーブルが昇順で並んでいることを確認する(Development用)。
//昇順であればtrue,そうでなければfalse。
static bool check_order_twl_user_info_font_table_();
#endif
//==========================================================================
static bool data_user_info_( int kind, int type ); // CFGデータLoad/Save
static bit32 get_cfg_key_( bit32 category, bit32 id )
{
return ( ( static_cast<bit32>( category ) << 16 ) | ( static_cast<bit32>( id ) ) );
}
//==========================================================================
static void set_first_boot_ac_();
//==========================================================================
static UserInfo msUserInfo;
static UserInfo msBackupUserInfo;
//==========================================================================
static TwlInfo msTwlInfo;
static TwlInfo msBackupTwlInfo;
static TwlInfo2 msTwlInfo2;
static TwlInfo2 msBackupTwlInfo2;
//==========================================================================
// 設定用ワーク
static WorkInfo msWorkInfo;
static WorkInfo msBackupWorkInfo;
//==========================================================================
static nn::cfg::CTR::ParentalControlInfo msParentInfo;
static nn::cfg::CTR::ParentalControlInfo msBackupParentInfo;
//==========================================================================
static nn::cfg::CTR::detail::CoppacsCfgData msCoppaInfo;
static nn::cfg::CTR::detail::CoppacsCfgData msBackupCoppaInfo;
//==========================================================================
static NetInfo msNetInfo;
static NetInfo msBackupNetInfo;
// インターネット設定用
static int msAccNum; // 接続先
static int msTmpNum; // 設定先
//==========================================================================
// BOSS 送信情報
static BossSendInfo msBossSendInfo;
//==========================================================================
// データ更新用
enum
{
eNoneInfo = 0,
eUserInfo = 0x01,
eTwlInfo = 0x02,
eTwlInfo2 = 0x04,
eNetInfo = 0x08,
eParentInfo = 0x10,
eNetInfo2 = 0x20,
eCoppaInfo = 0x40,
eWorkInfo = 0x80,
eAllInfo = 0xff
};
enum
{
eKindUserName = 0, // eUserInfo
eKindAddressId,
eKindAddressCountry,
eKindAddressRegion,
eKindAddressPosition,
eKindBirthday,
eKindLanguage,
eKindSound,
eKindEula, // eNetInfo2
eKindBoss,
eKindParental, // eParentInfo
eKindCoppa, // eCoppaInfo
eKindDsData, // eTwlInfo
eKindDsCountry, // eTwlInfo2
eKindDsParental,
eKindDsEula,
eKindFirst, // 別
eKindMax
};
static u32 msDirty; // セーブのためのフラグ
//==========================================================================
static nn::cfg::CTR::detail::FirstLaunchInfoCfgData msFirstInfo;
static FirstInfo msFirst;
static u16 msCountryNum; // 現リージョンでの国数
static u8* mpSharedAreaBuf;
static bool msIsNetSave;
static bool msIsCoppa;
//==========================================================================
// スライダーバーで使用する要素(全スライダーバー共通で使用)
enum
{
eFactNum = 100,
eStrSize = 64
};
static wchar_t msSlideStr[eFactNum][eStrSize];
static const wchar_t* mspSlideFact[eFactNum];
friend class ProcessManager;
};
}
#endif