Curso de Basic
As Tabelas de Nomes, Caracteres e Cores do MSX 1
Você está em: MarMSX >> Cursos >> BASIC
As tabelas de nomes, caracteres e cores do MSX tem como por objetivo gerenciar o desenho da tela em todos modos gráficos do MSX 1, ou seja, as screens 0, 1, 2 e 3.
Para entender bem como funcionam essas tabelas, é necessário entender primeiro como é dividida a tela do MSX 1.
Divisão da tela no MSX
Em todas as telas, um caractere será sempre representado em memória por um bloco de 8 colunas por 8 linhas, onde cada coluna é representada por um bit e cada linha por um byte (conjunto de colunas). Desse modo, um caractere ocupará sempre 8 bytes. Entretanto, a representação de um caractere na tela diferente em cada screen, resultando em diferentes divisões de tela.
A tela é dividida em blocos de 8x6 pixels na screen 0, 8x8 pixels nas screens 1 e 2, e 8x32 pixels na screen 3, onde cada bloco equivale a um caractere. A equivalência de um caractere em cada modo de tela fica assim:
Memória
┌┬┬┬┬┬┬┬┐
├┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┤ ---->
├┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┤
└┴┴┴┴┴┴┴┘
Caractere
Tela
┌┬┬┬┬┬┐
├┼┼┼┼┼┤
├┼┼┼┼┼┤
├┼┼┼┼┼┤
├┼┼┼┼┼┤
├┼┼┼┼┼┤
├┼┼┼┼┼┤
├┼┼┼┼┼┤
└┴┴┴┴┴┘
Screen 0
Tela
┌┬┬┬┬┬┬┬┐
├┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┤
└┴┴┴┴┴┴┴┘
Screens 1 e 2
Tela
┌┬┬┬┬┬┬┬┐ 0
├┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┤
...
├┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┤
└┴┴┴┴┴┴┴┘ 31
Screen 3
Desse modo, é possível ter 40 colunas e 24 linhas na screen 0, 32 colunas e 24 linhas nas screens 1 e 2, e 31 colunas e 6 linhas na screen 3.
Para ilustrar a divisão da tela em caracteres, será paresentada a seguir a divisão da tela nas screens 1 e 2.
┌┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┐
├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤
├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤
└┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┘
Screens 1 e 2
Os blocos são numerados sempre começando da esquerda para a direita, e depois do topo para baixo. Assim, temos:
0 1 2 3 ... 39
40 41 42 43 ... 79
...
920 921 922 923 ... 959
para a screen 0, e:
0 1 2 3 ... 31
32 33 34 35 ... 63
...
736 737 738 739 ... 767
para as screens 1 e 2.
0 1 2 3 ... 31
32 33 34 35 ... 63
...
186 187 188 189 ... 191
para a screen 3.
Por exemplo, o bloco localizado no canto superior esquerdo da screen 0 é o bloco número 0, enquanto que o bloco superior direito da screen 1 é o bloco número 31 [2].
As tabelas gráficas
Uma vez entendido o conceito de divisão da tela em caracteres, podemos entender qual o objetivo de cada tabela.
Entretanto, devemos ressaltar que o VDP do MSX 1 ainda divide cada caractere em 8 blocos de 8x1 pixels (linhas).
- Tabela de Caracteres - Responsável pela definição do padrão de desenho dos pixels em cada linha de um caractere.
- Tabela de Cores - Responsável pela definição da cor de frente e fundo em cada linha de um caractere.
- Tabela de Nomes - Responsável por mapear um bloco, localizado em uma determinada posição da tela, com as tabelas de caracteres e cores.
A tabela de cores
Define as cores de frente e fundo de cada linha de um caractere.
Esta tabela trabalha sempre em conjunto com a tabela de caracteres, que definirá se o padrão de acendimento de cada pixel do grupo de 8x1 pixels é a cor de frente ou de fundo.
Cada linha é representada por um byte na tabela de cores, onde os quatro bits mais significativos definem a cor de frente, enquanto que os quatro bits menos significativos definem a cor de fundo.
Ex:
Cor de frente = ciano (código de cor 7)
Cor de fundo = cinza (código de cor 14)
Código de cor da linha: 126
Representações das cores em outros sistemas de numeração:
Binário = 01111110
Hexadecimal = 7E
Nota importante: o sistema de numeração hexadecimal torna mais fácil a identificação das cores de frente e fundo do que os demais sistemas.
Os oito bytes consecutivos na tabela de cores representam um caractere. Assim, temos:
Endereço
VRAM
-----------------------------------
8192 Primeira linha do caractere 0
8193 Segunda linha do caractere 0
8194 Terceira linha do caractere 0
8195 Quarta linha do caractere 0
8196 Quinta linha do caractere 0
8197 Sexta linha do caractere 0
8198 Sétima linha do caractere 0
8199 Oitava linha do caractere 0
-----------------------------------
8200 Primeira linha do caractere 1
8201 Segunda linha do caractere 1
8202 Terceira linha do caractere 1
8203 Quarta linha do caractere 1
8204 Quinta linha do caractere 1
8205 Sexta linha do caractere 1
8206 Sétima linha do caractere 1
8207 Oitava linha do caractere 1
-----------------------------------
...
A tabela de cores existe somente nas screens 1 e 2. O endereço delas na VRAM são:
Endereço inicial Endereço Final Tamanho
Screen 0 x x x
Screen 1 8192 8224 32 bytes
Screen 2 8192 14335 6144 bytes / 768 caracteres
Screen 3 x x x
A tabela de cores da screen 1 funciona um pouco diferente da screen 2. Veja nessa seção.
A tabela de caracteres
A tabela de caracteres é responsável por definir o padrão de desenho de cada linha dos caracteres.
Nas screens de modo texto, define o desenho de todos os caracteres de texto (letras, números e símbolos). Na screen 2, define o padrão de plotagem dos pixels em conjunto com a tabela de cores. Na screen 3, define duas cores de blocos de 8x4 pixels.
As localizações das tabelas de caracteres são:
Endereço inicial Endereço Final Tamanho
Screen 0 2048 4095 2048 bytes / 256 caracteres
Screen 1 0 2047 2048 bytes / 256 caracteres
Screen 2 0 6143 6144 bytes / 768 caracteres
Screen 3 0 2047 2048 bytes / 256 caracteres
As screens 0 e 3 não possuem tabelas de cores. Desse modo, a screen 0 possui caracteres monocromáticos. No caso da screen 3, cada linha possui blocos de 8x4 pixels (com duas cores de 4x4) e um caractere possui 8x32 pixels (8 linhas de 4 pixels).
Cada byte na tabela de caracteres representa uma linha do caractere, onde o bit "0" representa a cor de fundo, enquanto que o bit "1" representa a cor de frente. No caso da screen 0, a cor de frente é a cor acesa e a cor de fundo, a cor apagada.
Na screen 3, os bits mais significativos representam a cor do bloco 4x4 mais à esquerda. Os bits menos significativos representam a cor do bloco 4x4 mais à direita.
Exemplos:
1. Como o caractere "A" é representado na tabela de caracteres da screen 0.
VRAM Bits
2568 = 0 0 1 0 0 0 0 0
2569 = 0 1 0 1 0 0 0 0
2570 = 1 0 0 0 1 0 0 0
2571 = 1 0 0 0 1 0 0 0
2572 = 1 1 1 1 1 0 0 0
2573 = 1 0 0 0 1 0 0 0
2574 = 1 0 0 0 1 0 0 0
2575 = 0 0 0 0 0 0 0 0
2. Seja a seguinte linha de caractere:
76543210
O programa em Basic a seguir mostra como é gerada essa linha, modificando a tabelas de cores e caracteres na screen 2.
10 SCREEN 2
20 VPOKE 8192, &H7E : ' Cor
30 VPOKE 0, &B11100101 : ' Caractere
40 GOTO 40
Nota importante: o sistema de numeração binário é o mais adequado para a manipulação de pixels.
Observe o padrão utilizado juntamente com o desenho da linha:
Cor de frente (1) -
Cor de fundo (0) -
76543210
11100101 - Padrão
Encontrando um dado caractere na tabela de caracteres / cores
A partir da fórmula a seguir, podemos encontrar qualquer caractere em uma das tabelas.
endereço = endereço_inicial_da_tabela + (número_do_caractere x 8)
Ex: encontrar o endereço inicial do caractere "A" (código ASCII ou número do caractere igual a 65) na tabela de caracteres da screen 0.
endereço = 2040 + 65 x 8
endereço = 2568
Compare o endereço encontrado com o exemplo anterior da letra "A" na seção de tabela de caracteres.
A tabela de nomes
A tabela de nomes possui a função de mapear cada caractere da tela com as tabelas de caractere / cores.
Dessa forma, cada posição de caractere (definida na seção "Divisão da tela no MSX") irá apontar para uma entrada da tabela de caracteres e cores e desenhar o respectivo caractere. Esse mapeamento é possível em todas as telas do MSX 1.
As localizações das tabelas de nomes são:
Endereço inicial Endereço Final Tamanho
Screen 0 0 959 960 bytes / caracteres
Screen 1 6144 6911 768 bytes / caracteres
Screen 2 6144 6911 768 bytes / caracteres
Screen 3 2048 2239 192 bytes / caracteres
É esta tabela que irá desenhar os caracteres nas screens 0 e 1.
Exemplo:
Escrever o caractere "A" da tabela de caracteres no canto superior esquerdo da screen 0 (posição 0).
10 SCREEN 0
20 VPOKE 0,65
Este programa mapeia o caractere na posição 0 da tabela de nomes para ter o desenho da letra "A", definido pelo índice 65 da tabela de caracteres.
Gerando os caracteres especiais na tela
Conforme podemos observar na imagem da seção anterior, o uso da função CHR$ do Basic não consegue gerar os caracteres especiais de 0 a 31 (&h1F). Essa área é normalmente reservada para funções especiais de texto como nova linha (return), cls, backspace etc.
Para imprimir os caracteres da tabela ASCII localizados nessa região, o interpretador Basic espera por byte extra que sinaliza que o código de caractere em seguida é para ser impresso e não para que seja ativada a função especial de texto. Dessa forma, somamos o valor hexadecimal &H0140 ao código de caractere e esse caractere passa a ter 2 bytes em vez de 1.
Veja os exemplos a seguir.
10 PRINT CHR$(&H1)
A saída será a função especial de texto reservada para o código ASCII igual a 1.
Já no programa:
5 REM &H0140 + &H01 = &H0141
10 PRINT CHR$(&H1) + CHR$(&H41)
A saída será o caractere da carinha (micros internacionais).
Esse mecanismo funciona para os demais caracteres da tabela ASCII.
O programa ASCII na seção Basic MarMSX mostra como gerar a tabela completa para as screens 1, 2 e 5.
O truque funciona também para o armazenamento em variáveis. Veja o exemplo a seguir.
10 A$ = CHR$(&H1) + CHR$(&H41)
20 PRINT A$
Para o uso da função MKI$ do Disk Basic, temos que inverter a ordem dos bytes.
10 A$ = MKI$(&H4101)
20 PRINT A$
Considerações finais
Nos modos de texto, os caracteres são "padronizados". Desse modo, o que é alterado constantemente é a tabela de nomes. Entretanto, nada nos impede de alterar a tabela de caracteres. Mas tenha em mente que a alteração de determinados caracteres poderá deixar o texto ilegível.
Nos modos gráficos, são as tabelas de caracteres e cores que são modificadas constantemente. Porém, é possível utilizar a tabela de nomes para criar desenhos ou animações. Veremos como em outra oportunidade.
Referências
[1] - O Livro Vermelho do MSX, Avalon Software, editora McGraw Hill.
[2] - Artigo "Menu de Barras na Screen 0", MarMSX em http://marmsx.msxall.com.