Skip to content

DMA beta

Seção nova, escrita à mão - veja a nota na folha de referência.

O Direct Memory Access (DMA) move blocos de dados entre a RAM principal e os outros componentes do PS2 sem a EE copiá-los à mão. Como o GS, a VU1, e o IOP (via SIF) são todos destinos separados fora da própria memória da EE, o DMA é como os dados realmente chegam a qualquer um deles em um programa real - não é uma otimização que você adiciona depois.

Dez canais, um trabalho cada um

A lista real e embutida de canais deste SDK (ee/dma/include/dma.h):

CanalValorDireção
DMA_CHANNEL_VIF00EE → VU0
DMA_CHANNEL_VIF11EE → VU1
DMA_CHANNEL_GIF2EE (ou VU1) → GS
DMA_CHANNEL_fromIPU / DMA_CHANNEL_toIPU3 / 4A Image Processing Unit - a IPU é o que realmente faz o trabalho de decodificação MPEG2 que core/mpeg envolve (veja a folha de referência)
DMA_CHANNEL_fromSIF0 / DMA_CHANNEL_toSIF15 / 6EE ↔ IOP (veja EE, IOP e SIF)
DMA_CHANNEL_SIF27Um segundo caminho EE↔IOP separado (usado com menos frequência que SIF0/1)
DMA_CHANNEL_fromSPR / DMA_CHANNEL_toSPR8 / 9Scratchpad RAM (uma memória pequena e rápida local à EE)

O canal que você usa segue diretamente de para onde os dados estão indo - enviar dados de vértice/textura para o GS significa o canal GIF, enviar uma requisição RPC para o IOP significa um canal SIF, e assim por diante. Não existe uma chamada genérica de "DMA para qualquer lugar."

Por que o dmakit existe

Enfileirar uma transferência DMA de verdade significa construir uma tag DMA (um pequeno cabeçalho descrevendo a transferência - origem, tamanho, e o que fazer quando terminar ou quando encadear com a próxima tag) e escrevê-la nos registradores do canal certo. dmakit (tier world) envolve isso: construir cadeias de tags, esperar a conclusão, e os padrões comuns (envie este buffer, depois este outro, depois me interrompa) em vez de montar bytes de tag à mão em cada ponto de chamada.

Por que isso importa para como você estrutura o código

Como as transferências DMA rodam concorrentemente com a CPU, um programa real construído em torno disso se parece diferente de um que apenas chama uma função bloqueante de "desenhe agora": você enfileira trabalho, faz outra coisa (monta os dados do próximo frame, roda a lógica do jogo), e só sincroniza quando realmente precisa do resultado ou precisa reusar um buffer que o motor DMA ainda não terminou de ler. Reusar um buffer de origem antes que sua transferência DMA de fato tenha terminado é um bug clássico do PS2 - os dados que o GS/VU acaba vendo são o que estava na memória no momento em que o motor DMA chegou até eles, não no momento em que você chamou a função.

Veja também