SCROLL2 v2: scroll fino estilo Space Manbow em SCREEN 5
Vertical por hardware (R#23), horizontal por 1-2 blits com wrap seamless. A mesma técnica que o Space Manbow usou para 60 fps de scroll no MSX 2.
1. A ideia
O SCROLL2 v2 separa os dois eixos:
- Vertical — usa o registrador R#23 do V9938 (Vertical Scroll Register). Custo: 0 CPU e 0 blitter. O hardware do VDP faz o deslocamento durante o refresh — fluidez 60 fps sem esforço.
- Horizontal — usa 1 ou 2 LMMMs por banda ativa por frame. Cada banda copia uma "janela" de largura
vpWda página fonte para a viewport, começando emsx = (sxBase + offset) mod 256. Quando a janela cruza a borda direita da página fonte, dois blits fazem o wrap seamless.
O que fica fora das bandas — texto, HUD, sprites — não é afetado (é o mesmo padrão do v1).
2. API
| Comando | Efeito |
|---|---|
SCROLL2 VIEWPORT vpX, vpY, vpW, vpH | Define a área destino visível. vpW normalmente é 256 (tela cheia). Zera todas as bandas e reseta R#23. |
SCROLL2 HSTRIP id, srcPage, sx, sy, dstY, h, speed | Configura uma banda horizontal (id 0..7). srcPage=0..3 é a página fonte. sx, sy são a origem no strip. dstY é o Y na viewport. speed é signed (-8..+8) em px/frame; 0 desativa. |
SCROLL2 VSCROLL speed | Define a velocidade do scroll vertical por hardware (R#23), em px/frame. |
SCROLL2 HADJUST n | Desloca a tela inteira de n pixels na horizontal (-8..+7) via R#18. Custo: 1 OUT. Zero blitter. |
SCROLL2 TICK | Avança offsets e emite 1-2 LMMMs por banda ativa; atualiza R#23. |
SCROLL2 STOP | Desativa todas as bandas e zera R#23. |
2.1 HADJUST — o deslocamento fino grátis
O V9938 tem um registrador de Display Adjust (R#18) que desloca a imagem
inteira de -8 a +7 pixels em cada eixo. SCROLL2 HADJUST n escreve o
nibble horizontal desse registrador (o ajuste vertical da máquina é
preservado).
O que isso significa na prática: movimento horizontal de 1 px/frame com custo zero de CPU e zero de blitter, ou seja, 60 fps garantidos em qualquer altura de tela — inclusive 212 linhas.
SCROLL2 VIEWPORT 0, 0, 256, 212
DIM adj AS INT
DIM dir AS INT
adj = 0 : dir = 1
WHILE STRIG(0) = 0
SCROLL2 HADJUST adj
adj = adj + dir
IF adj > 7 THEN dir = 0 - 1
IF adj < -8 THEN dir = 1
WAIT
WEND
Os dois limites, ditos com clareza:
- Alcance de 8 pixels. R#18 não é scroll infinito — é um deslocamento fino
dentro de uma janela de 8 px. Para rolagem contínua ele precisa de um
parceiro que faça o passo de 8 px (uma banda
HSTRIPcomspeed 8). - Afeta a tela toda, HUD e sprites incluídos. Se o HUD precisa ficar
parado, use
HSTRIPpara a faixa de fundo e deixe o R#18 para efeitos.
Usos naturais: sway de cenário, screen shake de explosão, tremor de impacto e o sub-pixel de um scroll híbrido.
O que os jogos consagrados realmente fazem
A pesquisa nas fontes de hardware fecha a questão:
- Space Manbow (Konami, 1989) usa exatamente o R#18 no MSX 2, em SCREEN 4, com o mesmo alcance de 8 px — e mascara as bordas com ~16 px de sprites/faixa preta em cada lado, porque o R#18 desloca a borda junto com a imagem. O 8 px grosso vem de reescrever a tabela de nomes (768 bytes, barato), não de copiar bitmap.
- Em MSX 2+ (VDP V9958) existem os registradores R#26/R#27, que fazem scroll horizontal contínuo de verdade, sem o limite de 8 px. O próprio Space Manbow tem um caminho de código alternativo para MSX 2+ onde a borda não "pisca". Os patches da comunidade que transformaram o scroll 8×8 do Nemesis 2, Nemesis 3, Salamander e Parodius em 1×1 usam esses registradores — e por isso exigem máquina MSX 2+ ou turboR real; em MSX 2 puro eles não ativam.
- Conclusão honesta: scroll horizontal 1 px de tela cheia e contínuo a 60 fps é recurso do V9958 (MSX 2+), não do V9938 (MSX 2). No MSX 2, o que existe é o R#18 dentro da janela de 8 px (o que o CrossScript agora expõe) mais o passo de 8 px por tabela de nomes / blitter.
ATENÇÃO
R#18 e o blitter não podem se cruzar
Escrever no R#18 enquanto um comando do Command Engine está em execução
corrompe o byte que o VDP está processando. O SCROLL2 HADJUST já espera o
bit CE ficar em 0 antes de escrever — você não precisa fazer nada, mas saiba
que chamar HADJUST logo depois de um TICK pesado custa essa espera.
ATENÇÃO
O orçamento do blitter é real
Uma banda HSTRIP de largura 256 e altura 191 move 48.896 pixels
(24 KB de VRAM) por TICK. O LMMM do V9938 gasta ~19 a 32 ms nisso — mais
de um frame inteiro. O resultado é um passo de 1 px acontecendo a cada 2 a 4
frames, de forma irregular. Bandas de 48 a 64 linhas cabem folgado em
1 frame e é aí que o parallax fica realmente fluido. Para movimento fino em
tela cheia, o caminho é HADJUST (hardware), não o blitter.
3. Programa 22.1 — Parallax de 3 bandas
USES SCREEN 5, SCROLL2, TILES, KEYBOARD, BPRINT
SCREEN 5 : COLOR 15, 1, 1 : CLS
BPRINT 8, 4, "SCROLL2 V2 DEMO", 15
TILECREATE 96, $FF,$81,$BD,$A5,$A5,$BD,$81,$FF
TILECREATE 97, $18,$3C,$7E,$FF,$FF,$7E,$3C,$18
DIM i AS BYTE
FOR i = 0 TO 30 STEP 3
TILE i, 6, 96 ' banda 0 (ceu)
TILE i, 14, 97 ' banda 1 (montanha)
TILE i, 22, 96 ' banda 2 (chao)
NEXT i
SCROLL2 VIEWPORT 0, 0, 256, 212
SCROLL2 HSTRIP 0, 0, 0, 24, 24, 48, 1 ' ceu: 1 px/frame
SCROLL2 HSTRIP 1, 0, 0, 72, 72, 64, 2 ' montanha: 2 px/frame
SCROLL2 HSTRIP 2, 0, 0, 136, 136, 72, 4 ' chao: 4 px/frame
WHILE STRIG(0) = 0
SCROLL2 TICK
WAIT
WEND
4. Scroll vertical por hardware
SCROLL2 VIEWPORT 0, 0, 256, 212
SCROLL2 VSCROLL 1 ' 1 px/frame para cima (R#23 += 1 por TICK)
WHILE STRIG(0) = 0
SCROLL2 TICK ' escreve R#23 no VDP
WAIT
WEND
Use SCROLL2 VSCROLL -1 para inverter a direção. O valor é signed.
5. Limites (v2)
- Até 8 bandas horizontais simultâneas (
id 0..7). - Velocidade signed em px/frame (recomendado -8..+8; sem clamp de runtime).
- Cada banda ativa custa 1-2 LMMMs por frame — planeje: 8 bandas cheias por frame estouram o VBlank; comece com 3-4.
- O strip fonte tem largura 256 (uma coluna de página) e sofre wrap horizontal na borda direita. Para strips maiores, use
sxBasefixo em outra página. vpYestá confinado a page 0 nesta versão (não coexiste comBOB PAGEFLIP ON).- Coexiste com BOBs sem pageflip: chame
SCROLL2 TICKantes dosBOB MOVEdo frame. - Não chame
SCROLL2 TICKde dentro do handler de VBLANK — o custo do blitter pode estourar o tempo disponível.
DICA
Pause sem perder o cenario
Chame SCROLL2 HSTRIP id, ..., 0 (speed = 0) para pausar; a banda mantém a configuração.
6. Resumo do capítulo
- Vertical: hardware puro (R#23), custo zero.
- Horizontal: 1-2 LMMMs por banda com wrap seamless — muito mais fluido que a v1 (3 blits/banda).
- API cirúrgica:
VIEWPORT,HSTRIP,VSCROLL,TICK,STOP. HADJUSTdá deslocamento horizontal fino de -8..+7 px por hardware, custo zero.- Orçamento do blitter: mantenha cada banda em 48-64 linhas para 60 fps.
- Inspirado na técnica do Space Manbow (Konami, 1989).