Falando direto com a memória: PEEK, POKE, VPEEK, VPOKE
Debaixo dos comandos amigáveis, tudo é memória. Aprender a ler e escrever bytes crus abre a porta para efeitos que nenhum comando de alto nível oferece.
1. Duas memórias, duas famílias de comandos
O MSX tem duas memórias separadas:
- RAM (a memória do Z80) — onde ficam variáveis, código e a área de trabalho da BIOS. Manipulada com
PEEKePOKE. - VRAM (a memória do VDP) — onde ficam padrões de tiles, tabela de nomes, sprites e paleta. Manipulada com
VPEEKeVPOKE.
A regra de ouro: PEEK/POKE nunca falam com a VRAM, e VPEEK/VPOKE nunca falam com a RAM. Confundir as duas é o erro clássico do programador iniciante de MSX.
2. PEEK e POKE — a RAM do Z80
DIM v AS BYTE
v = PEEK($FCA9) ' lê byte da RAM
POKE $C000, 42 ' escreve 42 na RAM em $C000
Endereços úteis:
| Endereço | O que é |
|---|---|
$FC9E | JIFFY — contador de VBLANK (60 Hz) |
$FCA9 | Status atual do PSG |
$F3AE..$F3B7 | Cores de fundo, borda e texto de cada SCREEN |
DIGITE E VEJA
Programa 17.1 — Cronômetro
USES SCREEN 1, KEYBOARD
SCREEN 1 : CLS
DIM t AS WORD
WHILE STRIG(0) = 0
t = PEEK($FC9E)
LOCATE 0,0
PRINT "JIFFY = "; t; " "
WEND
A cada 1/60 de segundo o número cresce.
3. VPEEK e VPOKE — a memória de vídeo
A VRAM é onde vive tudo que aparece na tela. Em SCREEN 1, o mapa lógico é:
| Faixa VRAM | Conteúdo |
|---|---|
$0000–$07FF | Padrões dos tiles (256 tiles × 8 bytes) |
$1800–$1AFF | Tabela de nomes (32×24 = o que aparece onde) |
$2000–$27FF | Tabela de cores |
$1B00–$1B7F | Atributos de sprites (posição + cor) |
$3800–$3FFF | Padrões dos sprites |
DIGITE E VEJA
Programa 17.2 — Pintando a tela direto na VRAM
USES SCREEN 1
SCREEN 1 : CLS
DIM addr AS WORD
DIM i AS WORD
' Escreve o caractere 'A' (código 65) na primeira linha inteira
FOR i = 0 TO 31
VPOKE $1800 + i, 65
NEXT i
TELA ESPERADA
Uma linha cheia de "A"
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA no topo da tela. Você pintou direto na tabela de nomes, sem PRINT.
4. Casos onde VPEEK/VPOKE brilham
- Ler o cenário para saber com o que o herói está colidindo (é um tijolo? uma escada?).
- Efeitos de "scroll" fake copiando faixas de memória com
FOR. - Salvar/restaurar um pedaço da tela antes de abrir um menu popup.
- Ler pixels em SCREEN 2 para colisão pixel-perfect.
DICA
Bloco grande? Traga do cartucho, não byte a byte
VPOKE é feito para escritas pontuais. Para preencher a tela inteira, o
caminho rápido é PAGELOAD (capítulo 21) ou GFXLOAD na MegaROM ASCII8
(seção 9 deste capítulo): o runtime escreve os bytes em rajadas, sem resolver
endereço a cada byte. Um FOR de VPOKE sobre 27 KB é lento em qualquer MSX.
Para mover um retângulo de dentro da própria VRAM, use V9968 COPY (só V9968).
5. XPTR: quando 64KB é pouco
Para acessar mais de 64KB de RAM (cartuchos com Mapper, expansões), use XPTR — coberto no capítulo 25 (LMM). A ideia é a mesma: PEEK(p) e POKE p, v, mas p carrega também o segmento.
6. OUT e IN — as portas do Z80
Além das duas memórias, o Z80 conversa com os chips (vídeo, som, cartuchos) por portas numeradas de 0 a 255.
OUT porta, valor— manda um byte para a porta.IN(porta)— lê um byte da porta.
USES SCREEN 1
SCREEN 1 : CLS
DIM v AS BYTE
v = IN($A8) ' qual slot está em cada página de memória
PRINT "SLOTS: "; v
ATENÇÃO
Portas mexem direto no hardware
Um OUT errado no chip de vídeo ($98–$9B) ou nos slots ($A8) pode travar a máquina. Prefira os comandos prontos da linguagem e use portas só quando souber o que o chip espera.
7. ⚠ Cuidados
ATENÇÃO
Endereços proibidos
Escrever em $F380–$FFFF sem saber o que faz trava o MSX. Essa faixa é a área de trabalho da BIOS. Antes de qualquer POKE acima de $F000, confirme o endereço em uma tabela de referência.
8. Resumo do capítulo
PEEK/POKE→ RAM do Z80.VPEEK/VPOKE→ VRAM do VDP.- Nunca misture as duas famílias.
- A VRAM tem endereços mapeados por SCREEN — decore os principais de SCREEN 1 e 2.
- Bloco grande:
PAGELOAD,GFXLOAD(seção 9) ouV9968 COPY.VPOKEfica para escritas pontuais. - Para além de 64KB, veja
XPTRno capítulo 25. OUT porta, valoreIN(porta)falam direto com os chips pelas portas do Z80.
9. Dados gráficos na MegaROM ASCII8
A opção MegaROM ASCII8 nos editores SCR Edit, TILES e SPRITES, ou o formato MegaROM ASCII8 na exportação do Graphics Studio, guarda os dados gráficos fora dos primeiros 32 KB do cartucho. O código continua nessa área; música e gráficos ocupam os bancos adicionais, sem sobreposição. É uma opção explícita: as exportações ASM/ARRAY e os tocadores normais continuam iguais.
Isso usa o mapper do cartucho, não a memória mapper interna da máquina. Funciona também no MSX1 com cartucho ASCII8. A mapper nativa com DSK fica para uma versão futura. A VRAM não aumenta: só os dados de origem ficam na MegaROM.
| Comando | Operação |
|---|---|
USES GRAPHICSBANK | Habilita gráficos em bancos, somente para ROM. |
GFXDATA nome, bytes... | Declara bytes literais 0–255; linhas com o mesmo nome concatenam. Não ocupa RAM nem os 32 KB do programa. |
GFXLOAD nome, endereço [, offset, quantidade [, página64K]] | Copia bytes crus diretamente para VRAM. Endereço, offset, quantidade e página são literais. |
GFXCOPY nome, array [, offset, quantidade] | Copia para um ARRAY OF BYTE em RAM já declarado, com capacidade suficiente. |
offset é relativo ao começo do bloco; omitido, copia o bloco inteiro.
Cada chamada copia 1–65535 bytes. SCREEN 1/2/3 têm limite de 16 KB de VRAM;
SCREEN 4/5/7/8 permitem endereço 0–65535 e página64K 0 ou 1 (128 KB).
O compilador rejeita intervalos fora do bloco ou da memória de destino.
O cartucho tem até 2 MB, incluindo os 32 KB do programa; não há segmentação de código.
MEMORY 32
USES GRAPHICSBANK, SCREEN 2, SPRITES, TILES
SCREEN 2
CLS
' Padrão e cores do tile 1, repetidos nas três zonas
GFXDATA tile_ship, 24,60,126,255,126,60,24,0, 241,241,241,241,241,241,241,241
GFXLOAD tile_ship, $0008, 0, 8
GFXLOAD tile_ship, $0808, 0, 8
GFXLOAD tile_ship, $1008, 0, 8
GFXLOAD tile_ship, $2008, 8, 8
GFXLOAD tile_ship, $2808, 8, 8
GFXLOAD tile_ship, $3008, 8, 8
TILE 12, 10, 1
' Sprite 8x8, padrão 0
GFXDATA sprite_ship, 24,60,126,255,126,60,24,0
GFXLOAD sprite_ship, $3800
SPRITE 0, 120, 80, 0, 8
WHILE 1
WAIT
WEND
Telas SCREEN 5: a exportação Mapper exige largura 256 e altura até 212. São pixels crus 4bpp, não o arquivo comprimido usado por PAGELOAD. Uma linha tem 128 bytes. A página SCREEN 5 0 começa em endereço 0/página64K 0; a 1 em 32768/0; a 2 em 0/1; a 3 em 32768/1. Selecione SCREEN 5 antes de carregar.
Várias telas no mesmo cartucho
Cada imagem é um bloco GFXDATA com nome próprio. Declare cada uma uma única
vez, no nível do programa — o compilador rejeita GFXDATA dentro de WHILE,
FOR ou IF. Todas ficam gravadas nos bancos do cartucho (juntas até ~2 MB
menos os 32 KB do programa) e nenhuma delas ocupa RAM.
Para exibir, repita o GFXLOAD quantas vezes quiser, em qualquer ponto do
programa, com o SCREEN correspondente ativo. A cópia vai da mapper para a VRAM:
o original no cartucho não se gasta, então a mesma tela pode voltar depois de um
CLS, de um menu ou de outra fase.
| Quero… | Faço |
|---|---|
| Mostrar a tela 1 | GFXLOAD tela1, 0 com SCREEN 5 ativo |
| Mostrar a tela 2 | GFXLOAD tela2, 0 — escreve por cima da anterior |
| Editar os bytes de uma tela | GFXCOPY tela1, buf → mexe em buf → escreva buf na VRAM com VPOKE |
GFXLOAD sempre traz os bytes originais do cartucho. Se você editou buf, a
alteração precisa voltar para a VRAM (laço de VPOKE); chamar GFXLOAD de novo
descarta a edição e restaura a imagem como foi exportada.
Troca limpa. GFXLOAD escreve na página que está sendo mostrada, então uma
tela grande aparece em construção. Para trocar de imagem sem ver o redesenho,
apague a tela, carregue e reacenda:
SCREEN OFF ' apaga a imagem enquanto a cópia roda
GFXLOAD tela2, 0
SCREEN ON ' a tela nova aparece inteira
DIGITE E VEJA
Programa 17.3 — Duas telas alternando por uma tecla
Precisa de MSX 2 ou superior. SCREEN 5 não existe no MSX 1: lá o modo gráfico não muda, os bytes do GFXLOAD caem na tela de texto e aparecem como caracteres/pixels soltos no topo, com o cursor piscando. No RUN da IDE a máquina troca para MSX 2 sozinha; na página Emulador, escolha uma máquina MSX 2 (ou superior) no seletor antes de abrir a ROM.
MEMORY 32
USES GRAPHICSBANK, SCREEN 5
SCREEN 5
' Em um programa real, a exportação Mapper do Studio traz os bytes de cada
' tela (32768 para uma SCREEN 5 cheia). Aqui cada bloco tem 64 bytes: uma
' faixa de 128 pixels no topo da tela, preta (tela1) ou branca (tela2).
GFXDATA tela1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
GFXDATA tela2, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
WHILE 1
SCREEN OFF : GFXLOAD tela1, 0 : SCREEN ON
INPUT$(1)
SCREEN OFF : GFXLOAD tela2, 0 : SCREEN ON
INPUT$(1)
WEND
Aperte qualquer tecla: a faixa branca do topo alterna com a preta.
Paleta: telas exportadas com paletas diferentes precisam da paleta certa no momento em que são exibidas; os 16 valores 4bpp são só índices.
Página exibida: GFXLOAD escreve, mas não escolhe qual página aparece. Quem
muda a página mostrada é PAGELOAD nome, pagina ou BOB FLIP com BOB PAGEFLIP ON
(capítulo 21). Carregar na página 1 sem exibi-la deixa a segunda tela pronta na
VRAM, mas continua na tela a página 0.
Tiles e sprites: os editores mantêm a ordem dos padrões 8×8 e as três zonas
de SCREEN 2/4. O editor de sprites gera o layout de SCREEN 2; em SCREEN 5
os padrões de sprites ficam em $7800, portanto ajuste o destino ao trocar
de modo. Mapas usados pelo scroll e objetos BOB podem precisar de um buffer
temporário em RAM: GFXCOPY libera a ROM do programa, não essa área de trabalho.
Música: PLAYBANK/TICKBANK continuam usando os bancos iniciais de dados. GFXLOAD/GFXCOPY restauram o banco do programa entre pequenos blocos protegidos contra interrupção. TICKBANK cooperativo não avança sozinho durante uma cópia; chame-o no laço ou no seu VBLANK, como antes.
RUN e exportação: RUN seleciona ASCII8 automaticamente. O arquivo exportado
é main[ASCII8].rom; em outros emuladores, escolha o cartucho ASCII 8K.