summaryrefslogtreecommitdiff
path: root/src/Dolphin/card/CARDFormat.c
blob: ebfff8ba3fedf162365e2835fc19888737c3260e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include <dolphin/card.h>
#include <dolphin/dsp.h>
#include <dolphin/dvd.h>
#include <dolphin/os.h>

#include <dolphin/CARDPriv.h>
#include <dolphin/OSRtcPriv.h>
#include <dolphin/vi.h>

static void FormatCallback(s32 chan, s32 result) {
  CARDControl* card;
  CARDCallback callback;

  card = &__CARDBlock[chan];
  if (result < 0) {
    goto error;
  }

  ++card->formatStep;
  if (card->formatStep < CARD_NUM_SYSTEM_BLOCK) {
    result = __CARDEraseSector(chan, (u32)card->sectorSize * card->formatStep, FormatCallback);
    if (0 <= result) {
      return;
    }
  } else if (card->formatStep < 2 * CARD_NUM_SYSTEM_BLOCK) {
    int step = card->formatStep - CARD_NUM_SYSTEM_BLOCK;
    result = __CARDWrite(chan, (u32)card->sectorSize * step, CARD_SYSTEM_BLOCK_SIZE,
                         (u8*)card->workArea + (CARD_SYSTEM_BLOCK_SIZE * step), FormatCallback);
    if (result >= 0) {
      return;
    }
  } else {
    card->currentDir = (CARDDir*)((u8*)card->workArea + (1 + 0) * CARD_SYSTEM_BLOCK_SIZE);
    memcpy(card->currentDir, (u8*)card->workArea + (1 + 1) * CARD_SYSTEM_BLOCK_SIZE,
           CARD_SYSTEM_BLOCK_SIZE);
    card->currentFat = (u16*)((u8*)card->workArea + (3 + 0) * CARD_SYSTEM_BLOCK_SIZE);
    memcpy(card->currentFat, (u8*)card->workArea + (3 + 1) * CARD_SYSTEM_BLOCK_SIZE,
           CARD_SYSTEM_BLOCK_SIZE);
  }

error:
  callback = card->apiCallback;
  card->apiCallback = 0;
  __CARDPutControlBlock(card, result);
  callback(chan, result);
}

s32 __CARDFormatRegionAsync(s32 chan, u16 encode, CARDCallback callback) {
  CARDControl* card;
  CARDID* id;
  CARDDir* dir;
  u16* fat;
  s16 i;
  s32 result;
  OSSram* sram;
  OSSramEx* sramEx;
  u16 viDTVStatus;
  OSTime time;
  OSTime rand;

  result = __CARDGetControlBlock(chan, &card);
  if (result < 0) {
    return result;
  }

  id = (CARDID*)card->workArea;
  memset(id, 0xff, CARD_SYSTEM_BLOCK_SIZE);
  viDTVStatus = __VIRegs[55];

  id->encode = encode;

  sram = __OSLockSram();
  *(u32*)&id->serial[20] = sram->counterBias;
  *(u32*)&id->serial[24] = sram->language;
  __OSUnlockSram(FALSE);

  rand = time = OSGetTime();

  sramEx = __OSLockSramEx();
  for (i = 0; i < 12; i++) {
    rand = (rand * 1103515245 + 12345) >> 16;
    id->serial[i] = (u8)(sramEx->flashID[chan][i] + rand);
    rand = ((rand * 1103515245 + 12345) >> 16) & 0x7FFF;
  }
  __OSUnlockSramEx(FALSE);

  *(u32*)&id->serial[28] = viDTVStatus;
  *(OSTime*)&id->serial[12] = time;

  id->deviceID = 0;
  id->size = card->size;
  __CARDCheckSum(id, sizeof(CARDID) - sizeof(u32), &id->checkSum, &id->checkSumInv);

  for (i = 0; i < 2; i++) {
    CARDDirCheck* check;

    dir = (CARDDir*)((u8*)card->workArea + (1 + i) * CARD_SYSTEM_BLOCK_SIZE);
    memset(dir, 0xff, CARD_SYSTEM_BLOCK_SIZE);
    check = __CARDGetDirCheck(dir);
    check->checkCode = i;
    __CARDCheckSum(dir, CARD_SYSTEM_BLOCK_SIZE - sizeof(u32), &check->checkSum,
                   &check->checkSumInv);
  }
  for (i = 0; i < 2; i++) {
    fat = (u16*)((u8*)card->workArea + (3 + i) * CARD_SYSTEM_BLOCK_SIZE);
    memset(fat, 0x00, CARD_SYSTEM_BLOCK_SIZE);
    fat[CARD_FAT_CHECKCODE] = (u16)i;
    fat[CARD_FAT_FREEBLOCKS] = (u16)(card->cBlock - CARD_NUM_SYSTEM_BLOCK);
    fat[CARD_FAT_LASTSLOT] = CARD_NUM_SYSTEM_BLOCK - 1;
    __CARDCheckSum(&fat[CARD_FAT_CHECKCODE], CARD_SYSTEM_BLOCK_SIZE - sizeof(u32),
                   &fat[CARD_FAT_CHECKSUM], &fat[CARD_FAT_CHECKSUMINV]);
  }

  card->apiCallback = callback ? callback : __CARDDefaultApiCallback;
  DCStoreRange(card->workArea, CARD_WORKAREA_SIZE);

  card->formatStep = 0;
  result = __CARDEraseSector(chan, (u32)card->sectorSize * card->formatStep, FormatCallback);
  if (result < 0) {
    __CARDPutControlBlock(card, result);
  }
  return result;
}

s32 CARDFormatAsync(s32 chan, CARDCallback callback) {
  return __CARDFormatRegionAsync(chan, __CARDGetFontEncode(), callback);
}