ps2sdk  1.1
A collection of Open Source libraries used for developing applications on Sony's PlayStation 2® (PS2).
packet2_vif.c
Go to the documentation of this file.
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 
14 void 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 
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)
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)
Definition: packet2_vif.h:135
static void packet2_vif_mpg(packet2_t *packet2, u32 num, u32 addr, u8 irq)
Definition: packet2_vif.h:167
u32 packet2_vif_close_unpack_auto(packet2_t *packet2, u32 wl, u32 cl)
Definition: packet2_vif.c:34
vif_code_t * vif_code_opened_at
qword_t * next
#define NULL
Definition: tamtypes.h:91
unsigned int u32
Definition: tamtypes.h:30
unsigned short u16
Definition: tamtypes.h:24