Rotinas da BIOS e SUB-ROM do MSX 2


  A seguir são listadas as rotinas da BIOS do MSX 2 e da SUB-ROM. Utilize o MSX2 Technical Handbook [1] para maiores detalhes sobre cada rotina.
  Dos endereços 0000H a 0159H, consulte a BIOS do MSX 1, pois as rotinas são as mesmas.


  1. BIOS - Rotinas exclusivas do MSX 2

Endereço Nome Descrição
015CH SUBROM Realiza chamada inter-slot para a sub-rom do MSX
015FH EXTROM Realiza chamada inter-slot para a sub-rom do MSX
0168H EOL Apaga até o fim da linha
016BH BIGFIL Semelhante ao FILVRM
016EH NSETRD Habilita a VRAM a ser lida a partir de um endereço
0171H NSTWRT Habilita a VRAM a ser lida a partir de um endereço
0174H NRDVRM Lê o conteúdo da VRAM
0177H NWRVRM Escreve o conteúdo da VRAM


  2. SUB-ROM

  A SUB-ROM do MSX 2 se localiza em outro sub-slot diferente da BIOS. Assim, a rotina "EXTROM" da BIOS deverá ser utilizada, de forma a realizar uma chamada inter-slot e executar a rotina da SUB-ROM. O registrador IX contém o endereço da rotina da SUB-ROM a ser executada.
 LD IX, rotina
 CALL EXTROM

  Entretanto, se for necessário o uso do registrador IX por parte do seu programa, salve o conteúdo de IX e utilize a rotina SUBROM.
 PUSH IX
 LD IX, rotina
 JP SUBROM

Endereço Nome Descrição
0089H GRPRT Imprime um caractere gráfico nas screens 5-8
00C9H NVBXLN Desenha uma caixa no modo gráfico (line b)
00CDH NVBXFL Desenha uma caixa preenchida no modo gráfico (line bf)
00D1H CHGMOD Altera o modo de tela
00D5H INITXT Inicializa o modo de tela screen 0
00D9H INI32 Inicializa o modo de tela screen 1
00DDH INIGRP Inicializa o modo de tela screen 2
00E1H INIMLT Inicializa o modo de tela screen 3
00E5H INITXT Altera para o modo de tela screen 0
00E9H INI32 Altera para o modo de tela screen 1
00EDH INIGRP Altera para o modo de tela screen 2
00F1H INIMLT Altera para o modo de tela screen 3
00F5H CLRSPR Inicializa todos os sprites
00F9H CALPAT Retorna o endereço da tabela geradora de um sprite
00FDH CALATR Retorna o endereço da tabela de atributos de um sprite
0101H GSPSIZ Retorna o tamanho atual dos sprites
0105H GETPAT Retorna o padrão de um caractere
0109H WRTVRM Escreve um dado na VRAM
010DH RDVRM Lê um dado na VRAM
0111H CHGCLR Altera as três cores da tela
0115H CLSSUB Apaga a tela
011DH DSPFNK Mostra as teclas de função
012DH WRTVDP Escreve em um registrador do VDP
0131H VDPSTA Lê um dos registradores do VDP
013DH SETPAG Igual ao comando SET PAGE do Basic
0141H INIPLT Inicializa a paleta de cores e salva a atual na VRAM
0145H RSTPLT Restaura a paleta salva na VRAM
0149H GETPLT Obtém as cores de um índice da paleta
014DH SETPLT Altera as cores de um índice da paleta
017DH BEEP Dá um BEEP
0181H PROMPT Mostra o prompt
01ADH NEWPAD Lê o status do mouse ou light pen
01B5H CHGMDP Altera o modo de tela e a paleta é inicializada
01BDH KNJPRT Envia um caractere Kanji para um modo gráfico
01F5H REDCLK Lê dados do relógio do MSX 2
01F9H WRTCLK Escreve dados no relógio do MSX 2


  O exemplo a seguir ilustra o uso da SUB-ROM. Vamos desenhar uma caixa na screen 5.
  Para desenhar uma caixa em qualquer modo gráfico de 5 a 8, devemos utilizar a rotina NVBXLN. Vejamos como usar essa sub-rotina [1]:
NVBXLN (00C9H)
  Função: desenhar uma caixa
  Entradas: ponto inicial: BC para a coordenada X, DE para a coordenada Y
            ponto final: GXPOS (FCB3H) para a coordenada X
                         GYPOS (FCB5H) para a coordenada Y
            cor: ATRBYT (F3F3H) para o atributo
            operação lógica: LOGOPR (FB02H)
  Saídas: nada
  Registradores afetados: todos
  Obs: os parâmetros GXPOS, GYPOS, ATRBYT e LOGOPR são passados através da memória RAM, precisamente onde se localizam as variáveis de sistema do MSX. Dessa forma, colocamos o dado no endereço correspondente e a sub-rotina se encarrega de ler ele.

  Código em Assembly:
10 ORG &HC000
20 NVBXLN: EQU &HC9
30 EXTROM: EQU &H15F
40 CHGMOD: EQU &H5F
50 CHGET: EQU &H9F
60 GXPOS: EQU &HFCB3
70 GYPOS: EQU &HFCB5
80 ATRBYT: EQU &HF3F3
90 LOGOPR: EQU &HFB02
94 ;
95 ; -- Altera para screen 5
96 ;
100 LD A,5
110 CALL CHGMOD
114 ;
115 ; -- Prepara dados e desenha caixa
116 ;
120 XOR A
130 LD (LOGOPR),A
140 LD A,15
150 LD (ATRBYT),A
160 LD HL,100
170 LD (GXPOS),HL
180 LD HL,100
190 LD (GYPOS),HL
200 LD BC,10
210 LD DE,10
220 LD IX,NVBXLN
230 CALL EXTROM
234 ;
235 ; -- Aguarda tecla
236 ;
240 CALL CHGET
244 ;
245 ; -- Volta a screen 0
246 ;
250 XOR A
260 CALL CHGMOD
270 RET

  Programa Basic equivalente:
10 SCREEN 5
20 LINE(10,10)-(100,100),15,B,PSET
30 A$=INPUT$(1)
40 SCREEN 0

  Programa em Basic para testar o código:
10 E=&HC000
20 READ A$:IF A$="M" THEN 60
30 POKE E,VAL("&H"+A$)
40 E=E+1
50 GOTO 20
60 DEFUSR=&HC000:X=USR(0)
70 DATA 3E,05,CD,5F,00,AF,32,02
80 DATA FB,3E,0F,32,F3,F3,21,64
90 DATA 00,22,B3,FC,21,64,00,22
100 DATA B5,FC,01,0A,00,11,0A,00
110 DATA DD,21,C9,00,CD,5F,01,CD
120 DATA 9F,00,AF,CD,5F,00,C9,M


  O Relógio do MSX

  A partir do MSX 2, foi inserido um chip de relógio que é mantido ativo com uma bateria, preservando as horas do sistema sempre atualizadas, mesmo com o micro desligado.
  O chip, chamado de CLOCK-IC, possui uma SRAM que armazena as informações de data e hora, alarme e algumas configurações do MSX.
  O CLOCK-IC possui quatro blocos de memória, endereçados de 0 a 12 (registradores) [2].

  Blocos:
  1. Relógio
  2. Alarme
  3. Configurações do MSX
  4. Configurações título/password/prompt

  Os blocos e seus respectivos registradores [2] serão descritos a seguir.

Bloco 0 - Relógio Bloco 1 - Alarme
Descrição bits
7654 3210
Descrição bits
7654 3210
Segundo x111 0000    
Minuto x333 2222 Minuto x333 2222
Hora xx55 4444 Hora xx55 4444
Dia da semana xxxx x666 Dia da semana xxxx x666
Dia xx88 7777 Dia xx88 7777
Mês xxAA 9999 12/24 horas xxxx xxxA
Ano xxCC BBBB Ano bissexto xxxx xxBB


  Cada registrador possui 4 bits. Na tabela acima, os bits são representados pelo número do registrador, configurados da seguinte maneira:
Dezena   Unidade
reg+1    reg
  Por exemplo, para a data o registrador 8 retorna 1 e o registrador 7 retorna 3:
Dezena Unidade
  1      3
Reg#8   Reg#7

O dia é 13.
  Obs: o dia da semana, 12/24h e ano bissexto vão ler somente um registrador, que é o valor final do dado.

  O ano é representado por dois dígitos apenas. Para calcular o ano, devemos somar 80 ao valor encontrado, pois 1980 é o ano base.

  No bloco de alarme, a opção 12/24 horas configura a saída de hora no sistema para 12 horas (0) ou 24 horas (1). Por exemplo, 5 horas da tarde será representado por "5:00 pm" no modo 12 horas, e "17:00" no modo 24 horas.
  No modo 12 horas, o bit 1 do registrador 5 do bloco 0 indica 0 para "am" e 1 para "pm".

  O registrador 11 do bloco 1 indica se um ano é bissexto, quando o valor retornado é 0.


Bloco 2 - Conf. MSX
Reg. bit 3 bit 2 bit 1 bit 0
0 ID
1 Ajuste horizontal (-8 a +7)
2 Ajuste vertical (-8 a +7)
3 - Interlace Screen
4 Largura da tela (WIDTH) - low
5 Largura da tela (WIDTH) - high
6 Cor de frente
7 Cor de fundo
8 Cor da borda
9 Cassette Printer Click Keys
10 Tom do beep Volume do beep
11 - Tela de boot
12 Código nativo


  O bloco 3 pode armazenar três tipos de informações distintas, dependendo do valor do ID no registrador 0:   Para os IDs 0 e 2, os registradores de 1 a 12 armazenam os 6 caracteres da seguinte forma:
Registrador   Dado
----------------------------------
     1        Caracterere 1 (low)
     2        Caracterere 1 (high)
     3        Caracterere 2 (low)
     4        Caracterere 2 (high)
     5        Caracterere 3 (low)
     6        Caracterere 3 (high)
     7        Caracterere 4 (low)
     8        Caracterere 4 (high)
     9        Caracterere 5 (low)
    10        Caracterere 5 (high)
    11        Caracterere 6 (low)
    12        Caracterere 6 (high)

  Exemplo de como a letra "A" é armazenada como o caractere 1:
Código ASCII: &H41

high  low
 4     1

Registrador  1  2
Valor        1  4

  Registrador de modo #13:

  O registrador de modo serve para selecionar um bloco, ligar/desligar o alarme e ligar/desligar o relógio. Ele é acessado independentemente do bloco selecionado.
  Configuração dos 4 bits:
3 2 1 0
R A M M

R - Relógio, onde 0-parado e 1-funcionando.
A - Alarme, onde 0-desligado e 1-ligado.
M - Modo, que equivale ao número do bloco.

  Funções da SUB-ROM para leitura e escrita no relógio do MSX:
REDCLK (01F5H)
Função: Ler um registrador do CLOCK-IC.
Entrada: C - endereço do CLOCK-IC.
Saída: A - Dado lido (somente os primeiros 4 bits). 
WRTCLK (01F9H)
Função: Escrever no registrador do CLOCK-IC.
Entrada: C - endereço do CLOCK-IC.
Saída: A - Dado a ser escrito (somente os primeiros 4 bits). 

  Onde o endereço do CLOCK-IC é:
Bit 7 6 5 4 3 2 1 0
        B B E E E E

B - Bloco, de 0 a 3.
E - Endereço, de 0 a 15.
  Por exemplo, para acessar o registrador 4 (&HB0100) do bloco 1 (&HB001), colocamos em C: 0001 0100.


  Programa em Assembly para ler o dia armazenado no relógio, no bloco 0.
10 ORG &HC000
20 EXTROM: EQU &H15F
30 REDCLK: EQU &H1F5
40 LD C,&HB00001000
50 LD IX,REDCLK
60 CALL EXTROM		; Lê registrador 8
70 LD (&HD000),A	; Armazena o resultado da dezena em D000
80 LD C,&b00000111
90 LD IX,REDCLK
100 CALL EXTROM		; Lê registrador 7
110 LD (&HD001),A	; Armazena o resultado da unidade em D001
120 RET
  Ao rodar o programa, buscar o resultado em &HD000 e &HD001.

  Teste no Basic. Substitua as linhas 70-120 do programa de teste do desenho do retângulo por essas linhas:
70 PRINT"Dia:";PEEK(&HD000)*10+PEEK(&HD001)
80 DATA 0E,08,DD,21,F5,01,CD,5F
90 DATA 01,32,00,D0,0E,07,DD,21
100 DATA F5,01,CD,5F,01,32,01,D0
110 DATA C9,M
  Troque o número dos registradores (assinalados em vermelho) por outros e teste, por exemplo, o mês e ano.

  O programa em Basic a seguir lê as informações do bloco 2 do CLOCK-IC.
10 E=&HC000
20 READ A$:IF A$="M" THEN 60
30 POKE E,VAL("&H"+A$)
40 E=E+1
50 GOTO 20
60 DEFUSR=&HC000:X=USR(0):CLS
70 PRINT"Informacoes do relogio do MSX":PRINT
80 PRINT"ID:";PEEK(&HD000)
90 POKE &HC001,&H21:X=USR(0)
100 PRINT"Ajuste horizontal:";PEEK(&HD000)
110 POKE &HC001,&H22:X=USR(0)
120 PRINT"Ajuste vertical:";PEEK(&HD000)
130 POKE &HC001,&H24:X=USR(0):A=PEEK(&HD000)
140 POKE &HC001,&H25:X=USR(0)
150 PRINT"Width:";PEEK(&HD000)*16+A
160 POKE &HC001,&H26:X=USR(0)
170 PRINT"Cor de frente:";PEEK(&HD000)
180 POKE &HC001,&H27:X=USR(0)
190 PRINT"Cor de fundo:";PEEK(&HD000)
200 POKE &HC001,&H28:X=USR(0)
210 PRINT"Cor da borda:";PEEK(&HD000)
220 POKE &HC001,&H29:X=USR(0)
230 PRINT"Printer:";INT(PEEK(&HD000)/4)
240 PRINT"Click:";INT(PEEK(&HD000)/2) AND 1
250 PRINT"Keys:";PEEK(&HD000) AND 1
260 POKE &HC001,&H2A:X=USR(0)
270 PRINT"Tom do beep:";INT(PEEK(&HD000)/4)
280 PRINT"Volume do beep:";PEEK(&HD000) AND 3
290 POKE &HC001,&H2B:X=USR(0)
300 PRINT"Tela de boot:";PEEK(&HD000) AND 3
310 POKE &HC001,&H2C:X=USR(0)
320 PRINT"Codigo nativo:";PEEK(&HD000)
500 DATA 0E,20,DD,21,F5,01,CD,5F
510 DATA 01,32,00,D0,C9,M

  Programa em Basic para verificar o título ou prompt armazenado no CLOCK-IC.
10 E=&HC000
20 READ A$:IF A$="M" THEN 60
30 POKE E,VAL("&H"+A$)
40 E=E+1
50 GOTO 20
60 DEFUSR=&HC000:X=USR(0):CLS:DIM N$(2)
70 N$(0)="Titulo":N$(1)="Senha":N$(2)="Prompt"
80 PRINT"Informacoes do relogio do MSX":PRINT
90 PRINT"Tipo: ";N$(PEEK(&HD000)):PRINT"String: ";
100 FOR I=1 TO 12 STEP 2
110 POKE &HC001,VAL("&H3"+HEX$(I)):X=USR(0)
120 A=PEEK(&hD000)
130 POKE &HC001,VAL("&H3"+HEX$(I+1)):X=USR(0)
140 PRINT CHR$(PEEK(&HD000)*16+A);
150 NEXT I
500 DATA 0E,30,DD,21,F5,01,CD,5F
510 DATA 01,32,00,D0,C9,M



  Referências:

  [1] - MSX2 Technical Handbook, ASCII Corporation, 1987.
  [2] - MSX Top Secret 2, Edison Moraes, 2004.


MarMSX 2018