Mostrando postagens com marcador 8-bit. Mostrar todas as postagens
Mostrando postagens com marcador 8-bit. Mostrar todas as postagens

quarta-feira, 1 de abril de 2026

E uma bruxa passou pela minha janela

 

Um tanto atrasado para o Halloween de 2025, um tanto adiantado para o Halloween de 2026. Tenho tido pouco tempo para programar, então o desenvolvimento dos projetinhos tem sido mais lento. Porque caótico, sempre foi mesmo. Além disso, juntar forças para organizar, documentar e descrever o processo aqui no blog também é uma mão de obra a parte. Mas, de qualquer forma, é sempre uma satisfação quando o publico o registro da peripécias por aqui. Então vamos lá.

Sempre quis trabalhar com a ideia de animação suave no ZX81, então me propus a fazer um programa com as seguintes características:

  • a animação de uma bruxa voando de vassoura pelo céu, em movimento horizontal, da perspectiva de quem a estivesse vendo por uma janela;
  • a animação deveria ser o mais suave possível, dentro das limitações do computador. Então deveria ser pixel por pixel, e não caractere por caractere;
  • a bruxa deveria surgir aos poucos de um lado da tela, e desaparecer aos poucos do outro lado da tela;
  • a bruxa deveria voar em velocidades diferentes, escolhidas aleatoriamente a cada passagem;
  • a bruxa deveria voar em direções diferentes (esquerda para a direita ou direita para a esquerda), escolhidas aleatoriamente a cada passagem;
  • a bruxa deveria voar em alturas diferentes na janela, escolhidas aleatoriamente a cada passagem.

Primeiramente, fui achar uma pixel art de uma "bruxa-de-vassoura" em baixa resolução, em um tamanho bacana para a resolução do ZX81.

Depois que encontrei, copiei a figura ponto por ponto, utilizando uma ferramenta rústica para desenhar que fiz no Sinclair BASIC, utilizando os comandos PLOT e UNPLOT. Com ela, ao terminar o desenho, posso transferir a tela toda para uma variável (sim, o ZX81 permite isso) e assim salvar o desenho. Há também uma rotina para enviar a tela para a RAMTOP, o que permite utilizar o desenho em outro programa.

Para implementar a ideia de movimento ponto por ponto e não caractere por caractere, desenhei 4 sprites da bruxa:  dois com ela na direção esquerda para a direita, e mais dois com ela da direita para a esquerda. Isso porque a tela do ZX81 não é realmente dividida em pixels, mas em caracteres, cada um podendo representar 4 pixels (acesos ou apagados). Então o desenho que emula a bruxa um pixel à direita ou um pixel à esquerda é formado por um conjunto de caracteres gráficos completamente diferente. O quadro abaixo, com o exemplo de uma figura bem simples, de 3x2 caracteres, ilustra melhor o que estou dizendo:

 

A animação, em assembly, eu quis fazer utilizando ferramenta nativa, então usei o ZX Assembler. Entretanto, como passaria os dados dos desenhos para o programa-fonte a ser editado no assembler? A solução for fazer um patch do programa-fonte do ZX Assembler, inserindo os dados dos desenhos diretamente na área de memória onde se encontrava o programa-fonte, com os seguintes passos:

  1. Primeiro, no editor do ZX Assembler, inseri linhas de dados no programa-fonte, para criar espaço e salvei;
  2. Depois baixei a RAMTOP para 30000 e carreguei o programa com o desenho; 
  3. A seguir, utilizei uma rotina (que já estava pronta no programa para desenhar) e passei a tela do desenho para a RAMTOP;
  4. Carreguei o programa-fonte do ZX-Assembler e apaguei a linha 1, que contém o código-objeto gerado pelo assembler. Assim poderia descobrir com mais facilidade os endereços dos dados no programa-fonte do assembler;
  5. Com o programa-fonte na memória, programei uma rotina para descobrir, com PEEKs, o endereço inicial e final de cada linha de dados;
  6. Anotei o endereço inicial dos dados da primeira linha;
  7. Anotei quantos bytes deveria pular para recomeçar a inserir os dados a cada nova linha do programa-fonte;
  8. Com essas informações anotadas, escrevi um programinha em BASIC que passasse cada linha do desenho de cada bruxa (com 14 bytes por linha), que estava na RAMTOP, para cada linha de dados que eu havia reservado, pulando, evidentemente, os bytes de formatação do programa-fonte.

O resultado foi esse, na listagem do programa fonte dentro do editor do ZX Assembler: 

 

A seguir, programei a animação. Conforme planejado, alternei 2 desenhos da bruxa em cada direção para emular que ela se dava ponto-por-ponto antes de passar para a posição na tela. 

Enfim, quando já via a bruxa voando pela tela, naquele momento achei que estava faltando algo na animação. Então defini mais alguns elementos a serem implementados:

  • Que deveria haver estrelas no céu, representadas por asteriscos;
  • Que as estrelas apareceriam em posições aleatórias no céu;
  • Que as estrelas, obviamente, deveriam parecer estar em um plano mais afastado em relação ao plano da bruxa (a bruxa passando em frente às estrelas).

Então escrevi mais essa parte do programa até atingir o resultado desejado. Apesar de o sprite da bruxa ser, na realidade, branco (a bruxa) sobre fundo preto, o resultado final o sprite da bruxa parece ter fundo transparente, como num sprite por hardware. 

Animação finalizada, faltava ainda uma mensagem "Happy Halloween" alternando com as animações. Fiz como transição um efeito "veneziana", se abrindo, ou se fechando, para ficar coerente com a ideia da janela. Depois desenhei, na munheca, a mensagem de "Happy Halloween!!!" junto a uma lanterna de abóbora (jack-'o-lantern), que fiz "piscar" algumas vezes, invertendo as cores da tela, antes de usar novamente o efeito de transição e reiniciar a animação. O envio dos dados da tela com a mensagem foi feito da mesma maneira que procedi com as figuras da bruxa, com a diferença de que eram bem mais dados a serem transferidos ao código-fonte do montador (420 bytes).

Nessa aventura, um dos meus objetivos era testar os limites práticos, em termos de memória, do ZX Assembler. De fato, nas últimas montagens do programa, recebi mensagem de que a memória estava cheia. Na memória RAM de 16kB do ZX81 ficam o montador (ZX Assembler), o código-fonte do usuário (que reside na linha 2 do BASIC), e o código-objeto do usuário (que reside na linha 1 do BASIC), além de outras linhas de programa BASIC eventualmente utilizadas. Após a mensagem de "memória cheia", tive que fazer alguns ajustes, cortando desperdícios em linhas de comentários e fazendo algumas otimizações para reduzir o tamanho do programa.

Na versão final, ainda programei os créditos que aparecem no início da execução do programa. Não sobraram muitos bytes depois disso.

O "artesanato" dá trabalho, mas ver o resultado na tela é impagável, principalmente na de tubo. No vídeo abaixo é possível conferir como ficou, rodando no TK85: 


 O download do programa está disponível aqui.

[update 07.04.2026: fiz alguns ajustes e calibrei melhor a temporização das transições, de modo a levar em consideração a diferença de velocidade de processamento entre o ZX81 e o TK85]. 

 

quinta-feira, 18 de setembro de 2025

Os padrões de ladrilhos de Truchet para o ZX81

Depois de fazer o programa de apresentação dos ladrilhos de Truchet para MSX,  cuja origem, história e processo descrevi em outro artigo publicado neste blog, fiquei pensando sobre um programa semelhante no ZX81, mesmo com as suas limitações gráficas.

No MSX, cada ladrilho (tile) equivale a um caractere de 8x8 pixels, para uma tela de resolução de 256x192. No ZX81, utilizar ladrilhos 8x8 seria inviável, tendo em vista que, pela baixa resolução do micro (64x48), a tela comportaria a impressão de poucos ladrilhos, impossibilitando o efeito visual que justamente se dá pelo conjunto dos diversos ladrilhos organizados em padrões.

Pensei então em ladrilhos em uma grade de 4x4 "pixels", formados por 4 caracteres gráficos do ZX81. Mãos à obra, iniciei por desenhar os ladrilhos e encontrar os códigos dos caracteres gráficos correspondentes. Na mão mesmo:

Em seguida, escrevi um programinha em BASIC no TK85 para testar e dispor os ladrilhos na tela. Ali pude constatar que valia a pena seguir em frente.

Conforme contei no artigo sobre os ladrilhos no MSX, havia feito um programa em BASIC para entrar como os dados dos padrões em linhas DATA. A ideia agora era reaproveitar os dados do MSX e exportá-los para o programa assembly do ZX81 que, já estava decidido, seria montado no Pasmo. 

Com este propósito, no MSX, utilizei duas ferramentas simples.

Primeiro, utilizei um programa para jogar os dados das linhas DATA com os padrões de Truchet para a memória do MSX, que eu já havia utilizado na versão para aquela máquina. Fiz algumas adaptações dos dados para o ZX81, porque o MSX utiliza o código de caracteres ASCII e, na época do desenvolvimento do ZX81, a Sinclair Research achou por bem utilizar seu próprios códigos de caracteres. Então, ao mover os dados para a memória, fiz um filtro de conversão dos caracteres ASCII que nomeiam os padrões de Truchet (A-Z, 1-6), para os respectivos códigos do ZX81 (de caracteres invertidos, mais especificamente). Tive que improvisar com o padrão nomeado por Truchet de "&", caractere que simplesmente não existe no ZX81, colocando um "+" no seu lugar. No mais, converti também o código dos caracteres redefinidos no MSX, nºs 192, 193, 194 e 195, que não fariam sentido no ZX81, para 0, 1, 2 e 3. 

Feito isto, utilizei outro programa, que eu eu já possuía, para ler os bytes da memória e gerar linhas de dados (DEFB) num arquivo ASCII. Este programa eu havia utilizado para exportar a tabela com caracteres katakana e outros caracteres redefinidos quando escrevi a versão do programa Matrix - Raining Code para MSX-DOS, o que fiz utilizando o excelente Gen80, da Hightech.  

A partir daí, poderia passar a trabalhar no programa assembly para o ZX81, uma vez que a estrutura dos dados já havia sido testada na versão para MSX.

Programa no MSX-BASIC para geração de linhas DEFB num arquivo ASCII

Em seguida, exportei o arquivo ASCII resultante, através de um comando do emulador openMSX, para uma pasta, a fim de que depois pudesse importá-lo no editor de texto que utilizo nos projetos para ZX81, o glorioso nano. É isso mesmo, vivo no terminal do Linux Debian de um Raspberry Pi dedicado à retroprogramação. Sem firulas de interface gráfica: salvo o programa do editor, executo um shell script para, numa tacada, montar o programa no Pasmo, gerar o arquivo .p (com o appmake) e já mover esse arquivo para a pasta do emulador de ZX81, o qual deixo ativo em outro terminal TTY para que eu possa testar o programa recém montado. É um fluxo de trabalho que funciona muito bem.

Sobre o programa assembly, ainda que o MSX e o ZX81 tenham a mesma CPU, optei por reescrever o programa para o ZX81 do zero. As peculiaridades do hardware de vídeo do MSX (com processador de vídeo dedicado e memória de vídeo externa) versus as peculiaridades da estrutura da memória de vídeo do ZX81 (D_FILE), fizeram-me pensar que escreveria um código melhor se não aproveitasse o anterior. 

Mas de qualquer forma, implementei os mesmos recursos da versão MSX: apresentação dos padrões em tela cheia, com passagem automática após alguns segundos para o próximo padrão, passagem manual ao próximo padrão (para quem tem pressa neste mundo) pressionando SPACE e, ainda, opção de ativar ou desativar as legendas que nomeiam o padrões, pressionando NEW LINE. Volta-se ao BASIC pressionando "Q". Fiz também uma moldura com caracteres "cinzas", para que os desenhos dos padrões não emendassem com a borda branca da tela do ZX81, o que altera um tanto o efeito dos padrões. O resultado se vê no vídeo abaixo que, de de minha parte, considero bastante satisfatório. Estrelando, o TK85 da Microdigital:

Depois que gravei esse vídeo, ainda acertei uns pequenos detalhes. O arquivo do programa em formato .p está disponível no link abaixo.

Download do arquivo .p

quarta-feira, 17 de setembro de 2025

Os padrões de ladrilhos de Truchet para MSX

Mais uma vez, assistindo ao excelente canal do Youtube 8-Bit Show and Tell, tomei gosto pela história ali contada e resolvi replicar o programa, feito pelo Robin para o Commodore 64, no seu primo contemporâneo, o MSX.

Não é a primeira vez que isso acontece. Também me empolguei quando vi o vídeo sobre o "Pitfall Pamphlet", no mesmo canal, e fiz uma versão para MSX, que publiquei aqui uns anos atrás.

Desta vez, o episódio era sobre os "Ladrilhos de Truchet em PETSCII" (Truchet's tiles in PETSCII) que, resumidamente, conta a história do estudo com padrões de ladrilhos feito pelo padre dominicano Sébastien Truchet, em 1704. Em seguida, o apresentador mostra um programa feito por ele que imprime os padrões de Truchet na tela do C64.

Ao trabalho, comecei por obter a publicação original de Truchet, que foi feita no Memoires de l'Academie Royale des Sciences, de 1704, que era uma espécie de um anuário científico com diversos artigos sobre matemática, física, etc. A propósito, acho fantástico que possamos ter acesso a esses tipos de documentos históricos pela internet.

O estudo de Truchet, chamado Memoire Sur Les Combinaisons, inclui 30 padrões diferentes. Mostro aqui os primeiros 12, por brevidade: 

Primeiros doze padrões do estudo de Truchet.

Como se pode observar, os padrões são elaborados a partir de um único ladrilho quadrado, dividido diagonalmente, metade preto, metade branco, sendo este ladrilho rotacionado nas quatro posições a seguir:

 

Ladrilhos, do original 
 

O MSX não tem os caracteres necessários na sua tabela padrão, como é o caso do  Commodore 64 (PETSCII). Por isto, utilizando o meu editor de caracteres "Pixit", redefini os caracteres nºs 192,193,194 e 195 (escolhidos a esmo), para que correspondessem aos ladrilhos nas quatro posições originais. 

Detalhe da edição no Pixit.
Como bem observou o Robin no seu vídeo, se tentarmos dividir uma grade 8x8 numa diagonal, com uma "metade" de pixels acesos e a outra "metade" apagados, na realidade, o número de pixels acesos e apagados nunca será igual numa grade quadrada de dimensões pares: a própria linha diagonal que divide as metades deverá ser composta ou de pixels acesos, ou de pixels apagados. Optei por uma maior quantidade de pixels apagados (pretos), porque achei que ficaria mais próximos ao desenhos originais, que possuem linhas divisórias pretas entre os ladrilhos.

Como a definição dos 4 caracteres corresponde a apenas 32 bytes, anotei os hexadecimais (descritos na lateral esquerda da grade de edição), para depois passar os dados ao programa.

Em seguida, escrevi um programa no MSX BASIC, onde poderia entrar manualmente com os dados dos padrões (através de linhas data) e, ainda, testar a estrutura dos mesmos, visualmente, na tela. Fui então traduzindo, por análise visual, cada padrão para os dados correspondentes. O padrão "A", por exemplo, é uma matriz de 1 linha por 1 coluna, e o caractere utilizado, na minha convenção, é o 192. A linha data seria:

DATA 1,1,192 

O padrão "B", é composto de 2 linhas e 1 coluna, e os caracteres são 192 e 194:

DATA 2,1,192,194

O padrão "C", é composto de 2 linha e 2 colunas, e os caracteres são 192 e 194 na primeira linha, e 194 e 192 na segunda:

DATA 2,2
DATA 192,194
DATA 194,192 

E assim por diante. Dá para perceber que o estudo de Truchet vai se tornando mais complexo a cada padrão apresentado. 

Claro, é um bocado de dados digitados manualmente. Um dos padrões, sozinho é uma matriz de 12x12, ou seja, só ali são 144 bytes. Mas isso não é nada para quem viveu a experiência oitentista de digitar programas de revistas, cheios de linhas data maçantes e que, frequentemente, continham dados errados. Assim, imbuído da daquela paciência de artesão, que vê com prazer o resultado das minúcias de seu trabalho surgir aos poucos, dei sequência e logo concluí a empreitada.  

Acrescentei ainda, no início dos dados de cada padrão, a letra ou número que Truchet utilizou para nomeá-los. Achei que ficaria interessante mostrar a identificação original numa legenda abaixo do padrão. No final, ficou assim o resultado do programa BASIC na tela: 

 

Como se vê, a ideia do programa é, preencher a tela toda com um padrão, tenha ele a dimensão que tiver (1x1, 2x1, 4x4, 10x10). No BASIC, reduzi o tamanho da janela de impressão porque a intenção do programa ali era apenas servir de teste e porque o interpretador demorava um tanto para imprimir cada tela. Na verdade, durante os testes, por questão de agilidade, a janela era ainda menor do que aparece aí na imagem acima. Depois é que dei uma melhorada na estética. Entretanto, na versão definitiva, em assembly, a tela toda viria a ser utilizada, 32x24, na Screen 1. 

Encerrada esta etapa do BASIC, era hora de iniciar o programa em assembly. Comecei escrevendo no Mega Assembler o código que mostrasse na tela toda um padrão de 2 linhas por 3 colunas, com dados quaisquer (utilizei as letras ABC e DEF, só para testar o mecanismo).

Com o mecanismo básico funcionando a contento, utilizei o BASIC mais uma vez. Carreguei o programa dos ladrilhos em BASIC e apaguei toda a parte que imprimia os dados na tela, deixando apenas as linhas de dados. Então escrevi uma rotina para jogar os dados na memória RAM e, ao final, apresentar o endereço final dos mesmos. Escolhi como endereço inicial C000H (na realidade, depois alterei esse endereço para C200H):


Executado o programa, agora eu possuía o endereço inicial e o endereço final dos dados. Salvei-os com o comando BSAVE num arquivo de formato binário.

Em seguida, alterei o endereço inicial de montagem do programa em assembly para o byte imediatamente seguinte ao do final dos dados, de forma que poderia salvar tudo com BSAVE em um único binário, com o endereço inicial dos dados, o endereço final do executável e o respectivo endereço de execução.

Depois foi "só" uma questão de depuração do programa, otimização, ajustes e inclusão de alguns recursos, como a possibilidade de se incluir ou retirar as legendas nas telas apresentadas (teclando RETURN) e de se avançar manualmente a apresentação dos padrões (teclando ESPAÇO), já que se nenhuma tecla for pressionada, o programa vai exibindo automaticamente cada padrão por alguns segundos, como numa apresentação. ESC volta ao BASIC.

Acrescento ainda, como curiosidade, a rotina que impedia a repetição das teclas pressionadas, que estava funcionando normalmente no emulador, no Expert estava resultando em salto dos padrões que deveriam ser apresentados. Fiz a edição do ajuste necessário no Mega Assembler, no Expert. Pra se ver que emulação nunca é 100%.

E o resultado final é esse do vídeo abaixo, em toda a glória de uma TV de tubo.

Imagem do disco para download

 

 
 


 

 

domingo, 31 de outubro de 2021

Doom Fire para MSX, ZX81 e TRS-80

Após descobrir o tal "algoritmo do fogo do Doom", cuja existência até então ignorava por completo, resolvi brincar com ele. Desta vez, fiz logo três versões de uma vez. 

Primeiro para o ZX81, onde desenvolvi o mecanismo e fui otimizando o código. Depois disso, portar para o TRS-80 foi bem tranquilo. Na verdade colocar coisas na tela do TRS-80 é mais simples do que no ZX81, então foi só um pequeno trabalho de descomplicação. 

Já no MSX, tive que aprender como funciona a tela no modo 3 (multicolor), que nunca havia lidado a não ser no BASIC. A cada frame os dados são processados em três etapas. A primeira atualiza os valores dos 1536 bytes correspondentes, cada um, a uma célula do fogo. Como a Screen 3 não é um modo bitmap, os dados são organizados, na segunda etapa, para que fiquem dispostos num buffer da maneira que exige o processador gráfico. Só então os dados são impressos na tela, numa terceira etapa.

A versão do ZX81 desenvolvi na tabelinha nano/Pasmo, testando no emulador sz81. A do TRS-80, fiz no EDTASM, rodando no emulador SLDTRS. E a do MSX fiz no Mega Assembler, rodando no openMSX. 

Download: Doom Fire - MSX/ZX81/TRS-80

Versão MSX (a versão final tem a animação um pouco mais fluída do que a que aparece no vídeo):


Versão TRS-80:


Versão ZX81:








sábado, 30 de outubro de 2021

Matrix - Raining Code para TRS-80



Portar o código em si do ZX-81 para o TRS-80 foi bem simples. O que me deu um pouco mais de trabalho foi entrar no mundo do TRS-80. Como só uso ferramentas externas em último caso (em único caso, na verdade, do ZX-81, que uso cross-assembler), aprendi basicamente como funciona o emulador SDLTRS, o sistema operacional do TRS-80 e o assembler EDTASM. Levei um tempinho pra me acostumar com todas essas novidades, mas valeu a pena. Afinal eu me meto nessas velharias mesmo pra ter o prazer de aprender e lidar com elas.  E faz tempo que eu queria mexer com o TRS-80, porque o CP-500 foi um dos primeiros computadores que vi funcionar. E que impressão aquele monstrinho branco dava!

Bom, segue o download de uma imagem de disquete contendo o programa.

Download: Matrix - Raining Code - TRS-80




quinta-feira, 23 de julho de 2020

Matrix - Raining Code para o ZX81

Portei  para o ZX81(linha que no Brasil foi representada pelo TK-85, CP-200, etc) o programa que havia escrito para o MSX. Uma boa parte teve que ser reescrita, principalmente porque na versão para MSX eu utilizei o modo gráfico ("screen 2"). O algoritmo de animação, de um modo geral, é o mesmo, respeitadas as limitações da maquininha.

Para inciar o programa, digite RUN. Para interromper a execução, tecle NEW LINE.

Atualização em 20.07.2024: fiz uma versão para máquinas capazes de gerar vídeo reverso (fundo preto com caracteres em branco). Assim, no pacote ZIP há duas versões, a normal (matrix.p) e a para vídeo reverso (matrix-r.p). Eu aproveitei para fazer alguns ajustes, em especial, agora o programa irá rodar aproximadamente na mesma velocidade em computadores NTSC/PAL-M ou PAL europeu (60/50Hz de sincronismo vertical).

Download: Matrix-ZX81.zip





domingo, 3 de novembro de 2019

Matrix - Raining Code no MSX

Implementação do efeito "raining code" no MSX, em assembler, utilizando a "screen 2". Para retornar ao Basic, tecle ESC.

Programa montado no Mega Assembler.

Update 15.10.2020

Fiz algumas alterações e ajustes no programa .bin. Agora o programa inicia com mensagens no "terminal".

Também fiz uma versão para MSX-DOS (matrix.com). Para isso, desta vez utilizei o Gen80. No final, a adaptação foi mais simples do que imaginei. Digo, "mais simples" depois de pronto, porque levei um tempinho pra descobrir como fazer. Leiam os manuais! Agradeço a ideia da versão DOS, dada por Xavi Sorinas. ¡Muchas gracias, Xavi! 

As duas versões estão em imagens de disco separadas, dentro do pacote compactado.

Download: Matrix - Raining Code


O vídeo é da primeira versão, mas dá pra ter uma ideia de como funciona:

 

E uma bruxa passou pela minha janela

  Um tanto atrasado para o Halloween de 2025, um tanto adiantado para o Halloween de 2026. Tenho tido pouco tempo para programar, então o de...