PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
packet2_vif.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# (c) 2020 h4570 Sandro Sobczyński <sandro.sobczynski@gmail.com>
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include "packet2_vif.h"
12#include "packet2_chain.h"
13
14void packet2_vif_add_micro_program(packet2_t *packet2, u32 dest, u32 *start, u32 *end)
15{
16 // get the size of the code as we can only send 256 instructions in each MPGtag
17 u32 count = (end - start) / 2;
18 if (count & 1)
19 count++;
20
21 u32 *l_start = start;
22 while (count > 0)
23 {
24 u16 curr_count = count > 256 ? 256 : count;
25 packet2_chain_ref(packet2, l_start, curr_count / 2, 0, 0, 0);
26 packet2_vif_nop(packet2, 0);
27 packet2_vif_mpg(packet2, curr_count & 0xFF, dest, 0);
28 l_start += curr_count * 2;
29 count -= curr_count;
30 dest += curr_count;
31 }
32}
33
34u32 packet2_vif_close_unpack_auto(packet2_t *packet2, u32 wl, u32 cl)
35{
36 assert(packet2->vif_code_opened_at != NULL); // There is open UNPACK/DIRECT.
37 assert(((u32)packet2->next & 0x3) == 0); // Make sure we're u32 aligned
38 assert((packet2->vif_code_opened_at->cmd & 0x60) == 0x60); // It was UNPACK
39
40 u32 vn = (packet2->vif_code_opened_at->cmd & 0xC) >> 2;
41 u32 vl = packet2->vif_code_opened_at->cmd & 0x3;
42
43 // "the goal here is to find the num field of the open unpack, which is the number of
44 // qwords ACTUALLY WRITTEN to vu memory (it does not count quads that are skipped in
45 // "skipping write" mode.) But first forget about skipping/filling writes and compute the number
46 // of qwords that the data in this packet will expand to."
47 u32 bytes_count = (u32)packet2->next - (u32)packet2->vif_code_opened_at - 4;
48 u32 block_bytes_count = 4 >> vl;
49 u32 quad_blocks_count = vn + 1;
50
51 // "make sure that the data length is a multiple of 8, 16, or 32 bits, whichever is appropriate"
52 assert((bytes_count & (block_bytes_count - 1)) == 0);
53 u32 quads_count = (bytes_count / block_bytes_count) / quad_blocks_count;
54
55 // "We have the number of quads our data will directly expand to, so now we need to account for
56 // skipping/filling write modes.""
57
58 // "skipping write is easy -- we are already done"
59
60 // "filling write: now we get ambiguous -- what to do when quads_count == CL in the last
61 // block? I will say that in this case the vif should still do the full wl length block, filling
62 // with internal registers. If you want different behavior call packet2_vif_close_unpack_manual
63 // with a num field you've computed yourself"
64 if (cl < wl)
65 {
66 u32 wl_blocks_count = (quads_count / cl);
67 u32 last_block_quads = quads_count - wl_blocks_count * cl;
68 if (last_block_quads == cl)
69 last_block_quads = wl;
70 quads_count = wl_blocks_count * wl + last_block_quads;
71 }
72
73 packet2_vif_close_unpack_manual(packet2, quads_count);
74 return quads_count;
75}
static void packet2_chain_ref(packet2_t *packet2, const void *ref_data, u32 qw_length, u8 irq, u8 spr, u32 pce)
vif_code_t * vif_code_opened_at
qword_t * next
static void packet2_vif_close_unpack_manual(packet2_t *packet2, u32 unpack_num)
Definition packet2_vif.h:68
void packet2_vif_add_micro_program(packet2_t *packet2, u32 dest, u32 *start, u32 *end)
Definition packet2_vif.c:14
static void packet2_vif_nop(packet2_t *packet2, u8 irq)
static void packet2_vif_mpg(packet2_t *packet2, u32 num, u32 addr, u8 irq)
u32 packet2_vif_close_unpack_auto(packet2_t *packet2, u32 wl, u32 cl)
Definition packet2_vif.c:34
u32 count
start sector of fragmented bd/file