| English | Português (Brasil) |
O NES Pascal modela exatamente 2.048 bytes de RAM física interna da CPU:
$0000-$07FF. Os endereços $0800-$1FFF são espelhos de hardware dessa mesma RAM
e nunca são tratados como armazenamento adicional.
| Intervalo | Tamanho | Proprietário | Finalidade |
|---|---|---|---|
$0000-$000F |
16 bytes | Runtime | Reserva obrigatória de runtime na Zero Page |
a partir de $0010 |
0 a 16 bytes combinados | Compiler | Temporários de expressão no pico de uso, seguidos por limites de for em cache |
até $001F |
bytes restantes | Free | Capacidade de temporários recuperada e visível ao alocador |
$0020-$007F |
96 bytes | Reserved | Espaço estável para futuras declarações explícitas na Zero Page |
$0080-$00FF |
128 bytes | User | Promoção automática opcional de variáveis globais |
$0100-$01FF |
256 bytes | Reserved | Pilha de hardware do 6502 |
$0200-$02FF |
0 ou 256 bytes | Runtime | Shadow de OAM alinhado a página, incluído por operações gerais ou legadas de sprites |
de $0200 sem sprites, senão $0300 |
0 ou 5 bytes | Runtime | Registro legado de preparação do sprite 0, alocado apenas quando usado |
| após blocos anteriores de runtime | 0, 65 ou 66 bytes | Runtime | Tabela de Y lógico de sprites gerais e um ou dois bytes auxiliares |
| após blocos anteriores de runtime | 4N + 8 ou 8N + 8 bytes |
Runtime | Estado estático ou com animação de metasprites mais rascunho compartilhado do renderizador |
| após o estado de runtime do fundo | 0, 2 ou 10 bytes | Runtime | Entrada e rascunho compartilhado de retângulos ativados por helpers de colisão |
| após blocos anteriores de runtime | 4 bytes | Runtime | Estado autoritativo de PPUCTRL, PPUMASK e rolagem |
| após blocos anteriores de runtime | 0 ou 41 bytes | Runtime | Shadow de paleta e flags atômicas de dirty, alocado apenas para chamadas de paleta em runtime |
| após blocos anteriores de runtime | 0 ou 960 bytes | Runtime | Shadow de tiles confirmados, incluído apenas por nes.get_tile |
| após o shadow opcional de tiles | 0 a 23 bytes | Runtime | Estado condicionalmente selecionado de fila de fundo, flags e helpers |
| após os dados comuns de runtime | um byte por função | Compiler | Armazenamento estático do resultado de cada função |
| após os resultados do compilador | RAM comum restante | User/free | Globais não promovidas e parâmetros de procedimentos/funções |
As janelas da política da Zero Page são fixas e não se sobrepõem. Símbolos de
runtime, slots de expressão medidos e caches do compilador são obrigatórios quando
usados. Eles nunca tomam emprestado do espaço opcional de promoção. O runtime detém
runtime_frame_counter em $0000 e runtime_frame_ready
em $0001. O laço de atualização detém runtime_last_processed_frame em $0002.
O estado atual, anterior e a proteção de consulta dos controles ocupam $0003-$0008.
Esses bytes de runtime não podem se sobrepor ao armazenamento do compilador. O
Dentro de $0010-$001F, o compilador primeiro aloca exatamente o número máximo de
slots de expressão simultaneamente ativos e depois os limites de for em cache. O
sufixo não usado fica livre e visível ao alocador. Necessitar de mais de 16 bytes
combinados de expressão/cache é um erro de compilação.
Os slots de expressão têm nomes determinísticos (expression_temporary_0,
expression_temporary_1 e assim por diante). A geração adquire explicitamente o
slot livre de menor índice, mantém o aluguel enquanto o valor é necessário e o
libera para expressões posteriores. A reserva usa o pico medido no programa todo,
não a profundidade da AST nem a quantidade de expressões. Um programa sem essa
necessidade reserva zero bytes de expressão. Valores for_limit_* continuam sendo
uma categoria contábil separada.
Escritas com índice variável em arrays e arrays de records continuam preservando o índice calculado na pilha de hardware do 6502 durante a avaliação do lado direito. Esses bytes da pilha não contam como reserva de temporários de expressão. Argumentos de procedimentos, funções e builtins mantêm sua ordem de avaliação e reutilizam o pool apenas depois que aluguéis anteriores terminam.
Escopos de chamada preservam todos os slots pertencentes ao chamador. Uma chamada
aninhada que produza expressão deve adquirir outro slot até o chamador liberar o
valor ativo. A análise aplica essa regra ao grafo acíclico completo. Argumentos
anteriores também recebem slots quando um argumento posterior pode chamar uma
função e sobrescrever parâmetros estáticos. Cada função tem um byte de resultado
em RAM comum e retorna em A; não há frame de runtime nem área fixa global de
retorno. Cada JSR ativo usa apenas seu endereço de retorno normal de dois bytes
na pilha de hardware, reportado pela métrica de profundidade de chamadas.
A profundidade máxima estaticamente conhecida de chamadas aninhadas é limitada
para manter os endereços de retorno de JSR dentro da pilha de hardware
reservada de 256 bytes ($0100-$01FF). Dez bytes são reservados além dos
endereços de retorno: quatro para frames de JSR internos do runtime
alcançáveis a partir de instruções do usuário e seis para uma NMI que pode
ocorrer durante a execução do código do jogo. Com dois bytes por chamada ativa,
a profundidade máxima suportada de chamadas de fonte é 123 ((256 - 10) / 2).
Um programa cuja cadeia de chamadas mais profunda exceda esse limite é rejeitado
na compilação com E5007; recursão é rejeitada antes com E3014.
Operações gerais de sprites incluem condicionalmente o shadow de OAM de 256 bytes
alinhado a página em $0200-$02FF. Elas reservam runtime_sprite_logical_y em
$0300-$033F e runtime_sprite_value em $0340. nes.sprite_set_position adiciona
condicionalmente runtime_sprite_secondary_value em $0341; os quatro bytes de
estado autoritativo da PPU iniciam, portanto, em $0341 ou $0342. A tabela de Y
lógico permite que ocultar/exibir restaure uma posição para cada um dos 64 sprites.
O helper legado do exemplo de controles reserva, em vez disso, um registro de preparação
de cinco bytes; quando ambas as APIs são usadas, esse registro precede o estado de 65
ou 66 bytes de sprites gerais.
Programas apenas com metasprites reservam $0200-$02FF para o shadow compartilhado
de OAM. Eles também reservam dois ponteiros indiretos de dois bytes em $0009-$000C,
quatro bytes de RAM comum por instância (X, Y, quadro, flags) e oito bytes de rascunho
compartilhados em RAM comum. Uma instância, portanto, utiliza 12 bytes comuns mais quatro
bytes compartilhados na Zero Page; cada instância adicional adiciona quatro bytes comuns.
Esses blocos seguem qualquer estado de runtime de sprites individuais e precedem o
estado de paleta/PPU/fundo. Os índices de componentes estaticamente detidos e a geometria
imutável residem na PRG-ROM, e não na RAM.
Quando um programa utiliza uma operação de animação ou consulta de conclusão, cada
instância de metasprite adiciona quatro bytes de RAM comum para ID de animação, índice
de sequência, temporizador de quadro e flags de reprodução. O custo resultante em RAM
comum é 8N + 8; o shadow de OAM, o rascunho compartilhado e os ponteiros na Zero Page
não aumentam. Programas limitados à seleção estática de quadros mantêm 4N + 8 e omitem
todo o estado e rotinas de animação.
Predicados e helpers de bounds compartilham dez bytes de RAM comum para dois
retângulos e um ponto ou instância. Um programa que usa apenas
nes.background_collision necessita de dois desses bytes como entrada de
pixel/índice. Qualquer caminho inclui o runtime_collision_pointer de dois
bytes em $000D-$000E, dentro da partição Zero Page existente de 16 bytes do
runtime. O mapa de fundo compactado e imutável e as caixas por frame de
metasprites residem na PRG-ROM. Sem chamadas de colisão, todos esses símbolos e
rotinas são omitidos. Bounds de sprite/metasprite ainda exigem seu estado normal
de OAM/instância; colisão de fundo não exige o shadow confirmado de 960 bytes.
Programas sem operações individuais de sprites, metasprites ou OAM omitem o símbolo de
OAM, segmento no Assembly, região no linker, código de DMA e estado de sprites. Sua
alocação comum de runtime e usuário inicia em $0200, disponibilizando essa página de
256 bytes em vez de reservá-la implicitamente.
Bytes de resultado de funções começam imediatamente após os dados comuns de
runtime e antes do armazenamento comum do usuário. Eles aparecem no segmento
FUNCTION_RESULTS e em Compiler Symbols no mapa. Um programa sem funções
omite a região, o segmento, os símbolos e o código.
Programas com chamadas de paleta em runtime reservam um shadow de paleta de 32 bytes,
quatro flags de paleta de fundo, quatro flags de paleta de sprites, uma flag de cor
universal e quatro bytes de restauração da PPU na RAM comum de runtime. Os bytes de
restauração armazenam PPUCTRL, PPUMASK, scroll X e scroll Y. Esse bloco de 45 bytes
inicia em $0200 sem sprites, $0305 após a preparação legada de sprite fixo,
$0341-$0342 após a API geral, ou $0346-$0347 quando ambas as APIs estão incluídas.
Ele não utiliza Zero Page adicional. A RAM do usuário se inicia imediatamente após os
blocos de runtime alocados condicionalmente.
Todo programa reserva quatro bytes de RAM comum para os shadows autoritativos de
PPUCTRL, PPUMASK, rolagem horizontal e rolagem vertical. Um programa que chama
nes.set_scroll reserva três bytes adicionais para um par pendente publicado atomicamente.
Programas sem essa chamada mantêm os padrões zerados de rolagem e omitem o registro de preparação.
Escritas apenas de tiles reservam 16 bytes para quatro arrays de pronto/endereço/valor,
uma flag de estouro persistente, cinco bytes auxiliares e quatro bytes de restauração de
estado da PPU: 26 bytes no total. Escritas apenas de atributos omitem os dois helpers de
índice de tiles e necessitam de 24 bytes. nes.clear_background_updates() adiciona
condicionalmente o bloqueio de cancelamento de um byte; APIs apenas de estouro necessitam
apenas da flag persistente. O shadow de 960 bytes de tiles confirmados 32 por 30 é
adicionado apenas quando nes.get_tile() é utilizado. A fila mais o shadow reservam,
portanto, 986 bytes sem cancelamento e, sem sprites, iniciam a RAM do usuário em $05DA.
Adicionar cancelamento eleva isso para 987 bytes e inicia a RAM do usuário em $05DB. Um
programa apenas com get_tile necessita do shadow, quatro bytes auxiliares de índice de
tiles e os quatro bytes de estado da PPU, totalizando 968 bytes.
Com suporte a paleta em runtime, a paleta e a fila compartilham os quatro bytes de
estado da PPU. Paleta, fila e shadow reservam 1.027 bytes sem cancelamento ou 1.028 bytes
com cancelamento, deixando 509 ou 508 bytes de RAM comum quando nenhum helper de sprite
é utilizado. O suporte legado a sprite fixo reserva a página de 256 bytes de OAM e cinco
bytes escalares, deixando 248 ou 247 bytes. A API geral de sprites reserva essa página
mais 65 bytes, ou 66 com nes.sprite_set_position, deixando 188 a 186 bytes; incluir ambas
deixa 183 a 181 bytes. O espaço de promoção automática na Zero Page permanece disponível
independentemente. O shadow permanece como a implementação mais clara de leituras aleatórias
de tiles confirmados. Mapas de metatiles, dicionários de tiles modificados e caches compactos
de leitura foram postergados porque adicionariam custo de busca ou complexidade em runtime.
A validação de callbacks de VBlank rejeita qualquer operação acessível que utilize slots de expressão ou caches compartilhados do compilador. O caminho de interrupção utiliza, portanto, o estado da Zero Page pertencente ao runtime mais as variáveis do callback, nunca expressões do contexto principal ou armazenamento de laços em cache.
O intervalo explícito futuro impede que uma sintaxe futura para variáveis explícitas na Zero Page desloque a ABI de promoção automática. A sintaxe de Zero Page explícita ainda não está implementada.
A promoção é opcional e conservadora:
$0080 em diante.Todos os tipos embutidos atuais ocupam um byte e podem ser promovidos. A política não realiza análise de tempo de vida, sobreposição de armazenamento, análise de grafo de chamadas, perfilamento dinâmico ou estimativa avançada de pontos críticos (hotness).
Os segmentos do ca65 são marcados como zeropage, de modo que instruções que referenciam
globais promovidas ou temporários do compilador utilizam opcodes de Zero Page. Variáveis
comuns mantêm o endereçamento absoluto.
Compilar o exemplo focado examples/zero_page.nsp em build/zero_page.nes
grava build/zero_page.map. O relatório separa a reserva de expressão no pico,
caches do compilador, reserva por política, Zero Page recuperada, promoção
opcional e reserva de hardware. Ele identifica cada símbolo do usuário como
Zero Page ou Regular RAM.
Um trecho da tabela de regiões gerada é:
Start End Size Owner Region
$0000 $000F 16 Runtime Zero Page runtime
$0010 ---- 0 Compiler Expression temporaries
$0010 $001F 16 Free Recovered temporary Zero Page
$0020 $007F 96 Reserved Future explicit Zero Page
$0080 $00FF 128 User Automatic Zero Page variables (2 used, 126 available)
$0100 $01FF 256 Reserved 6502 hardware stack
$0200 $0203 4 Runtime Runtime data
$0204 $0204 1 User Regular user variables
$0205 $07FF 1531 Free General free RAM
O mapa também imprime Expression temporary reservation: 0 bytes (maximum
simultaneously live) e Other compiler caches: 0 bytes neste exemplo. O .cfg
gerado, os segmentos no Assembly e o relatório .map utilizam todos o mesmo
objeto de layout validado, de modo que seus cálculos de endereço não podem divergir.
A tabela de símbolos de runtime também reporta:
$0000 1 runtime_frame_counter volatile 8-bit NMI frame counter
$0001 1 runtime_frame_ready best-effort advisory frame-ready latch
$0002 1 runtime_last_processed_frame persistent update-loop baseline
$0003 1 runtime_controller_1_current controller 1 current state
$0004 1 runtime_controller_1_previous controller 1 previous state
$0005 1 runtime_controller_2_current controller 2 current state
$0006 1 runtime_controller_2_previous controller 2 previous state
$0007 1 runtime_controller_polled_frame most recently polled frame
$0008 1 runtime_controller_poll_valid distinguishes initial RAM from frame zero
Quando o suporte a sprites gerais está presente, a tabela de regiões adiciona o shadow
de OAM em $0200-$02FF, e a tabela de símbolos de runtime reporta runtime_oam_shadow,
runtime_sprite_logical_y e runtime_sprite_value. runtime_sprite_secondary_value
aparece apenas com nes.sprite_set_position. Os cinco símbolos runtime_sprite_zero_*
são adicionalmente reportados apenas para o helper legado de compatibilidade do sprite 0.
Quando o suporte a paleta em runtime está presente, a tabela também reporta
runtime_palette_shadow, runtime_palette_background_0_dirty até
runtime_palette_background_3_dirty, runtime_palette_sprite_0_dirty até
runtime_palette_sprite_3_dirty, runtime_palette_universal_dirty,
runtime_ppuctrl_shadow, runtime_scroll_x_shadow e runtime_scroll_y_shadow.
Quando nes.get_tile está presente, a tabela reporta runtime_background_shadow.
Quando atualizações enfileiradas estão presentes, ela reporta os arrays de quatro
elementos runtime_background_queue_ready, runtime_background_queue_high,
runtime_background_queue_low e runtime_background_queue_value. Gravadores e APIs
de estouro adicionam runtime_background_queue_overflow; cancelamento adiciona
runtime_background_queue_cancel_lock. Helpers de coordenadas, valores e índice de
tiles são reportados apenas para pontos de entrada que os utilizam. Os símbolos de
restauração da PPU são alocados para transferências de paleta ou fundo e compartilhados
quando ambos os recursos estão presentes.
Quando números aleatórios são vinculados, o mapa nomeia os dois bytes regulares
runtime_random_state_low e runtime_random_state_high. Programas com
nes.random_range também nomeiam runtime_random_span e
runtime_random_cutoff; programas sem RNG não contêm esses símbolos.