]> FriiDump Source - friidump.git/blob - tests/test_xbox_portable_metadata.c
FriiDump 0.5.3.16: finalize release identity and documentation
[friidump.git] / tests / test_xbox_portable_metadata.c
1 #include "xbox_portable.h"
2 #include "xbox_region.h"
3
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7
8 #define SECTOR_SIZE 2048U
9 #define MAX_SECTORS 512U
10
11 static unsigned char g_sectors[MAX_SECTORS][SECTOR_SIZE];
12 static unsigned char g_dmi[SECTOR_SIZE];
13
14 static void put_le16(unsigned char *p, unsigned int value)
15 {
16     p[0] = (unsigned char)(value & 0xffU);
17     p[1] = (unsigned char)((value >> 8) & 0xffU);
18 }
19
20 static void put_le32(unsigned char *p, unsigned long value)
21 {
22     p[0] = (unsigned char)(value & 0xffUL);
23     p[1] = (unsigned char)((value >> 8) & 0xffUL);
24     p[2] = (unsigned char)((value >> 16) & 0xffUL);
25     p[3] = (unsigned char)((value >> 24) & 0xffUL);
26 }
27
28 static int fake_read10(void *context,
29                        uint32_t lba,
30                        uint32_t sectors,
31                        unsigned char *buffer,
32                        size_t buffer_size)
33 {
34     uint32_t index;
35     (void)context;
36
37     if (!buffer || sectors == 0 || lba + sectors > MAX_SECTORS)
38         return -1;
39     if (buffer_size < (size_t)sectors * SECTOR_SIZE)
40         return -1;
41
42     for (index = 0; index < sectors; ++index)
43         memcpy(buffer + ((size_t)index * SECTOR_SIZE),
44                g_sectors[lba + index],
45                SECTOR_SIZE);
46     return 0;
47 }
48
49 static int fake_read_structure(void *context,
50                                uint8_t format,
51                                uint8_t layer,
52                                unsigned char *buffer,
53                                size_t buffer_size)
54 {
55     (void)context;
56     (void)layer;
57
58     if (format != 0x04U || !buffer || buffer_size < sizeof(g_dmi))
59         return -1;
60     memcpy(buffer, g_dmi, sizeof(g_dmi));
61     return 0;
62 }
63
64 static void require_true(int condition, const char *message)
65 {
66     if (!condition) {
67         fprintf(stderr, "FAIL: %s\n", message);
68         exit(1);
69     }
70     printf("PASS: %s\n", message);
71 }
72
73 static void write_utf16_title(unsigned char *certificate, const unsigned short *title)
74 {
75     size_t index;
76     for (index = 0; index < 40U && title[index] != 0; ++index)
77         put_le16(certificate + 0x00CU + (index * 2U), title[index]);
78 }
79
80 int main(void)
81 {
82     static const unsigned short title[] = {
83         'R','e','d',' ','F','a','c','t','i','o','n',0x00AE,' ','I','I',0
84     };
85     xbox_portable_metadata metadata;
86     unsigned char *volume;
87     unsigned char *root;
88     unsigned char *xbe;
89     unsigned char *certificate;
90
91     memset(g_sectors, 0, sizeof(g_sectors));
92     memset(g_dmi, 0, sizeof(g_dmi));
93
94     volume = g_sectors[32];
95     memcpy(volume, "MICROSOFT*XBOX*MEDIA", 20);
96     put_le32(volume + 0x14U, 100U);
97     put_le32(volume + 0x18U, SECTOR_SIZE);
98
99     root = g_sectors[100];
100     put_le16(root, 0U);
101     put_le16(root + 2U, 0U);
102     put_le32(root + 4U, 200U);
103     put_le32(root + 8U, 2314240U);
104     root[12U] = 0U;
105     root[13U] = 11U;
106     memcpy(root + 14U, "default.xbe", 11U);
107     root[28U] = 0U;
108
109     xbe = g_sectors[200];
110     put_le32(xbe, 0x48454258UL);
111     put_le32(xbe + 0x104U, 0x00010000UL);
112     put_le32(xbe + 0x118U, 0x00010800UL);
113
114     certificate = g_sectors[201];
115     put_le32(certificate + 0x008U, 0x54510005UL);
116     write_utf16_title(certificate, title);
117     put_le32(certificate + 0x09CU, 0x00000020UL);
118     put_le32(certificate + 0x0A0U, XB_REGION_US_CANADA);
119     put_le32(certificate + 0x0A4U, 0x00000001UL);
120     put_le32(certificate + 0x0A8U, 0U);
121     put_le32(certificate + 0x0ACU, 1U);
122
123     memcpy(g_dmi + 8U, "TQ00501A", 8U);
124
125     require_true(
126         xbox_portable_read_metadata(fake_read10,
127                                     fake_read_structure,
128                                     NULL,
129                                     &metadata) == 1,
130         "portable Xbox metadata parser accepts a valid XDFS/XBE fixture");
131     require_true(metadata.valid == 1,
132                  "portable Xbox metadata result is marked valid");
133     require_true(metadata.xdfs_volume_lba == 32U,
134                  "standard Xbox game-view XDFS volume LBA is retained");
135     require_true(strcmp(metadata.title, "Red Faction\xC2\xAE II") == 0,
136                  "UTF-16 XBE title is converted to UTF-8");
137     require_true(strcmp(metadata.media_id, "TQ00501A") == 0,
138                  "DMI media ID is retained");
139     require_true(metadata.title_id == 0x54510005UL,
140                  "XBE title ID is retained");
141     require_true(metadata.game_region == XB_REGION_US_CANADA,
142                  "raw XBE GameRegion mask is retained");
143     require_true(strcmp(metadata.region, "North America") == 0,
144                  "XBE GameRegion is formatted consistently");
145
146     printf("XBOX PORTABLE METADATA CONTRACT: PASS\n");
147     return 0;
148 }