Programação para Atari 2600

73,232 views

Published on

Palestra apresentada em 27/Ago/2011 no Dev in Sampa (http://devinsampa.com.br/), em 06/Nov/2011 no Dev In Vale e em 11/Fev/2012 no Campus Party Brasil (5a. edição, #cpbr5)

O vídeo da palestra no Dev In Sampa (filmada pelo @agaelebe) está disponível em: http://chester.blog.br/archives/2011/08/palestra-sobre-programacao-para-atari-2600-no-dev-in-sampa-2011.html

2 Comments
19 Likes
Statistics
Notes
No Downloads
Views
Total views
73,232
On SlideShare
0
From Embeds
0
Number of Embeds
61,625
Actions
Shares
0
Downloads
251
Comments
2
Likes
19
Embeds 0
No embeds

No notes for slide

Programação para Atari 2600

  1. 1. game program™PROGRAMAÇÃO PARA ATARI 2600 Use with Joystick Controllers
  2. 2. Proposta Entender o que torna o Atari tão diferente de outros sistemas, aprendendo o básico para escreverum “Hello, World” e poder apreciarclássicos como Enduro ou Pitfall! pela habilidade de seus criadores http://slideshare.net/chesterbr
  3. 3. Palestrante @chesterbr http://chester.me
  4. 4. Palestrante @chesterbr http://chester.me
  5. 5. Atari 2600(Video Computer System)
  6. 6. imagem: mitchelaneous.com Mais de 600 jogos...
  7. 7. mas por que eram tão... “Atari”?
  8. 8. Por dentro do Atari (Jr.) Fotos: Larry Ziegler (2600 CE)
  9. 9. CPU: 6507Fotos: Larry Ziegler (2600 CE)
  10. 10. CPU: 6507 2 650Fotos: Larry Ziegler (2600 CE)
  11. 11. Video: TIAFotos: Larry Ziegler (2600 CE)
  12. 12. Todo o resto: RIOT (6532) Fotos: Larry Ziegler (2600 CE)
  13. 13. Mapa da Memória0000-002C – TIA (Escrita)0030-003D – TIA (Leitura)0080-00FF – RIOT (RAM)0280-0297 – RIOT (I/O, Timer)F000-FFFF – Cartucho (ROM)
  14. 14. Mapa da Memória 4 KBytes!F000-FFFF – Cartucho (ROM)esse nem é o maior problema...
  15. 15. Mapa da Memória 128 BYTES!!!!! (1/8 de KB) 0080-00FF – RIOT (RAM)e esse ainda não é o maior problema...
  16. 16. VRAM Um chip de vídeo típicotransforma padrões de bitsarmazenados em memória(VRAM) em pixels e cores
  17. 17. VRAM VRAM VRAM 38 44 44 7C 44 44 EE 00
  18. 18. VRAM Quanto mais memória (VRAM),maior a resolução, e variedade decores. Memória era cara nos anos 70/80, levando a um tradeoff. Quanta VRAM o Atari tem?
  19. 19. Mapa da Memória0000-002C – TIA (Escrita)0030-003D – TIA (Leitura)0080-00FF – RIOT (RAM)0280-0297 – RIOT (I/O, Timer)F000-FFFF – Cartucho (ROM)
  20. 20. Mapa da Memória????-???? – VRAM
  21. 21. Mapa da Memória 0 bytes !!!!????-???? – VRAM #comofas?
  22. 22. TIA(Television Interface Adaptor)
  23. 23. Funcionamento da TV Fonte: How Stuff Works
  24. 24. Funcionamento da TV Fonte: How Stuff Works
  25. 25. Scanlines 60 quadros (frames) por segundo Fonte: How Stuff Works
  26. 26. TIA opera em scanlinesPara cada scanline, você escreve em posições de memória do TIA que configuram “objetos desenháveis” É difícil mudar a cor/forma de um objeto numa mesma scanline
  27. 27. Isso explica vs.
  28. 28. E que objetos são esses?● Playfield (PF)● Players (P0, P1)● Missiles/Ball (M0, M1, BL)
  29. 29. PlayfieldUm padrão de 20 bits (representando cor de frente e cor de fundo) que ocupa o lado esquerdo da scanline. O lado direito repete o mesmo padrão, ou, opcionalmente, uma versão “espelhada” dele
  30. 30. PLAYFIELD
  31. 31. PLAYFIELD
  32. 32. PLAYFIELD
  33. 33. PLAYFIELD
  34. 34. Configurando o playfield PF0 = 0000 ←← leitura PF1 = 00000000 leitura →→ PF2 = 00000000 ←← leitura REFLECT = 0 scanline resultante████████████████████████████████████████
  35. 35. Configurando o playfield PF0 = 0001 ←← leitura PF1 = 00000000 leitura →→ PF2 = 00000000 ←← leitura REFLECT = 0 scanline resultante████████████████████████████████████████
  36. 36. Configurando o playfield PF0 = 0011 ←← leitura PF1 = 00000000 leitura →→ PF2 = 00000000 ←← leitura REFLECT = 0 scanline resultante████████████████████████████████████████
  37. 37. Configurando o playfield PF0 = 0111 ←← leitura PF1 = 00000000 leitura →→ PF2 = 00000000 ←← leitura REFLECT = 0 scanline resultante████████████████████████████████████████
  38. 38. Configurando o playfield PF0 = 1111 ←← leitura PF1 = 11110000 leitura →→ PF2 = 00000000 ←← leitura REFLECT = 0 scanline resultante████████████████████████████████████████
  39. 39. Configurando o playfield PF0 = 1111 ←← leitura PF1 = 11111110 leitura →→ PF2 = 00010101 ←← leitura REFLECT = 0 scanline resultante████████████████████████████████████████
  40. 40. Configurando o playfield PF0 = 1111 ←← leitura PF1 = 11111110 leitura →→ PF2 = 00010101 ←← leitura REFLECT = 1 scanline resultante████████████████████████████████████████
  41. 41. PlayersCada um dos players é um padrão de 8 bits com sua própria cor Ex.: 10100001 → ████████ Os dois padrões (GRP0/GRP1)podem aparecer na mesma scanline
  42. 42. PLAYERS
  43. 43. PLAYERS
  44. 44. Players É possível esticar/multiplicar einverter o desenho de cada playerusando os registradores NUSIZn e REFPn (n=0 ou 1)
  45. 45. NUSIZn (em 5 scanlines) 000 001 010NUSIZn 011 100 101 110 111
  46. 46. Ligando o REFPn 000 001 010NUSIZn 011 100 101 110 111
  47. 47. NUSIZn
  48. 48. NUSIZn
  49. 49. NUSIZn
  50. 50. NUSIZn
  51. 51. 8 bits exigem criatividade vs.
  52. 52. Missiles/Ball Cada um representa um pixel na scanline, mas pode ter sua largura ampliada em 2, 4 ou 8 vezes.Os missiles têm as cores dos players,enquanto ball tem a cor do playfield.
  53. 53. MISSILES
  54. 54. BALL
  55. 55. BALL MISSILE
  56. 56. BALL MISSILE
  57. 57. Idéia geral Para cada scanline, você configura oformato dos objetos (playfield, players, missiles/ball) e as cores/efeitos deles.O que você configura em uma scanlinevale para as seguintes, mas ainda assim o tempo é um problema
  58. 58. Contas de padaria:6502 ≈ 1,19Mhz (1.194.720 ciclos/seg) NTSC: 60 frames (telas) por seg1.194.720/60 ≅ 19.912 ciclos por tela
  59. 59. Contas de padaria: CPU: 19.912 ciclos por tela NTSC: 262 scanlines por frame19.912 / 262 = 76 ciclos por scanline
  60. 60. Contas de padaria: CPU: 19.912 ciclos por tela NTSC: 262 scanlines por frame19.912 / 262 = 76 ciclos por scanline e o que se faz com “76 ciclos”? (aliás, o que exatamente é um “ciclo”?)
  61. 61. Assembly 6502
  62. 62. 6502
  63. 63. 6502 (no Atari)Executa instruções armazenadas naROM que manipulam e transferembytes entre o RIOT (RAM + I/O + timers) e o TIA, com o apoio de registradores internos.
  64. 64. Instruções Cada instrução é composta por um opcode (1 byte) seguido por um parâmetro (0 a 2 bytes)Dependendo do opcode, a instrução leva de 2 a 6 ciclos para ser executada
  65. 65. Registradores do 6502A = Acumulador (8 bits)X,Y= Índices (8 bits)S = Stack Pointer (8 bits)P = Status (flags, 8 bits)PC = Program Counter (16 bits)
  66. 66. Exemplo de Programa● Ler o byte da posição de memória 0x0200 para o acumulador (A)● Somar 1 (um) no A● Guardar o resultado (A) na posição de memória 0x0201
  67. 67. Código de Máquina 6502 AD Opcode (Memória→A) 00 2a. Parte de “0200” 02 1a. Parte de “0200” 69 Opcode (valor+A→A) 01 valor “01” 8D Opcode (A→Memória) 01 2a. Parte de “0201” 02 1a. Parte de “0201”
  68. 68. Linguagem AssemblyAtribui a cada opcode uma sigla (“mnemônico”) e define uma notação para os parâmetros
  69. 69. Código de Máquina 6502 AD Opcode (Memória→A) 00 2a. Parte de “0200” 02 1a. Parte de “0200” 69 Opcode (valor+A→A) 01 valor “01” 8D Opcode (A→Memória) 01 2a. Parte de “0201” 02 1a. Parte de “0201”
  70. 70. Assembly 6502AD LDA $0200000269 ADC #01018D STA $02010102
  71. 71. Assembler (Montador)Programa que lê um arquivo-texto escrito em linguagem Assembly emonta o arquivo binário (código de máquina) correspondente foo.asm foo.binLDA $0200 ASSEMBLER AD000269ADC #01 018D0102STA $0201 ......
  72. 72. DASM● Macro Assembler 6502● Inclui headers para Atari● Multiplataforma● Livre (GPLv2) http://dasm-dillon.sourceforge.net/
  73. 73. Notação (para hoje)#... = valor absoluto$... = endereço, em hexa$..., X = endereço + X, em hexa#$... = valor absoluto em hexa http://www.obelisk.demon.co.uk/6502/addressing.html
  74. 74. Instruções do 6502 = mais relevantes para o Atari
  75. 75. Transferindo Dados LDA, LDX, LDY = Load STA, STX, STY = Store TAX, TAY, TXA, TYA, TSX, TXS = TransferLDA #$10 0x10→ASTY $0200 Y→m(0x0200)TXA X→A
  76. 76. Aritmética ADC, SBC = +,- (C=“vai um”) INC, DEC = ++,-- (memória) INX, INY, DEX, DEY = ++,--ADC $0100 m(0x100)+A→AINC $0200 m(0x200)+1→ m(0x200)DEX X-1→X
  77. 77. Operações em BitsAND, ORA, EOR = and, or, xor (A)ASL, LSR = Shift aritmético/lógicoROL, ROR = Shift “rotacional”AND #$11 A&0x11→ALSR A>>1→A (A/2→A)ROR A>>1 (bit 7=carry)
  78. 78. Comparações e DesviosCMP, CPX, CPY = compara A/X/Y (-)BCS, BCC = desvia se Carry/NãoBEQ, BNE = desvia se Equal/NãoBVS, BVC = desvia se Overflow/NãoBMI, BPL = desvia se Minus/PlusCPY $1234 se y=m(0x1234),BEQ $0200 0x0200→PC
  79. 79. Pilha e SubrotinasJSR, RTS = chama subrotina/retornaPHA, PLA = push/pop(pull) do APHP, PLP = push/pop do status (P)JMP $1234 0x1234→PCJSR $1234 PC(+3)→pilha, 0x1234→PCRTS pilha→PC
  80. 80. O Resto...NOP = No Operation (nada!)JMP = Desvio direto (GOTO)SEC, CLC = Set/Clear CarrySEV, CLV = Set/Clear oVerflowSEI, CLI = Set/Clear Interrupt-offSED, CLD = Set/Clear DecimalRTI = Return from InterruptBRK = Break
  81. 81. © 1999 Warner BrosNeo: “I know kung fu.”Morpheus: “Show me.”
  82. 82. Hello, World!
  83. 83. Hello, World! Escrever na horizontal é complicado(muitos pixels/elementos por scanline)
  84. 84. Hello, World! É mais fácil escrever na vertical →(menos pixels/scanline) Podemos usar um player ou o playfield
  85. 85. Display kernel É a parte do programa que rodaquando o canhão está desenhando a tela propriamente dita (através do playfield, players e missiles/ball)
  86. 86. (3+37+30).76 = 5320 ciclosLÓGICA DO JOGO KERNEL Fonte: Stella Programmers Guide, Steve Wright, 1979
  87. 87. Estrutura do programa VSYNC VBLANK KERNEL (desenha a tela) OVERSCAN
  88. 88. Estrutura do programa VSYNCPlayfield VBLANK OVERSCAN
  89. 89. Estrutura do programa VSYNC VBLANK Loop 11 chars xPrincipal 8 linhas x (eterno) 2 linhas por Kernel scanline = loop X: 0 a 191 176 (192 scanlines) scanlines OVERSCAN
  90. 90. Começando o programaPROCESSOR 6502INCLUDE "vcs.h"ORG $F000 ; Início do cartucho VSYNC VBLANK KERNEL OVERSCAN
  91. 91. Início do frame (loop principal) InicioFrame: lda #%00000010 ; VSYNC inicia sta VSYNC ; setando o bit 1 REPEAT 3 ; e dura 3 scanlines sta WSYNC ; (WSYNC = aguarda fim REPEND ; da scanline) lda #0 ; VSYNC finaliza sta VSYNC ; limpando o bit 1 VSYNC VBLANK KERNEL OVERSCAN
  92. 92. Desligando elementoslda #$00sta ENABL ; Desliga ballsta ENAM0 ; Desliga missilessta ENAM1sta GRP0 ; Desliga playerssta GRP1 VSYNC VBLANK KERNEL OVERSCAN
  93. 93. Configurando o Playfieldsta COLUBK ; Cor de fundo (0=preto)sta PF0 ; PF0 e PF2 ficam apagadossta PF2lda #$FF ; Cor do playfieldsta COLUPF ; (possivelmente amarelo)lda #$00 ; Reset no bit 0 do CTRLPFsta CTRLPF ; para duplicar o PFldx #0 ; X=contador de scanlines VSYNC VBLANK KERNEL OVERSCAN
  94. 94. VBLANK propriamente dito REPEAT 37 ; VBLANK dura 37 scanlines, sta WSYNC ; (poderíamos ter lógica REPEND ; do jogo aqui) lda #0 ; Finaliza o VBLANK, sta VBLANK ; "ligando o canhão" VSYNC VBLANK KERNEL OVERSCAN
  95. 95. KernelScanline: cpx #174 ; Se acabou a frase, pula bcs FimScanline; o desenho txa ; Y=X/2 (usando o shift lsr ; lógico para dividir, tay ; que só opera no A) lda Frase,y ; Frase,Y = mem(Frase+Y) sta PF1 ; PF1 = bits 5 a 11 do ; playfield VSYNC VBLANK KERNEL OVERSCAN
  96. 96. Kernel (continuação)FimScanline: sta WSYNC ; Aguarda fim da scanline inx ; Incrementa contador e cpx #191 ; repete até até a bne Scanline ; completar a tela VSYNC VBLANK KERNEL OVERSCAN
  97. 97. Fechando o loop principalOverscan: lda #%01000010 ; "Desliga o canhão": sta VBLANK ; 30 scanlines de REPEAT 30 ; overscan... sta WSYNC REPEND jmp InicioFrame ; ...e começa tudo de ; novo! VSYNC VBLANK KERNEL OVERSCAN
  98. 98. A frase, bit a bitFrase: .BYTE %00000000 ; H .BYTE %01000010 .BYTE %01111110 .BYTE %01000010 .BYTE %01000010 .BYTE %01000010 .BYTE %00000000 .BYTE %00000000 ; E .BYTE %01111110 ...
  99. 99. A frase, bit a bit... .BYTE %00000000 ; D .BYTE %01111000 .BYTE %01000100 .BYTE %01000010 .BYTE %01000010 .BYTE %01000100 .BYTE %01111000 .BYTE %00000000 ; Valor final do PF1
  100. 100. Configurações finaisORG $FFFA ; Ficam no final da ; ROM (cartucho).WORD InicioFrame ; Endereço NMI.WORD InicioFrame ; Endereço BOOT.WORD InicioFrame ; Endereço BRKEND
  101. 101. Montando e Executandodasm fonte.asm -oromcartucho.bin -f3 http://stella.sourceforge.net/
  102. 102. Técnicas Avançadas
  103. 103. Placar com playfield
  104. 104. Placar com playfield Para identificar os placares, épossível usar as cores dos players no playfield, setando o bit 1 doregistrador CTRLPF (score mode)O lado esquerdo fica com a cor do P0, e o direito com a cor do P1
  105. 105. CORES DOS PLAYERS
  106. 106. (isso dá idéias para melhorar nosso Hello World?)
  107. 107. (isso dá idéias para melhorar nosso Hello World?)
  108. 108. Placar com playfieldProblema: como mostrar coisas DIFERENTES em cada lado? Solução: mudar o playfield enquanto o canhão passa!
  109. 109. canhã oconfigure o playfield para “3” no início da scanline
  110. 110. canhãoquando o canhão estiver no meio, configure o playfield do “1”...
  111. 111. o canhã...e você terá um desenho diferente do outro lado!
  112. 112. Mundos gigantes
  113. 113. Pitfall! Cada uma das 256 telas é definida(objetos, árvores, paredes...) por 1 byte, que deveriam ser armazenados no cartucho (ROM) Tamanho da tabela: 256 bytes
  114. 114. Pitfall! Solução: gerador de sequência comaleatoriedade aceitável e que tambémgera o valor anterior a partir do atual, para voltar telas (LFSR bidirecional) Tamanho do código: 50 bytes http://en.wikipedia.org/wiki/Linear_feedback_shift_register
  115. 115. River Raid A mesma solução é aplicada com umgerador de 16 bits (que eventualmente se repete), com pequenos ajustes paratornar os primeiros setores mais fáceis. Ao passar a ponte, o jogo guarda o valor atual, recuperando em caso de morte para voltar no mesmo setor
  116. 116. Posição horizontal
  117. 117. Posição horizontal Não existe um registrador paradetermine a posição horizontal de players, missiles ou ball Você tem que contar o tempoaté que o canhão esteja na posiçãoe acionar o strobe correspondente
  118. 118. PONTOS DE STROBE (na teoria)
  119. 119. Dá pra calcular... 1 ciclo de CPU = 3 pixels WSYNC = 20 ciclos posição x ≈ (ciclos – 20) * 3...mas é aproximado, porque o TIA só lê os registros a cada 5 ciclos de CPU, tornando inviável para movimento ↔
  120. 120. Soluções Você pode mover player, missile ou ball relativamente à posição anterior, usando um registrador de 4 bits (isto é, movendo de -7 a +8 pixels) E o missile pode ser posicionado no meio do player correspondente,tornando fácil “atirar” ele (daí o nome)
  121. 121. PONTOS DE STROBE
  122. 122. MOVIMENTO ↔ registradores HMP0/1 e HMM0/1 MOVIMENTO ↕ basta desenhar o player/missle emuma scanline diferente a cada frame
  123. 123. Placar com múltiplos dígitos
  124. 124. Placar com múltiplos dígitos O truque é o mesmo do placar com playfield: mudar a imagem com ocanhão andando, mas o timing tem que ser muito mais preciso Digamos que o placar seja 456789...
  125. 125. Placar com múltiplos dígitos Comece cada scanline com a linha do 4 no GRP0 e do 5 no GRP1. Configure NUSIZ0 e NUSIZ1 para repetir três vezes: 4 4 4 5 5 5 Player 0 Player 1
  126. 126. Placar com múltiplos dígitos Posicione o player 1 à direita do player 0, encavalando as cópias: Player 1 454545 Player 0
  127. 127. Placar com múltiplos dígitos Troque o desenho dos players (GRP0/GRP1) sincronizando com o canhão, assim: 454545 CANHÃO
  128. 128. Placar com múltiplos dígitosQuando o canhão estiver terminandoa 1ª cópia do player 1, altere o player 0 para 6 e o player 1 para 7: 454545 CANHÃO
  129. 129. Placar com múltiplos dígitos Repita o truque ao final da 2ª cópia do player 2, dessa vez alternado oplayer 0 para 8 e o player 1 para 9 456767 CANHÃO
  130. 130. Placar com múltiplos dígitos Faça a mesma coisa para cada scanline do placar! 456789 CANHÃO
  131. 131. Placar com múltiplos dígitos É mais difícil do que parece: não dátempo de carregar bitmaps da memória quando o canhão passa, e só temos 3 registradores para guardar 4 dígitos... ...mas é isso que torna divertido!
  132. 132. Conclusões
  133. 133. Tirando leite de pedra Quando observar um jogo de Atari, tente identificar os truques que o(a) programador(a) usou: como dividiu atela, o que tem em cada scanline, como gastou a RAM e a ROM...
  134. 134. Mãos à obra!Você pode fazer seu jogo de Atari – éum desafio de programação divertido!Será preciso estudar várias coisas que não detalhamos: contagem de ciclos, som, leitura de joysticks... mas dá!
  135. 135. Para aprender maisO nosso Hello, World: http://pastebin.com/abBRfUjdSorteio 2600 http://github.com/chesterbr/sorteio2600Racing The Beam (livro): http://bit.ly/dSqhjSPalestra David Crane (Pitfall): http://youtu.be/MBT1OK6VAIUTutoriais do Crane para iOS: http://bit.ly/9pwYHs e http://bit.ly/qWBciZStella Programmers Guide: http://emu-docs.org/?page=Atari%202600Código-fonte de jogos clássicos: http://classicdev.org/wiki/2600/Source_CodeEspecificações do Atari: http://nocash.emubase.de/2k6specs.htmReferência 6502: http://bit.ly/hxG5c6Emulador no browser: http://jogosdeatari.com.br/Tutorial Andrew Dave: http://bit.ly/ptQDdA (o site todo é bom)Cartucho com leitor de SD: http://harmony.atariage.com/BAtari (compilador BASIC): http://bataribasic.comExemplos de som no TIA: http://bit.ly/tnbPrpBankswitching (mais ROM/RAM): http://bit.ly/tqhLZk
  136. 136. Dúvidas?Obrigado! @chesterbr http://chester.me http://slideshare.net/chesterbr
  137. 137. Créditos e Licenciamento Esta apresentação está licenciada sob os termos da licença Creative Commons “by-nc” 3.0, observadas as exceções abaixo O slide de abertura é baseado em ilustração © 2011 Ila Fox, licenciada exclusivamente para o autor e não inclusa na licença acimaFotos e ilustrações de terceiros usados sob premissa de “fair use” têm sua autoria mencionada e também excluídos da licença acimaAtari™, Adventure™, Donkey Kong™, Pitfall™, Super Mario™ e outrospersonagens/jogos citados para fins ilustrativos, bem como suas imagens e logomarcas, são de propriedade de seus detentores, com todos os direitos reservados, não havendo qualquer relação deles com o autor

×