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