terça-feira, 27 de julho de 2010

Upgrade histórico

Eu queria ter instalado drives de 3.5" no meu BBC B+ há 20 anos. Infelizmente, naquela época, os drives eram caros, eu pouco sabia sobre o assunto e os drives de 5.25" ainda funcionavam bem. As circunstâncias não eram propícias.

A foto abaixo (estrelada pela linda Maria Alice) mostra a configuração campeã. É um BBC B+ com 128KB de RAM e um processador 65C12 a 2MHz. Há também um monitor com conector TTL RGB e um par de drives de 5.25" que funcionam mal.


A controladora dos drives é uma Western Digital 1770. Ela é capaz de suportar densidade simples e densidade dupla, mas o sistema operacional só suporta densidade simples (256 bytes por setor). Os drives suportam as duas densidades e 40 ou 80 trilhas. Então, num único disquete de 5.25", gravam-se 400KB (80 trilhas x 10 setores x 256 bytes x 2 lados). Num drive de 3.5" moderno pode-se usar o mesmo formato; o computador não tem idéia do que está ligado nele.

No fim do ano passado, eu já tinha descoberto todas as questões a resolver para ligar um drive novo e as anotei num artigo. Naquele momento, eu já havia conectado um drive e gravado com sucesso um "Hello, World!" escrito em BASIC. No entanto, eu só consegui que o drive se comportasse como o segundo. Para conectar o drive como o primeiro, foi preciso adaptar um cabo.

Os drives modernos são todos configurados para serem o drive B. E para economizar uns centavos, eles nem têm um mecanismo de reconfiguração. Afinal, eles estão custando R$15 agora! No PC, as linhas 12 e 14 acionam, respectivamente, os drives B e A; as linhas 16 e 10 acionam o motor, conforme o drive selecionado. No padrão Shugart, que o BBC usa, as linhas 10, 12 e 14 acionam os drives 0, 1 e 2. E apenas a linha 16 aciona o motor. O BBC só usa os drives 0 e 1.

A tabela abaixo mostra as diferenças:

LinhaPCShugart
10Motor drive A:Aciona drive 0
12Aciona drive B:Aciona drive 1
14Aciona drive A:Aciona drive 2
16Motor drive B:Aciona motor

Os cabos novos têm uma voltinha para que quando o PC envie sinal para o drive A, ele o receba mesmo estando configurado como B. Para ligar o BBC, basta inverter as linhas 10 e 12. Ou seja, para acionar o drive 1, o BBC liga as linhas 12 e 16, exatamente como o PC faz para o drive B. Para acionar o drive 0, é preciso fazer o sinal da linha 10 chegar na linha 12. É simples, mas fabricar o cabo é difícil, porque as linhas são pequenas e os conectores menores ainda. A foto abaixo mostra os dois tipos de cabo (o da direita é o comum de PC).

Não dá para disfarçar o caráter artesanal do cabo! Eu cortei a ponta de um cabo normal, desfiz a volta e troquei as linhas 10 e 12. Bastam um estilete e muita paciência.

Na primeira tentativa, o BBC lia os disquetes, mas não gravava. A linha de proteção de gravação (linha 28 ou /WPT para os íntimos) provavelmente estava encostada numa vizinha. Na segunda tentativa, funcionou, mas o cabo não ficou firme e acabou se desmanchando. Na terceira, sucesso! O disquete gravado há 7 meses também funcionou muito bem. Como os disquetes modernos são fabricados para gravar em densidade alta, tive medo de que não funcionariam bem com densidade simples. A foto abaixo mostra que é preciso tapar o buraco oposto ao de proteção de gravação para enganar o drive a pensar que trata-se de um disquete de densidade simples ou dupla (repare no da direita; o furo está tapado com fita isolante):

As fotos a seguir mostram a instalação em funcionamento.


Na tela está o conteúdo do disquete: um arquivo BASIC chamado HELLO e um arquivo texto chamado TEXT.

No canto, vê-se o terminador da fonte que seria ligado ao computador. Sem aquele cabinho vermelho, a fonte não liga.

O próximo passo é escrever um programa para ler disquetes de PC. Com um pouco de código de máquina é possível ler disquetes com FAT de 360KB ou 720KB. E não estou exagerando, porque o sistema de disco (DFS ou Disc Filing System) cabe todo numa ROM de 16KB.

sexta-feira, 23 de julho de 2010

Hierarquias legíveis no SQL

A maneira mais comum de modelar hierarquias em tabelas é usar uma coluna para referenciar a própria tabela. Isso funciona muito bem no Oracle, porque a sintaxe tem umas facilidades para tratar esse tipo de construção. No entanto, não creio que seja a melhor maneira de resolver esse problema.

Joe Celko difundiu largamente a solução dos conjuntos aninhados. Eles já são um grande avanço, mas ainda não resolvem o problema que eu quero resolver: tornar os dados mais legíveis, sem precisar usar consultas complicadas. Eu queria executar um simples select com order by e pronto.

Uma maneira simples de fazer isso é colocar a hierarquia num texto usando uma notação posicional. Por exemplo, para representar um nodo "3.2.4" usa-se um texto "030204". O pai desse nodo (3.2) seria o "0302". Usando apenas números, tem-se 99 elementos por nível. Com o alfabeto, pode-se mais. Para todas as aplicações que vi até hoje, basta.

Criei uma tabela de testes assim (a chave é a coluna POSICAO):

Posição (POSICAO)Nome (NOME)
011
01011.1
01021.2
0101011.1.1
022
02012.1
02022.2
0202012.2.1

Para enumerar a hierarquia toda de uma única vez, basta a seguinte consulta:

select posicao, nome
from hierarquia
order by 1

Dá até mesmo para usar a sintaxe especial do Oracle e com isso, achatar a hierarquia e mostrar em cada registro todos os ascendentes:

select posicao, SYS_CONNECT_BY_PATH(nome,'>') nodo
from hierarquia
connect by prior posicao = substr(posicao,1,length(posicao)-2)
start with length(posicao)=2
order siblings by posicao

Isso vai mostrar algo assim:

POSICAONODO
01>1
0101>1>1.1
010101>1>1.1>1.1.1
0102>1>1.2
02>2
0201>2>2.1
0202>2>2.2
020201>2>2.2>2.2.1

Não é preciso completar os espaços vazios com zeros; isso dificulta muito as consultas. Por exemplo, na primeira tentativa, usei "010000" para o nível 1. Os zeros adicionais não só não ajudam, como tornam a consulta anterior muito mais complicada; sem eles, basta tirar dois caracteres do fim para achar o nodo pai; com eles, é preciso encontrar onde os pares de zeros terminam (ou começam, para quem vem da esquerda).

Se for preciso representar mais nodos por nível, basta usar mais posições. Com 3 por nível, já são possíveis 999 nodos. E para tornar a hierarquia mais alta, basta ir adicionando caracteres .

Esse tipo de construção, além de tornar os dados mais legíveis, facilita sobremaneira algumas pesquisas. Por exemplo, encontrar todos os nodos de terceiro nível com uma tabela auto-referenciada seria muito mais complicado.

segunda-feira, 19 de julho de 2010

Império dos 8 bits III

Finalmente, o Império chega ao Oriente. Essa região não produziu muitos modelos, mas produziu o melhor micro de 8 bits.

Apenas 5 países dessa região produziram computadores de 8 bits: Austrália, Coréia do Sul, Japão e Nova Zelândia. Hong Kong projetou um e o produziu noutros países.

Na Austrália, a Microbee produziu uma série de computadores baseada no Z80. O primeiro modelo, lançado em 1982, tinha 16KB ou 32KB de RAM, com 16KB de ROM contendo o BASIC e mais 12KB para funções opcionais (como editor de textos ou software de comunicação). Ele rodava a 3,375MHz e tinha a capacidade de exibir gráficos de até 512x256 pixeis (com duas cores), o que era impressionante para a época. Os modelos subsequentes foram adicionando memória (56KB, 64KB e 128KB) e usavam o CP/M, baseado em disco.

Também foi muito popular o VTech VZ200, baseado no Z80. Era muito mais simples, mas também era muito barato. O projeto era de Hong Kong, mas era produzido e vendido na Austrália e Nova Zelândia pela Dick Smith.

Na Nova Zelândia, o Poly 1 foi produzido de 1981 a 1989. Ele usava o 6809 e era extremamente caro. É provável que tenha sido o primeiro micro com função de rede.

Na Coréia do Sul, a Samsung projetou o SPC-1000. Ele foi fabricado, no entanto, no Japão. Era mais um micro baseado no Z80 e se não fosse o único projetado pela Coréia, nem valeria a pena ser mencionado; ele não tinha nenhuma característica marcante.

Por fim, o Japão. Deste país saiu o melhor micro de 8 bits. A Fujitsu lançou várias versões do FM-7 entre 1982 e 1988. Estranhamente, esse micro teve pouco sucesso fora do Japão. Os MSX, que eram tecnologicamente menos desenvolvidos, tiveram muito mais sucesso.

O primeiro modelo do FM-7 já tinha 64KB de RAM em 1982! No ano anterior, o ZX81 tinha feito enorme sucesso na Inglaterra com apenas 1KB de RAM. O modelo anterior (FM-8; não tente compreender a numeração dos modelos) já tinha 64KB em 1981. O último modelo (o FM77AV40SX) tinha 192KB de RAM (que podiam ser expandidos até 448KB) e ainda mais 192KB de VRAM. As capacidades gráficas também eram impressionantes. O FM-7 sustentava 640x200 pixeis em 8 cores; o último modelo, até 640x400 em 8 cores de uma paleta de 4096 ou 320x200 com 4096 cores. Ademais, era possível ter várias páginas de gráficos. Isto é, era possível ter em memória 2, 4, 6 ou 8 telas simultaneamente, conforme o modo gráfico.

Os Fujistu usavam dois processadores 68B09 (uma variação do 6809), sendo o segundo encarregado dos gráficos e do I/O. O 6809 foi o melhor processador de 8 bits. Ele podia endereçar até 1MB de RAM, em páginas de 4KB. Seus modelos rodavam a 1Mhz (6809), 1,5Mhz (68A09) e 2Mhz (68B09). Mesmo sendo mais lento que o Z80, ele (e seu primo 6502) eram muito mais rápidos ao acessar a memória e por isso pareciam produzir sistemas muito mais velozes, como se podia notar ao comparar o jogo Elite num Z80 de 3.58MHz com o mesmo jogo num 6502 de 2Mhz.

quinta-feira, 15 de julho de 2010

O vendedor de tapetes

Musad Algibar ganhou muito dinheiro vendendo tapetes e criando camelos. Tanto dinheiro que um dia decidiu tirar umas férias e finalmente conhecer o Índico.

Chegando a Dar Es Salaam, decidiu passear pelo comércio local e acabou encontrando uma pequena livraria. Era uma só desordem e um livro de camelos acabou entre os romances traduzidos de Saramago. A capa era bonita e o preço baixo, então ele o levou, mesmo não sabendo do que se tratava e duvidando que os ingleses soubessem algo sobre camelos. O pequeno Arif já sabia inglês e traduziria!

O livro não era sobre camelos, evidentemente, mas era deveras útil. Com pouco esfoço, Arif começou a criar dezenas de desenhos novos para tapetes com motivos matemáticos no computador de casa. O primeiro veio da simples x2+y2:



Será que a subtração produziria algo menos curvilíneo (para não atormentar os tecelões)?





Tentanto maiores potências, Arif descobriu que x4+y4 produz algo bastante tradicional, mas x5+y5 produz um desenho realmente moderno!





Finalmente, ao tentar sin(x)5+cos(x)5, um projeto surpreendente surgiu. Um psicoteste!




Que mensagem estará Alá a nos passar?

terça-feira, 13 de julho de 2010

Visões do camelo

O Perl não é conhecido por suas habilidades gráficas, mas com algumas bibliotecas é possível gerar imagens interessantes com muita facilidade.

O mais fácil é usar o módulo GD, conforme o exemplo abaixo:

use GD;

my $img=new GD::Image(256,256);

my @colours=();

for my $c (0..255) {
$colours[255-$c]=$img->colorAllocate($c, $c, $c);
}

for my $i (0..255) {
for my $j (0..255) {
$img->setPixel($i, $j, $colours[($i*$j)%255]);
}
}

binmode STDOUT;
print $img->png;

Esse pequeno programa faz o seguinte:
  1. Instancia uma imagem com 256 pontos de cada lado;
  2. Cria uma paleta de cinzas (sendo 0 branco e 255 preto);
  3. Atribui a cada ponto da imagem uma a cor dada pelo produto das coordenadas;
  4. Escreve a imagem para o stdout.
Porque a imagem é escrita para o stdout, é preciso usar um pipe ao rodar o programa:

imagem.pl > img.png


O resultado parece algo vindo de uma ruina Maia e também não ficaria mal num museu de arte moderna:


Trocando os números inteiros por primos (no eixo horizontal; o eixo vertical continua com os inteiros), o resultado ganha bastante ruído, mas continua interessante.

Finalmente, coloquei em cada ponto (i,j) o resto da divisão do i-ésimo primo pelo j-ésimo primo. Surgiu um deserto misterioso. Não é por nada que os primos deixam os matemáticos perdidos!

domingo, 11 de julho de 2010

Marxismo no TI

Há uma tentativa recorrente de implementar uma espécie de comunismo tecnológico nos departamentos de TI. Muitas vezes ouvi dizer que seria melhor ter todos os sistemas implementados numa única linguaguem ou tecnologia.

Pois, eu digo que compreenderam mal o marxismo! Karl Marx disse:

De cada um, de acordo com suas habilidades,
a cada um, de acordo com suas necessidades.


Portanto, só posso concluir que um verdadeiro socialista deve procurar a ferramenta certa para cada trabalho. Ademais, não deve perder de vista o momento histórico; as escolhas do passado devem ser vistas à luz das circunstâncias.

quarta-feira, 7 de julho de 2010

Zips exóticos em Java

A API do Java é enorme, mas ainda deixa alguns pontos importantes abertos. Apesar de ter facilidades para ler e escrever arquivos compactados, não suporta zips encriptados ou multi-volumes.

Por sorte, existe uma API para Java sobre o 7-zip. É preciso usar a API e as bibliotecas originais, então existe uma biblioteca para o Linux e outra para o Windows. Pode ser um pouco trabalhoso para quem desenvolve no Windows e usa o Linux para produção, como muitas vezes acontece.

Pois bem, a API é deveras estranha, então o melhor é conseguir um exemplo e reaproveitá-lo.

RandomAccessFile file=new RandomAccessFile(zip, "r");
ISevenZipInArchive zip=SevenZip.openInArchive(null,
new RandomAccessFileInStream(file));
ISimpleInArchive ui=zip.getSimpleInterface();
for(int i=0; i<zip.getNumberOfItems(); i++) {
final ByteArrayOutputStream stream=new ByteArrayOutputStream();
String nome=(String) zip.getProperty(i, PropID.PATH);
ISimpleInArchiveItem item=ui.getArchiveItem(i);
ExtractOperationResult result=item.extractSlow(new ISequentialOutStream() {
public int write(byte[] data) throws SevenZipException {
try {
stream.write(data);
} catch(Exception e) {

}
return data.length;
}
}, "senhasecreta");

O arquivo sendo analisado é o zip (uma referência do tipo File). Para cada arquivo dentro de zip, obtem-se um item (do tipo ISimpleInArchiveItem) e descompactam-se os dados originais usando o método extractSlow(). Esse método recebe uma instância de ISequentialOutStream que neste caso copia os dados para uma instância de ByteArrayOutputStream. O último parâmetro de extractSlow() é a senha, caso os dados estejam protegidos.

É muito útil, mas espero que a JDK logo ganhe novos métodos para suportar encriptação e multi-volumes. E com uma API mais elegante que esta!