V9968: o VDP estendido do MSX 2++
O V9968 mantem tudo o que o V9938 faz e acrescenta 256 KB de VRAM, uma paleta de 256 cores com 5 bits por canal e um blitter capaz de girar e escalar retangulos por hardware. O CrossScript expoe esse chip por uma familia unica de comandos: V9968.
ATENÇÃO
V9968 no emulador: recurso experimental
O WebMSX oficial não tem o V9968. O chip (e o coprocessador GEO3D) é simulado por um complemento próprio da IDE CrossScript, escrito a partir da documentação pública do chip. O resultado pode diferir do hardware real e mudar entre versões, e alguns recursos ainda estão incompletos (veja a seção 5). Use para estudo e testes e confira no hardware real antes de distribuir um programa. Problemas com o V9968 devem ser relatados pelo botão Reportar problema da IDE, não ao autor do WebMSX nem ao do chip.
1. O que muda em relacao ao V9938
O V9968 e um VDP compativel com o V9938/V9958, porem ampliado:
| Recurso | V9938 | V9968 |
|---|---|---|
| VRAM | 128 KB | 256 KB |
| Paleta | 16 cores de 3 bits/canal | ate 256 cores (EPAL) de 5 bits/canal |
| Blitter | copia, preenche, move | idem + LRMM (rotacao/escala), LFMC, LFMM |
| Registradores | ate R#46 | + R#47 a R#58 (vetores e janela de origem) |
| Sprites | modo 1 e 2 | + aproximacao do modo 3 |
Na pratica: voce ganha uma area de VRAM "fora da tela" enorme para guardar figuras, e um comando de hardware que desenha essas figuras giradas.
2. Declarando o alvo
Um programa que usa o chip precisa declarar a maquina no USES:
USES SCREEN 5, MACHINE V9968
Isso faz duas coisas: liga o bloco de runtime dos comandos V9968 e marca o
binario como MSX2++, de modo que a IDE inicia a previa ja com o chip
estendido ativo. Sem MACHINE V9968, os comandos abaixo nao compilam.
ATENÇÃO
O V9968 nao substitui o SCREEN
Voce continua escolhendo o modo de tela com SCREEN 5, SCREEN 7 ou
SCREEN 8. Os comandos V9968 atuam sobre esse modo, usando as
paginas extras de VRAM como area de trabalho.
3. A familia de comandos
3.1 V9968 INIT
Prepara o chip: habilita a VRAM estendida, zera os registradores de vetor e
janela e deixa o blitter pronto. Deve vir depois do SCREEN e antes de
qualquer outro comando V9968.
SCREEN 5
CLS
V9968 INIT
3.2 V9968 PALETTE indice, r, g, b
Grava uma entrada da paleta estendida (EPAL). O indice vai de 0 a 255 e
cada componente vai de 0 a 31 — quatro vezes mais tons por canal do que
o PALETTE do V9938.
V9968 PALETTE 1, 31, 0, 0 ' vermelho saturado
V9968 PALETTE 2, 0, 31, 0 ' verde
V9968 PALETTE 3, 12, 12, 31 ' azul claro
3.3 V9968 FILL x, y, largura, altura, cor
Preenche um retangulo com uma cor solida, por hardware. O y pode passar de
255: e assim que voce alcanca a VRAM estendida, fora da area visivel.
V9968 FILL 0, 0, 256, 212, 4 ' fundo azul na tela
V9968 FILL 128, 256, 96, 96, 15 ' area de trabalho fora da tela
3.4 V9968 COPY xo, yo, xd, yd, largura, altura
Copia um retangulo de VRAM para outro ponto de VRAM. Origem e destino podem estar em paginas diferentes; e o caminho para levar um sprite grande, um tile ou um texto ja desenhado para dentro da figura de trabalho.
V9968 COPY 0, 216, 140, 290, 80, 8
3.5 V9968 WINDOW x0, y0, x1, y1
Define a janela de origem (R#51–R#58) usada pela rotacao. Tudo o que o comando de giro ler fora desse retangulo e considerado "vazio" e recebe a cor de fundo. Use a janela para cercar exatamente a figura que vai girar.
V9968 WINDOW 128, 256, 223, 351
3.6 V9968 ROTATE xd, yd, largura, altura, vx, vy, xo, yo [, cor]
O comando central do chip. Desenha no destino (xd, yd) um retangulo de
largura x altura lendo a origem a partir de (xo, yo), avancando na
origem pelo vetor (vx, vy) a cada pixel. Os vetores estao em ponto fixo
8.8: 256 equivale a um pixel inteiro.
vx = 256,vy = 0→ copia sem girar.vx = 128,vy = 0→ dobra a figura na horizontal (zoom).vx = cos(a)*256,vy = sin(a)*256→ rotacao deagraus.
O nono argumento, opcional, e a cor de fundo (R#44) aplicada aos pixels do destino que caem fora da janela de origem. Sem ele o chip usa 0 (preto).
V9968 ROTATE 80, 58, 96, 96, VX, VY, SX, SY, 4
DICA
Tabelas em vez de trigonometria
O CrossScript nao tem seno e cosseno em tempo de execucao. Pre-calcule os
vetores numa ARRAY(32) OF WORD — 32 angulos de 11,25 graus dao um giro
visualmente suave e custam 128 bytes.
3.7 V9968 ROTATE ANGLE a, xd, yd, largura, altura [, cor]
A forma facil do giro. Em vez de vetores, voce informa apenas o angulo,
de 0 a 255 (uma volta inteira; cada passo vale 1,40625 grau, e o sentido
e horario). O runtime calcula seno e cosseno por tabela e posiciona a origem
de modo que o centro da janela (definida por V9968 WINDOW) caia no
centro do retangulo de destino — a figura gira no proprio eixo, sem
escorregar.
V9968 WINDOW 128, 256, 223, 351
V9968 ROTATE ANGLE ANG, 80, 58, 96, 96, 4
DICA
Sempre defina a janela antes
O eixo do giro vem de V9968 WINDOW. Sem ela o centro e (0,0) e a figura
sai da tela.
3.8 V9968 ZOOM xo, yo, xd, yd, largura, altura, escala
Copia a figura mudando o tamanho, sem girar. A escala esta em ponto fixo
8.8 e diz quanto da origem e consumido por pixel do destino:
256→ 1:1;128→ a figura aparece com o dobro do tamanho;512→ metade do tamanho.
largura e altura sao as do destino.
V9968 ZOOM 128, 256, 0, 110, 96, 96, 512 ' reduz pela metade
3.8.1 V9968 ZOOM SEQ xo, yo, xd, yd, largura, altura, inicio, fim, passo [, cor]
Faz a animacao inteira sozinho: parte da escala inicio, caminha de passo
em passo ate fim e desenha um quadro por etapa, sincronizando com o
retraco vertical. Antes de cada quadro o retangulo de destino e apagado com
cor (0 quando omitida), de modo que a figura nunca deixa rastro.
Como a escala esta invertida (menor = maior), 420 → 264 amplia e
264 → 420 reduz. Um par desses comandos dentro de um WHILE produz uma
pulsacao continua:
WHILE 1 = 1
V9968 ZOOM SEQ 128, 256, 96, 74, 64, 64, 420, 264, 12, 1
V9968 ZOOM SEQ 128, 256, 96, 74, 64, 64, 264, 420, 8, 1
WEND
DICA
O passo controla a velocidade
Passos pequenos dao movimento suave e demorado; passos grandes dao um "susto". Mantenha a escala sempre acima de 256 se a figura tiver de caber inteira no retangulo de destino.
3.9 V9968 FLIP H | V, xo, yo, xd, yd, largura, altura
Espelha o retangulo na horizontal (H) ou na vertical (V). O comando usa o
blitter em fatias (colunas para H, linhas para V), entao figuras grandes
custam mais de um quadro.
V9968 FLIP H, 128, 256, 0, 0, 96, 96
V9968 FLIP V, 128, 256, 160, 0, 96, 96
3.10 V9968 LOGIC IMP | AND | OR | EOR | NOT | TIMP | TAND | TOR | TEOR
Define a operacao logica aplicada a partir dali por FILL, COPY, ROTATE
e ZOOM. O estado e persistente: vale ate o proximo V9968 LOGIC ou
V9968 INIT (que volta para IMP). Os modos com T na frente sao
transparentes — a cor 0 da origem nao e escrita.
V9968 LOGIC TOR ' desenha por cima preservando o fundo
V9968 COPY 128, 256, 0, 0, 96, 96
V9968 LOGIC IMP ' volta ao normal
3.11 V9968 SCROLL x, y
Rolagem por hardware: x desloca a imagem para a esquerda em pixels
(0..255, com volta ao inicio dentro da propria pagina) e y desloca a
origem vertical da tela. Nao copia VRAM nenhuma — apenas escreve os
registros R#26/R#27 (horizontal) e R#23 (vertical), entao o custo e o
mesmo a cada quadro, independente do tamanho da area visivel.
Padrao de uso: desenhe a coluna nova na posicao x e, em seguida, mande
a tela andar ate ali. Como a pagina tem 256 pixels de largura, o buffer
funciona como um anel.
X = 0
WHILE 1 = 1
V9968 FILL X, 48, 8, 96, 0 ' abre a coluna nova
V9968 FILL X, 100, 8, 4, 11 ' desenha o dado do quadro
X = X + 8
V9968 SCROLL X, 0
WAIT
WEND
Para rolagem vertical use o segundo argumento; V9968 SCROLL 0, 0 volta
a tela para a posicao original.
3.11 V9968 WAIT
Aguarda o blitter terminar. Os comandos ja sincronizam entre si, mas use
V9968 WAIT antes de ler a VRAM com VPEEK ou antes de trocar de pagina.
4. Programa completo: figura girando com texto embutido
O exemplo V9968 Comandos CSX da IDE monta uma figura listrada numa area
fora da tela, escreve texto dentro dela com BPRINT + V9968 COPY, e a gira
continuamente:
USES SCREEN 5, MACHINE V9968, BPRINT
DIM ANG AS BYTE
DIM I AS BYTE
VAR TVX: ARRAY(32) OF WORD = (
256, 251, 237, 213, 181, 142, 98, 50,
0, 65486, 65438, 65394, 65355, 65323, 65299, 65285,
65280, 65285, 65299, 65323, 65355, 65394, 65438, 65486,
0, 50, 98, 142, 181, 213, 237, 251
)
VAR TVY: ARRAY(32) OF WORD = (
0, 65486, 65438, 65394, 65355, 65323, 65299, 65285,
65280, 65285, 65299, 65323, 65355, 65394, 65438, 65486,
0, 50, 98, 142, 181, 213, 237, 251,
256, 251, 237, 213, 181, 142, 98, 50
)
VAR TSX: ARRAY(32) OF WORD = (
112, 101, 92, 87, 85, 87, 92, 101,
112, 126, 141, 158, 176, 194, 211, 226,
240, 251, 260, 265, 267, 265, 260, 251,
240, 226, 211, 194, 176, 158, 141, 126
)
VAR TSY: ARRAY(32) OF WORD = (
240, 254, 269, 286, 304, 322, 339, 354,
368, 379, 388, 393, 395, 393, 388, 379,
368, 354, 339, 322, 304, 286, 269, 254,
240, 229, 220, 215, 213, 215, 220, 229
)
SCREEN 5
COLOR 15, 4, 4
CLS
V9968 INIT
V9968 PALETTE 1, 31, 0, 0
V9968 FILL 128, 256, 96, 96, 4
FOR I = 0 TO 5
V9968 FILL 128 + I * 16, 272, 16, 64, 9 + I
NEXT I
BPRINT SIZE 1
BPRINT 16, 27, "MSX BRASIL", 15, 4
V9968 COPY 128, 216, 144, 296, 80, 8
V9968 WINDOW 128, 256, 223, 351
ANG = 0
WHILE 1
V9968 ROTATE 80, 58, 96, 96, TVX(ANG), TVY(ANG), TSX(ANG), TSY(ANG), 4
ANG = (ANG + 1) AND 31
WAIT
WEND
Valores em TVX/TVY acima de 32767 sao negativos em complemento de dois:
65486 e -50, 65280 e -256. E assim que a figura passa dos 90 graus.
ATENÇÃO
Rotacao custa VRAM, nao CPU
O giro roda no blitter. O que limita a taxa de quadros e o tamanho do retangulo: 96x96 cabe folgado em um quadro; 256x212 nao cabe. Gire figuras pequenas e componha a tela em volta delas.
4.5 Paleta: carga em bloco, fade e ciclagem
O V9968 guarda 256 cores (EPAL) com 5 bits por canal. Alem do
V9968 PALETTE indice, r, g, b, que troca uma cor de cada vez, a CSX oferece
tres comandos de conjunto. Todos trabalham sobre uma copia da paleta mantida
em RAM (64 entradas), o que permite escurecer e restaurar sem perder os
valores originais.
V9968 PALETTE LOAD tabela, inicio, quantidade
Carrega varias cores de uma vez. tabela e o nome de um ARRAY OF BYTE com
trincas r, g, b (0..31 por canal), ou um endereco de RAM.
VAR PAL: ARRAY(48) OF BYTE = (
0, 0, 0, 4, 0, 8, 8, 0, 14, 12, 0, 20,
16, 0, 24, 20, 2, 28, 24, 6, 31, 28, 12, 31,
31, 18, 28, 31, 24, 20, 31, 28, 12, 28, 31, 6,
20, 31, 4, 12, 28, 8, 6, 20, 14, 2, 10, 10
)
V9968 PALETTE LOAD PAL, 0, 16
V9968 FADE inicio, fim, passo
Varia o brilho de toda a paleta de inicio ate fim, um quadro por passo.
O nivel vai de 0 (preto) a 16 (cor original). O comando so retorna quando
a animacao termina.
V9968 FADE 0, 16, 1 ' fade-in
V9968 FADE 16, 0, 1 ' fade-out
V9968 CYCLE inicio, fim
Gira circularmente as cores da faixa indicada — cada chamada avanca uma posicao. E o truque classico de agua corrente, fogo e estrelas piscando: a imagem nao e redesenhada, so a paleta muda.
WHILE 1 = 1
V9968 CYCLE 1, 15
WAIT
WEND
DICA
Ciclagem custa quase nada
CYCLE reescreve apenas registradores de paleta. Um fundo de cachoeira
animado por ciclagem consome menos tempo de CPU que um unico FILL.
Exemplo completo na IDE: V9968 Paleta: fade e cycle.
4b. Paginas, memoria e imagens
A VRAM estendida do V9968 comporta varias telas de 256x256 empilhadas. Os comandos abaixo tratam cada uma delas como uma pagina.
V9968 PAGE n e V9968 SHOW n
PAGE escolhe a pagina em que os comandos desenham (o Y de FILL, COPY,
ROTATE, LOAD e SAVE passa a ser contado dentro dela). SHOW escolhe a
pagina que aparece na tela. Usando as duas juntas voce desenha escondido e
troca de pagina pronta — o classico page flip, sem tremidas.
V9968 PAGE 1 ' desenha na pagina 1
V9968 FILL 0, 0, 256, 212, 4
V9968 SHOW 1 ' agora ela aparece
V9968 CLEAR pagina, cor
Pinta uma pagina inteira (256x256) de uma vez, independentemente da pagina de trabalho corrente. Nas SCREEN 5, 6, 7 e 8 usa o preenchimento por byte (HMMV), bem mais rapido; mesmo assim, limpar a pagina toda custa varios quadros para o chip de video. Em animacoes, prefira apagar so o que mudou.
V9968 CLEAR 0, 4 ' pagina 0 toda azul
V9968 MOVE xo, yo, xd, yd, larg, alt [, cor]
Copia o bloco e apaga a origem com a cor indicada (0 por omissao). E o
COPY com faxina embutida, util para mover um objeto sem deixar rastro.
V9968 MOVE 10, 10, 80, 60, 16, 16, 4
V9968 LOAD endereco, x, y, larg, alt
Envia uma imagem da RAM direto para a VRAM estendida. Cada byte guarda dois pixels (nibble alto = pixel da esquerda), entao a largura deve ser par.
VAR SPR: ARRAY(32) OF BYTE = ( ... )
V9968 LOAD SPR, 8, 100, 8, 8
V9968 SAVE x, y, larg, alt, endereco
O caminho inverso: captura um retangulo da VRAM para um ARRAY OF BYTE,
tambem com dois pixels por byte. Serve para guardar o fundo antes de
desenhar por cima e restaura-lo depois com LOAD.
VAR BUF: ARRAY(32) OF BYTE
V9968 SAVE 8, 100, 8, 8, BUF
DICA
Largura sempre par
LOAD e SAVE trabalham em pares de pixels. Uma largura impar deixa meio
byte solto e a imagem sai deslocada a partir da segunda linha.
Exemplo completo na IDE: V9968 Paginas: page flip e LOAD/SAVE.
4c. Desenho direto na VRAM estendida
Alem dos blocos, o V9968 desenha primitivas por hardware. Todas respeitam a
pagina de trabalho definida por V9968 PAGE e o modo logico de V9968 LOGIC.
V9968 PSET x, y, cor
Acende um unico pixel.
V9968 PSET 128, 90, 15
V9968 POINT x, y, variavel
Le a cor do pixel e guarda na variavel indicada.
VAR C: BYTE
V9968 POINT 128, 90, C
PRINT C
V9968 LINE x0, y0, x1, y1, cor
Traca uma reta entre os dois pontos usando o comando LINE do VDP (o Z80 so calcula a direcao e o lado maior; o desenho e todo do hardware).
V9968 LINE 0, 0, 255, 180, 7
V9968 BOX x, y, larg, alt, cor [, FILL]
Retangulo de contorno; com FILL no final, preenchido.
V9968 BOX 20, 20, 100, 60, 15
V9968 BOX 40, 40, 30, 20, 8, FILL
V9968 CIRCLE x, y, raio, cor
Circunferencia pelo algoritmo do ponto medio, plotando os oito pontos simetricos a cada passo. Pontos com coordenada negativa sao descartados.
V9968 CIRCLE 128, 100, 40, 6
Exemplo completo: V9968 Desenho: linha, caixa e circulo na lista da IDE.
5. Limites da versao atual
- No sprite mode 3 ainda faltam o aviso de colisao, o aviso de excesso por linha e as telas largas (SCREEN 6 e 7).
- O
BPRINTalcanca apenasY = 0..255; para escrever na VRAM estendida, escreva numa faixa baixa e traga o resultado comV9968 COPY. LFMCeLFMMexistem no runtime mas ainda nao tem comando CSX proprio.
Sprites modo 3, interrupção de linha e detecção do chip
V9968 DETECT ok ' ok = 1 quando o chip é o V9968
V9968 SPRITE MODE 3 ' sprite mode 3 + 16 sprites por linha (0 volta ao normal)
V9968 SPRITE SHEET 1 ' pagina 1 = folha de desenhos dos sprites
V9968 SPRITE PUT 0, x, y, 0, 32, 32, 0 ' plano, X, Y, desenho, largura, altura, atributo
V9968 SPRITE END 4 ' planos 4 em diante nao aparecem
V9968 INTERRUPT 106 GOSUB Meio ' chama Meio quando o feixe chega à linha 106
V9968 INTERRUPT OFF ' desliga a interrupção de linha
- DETECT lê o registrador de estado S#1 e devolve 1 só no V9968; em um MSX2 comum devolve 0, então o mesmo programa pode escolher outro caminho.
- Sprite mode 3 segue o formato do chip real: até 64 planos, 16 por linha, e cada ponto do desenho tem sua própria cor (16 cores, como em SCREEN 5). Funciona sobre qualquer modo de tela. Os comandos
SPRITE/SPRITECREATEcomuns não servem nesse modo. - SPRITE SHEET página escolhe a página da memória de vídeo que guarda os desenhos. Ela é organizada como uma tela SCREEN 5: o desenho
nfica na coluna(n AND 15) * 16e na linha(n SHR 4) * 16, com 16×16 pontos. Desenhe nela comV9968 PAGE,BOX,CIRCLE,LOADetc. A cor 0 é transparente. - SPRITE PUT plano, x, y, desenho, largura, altura, atributo posiciona um plano (0 a 63). X e Y vão até 1023. Largura e altura são o tamanho na tela: o chip amplia ou reduz o desenho de 16×16 até caber (altura 0 = 256; largura 0 esconde o plano). Atributo: bits 0–3 escolhem o conjunto de 16 cores da paleta de 256 (0 = cores normais), bit 4 espelha na horizontal, bit 5 na vertical, bits 6–7 dão transparência de 25%, 50% ou 75% (
$40,$80,$C0). - SPRITE END plano encerra a lista: esse plano e os seguintes não são desenhados. Use sempre após o último plano usado.
- O antigo
SPRITE COLORfoi retirado, porque o chip real não tem tabela de cor por linha nesse modo. - INTERRUPT chama a rotina no meio do quadro, a cada quadro. A rotina deve ser curta e terminar com
RETURN. É o recurso usado para dividir a tela, trocando cor, rolagem ou paleta a partir de uma linha.
GEO3D: figuras 3D desenhadas pelo coprocessador
O GEO3D é um coprocessador 3D criado por Alex Moncks. Ele não faz parte do V9968 oficial, mas usa o mesmo cartucho. O programa manda o modelo uma vez só. A cada quadro, basta mandar o ângulo: o GEO3D gira os pontos, corta as linhas na borda da tela e desenha tudo com o comando LINE do V9968.
| Comando | O que faz |
|---|---|
GEO3D INIT | Prepara a câmera para SCREEN 5 e a cor 15 |
GEO3D MODEL pontos, np, arestas, na | Envia o modelo: pontos é um ARRAY OF WORD com x, y, z de cada ponto; arestas é um ARRAY OF BYTE com pares de pontos |
GEO3D ROTATE ax, ay | Gira o modelo (0 a 255 dá uma volta inteira) |
GEO3D MOVE tx, ty, tz | Desloca o modelo; tz maior deixa a figura mais longe |
GEO3D COLOR cor | Cor das linhas |
GEO3D LOGIC op | Operação lógica das linhas: IMP (normal), AND, OR, XOR, NOT ou um número de 0 a 15 |
GEO3D RUN | Desenha na página escolhida por V9968 PAGE e espera terminar |
Exige USES MACHINE V9968. O exemplo “GEO3D Cubo 3D girando” mostra um cubo girando com troca de páginas: desenha na página escondida e depois a mostra com V9968 SHOW.
Velocidade. Quem desenha as linhas e o chip de video, nao o processador.
Por isso, no cubo de exemplo, apagar a pagina inteira a cada quadro deixava
a animacao em uns 3 quadros por segundo em qualquer velocidade de processador.
O exemplo agora apaga so o cubo anterior, redesenhando-o com GEO3D COLOR 0
(os mesmos angulos geram exatamente as mesmas linhas), e chega a 60 quadros
por segundo ja no clock normal. Um processador mais rapido so faz diferenca
quando o trabalho do processador por quadro nao cabe no tempo de um quadro.
Desenhar e apagar com XOR. Apagar redesenhando na cor do fundo só funciona
com fundo liso. Sobre um cenário, use GEO3D LOGIC XOR: cada ponto da linha
troca de cor ao ser desenhado e volta à cor original quando a mesma linha é
desenhada de novo. Basta repetir o cubo antigo (mesmos ângulos) para apagá-lo,
sem conhecer a cor de nada que está por baixo. O Geo3D original já tem esse
registrador de operação lógica (0x45); o comando só o preenche.
Dois detalhes: a cor que aparece é a mistura (XOR) da cor da linha com o fundo, então muda conforme o que está atrás; e os cantos onde duas arestas se encontram são desenhados duas vezes e podem sumir. Veja o exemplo “GEO3D Cubo XOR sobre cenario”.
CPU R800 — mais velocidade no Turbo R
CPU R800 liga o processador R800 do MSX Turbo R (e CPU Z80 volta ao Z80). Em máquinas sem Turbo R (MSX 1, 2 e 2+) o comando é ignorado, então o mesmo programa roda em qualquer máquina.
Chame CPU R800 antes de GEO3D INIT: o INIT verifica se é um Turbo R com o R800 ligado e, só nesse caso, o GEO3D ROTATE passa a usar a multiplicação por hardware do R800 (instrução MULUW). Nas outras máquinas a multiplicação continua sendo feita em software pelo Z80, exatamente como antes.
CPU R800 ' no Turbo R: R800; nas outras: nada muda
GEO3D INIT ' detecta o R800 e escolhe a multiplicacao