PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
sim.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright 2001-2004, ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include <stdio.h>
12#include <sysclib.h>
13#include <hdd-ioctl.h>
14
15#include "libapa.h"
16#include "hdsk-devctl.h"
17#include "hdsk.h"
18#include "sim.h"
19
20extern u32 TotalCopied;
21extern struct hdskBitmap hdskBitmap[];
22
23void hdskSimGetFreeSectors(s32 device, struct hdskStat *stat, apa_device_t *deviceinfo)
24{
25 u32 sectors, partMax;
26 int i;
27
28 sectors = 0;
29 stat->free = 0;
30 for (i = 0; hdskBitmap[i].next != hdskBitmap; sectors += hdskBitmap[i].length, i++) {
31 if (hdskBitmap[i].type == 0) {
32 if ((0x001FFFFF < hdskBitmap[i].length) || ((stat->free & hdskBitmap[i].length) == 0)) {
33 stat->free += hdskBitmap[i].length;
34 }
35 sectors += hdskBitmap[i].length;
36 }
37 }
38
39 for (partMax = deviceinfo[device].partitionMaxSize; 0x0003FFFF < partMax; partMax = deviceinfo[device].partitionMaxSize) { // As weird as it looks, this was how it was done in the original HDD.IRX.
40 for (; 0x0003FFFF < partMax; partMax /= 2) {
41 // Non-SONY: Perform 64-bit arithmetic here to avoid overflows when dealing with large disks.
42 if ((sectors % partMax == 0) && ((u64)sectors + partMax < deviceinfo[device].totalLBA)) {
43 if ((0x001FFFFF < partMax) || (stat->free & partMax) == 0) {
44 stat->free += partMax;
45 }
46 sectors += partMax;
47 break;
48 }
49 }
50
51 if (0x0003FFFF >= partMax) {
52 break;
53 }
54 }
55
56 APA_PRINTF(APA_DRV_NAME ": total = %08lx sectors, installable = %08lx sectors.\n", sectors, stat->free);
57}
58
59static void hdskSimClearHeader(struct hdskBitmap *header)
60{
61 memset(header, 0, sizeof(struct hdskBitmap));
62}
63
64static struct hdskBitmap *hdskSimDeleteFixPrev(struct hdskBitmap *part)
65{
66 struct hdskBitmap *prev;
67 u32 length;
68
69 while (hdskBitmap[0].next != part) {
70 prev = part->prev;
71 if (prev->type == 0) {
72 length = prev->length + part->length;
73 if (prev->start % length != 0) {
74 break;
75 }
76
77 if ((length & (length - 1)) == 0) {
78 prev->length = length;
79 hdskSimClearHeader((struct hdskBitmap *)apaCacheUnLink((apa_cache_t *)part));
80 } else {
81 break;
82 }
83 } else {
84 break;
85 }
86
87 part = prev;
88 }
89
90 return part;
91}
92
93static struct hdskBitmap *hdskSimDeleteFixNext(struct hdskBitmap *part)
94{
95 struct hdskBitmap *next;
96 u32 length;
97
98 while (hdskBitmap[0].prev != part) {
99 next = part->next;
100 if (next->type == 0) {
101 length = next->length + part->length;
102 if (part->start % length != 0) {
103 break;
104 }
105
106 if ((length & (length - 1)) == 0) {
107 part->length = length;
108 part->type = 0;
109 hdskSimClearHeader((struct hdskBitmap *)apaCacheUnLink((apa_cache_t *)part));
110 } else {
111 break;
112 }
113 } else {
114 break;
115 }
116 }
117
118 return part;
119}
120
121static void hdskSimSwapPartition(struct hdskBitmap *start)
122{
123 u32 OrigStart, OrigLen;
124 struct hdskBitmap *part;
125
126 part = hdskBitmap[0].prev;
127 if (start == part) {
128 do {
129 hdskSimClearHeader((struct hdskBitmap *)apaCacheUnLink((apa_cache_t *)part));
130 part = hdskBitmap[0].prev;
131 if (part == NULL) {
132 break;
133 }
134 } while (part->type != 0);
135 } else {
136 int i;
137
138 OrigStart = start->start;
139 OrigLen = start->length;
140 for (i = 0; i < 2; i++) {
141 start = hdskSimDeleteFixNext(hdskSimDeleteFixPrev(start));
142 }
143
144 if (start->start == OrigStart && start->length == OrigLen) {
145 start->type = 0;
146 }
147 }
148}
149
150void hdskSimMovePartition(struct hdskBitmap *dest, struct hdskBitmap *start)
151{
152 APA_PRINTF("MovePartition: %08lx to %08lx. sector count = %08lx.\n", start->start, dest->start, start->length);
153
154 TotalCopied += start->length;
155 APA_PRINTF("swap partition start...");
156
157 dest->type = start->type;
158 hdskSimSwapPartition(start);
159
160 printf("done\n");
161 APA_PRINTF("MovePartition: done\n");
162}
163
164struct hdskBitmap *hdskSimFindEmptyPartition(u32 size)
165{
166 struct hdskBitmap *part;
167
168 for (part = hdskBitmap; part->next != hdskBitmap; part = part->next) {
169 if (part->length == size && part->type == 0) {
170 APA_PRINTF("sim: found empty partition at %08lx, size %08lx.\n", part->start, part->length);
171 return part;
172 }
173 }
174
175 return NULL;
176}
177
178static int hdskCheckIfPrevPartEmpty(struct hdskBitmap *part, u32 size)
179{
180 return ((part->prev->length == size) && (part->prev->type == 0));
181}
182
183static int hdskCheckIfNextPartEmpty(struct hdskBitmap *part, u32 size)
184{
185 return ((part->next->length == size) && (part->next->type == 0));
186}
187
188struct hdskBitmap *hdskSimFindLastUsedPartition(u32 size, u32 start, int mode)
189{
190 u32 SliceSize;
191 struct hdskBitmap *part;
192
193 SliceSize = size * 2;
194 for (part = hdskBitmap[0].prev; start < part->start && part != hdskBitmap; part = part->prev) {
195 if (part->length == size && part->type != 0) {
196 if (mode != 0) {
197 if (part->start % SliceSize != 0) {
198 if (hdskCheckIfPrevPartEmpty(part, size) != 0) {
199 return part;
200 }
201 } else {
202 if (part == hdskBitmap[0].prev || hdskCheckIfNextPartEmpty(part, size) != 0) {
203 return part;
204 }
205 }
206 } else {
207 return part;
208 }
209 }
210 }
211
212 return NULL;
213}
214
215static int hdskCheckIsLastPart(struct hdskBitmap *part, u32 size, int mode)
216{
217 struct hdskBitmap *CurrPart;
218 u32 PartSize;
219
220 for (CurrPart = part, PartSize = part->length; (PartSize < size) && (CurrPart != hdskBitmap); PartSize += CurrPart->length) {
221 CurrPart = CurrPart->next;
222 if (CurrPart->type == 0) {
223 break;
224 }
225 }
226
227 if (PartSize == size) {
228 if (mode != 0) {
229 if (part->start % (size * 2) != 0) {
230 return (hdskCheckIfPrevPartEmpty(part, size) == 0 ? 0 : 1);
231 } else {
232 return (CurrPart != hdskBitmap[0].prev ? (hdskCheckIfNextPartEmpty(CurrPart, size) != 0) : 1);
233 }
234 } else {
235 return 1;
236 }
237 }
238
239 return 0;
240}
241
242struct hdskBitmap *hdskSimFindLastUsedBlock(u32 size, u32 start, int mode)
243{
244 struct hdskBitmap *part;
245
246 for (part = hdskBitmap[0].prev; start < part->start && part != hdskBitmap; part = part->prev) {
247 if ((part->start % size == 0) && (part->length < size) && (part->type != 0)) {
248 if (hdskCheckIsLastPart(part, size, mode) != 0) {
249 return part;
250 }
251 }
252 }
253
254 return NULL;
255}
256
257static struct hdskBitmap *hdskBitmapAlloc(void)
258{
259 struct hdskBitmap *part;
260 unsigned int i;
261
262 for (part = &hdskBitmap[1], i = 1; i < HDSK_BITMAP_SIZE; i++, part++) {
263 if (part->length == 0) {
264 return part;
265 }
266 }
267
268 return NULL;
269}
270
271static void hdskSimSplitEmptyPartition(struct hdskBitmap *part, u32 length)
272{
273 APA_PRINTF("split empty partition.\n");
274 while (part->length != length) {
275 struct hdskBitmap *end;
276
277 end = hdskBitmapAlloc();
278 part->length /= 2;
279 end->start = part->start + part->length;
280 end->type = 0;
281 end->length = part->length;
282 apaCacheLink((apa_cache_t *)part, (apa_cache_t *)end);
283 }
284}
285
286void hdskSimMovePartitionsBlock(struct hdskBitmap *dest, struct hdskBitmap *src)
287{
288 u32 size;
289
290 size = dest->length;
291 APA_PRINTF("MovePartitionsBlock: %08lx to %08lx. sector count = %08lx.\n", src->start, dest->start, dest->length);
292 do {
293 hdskSimSplitEmptyPartition(dest, src->length);
294 if (src->next == hdskBitmap) {
295 break;
296 }
297
298 hdskSimMovePartition(dest, src);
299 dest = dest->next;
300 size -= dest->length;
301 if (size == 0) {
302 break;
303 }
304
305 src = src->next;
306 } while (dest != hdskBitmap);
307
308 APA_PRINTF("MovePartitionsBlock: done\n");
309}