Na prática: Tocador PT3/PRO com analisador de espectro
Um programa completo, de verdade, dissecado trecho por trecho. Tudo o que você aprendeu até aqui trabalhando junto.
Apresentação do programa
O PT3SPEC é um tocador de música com analisador de espectro. Ele faz três coisas:
- Lista o disco: numa tela de texto de 80 colunas, mostra todos os arquivos de música
.PT3e.PROencontrados, organizados em até 4 colunas de 18 nomes. - Toca a música escolhida: você escolhe com as setas (o nome selecionado fica em vídeo invertido) e aperta o botão (barra de espaço). O programa carrega o arquivo na memória e começa a tocar.
- Mostra o espectro: a tela muda para o modo gráfico e 8 barras coloridas sobem e descem acompanhando a música, dos graves (esquerda) aos agudos (direita). Apertar o botão de novo para a música e volta para a lista.
Os dois formatos de música são bem diferentes:
| Formato | Origem | Chip de som |
|---|---|---|
.PT3 | Pro Tracker 3 / Vortex Tracker | PSG (AY-3-8910), presente em todo MSX |
.PRO | Tyfoon Pro-Tracker | MSX-MUSIC (FM, YM2413) |
Equipamento necessário (e por quê)
- MSX2 ou superior. O programa usa o SCREEN 0 com 80 colunas e o SCREEN 4, que só existem a partir do VDP V9938 do MSX2. Num MSX2++ (VDP V9968) ele usa automaticamente o SCREEN 5 com a paleta estendida.
- Unidade de disco com MSX-DOS (DOS 1 ou DOS 2/Nextor). O programa é gerado como arquivo
.COMe lê as músicas do disco. Um.COMcomeça em$0100e deixa a memória livre para a música, que é carregada em$9000— por isso cabem módulos grandes. - MSX-MUSIC (FM-PAC ou FM embutido) — só para os arquivos
.PRO. Sem ele, os.PROficam em silêncio; os.PT3tocam em qualquer máquina, porque o PSG existe em todo MSX. - Joystick ou teclado. Setas para escolher, espaço (ou botão 1) para tocar/voltar.
DICA
Como testar na IDE
Selecione o exemplo, gere o .COM (menu Arquivo), copie-o para um disco com o DOS junto com suas músicas, ligue o botão DOS 1 ou DOS 2 do emulador e use Ler DSK (drive A). No prompt do DOS, digite PT3SPEC.
Trecho 1 — Cabeçalho e diretivas
MEMORY COM NAME "PT3SPEC"
USES SCREEN 0, SCREEN 4, SCREEN 5, MACHINE V9968, DISK, PT3, PRO, KEYBOARD, TILES
MEMORY COMdiz ao compilador para gerar um executável MSX-DOS (.COM) em vez de um cartucho.NAME "PT3SPEC"é o nome do arquivo gerado — é o que você digita no DOS.USESlista os módulos do runtime que entram no programa. Cada um tem um motivo:SCREEN 0— a lista de arquivos em modo texto.SCREEN 4— o espectro no MSX2 comum.SCREEN 5eMACHINE V9968— o espectro no MSX2++ com os comandosV9968.DISK—DIRFIRST,DIRNEXT,LOADFILE,DSKERR(),DSKVER().PT3— o tocador PSG (PLAYPT3,TICKPT3,STOPPT3).PRO— o tocador FM (PLAYPRO,TICKPRO,STOPPRO,PROVOL(),PRONOTE()).KEYBOARD—STICK()eSTRIG().TILES—TILECREATEeTILECOLOR, usados nas barras do SCREEN 4.
Só entra na memória o que foi pedido: um programa que não use PRO não carrega o tocador FM.
Trecho 2 — Variáveis
DIM NOME AS STRING * 14
DIM ST AS BYTE
DIM N AS BYTE
DIM I AS BYTE
DIM R AS BYTE
DIM SEL AS BYTE
DIM OLDS AS BYTE
DIM D AS BYTE
DIM CO AS BYTE
DIM RO AS BYTE
DIM C AS BYTE
DIM V AS BYTE
DIM B AS BYTE
DIM H AS BYTE
DIM OH AS BYTE
DIM FI AS BYTE
DIM PH AS BYTE
DIM VID AS BYTE
DIM PLAY AS BYTE
DIM T AS BYTE
DIM P AS WORD
DIM X AS WORD
DIM N1 AS BYTE
DIM K AS BYTE
DIM SIG AS BYTE
DIM ISPRO AS BYTE
VAR LEV: ARRAY(8) OF BYTE = ( 0, 0, 0, 0, 0, 0, 0, 0 )
VAR OLD: ARRAY(8) OF BYTE = ( 0, 0, 0, 0, 0, 0, 0, 0 )
VAR COR: ARRAY(8) OF BYTE = ( 6, 9, 10, 11, 2, 13, 7, 15 )
NOME AS STRING * 14— uma string de tamanho fixo. Nomes do DOS têm 8 letras + ponto + 3 de extensão = 12 caracteres; 14 dá folga.- Quase tudo é
BYTE(0–255): é o tipo mais rápido no Z80. SóPeXsãoWORDporque guardam endereços de VRAM e posições de tela que passam de 255. - As mais importantes:
ST— status devolvido pelos comandos de disco (0 = deu certo).N/N1— total de arquivos e quantos deles são.PT3(os.PROvêm depois na lista).SEL/OLDS— item selecionado agora e o anterior (para apagar o destaque antigo).PLAY— 0 = na lista, 1 = tocando.ISPRO— 1 se a música carregada é.PRO.VID— qual chip de vídeo a máquina tem.
- Os arrays usam inicialização direta, sem laço:
LEVé a altura atual de cada banda,OLDa altura já desenhada eCORa cor de cada banda, dos graves aos agudos.
Trecho 3 — O laço eterno e o modo texto 80 colunas
WHILE 1 = 1
POKE $F3AE, 80
SCREEN 0
CLS
ASM
DI
LD B, $4F
LD C, 12
CALL WRTVDP
LD B, $F0
LD C, 13
CALL WRTVDP
EI
END ASM
FOR I = 0 TO 239
P = $0800 + I
VPOKE P, 0
NEXT I
WHILE 1 = 1— o programa inteiro roda num laço infinito: lista → toca → volta para a lista.POKE $F3AE, 80—$F3AEé a variável de sistema LINL40, que guarda a largura do SCREEN 0. Colocando 80 antes doSCREEN 0, o MSX2 entra no modo de 80 colunas.- O bloco
ASMescreve dois registradores do VDP pela rotinaWRTVDPda BIOS:- R#12 = $4F — cores usadas no texto "piscante": letra 4 (azul) sobre fundo F (branco). É assim que conseguimos o vídeo invertido.
- R#13 = $F0 — tempo de pisca: ligado o tempo todo, sem apagar. O texto marcado fica invertido de forma fixa.
DI/EIdesligam as interrupções durante a escrita, para a BIOS não mexer no VDP no meio do caminho.
- O laço
FORzera os 240 bytes a partir de$0800na VRAM: a tabela de piscar do modo 80 colunas. Cada linha usa 10 bytes (80 bits = 1 bit por caractere). Zerar = nenhum caractere destacado.
CURIOSIDADE
Um bit por letra
No modo 80 colunas o V9938 não inverte cores letra a letra: ele tem um mapa em que cada bit liga ou desliga o "pisca" de um caractere. Acender 16 bits seguidos destaca uma palavra inteira.
Trecho 4 — Lendo o diretório do disco
LOCATE 0, 0
PRINT "TOCADOR PT3 + ANALISADOR DE ESPECTRO"
LOCATE 0, 1
PRINT "SETAS = ESCOLHER BOTAO = TOCAR E ANALISAR"
N = 0
DIRFIRST "*.PT3", NOME, ST
WHILE ST = 0
IF N < 72 THEN
CO = N / 18
RO = N MOD 18
LOCATE CO * 16 + 1, RO + 3
PRINT NOME
END IF
N = N + 1
DIRNEXT NOME, ST
WEND
N1 = N
DIRFIRST "*.PRO", NOME, ST
WHILE ST = 0
IF N < 72 THEN
CO = N / 18
RO = N MOD 18
LOCATE CO * 16 + 1, RO + 3
PRINT NOME
END IF
N = N + 1
DIRNEXT NOME, ST
WEND
DIRFIRST "*.PT3", NOME, STprocura o primeiro arquivo que combina com a máscara. O nome vai paraNOMEe o resultado paraST(0 = achou).DIRNEXT NOME, STpega o próximo. OWHILE ST = 0repete até acabarem os arquivos.- Distribuição em colunas:
CO = N / 18(divisão inteira) dá a coluna eRO = N MOD 18a linha. Cada coluna tem 16 caracteres de largura (CO * 16) e a lista começa na linha 3 (RO + 3), abaixo do título. IF N < 72— cabem 4 × 18 = 72 nomes na tela. Os que sobram são contados, mas não mostrados.N1 = Nguarda quantos.PT3foram achados. Depois a mesma busca é feita para.PRO, que continuam a numeração. Assim, seSEL < N1o item é PT3; senão, é PRO.
Trecho 5 — Disco vazio
IF N = 0 THEN
LOCATE 0, 3
PRINT "NENHUM ARQUIVO .PT3 OU .PRO NO DISCO"
WHILE 1 = 1
WAIT
WEND
END IF
IF N > 72 THEN N = 72
SEL = 0
OLDS = 255
PLAY = 0
- Sem músicas, o programa avisa e fica parado. O
WAITespera um quadro de vídeo (1/60 s) — é a forma educada de "não fazer nada" sem ocupar o processador à toa. Né limitado a 72 para o cursor não andar sobre nomes invisíveis.OLDS = 255é um valor "impossível": força o destaque a ser desenhado na primeira passada.
Trecho 6 — O cursor em vídeo invertido
WHILE PLAY = 0
IF SEL <> OLDS THEN
IF OLDS < 72 THEN
CO = OLDS / 18
RO = OLDS MOD 18
P = $0800 + (RO + 3) * 10 + CO * 2
VPOKE P, 0
VPOKE P + 1, 0
END IF
CO = SEL / 18
RO = SEL MOD 18
P = $0800 + (RO + 3) * 10 + CO * 2
VPOKE P, 255
VPOKE P + 1, 255
OLDS = SEL
END IF
- Só redesenha quando a seleção mudou (
SEL <> OLDS) — economia de tempo. - O endereço na tabela de piscar:
$0800+ 10 bytes por linha × linha na tela + 2 bytes por coluna (2 bytes = 16 bits = 16 caracteres, exatamente a largura de uma coluna da lista). - Primeiro apaga o destaque antigo (
VPOKE ..., 0), depois acende o novo (VPOKE ..., 255= 8 bits ligados em cada byte).
Trecho 7 — Navegando com as setas
D = STICK(0)
IF D = 1 THEN
IF SEL > 0 THEN SEL = SEL - 1
FOR I = 0 TO 6
WAIT
NEXT I
END IF
IF D = 5 THEN
IF SEL < N - 1 THEN SEL = SEL + 1
FOR I = 0 TO 6
WAIT
NEXT I
END IF
IF D = 3 THEN
IF SEL + 18 < N THEN SEL = SEL + 18
FOR I = 0 TO 6
WAIT
NEXT I
END IF
IF D = 7 THEN
IF SEL > 17 THEN SEL = SEL - 18
FOR I = 0 TO 6
WAIT
NEXT I
END IF
STICK(0)lê as setas do teclado (porta 0). Direções: 1 = cima, 3 = direita, 5 = baixo, 7 = esquerda.- Cima/baixo andam 1 item; direita/esquerda pulam 18 (uma coluna inteira).
- Cada
IFinterno impede sair da lista. - Os 7
WAIT(cerca de 0,1 s) evitam que o cursor "voe": sem essa pausa, uma tecla segurada andaria 60 itens por segundo.
Trecho 8 — Escolhendo e carregando a música
IF STRIG(0) <> 0 THEN
STOPPT3
STOPPRO
IF SEL < N1 THEN
DIRFIRST "*.PT3", NOME, ST
K = SEL
ELSE
DIRFIRST "*.PRO", NOME, ST
K = SEL - N1
END IF
I = 0
WHILE I < K
DIRNEXT NOME, ST
I = I + 1
WEND
STRIG(0)é a barra de espaço. Diferente de zero = apertada.STOPPT3/STOPPROgarantem que nada está tocando antes de carregar outra música por cima.- O programa não guardou os nomes na memória (economiza RAM). Então ele refaz a busca no grupo certo e avança
Kposições até chegar ao arquivo escolhido.
IF ST = 0 THEN
LOCATE 0, 22
PRINT "CARREGANDO... "
LOADFILE NOME, $9000, ST
LOADFILElê o arquivo inteiro do disco para a RAM a partir de$9000. Os espaços no final doPRINTapagam qualquer mensagem anterior naquela linha.- Por que
$9000? Abaixo disso fica o próprio programa e suas variáveis; acima há espaço livre até perto do sistema. OLOADFILEjá sabe o teto seguro e devolveST = 2se a música não couber.
Trecho 9 — Descobrindo o formato pela assinatura
IF ST = 0 THEN
SIG = PEEK($9000)
ISPRO = 0
IF SIG = 80 AND PEEK($9001) = 84 AND PEEK($9002) = 49 AND PEEK($9003) = 48 THEN ISPRO = 1
IF SIG = 80 OR SIG = 86 OR ISPRO = 1 THEN
IF ISPRO = 1 THEN
PLAYPRO $9000
ELSE
PLAYPT3 $9000
END IF
PLAY = 1
ELSE
LOCATE 0, 22
PRINT "FORMATO NAO RECONHECIDO: "
LOCATE 24, 22
PRINT NOME
END IF
O programa não confia na extensão do arquivo: ele olha os primeiros bytes (a "assinatura").
- 80, 84, 49, 48 são os códigos ASCII de "PT10" — marca do Tyfoon Pro-Tracker →
PLAYPRO. - 80 = "P" ("ProTracker 3...") e 86 = "V" ("Vortex Tracker...") → módulo PT3 →
PLAYPT3. - Qualquer outra coisa é recusada com mensagem, em vez de tocar lixo ou travar.
PLAY = 1encerra o laço da lista e passa para o espectro.
ATENÇÃO
Renomear não converte
Mudar o nome de um arquivo de .PRO para .PT3 não muda o conteúdo. É exatamente por isso que o programa confere a assinatura.
Trecho 10 — Mensagens de erro de disco
ELSE
LOCATE 0, 22
IF ST = 2 THEN
PRINT "MODULO GRANDE DEMAIS PARA A RAM "
ELSE
PRINT "ERRO AO ABRIR: "
LOCATE 15, 22
PRINT NOME
LOCATE 32, 22
PRINT "COD "
LOCATE 36, 22
PRINT DSKERR()
LOCATE 42, 22
PRINT "VER "
LOCATE 46, 22
PRINT DSKVER()
END IF
END IF
END IF
FOR I = 0 TO 20
WAIT
NEXT I
END IF
WAIT
WEND
ST = 2= arquivo maior que a memória disponível.- Outros erros mostram o nome, o código do DOS (
DSKERR()) e a versão do DOS (DSKVER(): 1 para DOS 1, 2 ou mais para DOS 2/Nextor). Essas informações ajudam muito a descobrir o problema. - Os 21
WAITdepois do botão evitam que um único toque seja lido várias vezes.
Trecho 11 — Detectando o chip de vídeo
FOR I = 0 TO 7
LEV(I) = 0
OLD(I) = 0
NEXT I
VID = VDPID()
- Zera as barras (uma música nova começa do zero).
VDPID()pergunta ao VDP quem ele é. 3 = V9968 (MSX2++). Qualquer outro valor = MSX2 comum. Um mesmo.COMroda nas duas máquinas e aproveita o melhor de cada uma.
Trecho 12 — Tela do MSX2++ (V9968)
IF VID = 3 THEN
SCREEN 5
CLS
V9968 INIT
V9968 CLEAR 0, 0
V9968 PALETTE 6, 31, 4, 4
V9968 PALETTE 9, 31, 12, 0
V9968 PALETTE 10, 31, 20, 0
V9968 PALETTE 11, 31, 28, 6
V9968 PALETTE 2, 24, 31, 8
V9968 PALETTE 13, 12, 31, 14
V9968 PALETTE 7, 6, 26, 31
V9968 PALETTE 15, 31, 31, 31
V9968 BOX 0, 182, 255, 2, 15, FILL
SCREEN 5: 256 × 212 pixels, 16 cores por pixel.V9968 INITliga os recursos estendidos;V9968 CLEAR 0, 0limpa a página 0 com a cor 0.V9968 PALETTE cor, R, G, Bredefine uma cor com 5 bits por componente (0–31), bem mais tons que os 0–7 do MSX2. Aqui montamos um degradê do vermelho (graves) ao azul e branco (agudos) — as mesmas cores do arrayCOR.V9968 BOX x, y, largura, altura, cor, FILLdesenha um retângulo cheio pelo hardware. Este é a "linha do chão" branca embaixo das barras.
Trecho 13 — Tela do MSX2 (SCREEN 4 com tiles)
ELSE
SCREEN 4
CLS
TILECOLOR 0, 4, 4
TILECREATE 16, $00,$00,$00,$00,$00,$00,$00,$00
TILECOLOR 1, 4, 4
TILECREATE 272, $00,$00,$00,$00,$00,$00,$00,$00
TILECOLOR 2, 4, 4
TILECREATE 528, $00,$00,$00,$00,$00,$00,$00,$00
FOR I = 0 TO 7
TILECOLOR 0, COR(I), 4
TILECREATE 17 + I, $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
TILECOLOR 1, COR(I), 4
TILECREATE 273 + I, $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
TILECOLOR 2, COR(I), 4
TILECREATE 529 + I, $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
NEXT I
FOR I = 0 TO 23
FOR C = 0 TO 31
P = $1800 + I * 32 + C
VPOKE P, 16
NEXT C
NEXT I
END IF
- No SCREEN 4 a tela é feita de blocos de 8 × 8 (tiles), e ela é dividida em 3 terços — cada terço tem seus próprios 256 desenhos. Por isso cada tile é criado três vezes: 16, 272 (16 + 256) e 528 (16 + 512).
- Tile 16 = bloco vazio (todo
$00) com fundo azul. - Tiles 17 a 24 = blocos sólidos (todo
$FF), um para cada banda, na cor deCOR(I). TILECOLOR terço, frente, fundodefine a cor antes doTILECREATE.- O laço final escreve o tile 16 em toda a tabela de nomes (
$1800, 32 × 24 posições): a tela começa vazia.
Trecho 14 — O coração: tocar e medir
WHILE PLAY = 1
TICKPT3
TICKPRO
FOR I = 0 TO 7
IF LEV(I) > 0 THEN LEV(I) = LEV(I) - 1
NEXT I
TICKPT3eTICKPROavançam a música um quadro. Só o tocador que foi iniciado faz alguma coisa; o outro retorna na hora. Como o laço termina emWAIT, a música anda a 60 passos por segundo — o ritmo certo.- A "queda suave": cada banda perde 1 ponto por quadro. É isso que faz as barras descerem devagar, como num aparelho de som de verdade, em vez de piscar.
Trecho 15 — Análise de música FM (.PRO)
IF ISPRO = 1 THEN
FOR C = 0 TO 5
V = PROVOL(C)
IF V > 0 THEN
T = PRONOTE(C)
IF T > 0 THEN
B = T AND 7
IF V > LEV(B) THEN LEV(B) = V
END IF
END IF
NEXT C
- O MSX-MUSIC tem 6 canais melódicos. Para cada um:
PROVOL(C)— volume atual do canal (0 = calado).PRONOTE(C)— nota tocando no canal.
B = T AND 7espalha a nota por uma das 8 bandas.IF V > LEV(B)— a barra só sobe se o som for mais forte que a altura atual. Descer é trabalho da queda suave.
Trecho 16 — Análise de música PSG (.PT3)
ELSE
FOR C = 0 TO 2
V = PSGREG(8 + C) AND 15
IF V > 0 THEN
FI = PSGREG(C + C)
T = PSGREG(C + C + 1) AND 15
PH = T + T
IF FI >= 128 THEN PH = PH + 1
IF PH > 7 THEN PH = 7
B = 7 - PH
IF V > LEV(B) THEN LEV(B) = V
END IF
NEXT C
END IF
- O PSG tem 3 canais (A, B, C).
PSGREG(n)lê o registradorndo chip. - Registradores 8, 9, 10 = volume de cada canal (4 bits, por isso
AND 15). - Registradores 0–1, 2–3, 4–5 = o período do tom de cada canal (12 bits: 8 no registrador par, 4 no ímpar).
- Período grande = som grave; pequeno = agudo. O programa usa só a parte alta do período (
T) e o bit mais alto do byte baixo (FI >= 128) para chegar a um número de 0 a 7 (PH). B = 7 - PHinverte a ordem: grave vai para a esquerda, agudo para a direita.
Trecho 17 — Desenho no V9968
IF VID = 3 THEN
FOR I = 0 TO 7
IF LEV(I) <> OLD(I) THEN
X = I * 32 + 4
H = LEV(I) * 11
V9968 BOX X, 16, 24, 164, 0, FILL
IF H > 0 THEN
V9968 BOX X, 180 - H, 24, H, COR(I), FILL
END IF
OLD(I) = LEV(I)
END IF
NEXT I
- Só redesenha a banda que mudou (
LEV(I) <> OLD(I)). É o segredo da velocidade. - Cada banda ocupa 32 pixels de largura (barra de 24 + 8 de espaço).
- Volume máximo 15 × 11 = 165 pixels de altura.
- Primeiro apaga a coluna toda com a cor 0, depois pinta a barra de baixo para cima (a base fica em y = 180). Os dois
BOXsão feitos pelo hardware do VDP — muito mais rápido que pixel a pixel.
Trecho 18 — Desenho no MSX2 (tiles)
ELSE
FOR I = 0 TO 7
H = LEV(I) + 3
IF H > 18 THEN H = 18
IF LEV(I) = 0 THEN H = 0
OH = OLD(I)
IF H > OH THEN
FOR R = OH TO H - 1
P = $1800 + (23 - R) * 32 + I * 4
VPOKE P, 17 + I
VPOKE P + 1, 17 + I
VPOKE P + 2, 17 + I
NEXT R
END IF
IF H < OH THEN
FOR R = H TO OH - 1
P = $1800 + (23 - R) * 32 + I * 4
VPOKE P, 16
VPOKE P + 1, 16
VPOKE P + 2, 16
NEXT R
END IF
OLD(I) = H
NEXT I
END IF
- Aqui a altura é contada em blocos (máximo 18 linhas). O
+ 3deixa até os sons fracos visíveis. - Cada banda ocupa 4 colunas de tiles: 3 de barra (
I * 4,+1,+2) e 1 de espaço. 23 - Rconta as linhas de baixo para cima.- Se a barra subiu, só as linhas novas recebem o bloco colorido; se desceu, só as de cima recebem o bloco vazio. Nunca se redesenha a barra inteira.
DICA
Desenhe só a diferença
Esta é a técnica mais valiosa do programa: guardar o que já está na tela (OLD) e mexer apenas no que mudou. Ela vale para placares, barras de energia, mapas — qualquer coisa que se atualiza a cada quadro.
Trecho 19 — Voltando para a lista
IF STRIG(0) <> 0 THEN
STOPPT3
STOPPRO
PLAY = 0
FOR I = 0 TO 20
WAIT
NEXT I
END IF
WAIT
WEND
WEND
END
- Botão durante a música: para os dois tocadores (os
STOPtambém calam os chips), zeraPLAYe espera um pouco para o toque não ser lido de novo na lista. - O
WAITdo final é o metrônomo do programa: cada volta do laço dura um quadro, e por isso a música anda no tempo certo. - O
WENDexterno volta ao início — a tela de texto é refeita e a lista aparece de novo.
O que este programa ensinou
MEMORY COMeUSESpara montar um executável DOS enxuto.- Arquivos:
DIRFIRST,DIRNEXT,LOADFILE,DSKERR(),DSKVER(). - Reconhecer formatos pela assinatura, com
PEEK. - Modo texto 80 colunas e vídeo invertido pela tabela de piscar (
VPOKE+ registradores do VDP emASM). - Entrada:
STICKeSTRIGcom pausa anti-repetição. - Música:
PLAYPT3/TICKPT3/STOPPT3(PSG) ePLAYPRO/TICKPRO/STOPPRO(FM). - Leitura dos chips em tempo real:
PSGREG,PROVOL,PRONOTE. - Um programa, duas máquinas:
VDPID()escolhe entre V9968 (V9968 PALETTE,V9968 BOX) e SCREEN 4 (TILECREATE,TILECOLOR). - Desempenho: desenhar só o que mudou e usar
WAITcomo relógio.
EXPERIMENTE
Variações sugeridas
- Troque as cores do array
CORe da paleta do V9968. - Mude a queda suave para
LEV(I) - 2e veja as barras caírem mais rápido. - Mostre o nome da música tocando no topo da tela gráfica.
- Faça as setas esquerda/direita trocarem de música sem voltar à lista.