MSX: As sete faces da SCREEN 1 (parte 1)

Para ser sincero, tanto o modo texto de 32×24, a SCREEN 1, quanto o modo gráfico de 256×192, a SCREEN 2, dos MSX são visões diferentes do mesmo modo de vídeo. Ambas apresentam a mesma resolução física e a grande diferença é justamente a maneira como o VDP está organizando, na tela, aquilo que está armazenado na VRAM.

Falando assim até parece complicado mas minha ideia neste artigo é mostrar como mais ou menos como estão organizadas as coisas na VRAM e como é possível “dizer” ao VDP para mostrá-las de um jeito um pouco diferente para se produzir alguns efeitos bastante interessantes e com um custo (quase) zero de CPU.

Este artigo está dividido em três partes, nesta primeira temos uma enxurrada teórica e na segunda (depois de amanhã) algo um pouco mais divertido. Na terceira, as conclusões a respeito.

Organização da VRAM

A ideia aqui não é explicar detalhadamente o funcionamento do TMS-9918, é só mostrar onde ficam guardadas algumas coisas na VRAM. Intencionalmente estou deixando de lado a parte dos sprites (fica para uma outra oportunidade) e aquilo que nos interessa por enquanto saber é que dos 16KB da VRAM, endereçado entre 0 e 16383 (&H0000..&h3FFF), no caso específico das SCREEN 1 e SCREEN 2, estão organizados assim:

  • A tabela de padrões encontra-se entre 0 e 6143 (&H000..&H17FF) — já explico;
  • A tabela de atributos fica entre 8192 e 14335 (&h2000..&h37FF) — calma, já explico e
  • A tabela de nomes tem 768 bytes e fica espremida entre 6144 e 6911 (&h1800..&h1AFF) — já não disse que vou explicar?

Acontece que lá na distante década de 1980, quando o 9918 foi concebido, a memória já havia começado a ficar barata mas ainda não o suficientemente, então a solução para acomodar os 49152 pontos de uma tela em 256×192 usando 12KB (ou sejam 1/4 do espaço necessário) foi esta:

  • Cada bloco de 8×1 pontos ocupa um byte e representa apenas pontos acesos (1) e pontos apagados (0). Por exemplo, um padrão de tijolos com 8×8 pontos poderia ser desenhado (em hexa, em binário ficaria enorme mas lembrem-se que F é 1111 e E é 1110) como : FE, FE, FE, 00, EF, EF, EF, 00
  • E cada um deles é colorido também por um byte, onde os 4 bits mais significativos (os primeiros da esquerda para a direita) informam a cor dos pontos acesos (INK) enquanto que os outros, os menos significativos, a cor dos apagados (PAPER). Por uma “incrível coincidência” em 4 bits cabem perfeitamente todas as 16 cores VDP. Uma fórmula simples seria INK×16+PAPER e, assim, colorir o mesmo padrão de tijolos usando belos tons de vermelho usaríamos (ainda em hexa) : 91, 81, 61, 61, 91, 81, 61, 61

Se você ainda não conseguiu visualizar os tijolos, tente assim:

10 COLOR 15,0,0:SCREEN 2
20 FOR I=0 TO 7:READ J:VPOKE I,J:NEXT I
30 FOR I=0 TO 7:READ J:VPOKE 8192+I,J:NEXT I
40 GOTO 40
50 DATA &HFE, &HFE, &HFE, &H00, &HEF, &HEF, &HEF, &H00
60 DATA &H91, &H81, &H61, &H61, &H91, &H81, &H61, &H61

A parte chata desta abordagem é que ficamos limitados a ter apenas duas cores para cada conjunto horizontal de oito pontos. Ruim? Poderia ser pior, no caso do C64 o VIC-II implementa um modo bastante parecido, o HiRES (320×200, ou 40×25), que, tal qual o ZX Spectrum (256×192, ou 32×24), a tabela de cores faz referencia blocos inteiros de 8×8 pontos — sabem o que é color clashing? É claro que também poderia ser melhor, como é o caso dos modos FLI (Flexible Line Interpretation) e MCI (Multi Color Interlace), do mesmo C64.

A parede da cozinha

Mas voltando ao MSX, o primeiro sujeito, o dos pontos acesos e apagados, é a tal tabela de padrões e a que indica as cores a tabela de atributos. Estes dois conceitos são essenciais, mas ainda faltam outros. Um deles é a tabela de nomes que, no caso dela, é mais fácil mostrá-la em ação, no programa anterior inclua:

15 FOR I=0 TO 127:VPOKE 6144+I,0:NEXT I

E agora temos uma parede de tijolos ocupando 1/6 da tela! Mas como? Antes um outro exercício, altere a linha 10 do programa para:

10 COLOR 15,4,0:SCREEN 1

O que aconteceu? A princípio a mesma coisa mas os tijolos ficaram laranja e ao pressionar <CTRL>+<STOP> e interromper o programa descobrimos que as cores de alguns caracteres estão em tons de vermelho com o fundo preto, ao invés das agradáveis letras brancas em fundo azul. Isto acontece pois, por padrão, a tabela de atributos da SCREEN 1 tem somente 32 bytes e cada um deles colore de uma vez um conjunto de 8 caracteres.

Aliás, acharam curioso o mesmo programa funcionar da mesma maneira em modo “texto” e em modo “gráfico”? Agora altere o valor de 255 para 767 na linha 15 e veja que em SCREEN 1 a tela inteira será preenchida com tijolos enquanto que na SCREEN 2 teremos apenas 1/3 da tela será digna deles. Guarde este número, o 3 é nosso número mágico!

Mas voltando à tabela de nomes, imagine que ela é (aí falando bonito) uma tabela com vetores que apontam para um conjunto de 8 elementos, da tabela de padrões e consequentemente da de atributos e indica ao VDP qual é o “ladrilho” que deve ser posto naquela área específica da tela, na SCREEN 1 é fácil de visualizá-la em ação pois justamente é o modo texto, peça o ladrilho 65 e teremos uma letra “A”! Não a vemos com a mesma facilidade na SCREEN 2 pois ela é sempre inicializada de modo a ficar invisível para nós, mas sempre é possível bagunçar um pouco as coisas:

10 COLOR 15,1,0:SCREEN 2
20 FOR I%=0 TO 63 STEP 3:LINE (I%,I%)-(63-I%,191-I%),,B:NEXT I%
30 FOR J%=0 TO 23:FOR I%=0 TO 7
40 K%=6144+J%*32+I%
50 VPOKE K%+8,VPEEK(K%)
60 VPOKE K%+16,VPEEK(K%)
70 VPOKE K%+24,VPEEK(K%)
80 NEXT I%,J%
90 GOTO 90

E assim falta explicar que a VRAM não é linear*! Ou seja, os pontos não ficam enfileirados um ao lado do outro (como ficam os caracteres em uma tela de texto). Para o VDP tudo está organizado em caixas de 8×8 pontos, enfileiradas uma ao lado da outra como a parede de azulejos da cozinha (ou do banheiro). Se por um lado facilita a criação de um modo texto, a SCREEN 1, ou mesmo a produção de jogos tão distintos como ROAD FIGHTER e THE CASTLE, por outro aumentou razoavelmente a matemática necessária para se plotar um singelo ponto na tela a partir de coordenadas X e Y:

10 X=0
20 Y=0 
30 P=(Y\8)*256+(Y MOD 8)+(X\8)*8
40 A=2^(7-X MOD 8)
50 PRINT "ENDEREÇO NA VRAM=";P,"VALOR=";A

Altere a vontade os valores das variáveis X e Y com números entre 0 e 255, no caso do X, e 0 e 191, no caso do Y e veja como pontos vizinhos no eixo cartesiano podem não estar assim tão próximos dentro da VRAM. Ou seja, o 9918 foi feito mesmo para rodar ZAXXON e não para desenhar gráficos de pizza! Só não precisa ficar com remorso por cada vez que usou o PSET, LINE, CIRCLE ou PAINT!

(*) Apesar de que é possível deixá-la “quase” linear com auxílio da tabela de nomes; E em defasa do MSX, a organização do vídeo do ZX Spectrum é mais doida ainda.

A SCREEN2 não existe!

Aqui entra o principal conceito! Lembra do meu comentário sobre SCREEN 1 e SCREEN 2 serem o mesmo modo de vídeo mas interpretados de forma diferente? No MSX-BASIC a SCREEN 1 utiliza uma tabela de padrões de 2KB, uma de atributos de 32 bytes e, quando iniciada, tem cada uma das 768 posições da tabela de nomes preenchida com o valor 32 (que é o código ASCII para o espaço em branco). Duvida?

VPOKE 256,128

A SCREEN 2 consome mais VRAM, ela utiliza para cada uma das tabelas de padrões e atributos blocos de 6KB, cada, e preenche a de nomes com três sequências de 0 até 255 (sim, 0, 1, 2, 3, … 254, 255) na tabela de nomes. Mas para todos os efeitos é como se a SCREEN 2 fosse, na realidade, não uma tela de 256×192 contígua mas sim três telinhas de 256×64 (quase que) independentes e empilhadas uma sobre a outra. E este é o último conceito! (ou ninguém reparou que 6144 e 768 são múltiplos de 3?)

Dependendo de onde mexemos nos registradores do VDP a SCREEN 1 passa a apresentar um comportamento bem diferente de um modo texto e bem e mais próximo de um modo gráfico. Esta informação está lá no datasheet do integrado mas confesso que de uma maneira meio obscura (ao menos o que eu li no texto não batia muito bem com o que eu via na prática — talvez eu possa estar lendo errado). Ou seja, não há ineditismo, o único programa que conheço a utilizar alguns destes modos é o PRINT-X-PRESS, uma suíte de três** programas (DESIGNER, COMPILER e MANUSCRIPT) que formavam um despretensioso pacote de desktop publishing.

Foi dele que copiei a técnica usada para “colorir” a SCREEN 1 que usei no LIKE e num monte de outros programas meus desde então, sendo o (pen)último o RETROMANIA. Acredito que alguns jogos japoneses também tenham utilizado estes modos híbridos e a única forma de comprovar seria usando um emulador para verificar os valores dos registradores do VDP, mas com razoável certeza é possível afirmar que os jogos que foram convertidos de speccy não usaram.

E aqui encerramos esta primeira parte, já tem informação demais por hoje. Até a segunda parte!

(**) A minha versão o programa vinha com um quarto módulo, o FONT CONVERTER, que servia para fazer a conversão de fontes do GRAPHOS III para ele e vice-versa. Uma contribuição (anônima) feita por algum brasileiro.

Sobre Giovanni Nunes

Giovanni Nunes (anteriormente conhecido como “O Quinto Elemento”) é uma das mentes em baixa resolução que compõem o Governo de Retrópolis, responsável pela identidade visual de todas as facetas do nosso Império Midiático.

0 pensou em “MSX: As sete faces da SCREEN 1 (parte 1)

  1. Muita calma com essa de scr1=scr2. Em alguns modelos de MSX1, o truque de setar apenas 1 tabela de padroes/cores para toda a scr2 simplesmente não funciona, obrigando a sempre ter 3 tabelas na VRAM.

    1. Poxa SLotman, confesso que o único canto onde vi algo assim acontecendo foi em uma versão antiga de emulador mas agora estou na dúvida sobre qual foi mas fico entre o CJS MSX e fMSX.

      1. Não conhecia o joguinho (acrescentei um link no teu comentário), darei uma olhada nele a noite.

        1. Sério? Portanto não haveria de funcionar nos DD Plus? Eu tenho um 10P mas como ele não tem fonte nunca o liguei :-/ (tem como mandar uma tela?)

          1. O DD-Plus usa o Toshiba T7937A, que suporta o mirroring das tabelas.

            Além do T6950, tem outros VDPs que dão problema com apenas uma tabela: são os TMS9918 originais (não confundir com TMS9118). Neles ocorre sobre aquecimento e corrupção dos sprites.

            Qual jogo você sugere que eu teste no T6950?

  2. Saudações! Em primeiro lugar, parabéns pela bela série sobre screen 1 e 2, que me ajudou bastante a lembrar como funcionam esses modos.

    Como o time da pesada usou os comentários para discutir uma questão sobre hardware, acredito que os mortais que perceberam o erro no programa que converte as coordenadas X e Y para o respectivo endereço e valor na VRAM tenham se intimidado em comentar.

    A linha 30 do citado código utiliza misteriosas variáveis Y8 e X8, que por razão ainda mais misteriosa aparecem entre parênteses, o que lhes dá um ar de bruxaria avançada e autenticidade. Mas como são nomes válidos para variáveis no MSX-Basic, e como não são alteradas na execução do programa, permanecem com valor 0 e o resultado carregado em P (endereço da VRAM) é decepcionante.

    Retirar o misterioso “8” (ou talvez um infinito vertical?) e deixar P=Y*256+(Y MOD 8)+X*8 não ajudou muito. Por exemplo, para Y=0, P deveria ser 0 para X<7, o que não ocorre no caso. Bom, meu "esforço" matemático para corrigir a fórmula parou aí.

    De qualquer forma, seria legal corrigir o código para que os futuros retro programadores do presente subjuntivo e atemporal fiquem ainda mais agradecidos pelo artigo.

    Grande abraço!

    1. Obrigado! Estão faltando as barras invertidas na linha 30: “P=(Y\8)*256+(Y MOD 8)+(X\8)*8”, creio que isto tenha ocorrido durante a exportação do conteúdo e mesclagem dos antigos “Retrocomputaria” e “Retrocomputaria Plus” em dezembro de 2015. Código corrigido e grato agradecido pelo “bug report”. 🙂