Inicialmente, eu não planejava fazer uma demo no
Chaos Constritions 2018 , no entanto, 2-3 semanas antes do
cc, percebi que não podia ir a uma festa de demonstração de mãos vazias e decidi escrever uma demo curta para
386 / EGA / DOS .
Tendo compilado no
Turbo-C sob o
DOS minha
lib AnotherGraphicsLibrary , que idealmente se encaixava na estrutura do plano de batida do modo
EGA , fiquei desapontado com os freios, especialmente os freios
EGA . A demonstração na forma em que eu gostaria de vê-lo, por esse período muito limitado, era impossível de fazer.
No entanto, eu não podia desistir e não fazer nada. E então me lembrei que há muito tempo queria participar dos concursos de demonstração do
ZX-Spectrum . E como recebi dois reais de
48k no ano passado, tive prazer em criar uma demo. A propósito - para mim, a coisa mais importante ao escrever uma demonstração é testar na vida real, os
emulsificantes não dão tanto prazer ao processo, é uma sensação maravilhosa quando, após a próxima alteração no código, você carrega a demo na vida real e vê como o hardware real embaralha os bytes em efeito de desenho de memória.
Como eu tenho apenas
48k de reais, decidi fazer uma demo para
48k . E devido ao tempo limitado e à falta de desenvolvimentos, a escolha recaiu sobre a criação de
1k de introdução (demonstração de apenas 1 kilobyte ou 1024 bytes).
Na última vez,
cutuquei o
z80 asm no
EmuZWin - um ótimo emulador com montador embutido. Mas, infelizmente, o
EmuZWin não funciona com nada mais alto que o
Windows XP ou é um bug.
Tendo examinado várias opções, parei em um monte de programas
Unreal + sjAsm + Notepad ++ , que, na minha opinião, são muito
mais fáceis do que o EmuZWin em termos de conveniência, mas, por outro lado, estão vivos.
Enquanto escrevia esta introdução, conduzi, diretamente na fonte, um log de desenvolvimento, com base no qual o seguinte texto foi escrito:
Olá Mundo!
O que devo escrever primeiro, tendo quase zero de experiência no
z80 asm ? É isso mesmo, a saída do sprite 5x5 é familiar ou 40x40 pixels, para um dos efeitos (ironicamente, no futuro, para caber em 1k essa parte inacabada foi expulsa da introdução).
Surpreendentemente, foi muito fácil fazer isso do zero usando a etiqueta de endereço de linha pré-gerada usando
Down HL .
Ah, registradores de índice, quão convenientes são, mas mais lentos, literalmente consomem barras. Eu tive que jogar o uso deles em vários lugares.
Ainda aqui, no começo, me deparei com falhas
sjAsm incríveis, ou melhor, sua versão mais recente. O disrealismo em
Unreal mostrou uma sequência absolutamente louca de comandos. Baixei a penúltima versão - já era possível conviver com ela de alguma forma.

É claro que você não pode colocar um número adequado de sprites desenhados anteriormente em 1k, então decidi gerá-los dinamicamente. E de qualquer maneira, mas desenhe usando polígonos.
Portanto, o segundo procedimento que escrevi foi o procedimento para desenhar um triângulo. Na maioria das vezes, era uma portabilidade de seu próprio código escrito em
C. Com a única diferença global da versão
C , as linhas de varredura de polígono são geradas primeiro e somente então são desenhadas nessas linhas de varredura.
Depois de idiomas de alto nível, você gosta de
jr aka goto :
.sort_me_please: ld de,(tr_x2) ld bc,(tr_x0) ld a,d cp b jr nc,.skip1 ld (tr_x2),bc ld (tr_x0),de .skip1: ld de,(tr_x1) ld bc,(tr_x0) ld a,d cp b jr nc,.skip2 ld (tr_x0),de ld (tr_x1),bc jr .sort_me_please .skip2: ld de,(tr_x2) ld bc,(tr_x1) ld a,d cp b jr nc,.skip3 ld (tr_x2),bc ld (tr_x1),de jr .sort_me_please .skip3:
Fiquei um pouco chocado com o fato de que, em um tempo razoável, escrevemos um
draw_triangle em
z80 asm , que desenha um polígono pixel por pixel e sem buracos ao conectar polígonos.
Olá triângulos!Partículas

Devido à presença de um gerador de etiqueta de linha de tela, escrevi um procedimento de saída de ponto bastante curvo e lento usando essa etiqueta. O procedimento possui dois pontos de entrada - apenas o inverso do pixel e o inverso do pixel preenchendo-o com
INK +
BRIGHT + e a cor especificada em um dos registros.
No estágio de criação de um efeito com partículas, descobri que o exemplo com as estruturas dos exemplos no
wiki sjAsm simplesmente não funciona. O Google trouxe um tópico do site
zx-pk.ru , onde esse problema é descrito, e não há solução - ha, tudo bem - outra falha.
Decidi fazer tudo com clareza - atualizando as coordenadas independentemente da renderização, por interrupção. Sim ... mais bytes para gerar uma tabela de interrupção.
Havia poucas partículas nesse estágio e elas mal se encaixavam no quadro - essa é a maneira mais lenta do meu procedimento para gerar o ponto%). Mas usar uma tabela comum com sprites não me permitiu jogá-la fora e prepará-la, porque isso economizou bastante espaço na necessidade de apenas um gerador de mesa. E meu amor por bicicletas também :)
Poucas partículas ... aumentaram seu número, mas agora a renderização ficou engordada em dois quadros.
Teste no Peters WS64 , que eu peguei no último cc e consertei neste inverno :)A propósito, já nesta fase os pontos se transformaram em pontos horizontais em negrito
2: 1 , como no
Commodore 64 . Isso aconteceu por causa do número inicialmente pequeno de partículas e pela minha insatisfação com o fato de serem invisíveis quando executadas na vida real. Resolvido o problema substituindo a placa
db 128,64,32,16,8,4,2,1;
em
db 192,192,96,24,12,6,3,3;
o que piorava a precisão do posicionamento e tornava o vôo um pouco irregular, mas aumentava a visibilidade. Aqui, também jogou na mão que as partículas caíam de cima para baixo - sua visão manchada verticalmente.
Aliás, as partículas caem cada uma em sua própria velocidade aleatória e dois bytes são usados para armazenar coordenadas
Y.Sprites
Joguei fora o pedaço inacabado da parte do sprite, percebendo que não poderia encaixar
1k nela.
Além disso, já havia uma falta de espaço, então lembrei
do maravilhoso
artigo da Introspek sobre empacotadores, escolhi o
zx7 como empacotador, que economizou cerca de 110 bytes. A propósito, talvez alguém conheça um empacotador mais adequado para uma introdução de 1k?
Construções do caos

Como eu já tinha um procedimento para gerar um polígono, parecia uma boa idéia dividir o logotipo
cc em polígonos e exibi-los um por um.
Eu escrevi algum código de teste que exibe vários polígonos - tudo funcionou como eu pretendia - muito bem.
Para verificar se minha ideia se encaixa ou não em
1k , gerou um certo número de polígonos aleatórios, de acordo com estimativas, um número suficiente para o logotipo e o levou à fonte. Compilado e garantido que - excelente - a introdução, desta forma, se encaixe no limite de 1024 bytes.
Foto da vida, você reconhece o dispositivo em cima da mesa? :)))Decidi testar mais uma vez a introdução semi-acabada, já com polígonos e um empacotador, carregado para real e ... foi redefinido. Primeiro de tudo, comecei a pecar por me esquecer de inicializar a memória em algum lugar, a partir do qual, onde tudo funciona bem no emulador
0x00 , na vida real há lixo causando uma redefinição.
Nada é melhor para encontrar um lugar problemático do que o método de meia divisão e a
interrupção que eu não consegui encontrar.
Com uma redefinição do real por duas horas, não havia como localizar a falha ...
Como se viu, não estava no meu código, estava no
aprimorador de som incluído no telefone do qual carreguei WAVs. Um melhorador de um fluxo de bits em um arquivo
WAV gerou um fluxo de delírio.
Assim que desliguei tudo funcionou magicamente.
Ele delineou o logotipo no editor de gráficos de
erros greenpixel , dividindo-o em
vários triângulos e direcionou manualmente as coordenadas para a fonte. Depois de encher completamente o logotipo da
Chaos Constructions e executá-lo na vida real - fiquei feliz - parecia muito bom.
A primeira exibição do logotipo em realNo entanto, coloquei polígonos aleatórios muito pouco e, no logotipo real, havia um limite de
1k por 150 bytes. E isso apesar do efeito de partículas ainda não ter sido concluído e a transição entre as partes ter sido acentuada.
Para ir para a cama naquele dia, por causa da confusão com falhas, acabou logo às 8 da manhã 8)
E sim, tentei otimizar o tamanho armazenando as coordenadas e os índices de vértices separadamente, mas o empacotador não gostou muito, o que fez o tamanho aumentar apenas.
Final

Eu inventei como diversificar a saída do logotipo, para isso foram necessários quase nada além de mais dois rótulos de pixel:
fake_points1: db 1,2,4,8,16,32,64,128; 1 ch fake_points2: db 32,8,128,2,16,1,64,4; 2 ch normal_points: db 128,64,32,16,8,4,2,1; 3 ch
Isso deu um efeito interessante de aumentar os detalhes da renderização do logotipo, ou a falta inicial de detalhes e um aumento gradual da nitidez.
E finalmente, eu fiz a versão final com todas as transições, jogando um monte de tudo. No processo, encontrei uma falha no procedimento para desenhar um triângulo - se os dois vértices têm as mesmas coordenadas
Y , então o triângulo é desenhado tortamente (parece dividir por 0 ao calcular
dx ), ignorado com um corte temporário.
Testando a versão final em Leningrado 48Otimização de tamanho
Dígitos duplos são "bytes extras"94 bytes extras ...
Chegou a hora de cortar a preservação / restauração “cultural” dos registros dos procedimentos de entrada / saída, longe de onde for necessário, mas a memória está consumindo.
86 bytes ...
Testado na vida real - funciona! Ele perdeu um pouco mais de memória, consertando simultaneamente um bug dividido por 0 a 63 bytes!
57 bytes ...
Adicionado loop.
random_store: start:
O loop pelo caminho é feito no nível de desempacotamento, como como fonte de entropia para o
RNG , foram utilizados vários bytes do código de inicialização (para economizar espaço), que o
RNG estragou durante a primeira parte. Portanto, para repetir, após o final da introdução, há
ret , bem, e depois outra descompactação e transição para o código descompactado ...
Não foi possível me livrar dos últimos 48 bytes, tive que cortar o manipulador de interrupções, mas Hurrah! Recheado! Até 1 byte extra permaneceu.
E como não há interrupções, ele pode ser pontuado em quadros, e é difícil ver a seção transversal do feixe em um pixel no primeiro efeito, por isso aumentei o número de partículas por olho, com um comprometimento entre velocidade e entretenimento.
Picou ainda mais, movendo estupidamente códigos e dados de um lugar para outro, ajudando o empacotador. O que levou algum tempo :)
Isso liberou cerca de
10 bytes nos quais coloquei uma paródia do som. Khk, khe, som - isto é, em alguns lugares, pelo ouvido inserido:
ifdef UseSound ld a,d and
Não preguei o som, mas fiz uma definição, obtendo assim duas versões da introdução, com e sem som. Naquele sem som, em bytes "extras" amontoados
db 'e','r','r','o','r'
Eu coletei
trd e
toquei e
enviei tudo para o site da
cc .
Hooray - estou participando de demopati!
Posfácio
Acabou sendo engraçado com o som, alguém no patlace disse "som claro", alguém me olhou estranhamente e, em
pouet , encontrei o seguinte:

E isso:

Em geral, eu não entendi se alguém gostou do som de 10 bytes ou não :)
E a última - é uma pena que a competição
1k não tenha ocorrido este ano, o trabalho acabou decente, na minha opinião, mas é difícil competir com
640k , mas eu realmente queria competir.
Escreva demos, escreva 1k!E aqui está o que acabou (ps, cuide dos seus ouvidos):
Versão silenciosa: