Digimon World 3 decomp
The European version, SLES_039.36
Loading...
Searching...
No Matches
map_streamer.c
Go to the documentation of this file.
1/* The task that streams the map's tiles from the CD around the view and
2 draws them, and the cover that fades the screen */
3
4#include "field/field_mode.h"
5
6/* The stream task drawn or loaded the longest ago */
8 s32 i;
9 s32 oldest = GFX.funcs.getTime();
10 StreamTask *found = pool->tasks[0];
11
12 for (i = 0; i < 30; i++) {
13 if (pool->tasks[i]->time <= oldest) {
14 oldest = pool->tasks[i]->time;
15 found = pool->tasks[i];
16 }
17 }
18 return found;
19}
20
21/*
22 * Streams the map's tiles while the CD reader is free: a tile of viewTiles
23 * (0xFF for none) that a stream task has loaded is done, and each tile still
24 * waiting goes to the oldest task (FIELDSTG_findOldestStream), until the reader is busy.
25 * The match depends on each loop having a counter of its own.
26 */
28 s32 i;
29 s32 j;
30 s32 k;
31 s32 frame;
32 s32 tile;
33 StreamTask *task;
34
35 if (CD_READER.isBusy() == 0) {
36 for (i = 0; i < 30; i++) {
37 task = pool->tasks[i];
38 frame = task->getFrame(task);
39 for (j = 0; j < 30; j++) {
40 if (map->viewTiles[j] != 0xFF && map->viewTiles[j] == frame) {
41 map->viewTiles[j] = 0xFF;
42 task->updateTime(task);
43 break;
44 }
45 }
46 }
47 for (k = 0; k < 30; k++) {
48 if (map->viewTiles[k] != 0xFF) {
49 tile = map->viewTiles[k];
50 if (map->tiles[tile].size != 0) {
51 task = FIELDSTG_findOldestStream(pool);
52 if (task->isLoaded(task)) {
53 task->seek(task, tile, map->tiles[tile].sectors);
54 }
55 }
56 if (CD_READER.isBusy()) {
57 break;
58 }
59 }
60 }
61 }
62}
63
64/* Draws a 128-pixel block of the cover at (x, y), at a shade of level (8.8) */
65void FIELDSTG_drawCoverBlock(Layer *layer, s32 x, s32 y, s32 level) {
66 Vec2 scroll;
67 PrimPtr prim;
68 u_long *ot;
69 s32 i;
70 s32 shade;
71
72 ot = layer->getOtEntry(layer, 0);
73 shade = level >> 8;
74 layer->getScroll(layer, &scroll);
75 prim.any = GFX.funcs.getPrim();
76 for (i = 0; i < 4; i++) {
77 SetSprt(prim.sprt);
78 if (shade != 0xFF) {
79 SetSemiTrans(prim.sprt, 1);
80 }
81 prim.sprt->r0 = prim.sprt->g0 = prim.sprt->b0 = shade;
82 prim.sprt->x0 = x - scroll.x + ((i & 1) << 6);
83 prim.sprt->y0 = y - scroll.y + ((i << 5) & 0x40);
84 prim.sprt->u0 = FIELDSTG_state.images.field->u;
85 prim.sprt->v0 = FIELDSTG_state.images.field->v;
86 prim.sprt->w = 0x40;
87 prim.sprt->h = 0x40;
89 addPrim(ot, prim.any);
90 prim.sprt++;
91 SetDrawTPage(prim.tpage, 0, 1, GetTPage(0, 1, FIELDSTG_state.images.field->x, FIELDSTG_state.images.field->y));
92 addPrim(ot, prim.any);
93 prim.tpage++;
94 }
95 GFX.funcs.setPrim(prim.any);
96}
97
98/* The stream task that holds a frame (a tile of the map), or NULL */
100 s32 i;
101 StreamTask *task;
102
103 for (i = 0; i < 30; i++) {
104 task = pool->tasks[i];
105 if (task->getFrame(task) == frame) {
106 return task;
107 }
108 }
109 return NULL;
110}
111
112/* A tile of the map in view (FIELDSTG_drawMapTiles) */
113typedef struct MapSlot {
114 /* 0x00 */ s16 loaded; /* a StreamTask has its frame */
115 /* 0x02 */ s16 tile;
116 /* 0x04 */ StreamTask *stream;
117 /* 0x08 */ s32 entry; /* into MapStreamer.images, or -1 */
118 /* 0x0C */ s32 frame;
119 /* 0x10 */ s32 x;
120 /* 0x14 */ s32 y;
121} MapSlot;
122
123/* Draws the map's tiles in view, under a cover that fades from the new ones,
124 and while the decompressor is free, gives the first loaded tile without an
125 entry the oldest of the 12 */
127 Vec2 tile;
128 MapSlot slots[12];
129 Layer *layer;
130 StreamTask *stream;
131 s32 count;
132 s32 r;
133 s32 c;
134 s32 i;
135 s32 j;
136 s32 frame;
137 s32 level;
138 s32 oldest;
139 s32 best;
140
142 count = 0;
143 tile.x = task->scroll.x >= 0x20 ? (task->scroll.x - 0x20) / 128 : 0;
144 tile.y = task->scroll.y >= 8 ? (task->scroll.y - 8) / 128 : 0;
145 for (r = 0; r < 3; r++) {
146 if (r + tile.y >= task->height) {
147 break;
148 }
149 for (c = 0; c < 4; c++) {
150 if (c + tile.x >= task->width) {
151 break;
152 }
153 frame = c + tile.x + (r + tile.y) * task->width;
154 stream = FIELDSTG_findStream(pool, frame);
155 slots[count].tile = task->tiles[frame].size;
156 if (stream != NULL) {
157 slots[count].stream = stream;
158 slots[count].frame = frame;
159 slots[count].entry = stream->getSlot(stream);
160 slots[count].loaded = 1;
161 } else {
162 slots[count].loaded = 0;
163 }
164 slots[count].x = (c + tile.x) * 128;
165 slots[count].y = (r + tile.y) * 128;
166 count++;
167 }
168 }
169 for (i = 0; i < count; i++) {
170 if (slots[i].loaded && slots[i].entry != -1) {
171 level = task->images[slots[i].entry].cover;
172 if (level != 0) {
173 if (level == 0xFFFF && slots[i].stream->loadedTime < GFX.funcs.getTime() - 10) {
174 task->images[slots[i].entry].cover = 0;
175 } else {
176 FIELDSTG_drawCoverBlock(layer, slots[i].x, slots[i].y, level);
177 level -= 0x2AAA;
178 if (level <= 0) {
179 level = 0;
180 }
181 task->images[slots[i].entry].cover = level;
182 }
183 }
184 slots[i].stream->draw(slots[i].stream, layer, slots[i].x, slots[i].y);
185 task->images[slots[i].entry].time = GFX.funcs.getTime();
186 } else if (slots[i].tile != 0) {
187 FIELDSTG_drawCoverBlock(layer, slots[i].x, slots[i].y, 0xFFFF);
188 }
189 }
190 if (pool->decompressor->substate == 0) {
191 for (i = 0; i < count; i++) {
192 if (slots[i].loaded && slots[i].entry == -1 && slots[i].stream->isLoaded(slots[i].stream)) {
193 best = 0;
194 oldest = GFX.funcs.getTime();
195 for (j = 0; j < 12; j++) {
196 if (task->images[j].time < oldest) {
197 oldest = task->images[j].time;
198 best = j;
199 }
200 }
201 slots[i].stream->setSource(slots[i].stream, best, pool->decompressor);
202 if (task->images[best].frame != -1) {
203 stream = FIELDSTG_findStream(pool, task->images[best].frame);
204 if (stream != NULL) {
205 stream->clearSlot(stream);
206 }
207 }
208 task->images[best].frame = slots[i].frame;
209 task->images[best].time = GFX.funcs.getTime();
210 task->images[best].cover = 0xFFFF;
211 return;
212 }
213 }
214 }
215}
216
217/*
218 * Points the slots around the view at the map's tiles: viewTiles gets, for each
219 * of the 30 slots, the index of the tile it shows (0xFF off the map), and
220 * viewX/viewY the tile of the slots' top left corner. The slots come from
221 * the layout for the leader's direction, flipped as that direction says, and
222 * for the quadrant of its tile the view is in. The match depends on the y
223 * offset being written as scrollY less its tile's start: its two reads of
224 * scrollY rank that load ahead of the x test in local-alloc. It also depends
225 * on x holding the horizontal flip before it becomes the tile column, and on
226 * col counting the slots the first loop clears.
227 */
229 u8 slots[5][6];
230 s32 quadrant;
231 s32 set;
232 u32 flip;
233 s32 row;
234 s32 col;
235 s32 r;
236 s32 c;
237 s32 x;
238 s32 y;
239 s32 flipY;
240 Actor *leader;
241 s32 scrollY;
242 s32 offset;
243
244 leader = TASK_REGISTRY.funcs.find(FIELD_TASK_ACTOR, -1, 0);
245 offset = task->scroll.x & 0x7F;
246 quadrant = offset > 0x40;
247 set = FIELDSTG_dirLayouts[leader->dir][0];
248 flip = FIELDSTG_dirLayouts[leader->dir][1];
249 scrollY = task->scroll.y;
250 offset = scrollY - (scrollY & ~0x7F);
251 if (offset > 0x10) {
252 quadrant |= 2;
253 }
254 for (row = 0; row < 5; row++) {
255 for (col = 0; col < 6; col++) {
256 if (flip & 2) {
257 c = 5 - col;
258 } else {
259 c = col;
260 }
261 if (flip & 1) {
262 r = 4 - row;
263 } else {
264 r = row;
265 }
266 slots[row][col] = FIELDSTG_slotLayouts[set][quadrant][r][c];
267 }
268 }
269 x = flip >> 1;
270 x &= 1;
271 flipY = flip & 1;
272 task->viewX = task->scroll.x / 128 - FIELDSTG_slotOffsets[quadrant][0][x];
273 task->viewY = task->scroll.y / 128 - FIELDSTG_slotOffsets[quadrant][1][flipY];
274 for (col = 0; col < 30; col++) {
275 task->viewTiles[col] = 0xFF;
276 }
277 for (row = 0; row < 5; row++) {
278 y = row + task->viewY;
279 if (y >= 0 && y < task->height) {
280 for (col = 0; col < 6; col++) {
281 x = col + task->viewX;
282 if (x >= 0 && x < task->width) {
283 task->viewTiles[slots[row][col]] = x + y * task->width;
284 }
285 }
286 }
287 }
288}
289
290/* The map streamer's update: reads the map's header and creates the 30
291 stream tasks, then each frame points the slots at the tiles in view, draws
292 them and streams the missing ones */
294 MapFileHeader *header;
295 s32 count;
296 s32 i;
297 s32 j;
298 Layer *layer;
299
300 switch (task->state) {
301 case TASK_INIT:
302 default:
303 switch (task->substate) {
304 case 0:
305 default:
306 if (CD_READER.isBusy() == 0) {
307 task->header = HEAP.alloc(0x800, 2);
308 CD_READER.read(task->file, 0, 1, task->header, NULL);
309 task->nextSubstate(task);
310 }
311 break;
312 case 1:
313 if (CD_READER.isBusy() != 1) {
314 header = task->header;
315 task->width = header->width;
316 task->height = header->height;
317 task->frameSectors = header->tileBytes / 2048;
318 count = task->width * task->height;
319 task->tiles = HEAP.alloc(count * sizeof(MapTile), 2);
320 for (j = 0; j < count; j++) {
321 task->tiles[j].size = header->tileSizes[j];
322 task->tiles[j].sectors = header->tileSizes[j] >> 11;
323 }
324 HEAP.free(task->header);
325 task->header = NULL;
326 for (i = 0; i < 30; i++) {
327 pool->tasks[i] = FIELDSTG_createStream(task->frameSectors << 11, task->file);
328 }
329 for (i = 0; i < 12; i++) {
330 task->images[i].frame = -1;
331 task->images[i].time = 0;
332 }
334 task->nextState(task);
335 }
336 break;
337 }
338 break;
339 case TASK_RUN:
341 layer->getScroll(layer, &task->scroll);
343 FIELDSTG_drawMapTiles(task, pool);
344 FIELDSTG_requestTiles(task, pool);
345 break;
346 case TASK_DONE:
347 break;
348 case TASK_KILL:
349 if (task->header != NULL) {
350 HEAP.free(task->header);
351 }
352 if (task->tiles != NULL) {
353 HEAP.free(task->tiles);
354 }
355 break;
356 }
357}
358
359/* The map's size in pixels */
361 FIELDSTG_mapSize.x = task->width << 7;
362 FIELDSTG_mapSize.y = task->height << 7;
363 return &FIELDSTG_mapSize;
364}
365
366/* Creates the map streamer of a file */
369
370 task->file = file;
372 return task;
373}
374
375/* Covers the screen on the layer id at a shade of level (8.8) */
376void FIELDSTG_drawCover(s32 id, s32 level) {
377 Layer *layer = GFX.funcs.getLayer(id);
378 s32 x;
379 s32 y;
380
381 if (layer != NULL) {
382 for (y = 0; y < SCREEN_HEIGHT; y += 0x80) {
383 for (x = 0; x < SCREEN_WIDTH; x += 0x80) {
384 FIELDSTG_drawCoverBlock(layer, x, y, level);
385 }
386 }
387 }
388}
CdReader CD_READER
The CD reader.
Definition cd_reader.c:10
#define NULL
Definition common.h:17
signed int s32
Definition common.h:11
unsigned int u32
Definition common.h:12
signed short s16
Definition common.h:9
unsigned char u8
Definition common.h:8
Decompressor * createDecompressor(void)
A decompressor task.
GfxState GFX
GFX: the graphics state and its methods.
Definition display.c:209
#define TASK_RUN
Definition task.h:35
#define TASK_KILL
Definition task.h:37
#define TASK_INIT
Tasks: every game object is a task, a heap block that starts with this header and is updated once per...
Definition task.h:34
#define TASK_DONE
Definition task.h:36
#define FIELD_TASK_MAP
The ids of the field's tasks (createTaskWithId, TASK_REGISTRY.funcs.find)
Definition field_map.h:25
#define FIELD_LAYER_MAP
the map, its objects and characters, and the menus
Definition field_map.h:20
#define FIELD_TASK_ACTOR
every character (FIELDSTG_createActor)
Definition field_map.h:26
FIELDSTG.PRO: the field mode, where the player walks around the map.
u8 FIELDSTG_slotOffsets[][2][2]
the slots' offset in tiles: [quadrant][x, y][unflipped, flipped]
Definition fieldstg.c:1496
Vec2 FIELDSTG_mapSize
FIELDSTG_getMapSize's.
Definition fieldstg.c:3755
u8 FIELDSTG_dirLayouts[][2]
the layout and its flips for each direction
Definition fieldstg.c:1492
FieldState FIELDSTG_state
Definition fieldstg.c:2641
u8 FIELDSTG_slotLayouts[][4][5][6]
FIELDSTG_pickViewTiles's slot layouts: [layout][quadrant][row][column].
Definition fieldstg.c:1400
#define SCREEN_WIDTH
The screen the modes draw on (setDisplayMode, their layers' rects)
Definition gfx.h:36
#define SCREEN_HEIGHT
Definition gfx.h:37
Heap HEAP
The functions that return what a call left in v0 (allocMemHigh, findTask) and the ones that take othe...
Definition heap.c:184
void FIELDSTG_runMapStreamer(MapStreamer *task, StreamPool *pool)
The map streamer's update: reads the map's header and creates the 30 stream tasks,...
void FIELDSTG_drawCoverBlock(Layer *layer, s32 x, s32 y, s32 level)
Draws a 128-pixel block of the cover at (x, y), at a shade of level (8.8)
StreamTask * FIELDSTG_findOldestStream(StreamPool *pool)
The stream task drawn or loaded the longest ago.
Definition map_streamer.c:7
StreamTask * FIELDSTG_findStream(StreamPool *pool, s32 frame)
The stream task that holds a frame (a tile of the map), or NULL.
Vec2 * FIELDSTG_getMapSize(MapStreamer *task)
The map's size in pixels.
MapStreamer * FIELDSTG_createMapStreamer(s32 file)
Creates the map streamer of a file.
void FIELDSTG_requestTiles(MapStreamer *map, StreamPool *pool)
Streams the map's tiles while the CD reader is free: a tile of viewTiles (0xFF for none) that a strea...
void FIELDSTG_drawMapTiles(MapStreamer *task, StreamPool *pool)
Draws the map's tiles in view, under a cover that fades from the new ones, and while the decompressor...
void FIELDSTG_pickViewTiles(MapStreamer *task)
Points the slots around the view at the map's tiles: viewTiles gets, for each of the 30 slots,...
void FIELDSTG_drawCover(s32 id, s32 level)
Covers the screen on the layer id at a shade of level (8.8)
TaskRegistry TASK_REGISTRY
Definition registry.c:122
StreamTask * FIELDSTG_createStream(s32 size, s32 file)
Creates a stream task of a file, with a buffer of size.
Definition stream.c:168
A character on the field (FIELDSTG_createActor): the player (kind 0) and the other characters.
Definition field_map.h:334
s32 dir
Definition field_map.h:338
void(* read)(s32 file, s32 offset, s32 size, void *buf, s32 *done)
Definition file.h:64
s32(* isBusy)(void)
Definition file.h:63
s32 substate
Definition file.h:111
s16 x
in VRAM
Definition field_map.h:129
union FieldState::@12 images
FieldImage * field
the field's image (the first two ActorImages)
Definition field_map.h:453
void *(* getPrim)(void)
Definition gfx.h:19
struct Layer *(* getLayer)(s32 id)
Definition gfx.h:28
void(* setPrim)(void *next)
Definition gfx.h:20
s32(* getTime)(void)
Definition gfx.h:31
GfxFuncs funcs
Definition gfx.h:77
void *(* alloc)(s32 size, s32 tag)
Definition heap.h:29
void(* free)(void *ptr)
Definition heap.h:27
A drawing layer (GFX.funcs.createLayer): a DRAWENV with a pair of ordering tables,...
Definition gfx.h:128
void(* getScroll)()
Definition gfx.h:148
u_long *(* getOtEntry)(struct Layer *, s32 depth)
Definition gfx.h:155
The first sector of a map's tile file (MapStreamer.header)
Definition field_mode.h:462
s32 width
in 128-pixel tiles
Definition field_mode.h:464
s32 tileBytes
the room of a tile on the CD
Definition field_mode.h:466
u16 tileSizes[0]
width * height: each tile's bytes, 0 for none
Definition field_mode.h:467
s32 time
when it was last drawn
Definition field_mode.h:479
s32 cover
the level of the cover over a new tile (8.8), 0 for none
Definition field_mode.h:480
s32 frame
the tile it holds, or -1
Definition field_mode.h:478
A tile of the map in view (FIELDSTG_drawMapTiles)
StreamTask * stream
s32 entry
into MapStreamer.images, or -1
s16 loaded
a StreamTask has its frame
The task that streams the map's tiles from the CD around the view (FIELDSTG_runMapStreamer,...
Definition field_mode.h:487
s32 viewX
the tile column of the slots' left edge
Definition field_mode.h:500
s32 frameSectors
a tile's sectors on the CD
Definition field_mode.h:496
MapTile * tiles
width * height
Definition field_mode.h:498
Vec2 *(* getSize)(struct MapStreamer *)
in pixels (FIELDSTG_getMapSize)
Definition field_mode.h:502
s32 viewY
their top row
Definition field_mode.h:501
void(* nextState)(struct MapStreamer *task)
Definition field_mode.h:488
void(* nextSubstate)(struct MapStreamer *task)
Definition field_mode.h:488
MapFileHeader * header
the map file's, while it is read
Definition field_mode.h:490
s32 width
in 128-pixel tiles
Definition field_mode.h:494
s32 file
the map's tiles, read from the CD (FieldState.mapFile)
Definition field_mode.h:493
u8 viewTiles[30]
by the slots around the view, their tiles
Definition field_mode.h:499
MapImage images[12]
Definition field_mode.h:497
A tile of the map that MapStreamer streams.
Definition field_mode.h:471
s32 size
its bytes on the CD, 0 for none
Definition field_mode.h:472
s32 sectors
what it reads (StreamTask.seek)
Definition field_mode.h:473
The StreamTasks of a task's children (FIELDSTG_requestTiles)
Definition field_mode.h:454
Decompressor * decompressor
Definition field_mode.h:455
StreamTask * tasks[30]
Definition field_mode.h:456
A task that reads the frames of a file from the disc (FIELDSTG_createStream)
Definition field_mode.h:424
s32(* getFrame)(struct StreamTask *task)
Definition field_mode.h:447
s32(* getSlot)(struct StreamTask *task)
Definition field_mode.h:448
void(* seek)(struct StreamTask *task, s32 frame, s32 size)
Definition field_mode.h:443
void(* setSource)(struct StreamTask *task, s32 slot, Decompressor *source)
Definition field_mode.h:446
void(* updateTime)(struct StreamTask *task)
Definition field_mode.h:450
void(* draw)(struct StreamTask *task, Layer *layer, s32 x, s32 y)
Definition field_mode.h:445
s32(* isLoaded)(struct StreamTask *task)
Definition field_mode.h:444
s32 loadedTime
when its read ended, 0 while reading
Definition field_mode.h:427
void *(* find)(s32 id, s32 key1, s32 key2)
Definition task.h:18
TaskFuncs funcs
Definition task.h:76
Definition gfx.h:352
s32 y
Definition gfx.h:354
s32 x
Definition gfx.h:353
void * createTaskWithId(void(*update)(), s32 size, s32 childrenSize, s32 id)
Allocates a zeroed task of size bytes (header included) with room for childrenSize / 4 child tasks.
Definition task.c:80
The next free primitive of the packet buffer (getPrim), written as the kind that is drawn next.
Definition gfx.h:344
DR_TPAGE * tpage
Definition gfx.h:349
void * any
Definition gfx.h:345
SPRT * sprt
Definition gfx.h:346