domingo, 13 de maio de 2012

Conector da porta de cassete

Há muito tempo atrás eu comprei na Farnell Brasil um conector din de 8 pinos para montar um cabo de gravador cassete.  O código de compra do conector era o 3300390, mas este parece não existir mais.
Fiz uma nova busca e encontrei este daqui:

Order Code: 67C7909
Part Number: MAS 80 S
Fabricante: Hirschmann
Descrição: CONECTOR PLUGUE 8 VIAS
O preço é meio salgado, quase R$12,00

quarta-feira, 25 de abril de 2012

Outro adaptador de Nunchuck para MSX

Outro adaptador de Wii Nunchuck para MSX, só que desta vez utilizando um diminuto 68HC908QB8. O funcionamento é idêntico ao das versões anteriores, com a manete analógica simulando as quatro direções básicas em conjunto com os acelerômetros nos eixos X e Y. Os botões 1 e 2 do MSX são mapeados nos botões C e Z do nunchuck.

A foto abaixo mostra o adaptador conectado ao HotBit.

E eis aqui um close da plaquinha. O encapsulamento do CI é um TSSOP de 16 pinos com espaçamento entre os terminais de apenas 0,65mm.

terça-feira, 20 de março de 2012

CPLD Lab


O CPLD Lab é uma placa de desenvolvimento de dispositivos de lógica programável complexos   (CPLDs)   baseada   num   chip   EPM3064   da   Altera   com   64   macrocélulas   em encapsulamento PLCC 44 e que permite a utilização de até 36 pinos de I/O sendo 4 somente entradas destinadas aos sinais globais (/OE, CLOCK, /CLEAR) e mais 4 compartilhados com o conector de programação JTAG. A placa foi projetada para ser uma ferramenta de experimentação e desenvolvimento de projetos para microcomputadores de 8 bits. A placa conta com três opções para regulador de tensão de +3V3 com LEDs para monitoramento das alimentações;

Imagem da placa. A CPLD fica do lado de baixo

sábado, 17 de março de 2012

Mini Expansor de Slots com CPLD

Coloquei o Expansor de Slots que encontrei no MSXPRO numa CPLD utilizando as bibliotecas de chips TTL do Quartus II da Altera. O projeto utiliza apenas 19 macro-células e portanto cabe numa EMP3032, que está disponível em encapsulamento PLCC de 44 pinos (permitindo montagem em soquete) por menos de R$7,00. 
Apesar de operar com 3,3Volts, esta família (MAX3000) tem IO compatível com TTL 5V. 


Eis o circuito desenhado no Quartus:

sábado, 3 de março de 2012

Conector de teclado do HotBit

Na documentação existente sobre o HotBit alguns detalhes sobre o teclado estavam faltando, especificamente o funcionamento da chave de desligamento do Slot e qual a função do pino POWERON

Segue abaixo uma figura com a pinagem do teclado mais completa:

Matriz alternativa

Uma matriz de teclado alternativa pode ser feita com 10 registradores de deslocamento. Os bits entram serialmente (10 bytes) e são transferidos sincronamente. Daí qualquer microcontrolador pode ser usado, ou até mesmo a porta de joystick de um outro MSX (JSPI).

Circuito:

sábado, 25 de fevereiro de 2012

Medição dos tempos

Com o circuito ligado no MSX, mas ainda sem o sinal /Wait conectado ao barramento, fiz a medição dos tempos. O resultado encontra-se nas fotos abaixo.

A primeira foto está na escala de 500ns por divisão. O canal superior foi tomado no pino 5 do HCT139 e mostra a decodificação dos sinais [A0*/CS*/RD], ou seja o momento em que o MSX lê a porta B da PPI. O canal de baixo foi tomado na saída /Q do flip flop e mostra o tempo em que o sinal /WAIT fica acionado que corresponde ao tempo que o microcontrolador (ATMEGA8 @8MHz) leva para reconhecer a interrupção, ler os bits da porta C da PPI, colocar o dado correspondente na porta de saída e limpar o flip-flop para liberar o Z80. Tudo isso é feito em aproximadamente 4us.

500ns por divisão

A segunda foto foi tirada na escala de 50ns por divisão e mostra o "pulo do gato"...

Protótipo do adaptador de teclado

Comecei a montagem do adaptador de teclado. Testei estaticamente o mecanismo de wait, e encontrei um pequeno erro no inversor improvisado com o decodificador. O correto é ligar o sinal de clock do flip flop no pino 11 do HTC139 e não no pino 12.
Em seguida coloquei o microcontrolador (um ATMEGA8) com conector de programação e o fiz as conexões do microcontrolador ao conector de programação, ao conector que vai para o adaptador de teclado e os pinos /IRQ e /GO.

Pseudo Código para leitura de teclado

Apesar de existirem algumas bibliotecas para leitura de teclado PS/2 disponíveis, nenhuma que achei me serviu basicamente se utilizam de interrupções para ler o teclado e pela conversão de códigos para valores ASCII usando tabelas de estados com e sem shift, etc. Outras razões são o não processamento da teclas PAUSE/BREAK que pretendo utilizar STOP, e o excesso de 'orientação ao sucesso', por desconsiderar timeouts, bits errados, caracteres inesperados, etc.


Eis o primeiro passo, o pseudo codigo para leitura de scan codes, que apesar de ser por polling, pode ser facilmente adaptado para rodar por interrupçoes.


// pseudo codigo para comunicação // com teclado ps/2

quarta-feira, 22 de fevereiro de 2012

Overhead gasto nos ciclos de Wait para o adaptador de teclado.

A fim de calcular o overhead que os ciclos WAIT necessários para atender ao teclado representariam no MSX, fiz uma experiência usando linguagem C num AVR. O objetivo é calcular o tempo necessário
para:
- Atender a interrupção
- Decodificar a linha do teclado (ler porta C da PPI)
- colocar o valor das colunas (na porta B da PPI)
- Pulsar o sinal GO para liberar o Z80

Eis abaixo o código da rotina de interrupção:

terça-feira, 21 de fevereiro de 2012

Adaptador de teclado PS/2

Recapitulando o post anterior, para atender à temporização crítica da instrução IN do Z80 será necessário utilizar o Wait do Z80. A maneira mais simples de fazer isso é utilizar um decodificador dos sinais /CS, /RD e A0 diretamente na PPI e acionar um flip flop que segura a linha /Wait do Z80 em nível baixo e ao mesmo tempo  ativa a interrupção (/INT) do microcontrolador.
Mecanismo de Wait em Piggyback com a PPI

MSX + Arduino

A plataforma Arduino tem suas qualidades e seus defeitos, mas sem entrar nesse mérito, uma coisa é inegável: A plataforma que 'pegou'. É fácil de encontrar para comprar, e qualquer um pode programar facilmente plataforma, usando seu computador, seja ele um PC ou Mac, sem a necessidade de hardware de programação especial.

Sendo assim, eu resolvi refazer o adaptador de Nunchuck para MSX mas desta vez usando um Arduino como plataforma.

segunda-feira, 20 de fevereiro de 2012

Adaptador para teclado PS/2 - Problemas, considerações e idéias .

Antes de me aventurar num projeto de um adaptador de teclado PS/2 é importante estudar bem as particularidades do hardware do MSX.

O teclado do MSX é uma matriz de 11 linhas por 8 colunas. O MSX seleciona a linha através dos 4 bits menos significativos da porta C da PPI que vão a um decodificador BCD-Decimal (74LS145). A leitura das colunas referentes à linha selecionada é feita através da porta B da PPI.

Normalmente, uma leitura do teclado tem a seguinte estrutura:
A=linha selecionada
OUT (0AAh),A
IN A,(0A9H)
Considerando que as intruções OUT/IN executam em 12 ciclos de máquina (no MSX é inserido um 'wait' de um ciclo de clock cada ciclo M1), e que as instruções são normalmente consecutivas, dá pra se notar que o tempo disponível para a leitura de um teclado é bem estrito.

INSTRUCTION   BYTES   M1         M2        M3  
OUT (n),A     2       OCF(4+1)   OD(3)     PW(4)
IN A,(n)      2       OCF(4+1)   OD(3)     PR(4)


Para ser bem preciso, o tempo disponível entre a escrita na porta 0AAh e a leitura na porta 0A9H vai desde o meio segundo pulso de clock do ciclo M3 da instrução OUT (Port Write) até o meio do quarto pulso de clock do ciclo M3 da instrução IN, onde o Z80 efetivamente lê a porta.


Na ponta do lápis temos:
- 2,5 ciclos de clock restantes do ciclo M3 da instrução Write
- 5 ciclos de clock do 'Opcode Fetch' do ciclo M1 da instrução IN
- 3 ciclos de clock da leitura do operando da instrução IN (ciclo M2)
- 3 ciclos de clock da leitura da porta no ciclo M3 (no 3 1/2 o dado já deve estar pronto para ser lido)

Isso nos dá 13,5 ciclos de clock, o que equivale a 3,77 microssegundos numa máquina rodando a 3,58MHz .

Se quisermos ser mais estritos ainda, devemos considerar que nem todo programa precisa escrever na porta C da PPI antes de ler a porta B, pois basta escrever uma vez e ler quando necessário (por exemplo jogos que usem somente as setas cursoras e a barra de espaço).

Assim, considerando somente a leitura na porta B da PPI (0A9h) temos um tempo que vai desde o meio do segundo pulso ate o final do terceiro pulso de clock do ciclo M3 da instrução IN.
Isso equivale a 2,5 ciclos de clock ou 698 nanosegundos.

Penso em duas abordagens para o problema. A primeira é utilizar um CPLD e um microcontrolador. A CPLD é configurada como uma matriz de 10 linhas com 8 flip flops e mais um shift register capaz de endereçar a entrada de cada uma dessas 10 linhas. O microcontrolador lê o teclado PS/2 e cria internamente uma matriz de 11 bytes representando o estado de cada tecla (para o MSX). De tempos em tempos o microcontrolador desloca sequencialmente para o shift register interno cada um dos 10 bytes e apos transferir cada um dos bytes ele atualiza o estado dos flip flops da linha equivalente. A solução mais simples seria encadear todas as 11 linhas e fazer um shift register de 80 bits, mas isso poderia gerar falsos eventos caso o MSX estivesse lendo uma linha do teclado na hora em que o microcontrolador estivesse atualizando o shift register. Isso ia requerer pelo menos (11x8)+8 macrocélulas de uma CPLD, ou seja 98 macrocélulas. Uma abordagem parecida seria fazer um shift register de 88 bits com um latch de saída, mas isso ia requerer pelo menos 168 macro células.
Uma segunda abordagem utiliza somente o microcontrolador. Mas dados os tempos, qual microcontrolador utilizar? Um AVR rodando a 20MHz roda uma instrução a cada 50 nanossegundos, e pode rodar 14 instruções em 700 nanossegundos. Um PIC com mesmo clock teria uma 3 instruções apenas. Um 8051 a 12MHz nem teria como responder tão rápido. Embora seja possível utilizar microcontroladores mais rápidos, não creio que essa seja uma abordagem elegante, ainda mais que o tempo entre eventos de teclado normalmente é bem longo, da ordem de dezenas de milissegundos.

Pensando novamente, este problema de velocidade para atender a uma requisição do microprocessador não é novo, e a solução também não. O Z80 já tem um recurso para tratar esse problema que é a própria linha WAIT. Essa linha é amostrada no terceiro pulso de clock do ciclo M3 das instruções de I/O. Caso essa linha esteja em nível baixo, o Z80 vai fazendo novas amostragens até que a linha volte a nível alto (contudo deve-se tomar cuidado para não deixar o Z80 muito tempo neste estado, pois durante o "wait state" as memórias dinâmicas não sofrem refresh).

Essa segunda abordagem permite o uso de praticamente qualquer microcontrolador, basta adicionar um flip flop e um decodificador para os sinais /RD, /CS e A0 da própria PPI. O microcontrolador pode trabalhar por polling ou por interrupções, reconhecendo a mudança de estado da saída do flip flop (que vai a zero no momento em que /RD=0; /CS=0; A0=1). O microcontrolador então lê o estado dos bits 0-3 da porta C da PPI, determina qual a linha que o MSX deseja ler. Então o microcontrolador coloca na saída os bits correspondentes à coluna lida e reseta o flip flop, liberando a linha Wait. Se quisermos ser preciosistas, após liberar o Z80 basta aguardar por um tempo equivalente a um ciclo e meio de clock do Z80 e então desativar a porta de saída (bits da coluna).



sexta-feira, 3 de fevereiro de 2012

Interface MSX-Nunchuck


A interface é bem simples: Dois resistores de pull-up e alguns diodos e um capacitor para converter os +5V da porta de joystick nos +3,3V requeridos pelo Nunchuck.



O capacitor eletrolítico é soldado por baixo:


Interface encaixada no Hot Bit


quinta-feira, 2 de fevereiro de 2012

Road Fighter funcionando com Nunchuck

Finalmente tive um tempo para mexer na adaptação, e agora está funcionando.



Tive que mexer um pouquinho no código para mudar o limiar de sensibilidade em torno da posição central (era de +/- 32 e agora está +/- 20) e remapeei as direções UP DOWN LEFT RIGHT que estavam invertidas (tanto para os acelerômetros quanto para a manete analógica), e também inverti o mapeamento dos botões C e Z. O botão Z que é o maior ficou no trigger principal, ao passo em que o botão C ficou no trigger secundário.

Missão cumprida!!

Não sei quando eu vou poder me dedicar tão intensivamente ao MSX de novo, mas fico feliz de ter conseguido fazer essa adaptação.

Valeu Igor!!! Esse projetinho de final de ano nós começamos e terminamos. Acende aí a velinha pro Nosso Senhor do Bonfim e apaga a velinha do Nosso Senhor do Bom Começo, heheheh.

terça-feira, 31 de janeiro de 2012

Road Fighter para Nunchuck

Apesar de ter começado primeiro a adaptação de Road Fighter para Nunchuck eu acabei mudando um pouco o foco para o Ping Pong porque esse último exigiu uma rotina mais genérica, capaz de tratar de até dois Nunchucks simultaneamente.
Dessa forma é possível adaptar o mesmo bloco em binário que lê os nunchucks para a maioria dos jogos da Konami, bastando para isso alterar o ponto de entrada do loop infinito do jogo e o ponto de entrada da rotina que lê os joysticks.
A única modificação necesária no 'driver' J2C foi mudar o endereço de memória dos buffers, pois o Ping Pong ocupa (com variáveis) os endereços entre (E000-E3FF) enquanto o Road Fighter utiliza entre (E000-E7FF).
Segue abaixo o código do carregador em Basic + patch. Assim que possível vou experimentar na máquina real.
10 SCREEN 0:COLOR15,1,1:CLS
20 LOCATE 6,3
30 PRINT "ROAD FIGHTER PARA NUNCHUCK"
40 LOCATE12,5
50 PRINT "DANJOVIC 2012"
60 LOCATE 6,7
70 PRINT "HTTP://HOTBIT.BLOGSPOT.COM"
80 BLOAD"ROADFIGH.BIN"
90 FOR I=1 TO 2500:NEXT I
100 '
110 REM Enderecos base
120 BLOD=&H8800 ' carreg jogo
130 INIT=&HD000 ' init nunchucks
140 REQU=&HD022 ' request dados
150 '
160 'gancho loop infinito
170 POKE BLOD+&H7C,&HC3
180 POKE BLOD+&H7D,INIT AND 255
190 POKE BLOD+&H7E,INIT \ 255 AND 255
200 '
210 'gancho leitura joystick
220 POKE BLOD+&H6C5,&HCD
230 POKE BLOD+&H6C6,REQU AND 255
240 POKE BLOD+&H6C7,REQU \ 255 AND 255
250 POKE BLOD+&H6C8,&H18
260 POKE BLOD+&H6C9,&H8
270 '
280 'rotinas leitura nunchuck
290 BLOAD "NROAD.BIN"
300 '
310 'inicializa jogo
320 DEFUSR=&HC800:A=USR(0)


Segue o código do bloco em código de máquina

NROAD.BIN

D000 AF 32 06 E8 CD 9D D0 38 :41
D008 08 3A 06 E8 CB CF 32 06 :02
D010 E8 37 CD 9D D0 38 08 3A :D3
D018 06 E8 CB D7 32 06 E8 FB :AB
D020 18 FE CB 73 20 0A 3A 06 :BE
D028 E8 CB 4F 28 13 A7 18 08 :04
D030 3A 06 E8 CB 57 28 09 37 :B2
D038 CD C2 D0 CD 50 D0 FB C9 :10
D040 3E 0F CD 93 00 3E 0E F3 :EC
D048 CD 96 00 FB 2F E6 3F C9 :7B
D050 21 00 E8 1E 00 7E FE 94 :37
D058 38 02 CB DB FE 6C 30 02 :7C
D060 CB D3 23 7E FE 94 38 02 :0B
D068 CB CB FE 6C 30 02 CB C3 :C0
D070 23 7E FE 94 38 02 CB DB :13
D078 FE 6C 30 02 CB D3 23 7E :DB
D080 FE 94 38 02 CB CB FE 6C :CC
D088 30 02 CB C3 23 23 7E CB :4F
D090 4F 20 02 CB EB CB 47 20 :59
D098 02 CB E3 7B C9 CD 10 D1 :A2
D0A0 CD 67 D1 0E A4 CD 98 D1 :ED
D0A8 CD 59 D2 D8 0E 40 CD 98 :83
D0B0 D1 CD 59 D2 D8 0E 00 CD :7C
D0B8 98 D1 CD 59 D2 D0 CD 46 :44
D0C0 D1 C9 CD 10 D1 CD 67 D1 :4D
D0C8 0E A4 CD 98 D1 CD 59 D2 :E0
D0D0 D8 0E 00 CD 98 D1 CD 59 :42
D0D8 D2 D8 CD 46 D1 CD B0 D2 :DD
D0E0 CD 67 D1 0E A5 CD 98 D1 :EE
D0E8 CD 59 D2 D8 FD 21 00 E8 :D6
D0F0 2E 05 CD D5 D1 FD 71 00 :14
D0F8 FD 23 A7 CD 24 D2 2D 20 :D7
D100 F1 CD D5 D1 FD 71 00 37 :09
D108 CD 24 D2 CD 46 D1 A7 C9 :17
D110 F3 3E 0F D3 A0 DB A2 32 :62
D118 07 E8 38 15 CB B7 CB C7 :50
D120 D3 A1 CB CF D3 A1 47 CD :96
D128 46 D1 CD 46 D1 CD 46 D1 :DF
D130 C9 CB F7 CB D7 D3 A1 CB :6C
D138 DF D3 A1 47 CD 46 D1 CD :4B
D140 46 D1 CD 46 D1 C9 78 CB :07
D148 77 20 0E CB 87 D3 A1 CB :36
D150 CF D3 A1 CB C7 D3 A1 47 :90
D158 C9 CB 97 D3 A1 CB DF D3 :1C
D160 A1 CB D7 D3 A1 47 C9 78 :3F
D168 CB 77 20 16 CB CF D3 A1 :86
D170 CB C7 D3 A1 CB 87 D3 A1 :CC
D178 CB 8F D3 A1 CB C7 D3 A1 :D4
D180 47 C9 CB DF D3 A1 CB D7 :D0
D188 D3 A1 CB 97 D3 A1 CB 9F :B4
D190 D3 A1 CB D7 D3 A1 47 C9 :9A
D198 78 CB 77 20 1C 06 08 CB :CF
D1A0 21 CB 87 30 02 CB C7 D3 :0A
D1A8 A1 CB CF D3 A1 CB 8F D3 :DC
D1B0 A1 10 EC CB C7 D3 A1 47 :EA
D1B8 C9 06 08 CB 21 CB 97 30 :55
D1C0 02 CB D7 D3 A1 CB DF D3 :95
D1C8 A1 CB 9F D3 A1 10 EC CB :46
D1D0 D7 D3 A1 47 C9 78 CB 77 :15
D1D8 20 25 CB C7 D3 A1 01 00 :4C
D1E0 08 CB CF D3 A1 5F 3E 0E :C1
D1E8 D3 A0 DB A2 E6 10 ED 44 :17
D1F0 CB 11 3E 0F D3 A0 7B CB :E2
D1F8 8F D3 A1 10 E4 47 C9 CB :D2
D200 D7 D3 A1 01 00 08 CB DF :FE
D208 D3 A1 5F 3E 0E D3 A0 DB :6D
D210 A2 E6 10 ED 44 CB 11 3E :E3
D218 0F D3 A0 7B CB 9F D3 A1 :DB
D220 10 E4 47 C9 78 CB 77 20 :DE
D228 18 CB 87 D3 A1 30 02 CB :DB
D230 C7 D3 A1 CB CF D3 A1 CB :14
D238 8F D3 A1 CB C7 D3 A1 47 :50
D240 C9 CB 97 D3 A1 30 02 CB :9C
D248 D7 D3 A1 CB DF D3 A1 CB :34
D250 9F D3 A1 CB D7 D3 A1 47 :70
D258 C9 78 CB 77 20 29 CB C7 :5E
D260 D3 A1 CB CF D3 A1 E5 21 :88
D268 D0 07 47 3E 0E D3 A0 DB :B8
D270 A2 E6 10 28 06 2B 7C B5 :22
D278 20 F5 37 3E 0F D3 A0 78 :84
D280 CB 8F D3 A1 47 E1 C9 CB :8A
D288 D7 D3 A1 CB DF D3 A1 E5 :4E
D290 21 D0 07 47 3E 0E D3 A0 :FE
D298 DB A2 E6 10 28 06 2B 7C :48
D2A0 B5 20 F5 37 3E 0F D3 A0 :C1
D2A8 78 CB 9F D3 A1 47 E1 C9 :47
D2B0 E5 F5 21 6D 00 2B 7C B5 :C4
D2B8 20 FB F1 E1 C9 :B6

domingo, 29 de janeiro de 2012

Ping Pong


Depois de apanhar um pouco com algumas besteiras no código, consegui fazer funcionar a adaptação do jogo Ping Pong para uso com (ou sem) o nunchuck. Até que ficou bacaninha, mas o jogo ficou meio lento (video).

sábado, 28 de janeiro de 2012

Patch para nunchuck

Completei ontem o teste do patch para integrar o nunchuck num jogo.
O programa em Basic logo abaixo carregou o jogo, aplicou o patch, carregou as rotinas modificadas e executou o jogo, que que rodou normalmente (pois não havia nunchucks para serem detectados). Essa parte deu para desenvolver no emulador, mas agora está tudo pronto para testar no MSX real.
10 COLOR15,1,1:SCREEN2
20 DEFUSR=&H41:A=USR(0)
30 A$="* PING PONG *"
40 B$="Para Nunchuck"
50 OPEN"grp:"AS#1
60 X=128:Y!=LEN(A$)*4:Z=X-Y!:R=X+Y!
70 Q=LEN(B$)*4:W=X-Q
80 LINE(Z-5,100)-(R+3,110),4,BF
90 LINE(Z-7,98)-(R+5,112),4,B
100 PRESET(Z,102):PRINT#1,A$
110 PRESET(Z+1,102):PRINT#1,A$
120 PRESET(W,150):PRINT#1,B$
130 PRESET(W+1,150):PRINT#1,B$
140 DEFUSR=&H44:A=USR(0)
150 BLOAD"PING"
160 FOR I=1 TO 3500:NEXT I
170 '
180 REM Enderecos base
190 BLOD=&H8800 ' carreg jogo
200 INIT=&HD000 ' init nunchucks
210 REQU=&HD016 ' request dados
220 '
230 'gancho loop infinito
240 POKE BLOD+&H99,&HC3
250 POKE BLOD+&H9A,INIT AND 255
260 POKE BLOD+&H9B,INIT \ 255 AND 255
270 '
280 'gancho leitura joystick
290 POKE BLOD+&H807,&HCD
300 POKE BLOD+&H808,REQU AND 255
310 POKE BLOD+&H809,REQU \ 255 AND 255
312 POKE BLOD+&H80A,&H18
315 POKE BLOD+&H80B,&H8
320 '
330 'rotinas leitura nunchuck
340 BLOAD "PING.BIN"
350 '
360 'inicializa jogo
370 DEFUSR=&HC800:A=USR(0)


O programa tem um pouco de firulas no começo porque eu aproveitei o carregador em Basic do jogo. O importante acontece a partir da linha 180 e o código é auto explicativo.

domingo, 22 de janeiro de 2012

TXT para Mega Assembler em Python

Tenho usado o Pasmo para compilar os programas no PC, e depois gerar o bin para copiar pro disquete e carregar no MSX real. Mas como algumas coisas não são emuladas, o melhor mesmo é poder compilar direto no MSX.
Como o Mega Assembler não trabalha com arquivos TXT mas sim com um formato próprio, estudei um pouco esse formato e fiz um script em Python para converter o arquivo em assembly no formato TXT para o formato do arquivo do Mega Assembler.

O script é bem básico, mas funcionou bem nos testes que fiz.
Algumas coisas que precisam ser observadas na hora de gerar o arquivo no PC é se lembrar das caracteristicas do Mega Assembler, como o tamanho máximos dos labels (6 bytes) e a restrição de uso de alguns caracters como o "_" (underline).

Segue abaixo o script.

# -*- coding: cp1252 -*-
#
# TXT2SIMPLE
# converte arquivos Assembly em formato texto para
# arquivo compativel com o Simple Assembly.
# Daniel Jose Viana - Janeiro de 2012
# v0.01 - versao basica 11/jan/2012
#
from struct import *
from string import *

#caminho e nome do arquivo
path='c:\\Documents and Settings\\Danjovic\\Desktop\\'
file='NunJ2C.asm'

f=open(path+file,'rb')
tamanho=0
for line in f:
lline=line.strip() #remove terminador de linha
tamanho=tamanho+len(lline)+3 #2 bytes do numero da linha mais um byte do final de linha
print "Tamanho do arquivo:",tamanho


o=open(path+file+'.as','wb')
o.write('\xFE\x01\x00'+pack('<h',tamanho)+'\xFF\xFF'),
linha=0
incremento=10
f.seek(0) # reset posicao do arquivo
for line in f:
lline=line.strip() # remove terminador de linha
linha=linha+incremento # incrementa contador
print linha,lline #
o.write(pack('<h',linha)), # escreve numero da linha
o.write (lline), # escreve linha
o.write('\x00'), # escreve terminador (zero)

o.close() # fecha arquivos
f.close()

sexta-feira, 20 de janeiro de 2012

Jogos da Konami com Nunchuck

Estive vendo que alguns jogos da Konami são bem parecidos na inicialização e na leitura dos joysticks. Então o procedimento para modifica-los para usar o Nunchuck (ou outro joystick) é bem parecido.

Basicamente, os jogos que vi iniciam a área e variáveis e depois entram num loop infinito.


...
407C EI
407D JR 0407DH
...


As rotinas de leitura de joystick têm como entrada o registrador E contendo bit 6 (ABSEL) em 1 ou em 0 dependendo da porta de joystick que se quer ler e retornam o estado do registrador 14 do PSG com os dois bits mais significativos em zero.


...
46C5 LD A,00Fh
46C7 CALL WRTPSG
46CA LD A,0Eh
46CC DI
46CD CALL RDPSG
46D0 EI
46D1 CPL
46D2 AND 03Fh
...


Então para usar o nunchuck é necessário alterar esses dois pontos do codigo. O primeiro para colocar a rotina de inicialização do nunchuck e o segundo para fazer a leitura, retornando o estado do nunchuck mapeado para os pinos do joystick.

Um exemplo, para Road Fighter, São tres bytes que podem ser modificados para:


org 0407ch
JP INITNUNS


E rotina de leitura pode ser modificada assim

org 046c3h
CALL READNUN
JR 046d2h


Daí a rotina que inicializa os nunchucks pode inclusive sinalizar num flag se conseguiu identificar a presença do nunchuck, de forma que a rotina de leitura possa reverter para o joystick original, caso o nunchuck não responda no barramento I2C.


org 09000h
;
;
;
INITNUNS:
XOR A ; Zera A e seleciona J2C port A (CY =0)
LD (NUNFLG), A ; armazena zero em NUNFLG
CALL INITNUN ; inicia nunchuck e seta bit 1 de NUNFLG se nunch 1 ok.
JR C,INNUN1 ; Se nunchuck na porta 1 não respondeu tenta o outro
SET 1,A ; Se respondeu, marca o flag
INNUN1:
SCF ; seleciona J2C port B
CALL INITNUN ; inicia nunchuck e seta bit 1 de NUNFLG se nunch 1 ok.
JR C,INNUN2 ; Se nunchuck na porta 2 não respondeu entra no loop
SET 2,A ; Se respondeu, marca o flag

INNUN2:
EI
LOOP: JR LOOP ; loop infinito do jogo


E a rotina de leitura fica assim...

;
;
READNUN: ; Registro E como entrada. Bit 6 seleciona se porta A ou B
BIT 6,E ; Z= Porta A, NZ=Porta B
JR NZ,LEPORTB

LEPORTA: ; Processa joystick A
LD A,(NUNFLG)
BIT 1,A ; testa se há nunchuck na porta A
JR Z,READSTICK ; Lê joystick normalmente se nao houver nunchuck
AND A ; seleciona J2C port A (CY =0)
JR LEITURA ; Le e interpreta
;
LEPORTB: ; Processa joystick A
LD A,(NUNFLG)
BIT 2,A ; testa se há nunchuck na porta A
JR Z,READSTICK ; Lê joystick normalmente se nao houver nunchuck
SCF ; seleciona J2C port B (CY =1)
;
LEITURA:
CALL LENUNCH ; Lê nunchuck
CALL INTERPRETA ; Interpreta leitura (retorna 00BARLDU em A)
EI
RET


A rotina de interpretação mapeia os sensores do nunchuck da seguinte forma:

Eixo X > limiar positivo = Direita acionada
Eixo X < limiar negativo = Esquerda acionada
Eixo Y > limiar positivo = Acima acionado
Eixo Y < limiar negativo = Abaixo acionado

Acelerometro X > limiar positivo = Direita acionada
Acelerometro X < limiar negativo = Esquerda acionada
Acelerometro Y > limiar positivo = Acima acionado
Acelerometro Y < limiar negativo = Abaixo acionado

Botao C acionado = Trigger B acionado
Botao Z acionado = Trigger A acionado.

sexta-feira, 13 de janeiro de 2012

Adaptando Road Fighter para jogar com Nunchuck


Usando o MSXBlue, foi fácil localizar no código o local onde as portas de joystick são lidas no Road Fighter

46C3H LD E,08Fh
46C5H LD A,00Fh
46C7H CALL WRTPSG
46CAH LD A,0Eh
46CCH DI
46CDH CALL RDPSG
46D0H EI
46D1H CPL
46D2H AND 03Fh

Esta parte do código pode ser substituída para as chamadas para ler o nunchuck.
As rotinas de leitura têm que ser modificadas de forma a transformar a posição da alavanca, dos acelerometros e dos botoes de forma a gerar o mesmo byte ao final da rotina, ou seja:


7 6 5 4 3 2 1 0
+-----------------------------------------------+
| x | x | Joy | Joy | Joy | Joy | Joy | Joy |
¦ ¦ ¦Trg.B¦Trg.A¦Right¦Left ¦Back | Fwd |
+-----------------------------------------------+

quinta-feira, 5 de janeiro de 2012

Wii Nunchuck no MSX

Trabalho conjunto com o Igor Malaquias como projeto de férias.

http://www.youtube.com/watch?v=RNiMxM2kduk



Em 2 dias fizemos tudo (teria sido menos se tivéssemos desconfiado que a porta B do Expert que usamos estava com defeito)
O joystick está ligado diretamente na porta de joystick. Os únicos componentes utilizados foram para abaixar de 5V para 3V3 e 2 resistores de pullup.


O programa foi escrito em Basic e carrega uma rotina em Assembly que utiliza a biblioteca J2C.