AriA99 65b55f9d60
Dump cart ID2 properly in private header (#862)
* Add cart_id2 to gamecart.h

This prepares changes to fix private header dumps.

The name ID2 matches Lotus3 (see Switchbrew) since it's evident Lotus3 is just a continuation of the 3DS cart controller

* Add Cart_GetID2() to protocol.h

This prepares changes to fix private header dumps.

The name ID2 matches Lotus3 (see Switchbrew) since it's evident Lotus3 is just a continuation of the 3DS cart controller.

* gc protocol: Add support to get ID2

This renames the unknowna0_cmd to its proper name and the A0_Response to CartID2, matching Lotus3 terminology.

* Store ID2 in private header at +0x44

The ID2 contains important information that in particular determines the cryptographic keys used. It is impossible to decrypt a dump of cart<->controller communications without knowing the ID2 or trying all possible keys.

This behavior matches Gateway. I suppose that it was presumed that Gateway would always store zeroes there because regular cartridges on retail would always report zero and then everybody just copied this false assumption.

* fix build (gamecart.c): memset->memcpy

* fix build (protocol.c): Fix dupe definition of Cart_GetID()
2026-03-20 15:53:37 +01:00

45 lines
1.5 KiB
C

#pragma once
#include "common.h"
#include "card_spi.h"
#define CART_NONE 0
#define CART_CTR (1<<0)
#define CART_NTR (1<<1)
#define CART_TWL (1<<2)
#define MODC_AREA_SIZE 0x4000
#define PRIV_HDR_SIZE 0x50
typedef enum CardSaveType {
CARD_SAVE_NONE,
CARD_SAVE_SPI,
CARD_SAVE_CARD2,
CARD_SAVE_RETAIL_NAND,
} CardSaveType;
typedef struct {
u8 header[0x8000]; // NTR header + secure area / CTR header + private header
u8 storage[0x8000]; // encrypted secure area + modcrypt area / unused
u32 cart_type;
u32 cart_id;
u32 cart_id2; // crypto type, some special dev stuff, normally all-0 for retail
u64 cart_size;
u64 data_size;
u32 save_size;
CardSaveType save_type;
CardSPIType spi_save_type; // Specific data for SPI save
u32 arm9i_rom_offset; // TWL specific
} PACKED_ALIGN(16) CartData;
u32 GetCartName(char* name, CartData* cdata);
u32 GetCartInfoString(char* info, size_t info_size, CartData* cdata);
u32 SetSecureAreaEncryption(bool encrypted);
u32 InitCartRead(CartData* cdata);
u32 ReadCartSectors(void* buffer, u32 sector, u32 count, CartData* cdata, bool card2_blanking);
u32 ReadCartBytes(void* buffer, u64 offset, u64 count, CartData* cdata, bool card2_blanking);
u32 ReadCartPrivateHeader(void* buffer, u64 offset, u64 count, CartData* cdata);
u32 ReadCartInfo(u8* buffer, u64 offset, u64 count, CartData* cdata);
u32 ReadCartSave(u8* buffer, u64 offset, u64 count, CartData* cdata);
u32 WriteCartSave(const u8* buffer, u64 offset, u64 count, CartData* cdata);