Pergunta

Eu vi demos legal C64 mostrando sprites na zona fronteiriça da tela. Não deve ser possível; Eu acho que eles conseguiram enganar o chip gráfico de alguma forma. Como exatamente eles fazem isso?

Foi útil?

Solução

Sim, você precisa assembler. É um truque tempo de interrupção. O VIC é capaz de mostrar sprites na fronteira, mas o quadro é apenas escondê-los, de modo que os sprites pode deslizar por trás dele. Ele está conectado a linhas de varredura exibidos pelo VIC. Para as fronteiras mínimo / máximo é muito simples:

  • Programm uma interrupção, sincronizados para começar em uma determinada linha de varredura, 7 pixel ou algo parecido antes da borda inferior.
  • Definir o registo em VIC para fazer a fronteira menor. (Não é um registo que pode fazer isso.)
  • VIC acredita agora que a fronteira já começou e não começar a pintá-lo.
  • -.> Sem borda na parte inferior
  • Programa outra interrupção após a fronteira real para configurá-lo de volta ao original.

Para sprites nas fronteiras esquerda / direita, é mais complicado porque o processo tem de ser repetido para cada linha de varredura:

  • Programm uma interrupção, sincronizados para começar em uma determinada linha de varredura.
  • Em seguida, fazer algumas NOPs até que você esteja 7 pixels antes da borda direita.
  • Definir o registo em VIC para fazer a fronteira menor.
  • -.> Sem fronteira no lado direito
  • Faça alguns NOPs até que você esteja após a fronteira real e definir a volta registo de valor original.
  • Mais uma vez fazer algumas NOPs até a etapa 2.

O problema é que todas estas NOPs são ocupado espera e roubar os ciclos que você tem para o seu material.

Eu era capaz de encontrar algum código para você, a partir de um scroller Sprite na borda inferior. Aqui está o código. (Ele foi rasgado de alguma demonstração.)

C198  78        SEI
C199  20 2E C1  JSR C12E     # clear sprite area
C19C  20 48 C1  JSR C148     # init VIC
C19F  A9 BF     LDA #BF      # set up IRQ in C1BF
C1A1  A2 C1     LDX #C1
C1A3  8D 14 03  STA 0314
C1A6  8E 15 03  STX 0315
C1A9  A9 1B     LDA #1B
C1AB  8D 11 D0  STA D011
C1AE  A9 F7     LDA #F7
C1B0  8D 12 D0  STA D012
C1B3  A9 01     LDA #01
C1B5  8D 1A D0  STA D01A
C1B8  A9 7F     LDA #7F
C1BA  8D 0D DC  STA DC0D
C1BD  58        CLI
C1BE  60        RTS

----------------------------------
# init VIC
C148  A2 00     LDX #00
C14A  BD 88 C1  LDA C188,X
C14D  9D 00 D0  STA D000,X   # set first 16 values from table
C150  E8        INX
C151  E0 10     CPX #10
C153  D0 F5     BNE C14A
C155  A9 FF     LDA #FF
C157  8D 15 D0  STA D015
C15A  A9 00     LDA #00
C15C  8D 1C D0  STA D01C
C15F  A9 FF     LDA #FF
C161  8D 17 D0  STA D017
C164  8D 1D D0  STA D01D
C167  A9 C0     LDA #C0
C169  8D 10 D0  STA D010
C16C  A9 F8     LDA #F8
C16E  A2 00     LDX #00
C170  9D F8 07  STA 07F8,X
C173  18        CLC
C174  69 01     ADC #01
C176  E8        INX
C177  E0 08     CPX #08
C179  D0 F5     BNE C170
C17B  A9 0E     LDA #0E
C17D  A2 00     LDX #00
C17F  9D 27 D0  STA D027,X
C182  E8        INX
C183  E0 08     CPX #08
C185  D0 F8     BNE C17F
C187  60        RTS

----------------------------------
# data set into VIC registers
C188  00 F7 30 F7 60 F7 90 F7
C190  C0 F7 F0 F7 20 F7 50 F7

----------------------------------
# main IRQ routine
C1BF  A2 08     LDX #08
C1C1  CA        DEX
C1C2  D0 FD     BNE C1C1
C1C4  A2 28     LDX #28      # 40 or so lines
C1C6  EA        NOP          # "timing"
C1C7  EA        NOP
C1C8  EA        NOP
C1C9  EA        NOP
C1CA  CE 16 D0  DEC D016     # fiddle register
C1CD  EE 16 D0  INC D016
C1D0  AC 12 D0  LDY D012
C1D3  88        DEY
C1D4  EA        NOP
C1D5  98        TYA
C1D6  29 07     AND #07
C1D8  09 18     ORA #18
C1DA  8D 11 D0  STA D011
C1DD  24 EA     BIT   EA
C1DF  EA        NOP
C1E0  EA        NOP
C1E1  CA        DEX
C1E2  10 E4     BPL C1C8     # repeat next line
C1E4  A9 1B     LDA #1B
C1E6  8D 11 D0  STA D011
C1E9  A9 01     LDA #01
C1EB  8D 19 D0  STA D019
C1EE  20 00 C0  JSR C000   # call main code
C1F1  4C 31 EA  JMP EA31   # finish IRQ

Outras dicas

Tudo contou com timing. O C64 tinha um método para consultar localização vertical exacto do feixe de electrões, enquanto ele estava desenhando a tela. Quando uma nova linha começou, você tinha que esperar alguns ciclos (você poderia tempo isso usando a instrução NOP) e então você tinha que definir um registo do videochip que era responsável pela definição da screenmode (e a largura da borda) hardware. Cronometrando o valor correto, e fazê-lo a cada linha de varredura novamente, toda a sideborder desapareceu.

A borda inferior foi embora com um truque similar. Na linha de varredura exato onde a borda vertical iniciado, você também teve de definir o modo de video que desativado a borda inferior para esse quadro.

Na verdade, esta coisa toda teve que ser feito em conjunto. Caso contrário, você nunca poderia obter o timing exatamente correto.

Como uma nota lateral, eu acho que o truque sideborder foi creditada a 1001 Tripulação (um grupo holandês). Eu não tenho certeza de quem tirou o primeiro truque borda inferior.

Para um bom tutorial sobre o tema da abertura das fronteiras no C64, vá para o excelente artigo de Pasi Ojala em C = Cortando Issue 6 .

Sem ficar demasiadamente técnico, o truque usa um recurso da VIC chip para deixar você alternar entre 25/24 e 40/38 linhas colunas de texto / gráficos e envolve fazer essa opção no momento exato direito de enganar o VIC em pensar que já mudou as fronteiras em quando na verdade ele Não tem. Confira o artigo acima para uma explicação mais completa com exemplos de código.

Isso é há muito tempo.

Eu sei que houve uma solução que contou com a frequência do monitor.

Com um CRT, o pixel atual é conhecido mesmo que fosse fora da tela normal. Assim, você poderá manipular o ray.

Em algum lugar na minha junkpile deve haver alguns livros C64.

Offtopic, mas gráficos com o VIC20 (o antecessor do C64) foi divertido. Não havia nenhuma maneira de manipular cada pixel, mas você pode mudar os caracteres existentes. Então você encheu a tela com todos os personagens de 0 a ... e mudou os caracteres para definir pixels na tela. ; -).

O sincronismo era a chave. A imagem foi criada na fronteira mudando a cor overscan (fronteira) como o feixe do CRT movida da esquerda para a direita. Existem dois sinais de temporização necessários para a produção de uma imagem - actualização vertical e horizontal de actualização. Ao detectar quando a atualização horizontal e vertical ocorre você pode começar uma seqüência de instruções assembler para mudar a cor da borda para produzir uma imagem. Você precisa descobrir o número de relógio da CPU carrapatos por pixel fronteira e usar isso para criar um código que muda a cor da borda no ponto certo.

Ele não funciona muito bem quando se trata de escrever jogos como a sobrecarga da CPU é muito grande para que haja qualquer elevador tempo para a entrada do usuário processo e estado do jogo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top