Mostrando postagens com marcador assembly Z80. Mostrar todas as postagens
Mostrando postagens com marcador assembly Z80. Mostrar todas as postagens

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

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





terça-feira, 14 de julho de 2020

Blackjack para o ZX81

A ideia


Ok, eu sei, "mais um blackjack para o ZX81", mas enfim... A ideia era fazer o programa em BASIC e apenas inserir umas rotinas em assembler para deixar mais bonito e fluído. E, o mais importante, aprender com o processo.

E nesta minha primeira aventura em programar para o ZX81 (no Brasil, TK-85, CP-200, etc), realmente aprendi bastante sobre essa maquininha, suas limitações práticas de hardware, a estrutura da memória, o uso da pilha de cálculo e até as limitações, ao programador, no uso do Z80 (que comento mais ao final).

Por razões óbvias, abandonei minha ideia inicial (besta) de fazer tudo direto no emulador do ZX81, utilizando o MSX para montar as rotinas em linguagem de máquina. Acabei usando o Pasmo como assembler, e o Appmake (do pacote z88dk) para gerar o arquivo ".p".  Depois eu integro ao resto do programa BASIC usando um ótimo utilitário do próprio  ZX81 (Toolkit, da Artic).

O processo


Fiz questão de completar todo o programa em BASIC mesmo, até para conhecer as peculiaridades do Sinclair BASIC, pegar intimidade com a máquina e ver até onde chegavam as otimizações. Quando não tinha mais jeito, passei a resolver com assembler.

Pra quem não conhece o ZX81 e seus clones da vida (TK82, TK83, TK85 e CP-200 aqui no Brasil), pode soar estranho utilizar rotinas em código de máquina para um jogo tão simples. Acontece que as limitações do Sinclair BASIC e o do próprio hardware exigem que partes do programa, que rodariam tranquilamente em qualquer BASIC interpretado da época, devam ser feitas em linguagem de máquina no ZX81.

Assim, desde o início, percebi que a rotina de embaralhamento das cartas e, para minha surpresa, a atualização dos valores do "caixa" e da "aposta" na tela, teriam que ser feitas em linguagem de máquina.

Uma rotina de embaralhamento adequada simula um baralho real e permite ao jogador contar cartas durante as partidas, o que dá uma profundidade extra ao gameplay. A solução em linguagem de máquina foi bastante simples e a sua execução é praticamente instantânea.

Agora, a atualização dos valores de aposta e caixa me deu algum trabalho, quero dizer, muito mais pelo estudo que demandou do que pela solução em si. Pensei inicialmente que o problema estava no cálculo dos valores em BASIC, mas não. O que acontece é que, para imprimir um número na tela, o computador converte o valor em uma string de caracteres. E é essa conversão, feita pela ROM do ZX81, que leva uma eternidade. Então tive que fazer uma rotina própria de conversão, capturando os valores das variáveis do BASIC, para depois imprimir o resultado diretamente na tela. Como resultado, a rotina ficou bastante rápida. Nesse aprendizado, percorri todos os livros que dispunha (físicos e virtuais), mas foi o Mario Schaefer (Usando Linguagem de Máquina - Aplicações em Assembly Z80) quem me deu a dica, mas não a solução. Esta, eu fui encontrar apenas nos rolos de pergaminho de Toni Baker.

O resto foi trivial, tratando mais da parte cosmética, além de otimizações menores.

O que é executado em linguagem de máquina


  • A limpeza de tela (tanto em fundo preto, como em fundo branco). A rotina do CLS do BASIC é lenta demais, na minha opinião;
  • A impressão e a animação de parte da tela inicial;
  • O embaralhamento das cartas (como num baralho real, utilizando o algoritmo knuth shuffle) e a animação das cartas na tela; 
  • A decodificação do valor e naipe das cartas para o BASIC ;
  • A atualização dos valores do caixa e aposta na tela;
  • A impressão das cartas. Eu até gostava da velocidade de impressão das cartas no BASIC, que conferiam uma certa dramaticidade, mas no final achei que não estava mais combinando com o ritmo do resto do jogo;
  • A leitura de teclas dentro da rotina de aposta, que possibilitou um processamento mais rápido dos valores retornados no BASIC;
  • A tela final do jogo, quando o  jogador "quebra a banca" ao ganhar mais de $ 30.000.


O que aprendi nessa aventura


  • Toda a estrutura de memória do ZX81;
  • A estrutura das linhas do BASIC na memória;
  • Local e forma de armazenamento de variáveis na memória;
  • A utilização da pilha de cálculo e rotinas de cálculo do ZX81 em linguagem de máquina;

Aprendi também que "coisas terríveis irão acontecer" (crash) na execução de uma rotina em linguagem de máquina no ZX81 se você:

  • Utilizar EX AF,AF';
  • Não devolver a pilha de cálculo na mesma posição que a encontrou no início da rotina LM;
  • Ao voltar ao BASIC, não devolver HL' com o mesmo valor que entrou na rotina em LM;
  • Num cross-assembler, inserir dados em ASCII e mandar imprimir no ZX81. Isto é óbvio, mas como sou distraído, gastei uns bons minutos debugando a rotina em assembler para chegar à conclusão que ela, em si, estava correta. O problema eram os dados em ASCII, que devem ser convertidos previamente para os valores utilizados pelo ZX81.

Agradecimentos


Agradeço a Sandro Lemos pelo apoio moral, dicas de onde encontrar utilitários para o ZX81 e pelo beta-testing. Agradeço igualmente ao Daniel Afarelli, também pelo apoio moral e pelo beta-testing.





Download: blackjack.p

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...