Remove from this branch

This commit is contained in:
Pedro de Oliveira 2014-08-12 22:44:50 +01:00
parent 366a31ad41
commit 6f68a9777b
20 changed files with 0 additions and 824 deletions

View File

@ -1,4 +0,0 @@
z80
===
Random Z80 stuff

View File

@ -1,30 +0,0 @@
Scroller
=========
Scroller é uma implementação um scroller de texto em Assembly no ZX Spectrum.
Requisitos
-----------
O unico realmente necessário é o Assembler, mas para ver o resultado convem tambem ter um emulador, os verdadeiros podem converter o ficheiro [tap] para audio, passar para um leitor de mp3 e ligar a um Spectrum real :-D
* [Pasmo] - Assembler de Z80, é Open Source e Cross Platform
* [ZX Spin] - Emulador de ZX Spectrum para Windows que inclui um Debugger
Instalação
--------------
```sh
git clone https://github.com/falsovsky/z80.git
cd z80/scroller1
pasmo -v --tapbas --err main.asm main.tap
```
Licença
----
BSD
[tap]:http://www.worldofspectrum.org/faq/reference/formats.htm
[Pasmo]:http://pasmo.speccy.org/
[ZX Spin]:http://www.zophar.net/sinclair/zx-spin.html

View File

@ -1,45 +0,0 @@
attr_p equ $5c8d; Endereço que contem as cores permanentes
bordcr equ $5c48; Endereço que contem a cor da borda
rom_limpa_ecra equ $0daf; Rotina da ROM que limpa o ecrã
rom_define_borda equ $2294; Rotina da ROM que define a borda
; Cores
; Numero | Binario | Nome
; 0 | 000 | Preto
; 1 | 001 | Azul
; 2 | 010 | Vermelho
; 3 | 011 | Roxo
; 4 | 100 | Verde
; 5 | 101 | Cyan
; 6 | 110 | Amarelo
; 7 | 111 | Branco
; 8 bits para definir ink, paper, brightness e flash
; |F |B |P2|P1|P0|I2|I1|I0|
; F Flash
; B Brightness
; P Paper
; I Ink
; Então para definir o flash desligado, o brightness ligado com o
; fundo a preto e o texto a amarelo fica-se com:
; 01000110 = 70 = $46
; 01000000 = 64 = $40 - Tudo preto
; 01000111 = 71 = $47 - Fundo preto Texto Branco
screen_attribute equ $47
; Valor de 0 a 7
border_color equ $0
clear_screen
ld a, screen_attribute
ld (attr_p), a ; Variavel de sistema que permite definir
; o ink, paper, brightness e flash
call rom_limpa_ecra ; Clear screen
ld a, border_color ; Cor do border
call rom_define_borda+$7
; Chama a rotina da ROM para actualizar a borda, mas salta 7
; bytes à frente, porque são para ler o valor da borda do
; BASIC. O valor fica guardado em 23624.
ret

View File

@ -1,16 +0,0 @@
; Rotina de delay variavel, conforme o valor definido em A antes de a chamar
; Ripada do Paradise Café
delay
push bc
delay_start
ld c, 10
delay_loop2
ld b, 0
delay_loop1
djnz delay_loop1 ; b--, se b != 0 corre novamente o loop1
dec c ; c--
jr nz, delay_loop2 ; Se c != 0 corre o loop2
dec a ; a--
jr nz, delay_start ; Se a != 0 volta ao inicio da rotina
pop bc
ret

View File

@ -1,80 +0,0 @@
org 30000
tv_flag equ $5c3c ; Endereço que contem flags da tv
last_k equ $5c08 ; Contem a ultima tecla pressionada
k_cur equ $5c5b ; Contem a posição do cursor - TODO: Usar isto
; Depois de meter a 10,6 (y,x) fica com
; $5d16
; Video RAM
LINHA9 equ $4820
LINHA10 equ $4840
LINHA11 equ $4860
; 16 é para definir o INK
; 17 é para definir o PAPER
; 22 é para definir as Cordenadas Y,X
; 255 Marcador de fim da string
mystr db 22,10,0, 16,1, " ", 16,6, ".o0O0o. LOL GORDOS .o0O0o.", 16,1, " ", 255
start
xor a ; O mesmo que LD a, 0
ld (tv_flag), a ; Directs rst 10h output to main screen.
push bc ; Parece que é algum standard guardar o BC
; na stack, e tirar no fim do programa.
call clear_screen ; Limpa o ecrã
; Flood de numeros em todas as linhas
ld a, $0 ; Começa na linha 0
ld b, $16 ; Repete nas 22 linhas
lol_flood
ld c, a ; Guarda o A em C e o B em D porque
ld d, b ; são alterados no call
call printnumbers
ld a, c ; Le o A de volta
inc a ; Proxima linha
ld b, d ; Le o B de volta
djnz lol_flood ; B-- , se for != 0 salta
ld hl, mystr ; Le para HL o endereço da string a printar
printa_ate_255
ld a,(hl) ; Le para A o valor que esta no endereço em HL
cp $ff ; Se for 255...
jr z, mainloop ; então já se imprimiu tudo e é para sair
rst $10 ; Syscall para imprimir o no ecrã o que estiver em A
inc hl ; Incrementa o valor de HL
; Passa a ter o endereço do proximo caracater da str
jr printa_ate_255 ; Volta ao inicio da rotina
mainloop
ld a, $0
ld (last_k), a ; Limpa o valor da ultima tecla pressionada
ld hl, LINHA9
call scroll_direita
ld hl, LINHA10
call scroll_esquerda
ld hl, LINHA11
call scroll_direita
ld a, $1
call delay ; Chama a rotina de delay(1)
ld a, (last_k) ; Se o valor da ultima tecla pressionada ainda
cp $0 ; for 0, é porque ainda não se pressionou nenhuma
jr z, mainloop ; tecla, por isso... repete
exit
pop bc ; Tira o BC da Stack
ret ; Sai para o BASIC
INCLUDE "scroll_esquerda.asm"
INCLUDE "scroll_direita.asm"
INCLUDE "delay.asm"
INCLUDE "clear.asm"
INCLUDE "printnumbers.asm"
end start

Binary file not shown.

View File

@ -1,24 +0,0 @@
; printa numeros de 0 a 9 na linha definida em A
printnumbers
ld b, a ; guarda o valor de A em B
ld a, $16 ; AT
rst $10
ld a, b ; Y = B
rst $10
ld a, $0 ; X = 0
rst $10
ld b, $20 ; 32 colunas
ld h, $30 ; chr "0"
printnumbers_loop
ld a, h ; printa o chr em H
rst $10
inc h ; Incrementa
ld a, h ; Guarda o valor em A
cp $3a ; Compara com chr ":" (a seguir ao "0")
jr nz, printnumbers_continue
ld h, $30 ; Volta a meter a "0"
printnumbers_continue
djnz printnumbers_loop
ret

View File

@ -1,53 +0,0 @@
;videoAddr2 equ 4820h ; Linha 9
;videoAddr2 equ 4920h ; Faz o mesmo, tenho de entender porque
addractual2 db 0,0
primeiroaddr db 0,0
; Rotina de scroll de texto da esquerda para a direita pixel a pixel
; O endereço inicial tem de vir em HL
scroll_direita
; ld hl, videoAddr2 ; Endereço de Memoria Video a ser manipulado
ld c, $8 ; Numero de vezes que a rotina vai correr
; 8 é o numero de linhas de pixeis a scrollar
; Loop1
scroll_direita_0
ld (addractual2), hl ; Guarda o valor de HL em tmp1
call scroll_direita_1 ; Scrolla
ld hl, (addractual2) ; Le o valor de tmp1 para HL
inc h ; Incrementa H, mas como estamos a trabalhar com um
; endereço de 16bits, na realidade vai adicionar
; $100 a HL
; Isto vai fazer com que a segunda rotina seja
; chamada com os seguintes endereços em tmp1
; videoAddr, videoAddr+$100 videoAddr+$200,
; ..., videoAddr+$700
dec c ; Decrementa o contador C
jr nz, scroll_direita_0 ; Se C != 0 corre novamente o Loop1
ret
; Segunda rotina
scroll_direita_1
ld hl, (addractual2) ; Le o argumento tmp1 para HL
ld (primeiroaddr), hl
ld b, $20 ; Numero de vezes que vai correr
; Loop2
scroll_direita_2
ld a, (hl) ; Faz um rotate right aos 8 pixels no
rra ; endereço de video ram em HL, o bit
; perdido fica na carry
ld (hl), a ; Actualiza
inc hl ; Anda uma coluna para a direita
djnz scroll_direita_2 ; Se ainda nao chegou ao fim, repete
ld hl, (primeiroaddr) ; Le o valor do endereço da coluna
ld a, (hl) ; mais à esquerda, em A
jr nc, scroll_direita_sem_carry ; Não tem carry? vai para o fim
or $80 ; bit 7 = 1
scroll_direita_sem_carry
ld (hl), a ; Actualiza
ret

View File

@ -1,79 +0,0 @@
;videoAddr equ 4840h ; Endereço de Memoria Video da Linha 10
;videoAddr equ 4940h ; Faz o mesmo, tenho de entender porque
addractual1 db 0,0
ultimoaddr db 0,0
; Rotina de scroll de texto da direita para a esquerda pixel a pixel
; O endereço inicial tem de vir em HL
scroll_esquerda
; ld hl, videoAddr ; Endereço de Memoria Video a ser manipulado
ld c, $8 ; Numero de vezes que a rotina vai correr
; 8 é o numero de linhas de pixeis a scrollar
; Loop1
scroll_esquerda_0
ld (addractual1), hl ; Guarda o valor de HL em tmp1
call scroll_esquerda_1 ; Scrolla
ld hl, (addractual1) ; Le o valor de tmp1 para HL
inc h ; Incrementa H, mas como estamos a trabalhar com um
; endereço de 16bits, na realidade vai adicionar
; $100 a HL
; Isto vai fazer com que a segunda rotina seja
; chamada com os seguintes endereços em tmp1
; videoAddr, videoAddr+$100 videoAddr+$200,
; ..., videoAddr+$700
dec c ; Decrementa o contador C
jr nz, scroll_esquerda_0; Se C != 0 corre novamente o Loop1
ret
; Segunda rotina
scroll_esquerda_1
ld hl, (addractual1) ; Le o argumento tmp1 para HL
push bc
ld bc, $1f ; Soma $1f ao endereço para começar
adc hl, bc ; no fim da linha, tudo à direita
; Cada linha tem 32 bytes
ld (ultimoaddr), hl ; Guarda o endereço do fim da linha
pop bc
ld b, $20 ; Numero de vezes que vai correr
; Vai começar por fazer um rotate left à coluna mais à direita, e
; guarda o bit que se perde na carry, que vai ser usado como o
; bit 0 do proximo rotate left que for executado.
; Se no rotate da coluna mais à esquerda se perdeu alguma coisa,
; então é para passar para a coluna mais a direita.
; Se depois do ultimo rotate o carry estiver definido, faz-se um
; OR ao bit 0 da coluna mais à direita.
; Loop2
scroll_esquerda_2
ld a, (hl) ; Faz um rotate left aos 8 pixels no
rla ; endereço de video ram em HL, o bit
; perdido fica na carry
ld (hl), a ; Actualiza
dec hl ; Anda uma coluna para a esquerda
djnz scroll_esquerda_2 ; Se ainda nao chegou ao fim, repete
ld hl, (ultimoaddr) ; Le o valor do endereço da coluna
ld a, (hl) ; mais à direita, em A
; Se não tem carry significa que não perdeu pixel nenhum
; no ultimo rotate, então não é preciso passar nada para
; a coluna mais à direita porque já tem o bit 0 a 0 devido
; ao rotate inicial.
jr nc, scroll_esquerda_sem_carry ; Não tem carry? vai para o fim
; Se tem carry é porque se perdeu um pixel no ultimo
; rotate, então tem de se settar o bit 0 do coluna mais
; à direita a 1
or $1 ; bit 0 = 1
scroll_esquerda_sem_carry
ld (hl), a ; Actualiza
ret

View File

@ -1,30 +0,0 @@
Scroller
=========
Scroller é uma implementação um scroller de texto em Assembly no ZX Spectrum.
Requisitos
-----------
O unico realmente necessário é o Assembler, mas para ver o resultado convem tambem ter um emulador, os verdadeiros podem converter o ficheiro [tap] para audio, passar para um leitor de mp3 e ligar a um Spectrum real :-D
* [Pasmo] - Assembler de Z80, é Open Source e Cross Platform
* [ZX Spin] - Emulador de ZX Spectrum para Windows que inclui um Debugger
Instalação
--------------
```sh
git clone https://github.com/falsovsky/z80.git
cd z80/scroller2
pasmo -v --tapbas --err main.asm main.tap
```
Licença
----
BSD
[tap]:http://www.worldofspectrum.org/faq/reference/formats.htm
[Pasmo]:http://pasmo.speccy.org/
[ZX Spin]:http://www.zophar.net/sinclair/zx-spin.html

View File

@ -1,16 +0,0 @@
; Rotina de delay variavel, conforme o valor definido em A antes de a chamar
; Ripada do Paradise Café
delay
push bc
delay_start
ld c, 15
delay_loop2
ld b, 0
delay_loop1
djnz delay_loop1 ; b--, se b != 0 corre novamente o loop1
dec c ; c--
jr nz, delay_loop2 ; Se c != 0 corre o loop2
dec a ; a--
jr nz, delay_start ; Se a != 0 volta ao inicio da rotina
pop bc
ret

View File

@ -1,45 +0,0 @@
attr_p equ $5c8d; Endereço que contem as cores permanentes
bordcr equ $5c48; Endereço que contem a cor da borda
rom_limpa_ecra equ $0daf; Rotina da ROM que limpa o ecrã
rom_define_borda equ $2294; Rotina da ROM que define a borda
; Cores
; Numero | Binario | Nome
; 0 | 000 | Preto
; 1 | 001 | Azul
; 2 | 010 | Vermelho
; 3 | 011 | Roxo
; 4 | 100 | Verde
; 5 | 101 | Cyan
; 6 | 110 | Amarelo
; 7 | 111 | Branco
; 8 bits para definir ink, paper, brightness e flash
; |F |B |P2|P1|P0|I2|I1|I0|
; F Flash
; B Brightness
; P Paper
; I Ink
; Então para definir o flash desligado, o brightness ligado com o
; fundo a preto e o texto a amarelo fica-se com:
; 01000110 = 70 = $46
; 01000000 = 64 = $40 - Tudo preto
; 01000111 = 71 = $47 - Fundo preto Texto Branco
screen_attribute equ $47
; Valor de 0 a 7
border_color equ $0
limpa_ecra
ld a, screen_attribute
ld (attr_p), a ; Variavel de sistema que permite definir
; o ink, paper, brightness e flash
call rom_limpa_ecra ; Clear screen
ld a, border_color ; Cor do border
call rom_define_borda+$7
; Chama a rotina da ROM para actualizar a borda, mas salta 7
; bytes à frente, porque são para ler o valor da borda do
; BASIC. O valor fica guardado em $5c48.
ret

View File

@ -1,63 +0,0 @@
org 30000
tv_flag equ $5c3c ; Variavel das flags da tv
last_k equ $5c08 ; Variavel que contem a ultima tecla usada
LINHA10 equ $4840 ; Endereço da linha 10 na Memoria Video
o_barbas db 22,9,0, 16,6, "o_barbas disse:", 255
scroll_udg db $8 ; Numero de pixeis já scrollados no UDG#1
; Inicializado a 8 para "pedir" uma nova
; letra quando corre pela primeira vez.
start
xor a ; O mesmo que LD a, 0
ld (tv_flag), a ; Faz com que o rst $10 envie output pra tv
push bc ; Guarda BC na stack
call limpa_ecra ; Limpa o ecrã
ld hl, o_barbas ; Le para HL o endereço da string a printar
printa_string
ld a,(hl) ; Le para A o valor que esta no endereço em HL
cp $ff ; Se for 255...
jr z, main_loop ; então já se imprimiu tudo e é para sair
rst $10
inc hl ; Incrementa a posição na string
jr printa_string ; Volta ao inicio da rotina
main_loop
ld a, $0
ld (last_k), a ; Limpa o valor da ultima tecla pressionada
ld a, (scroll_udg) ; Le o numero de pixeis já scrollados no UDG#1
cp $8 ; São 8?
jr nz, main_loop_scroll ; Não? salta
call obtem_proxima_letra ; Sim, manda meter uma nova letra em UDG#1
ld a, 0
ld (scroll_udg), a ; Reseta o numero de pixeis scrollados no UDG#1
main_loop_scroll
ld hl, LINHA10
call scroll_esquerda ; Scrolla a linha 10
ld a, (scroll_udg)
inc a ; Incrementa o numero de pixeis já scrollados
ld (scroll_udg), a
ld a, $1
call delay ; Chama a rotina de delay(1)
ld a, (last_k) ; Se o valor da ultima tecla pressionada ainda
cp $0 ; for 0, é porque ainda não se pressionou nenhuma,
jr Z, main_loop ; por isso... repete
exit
pop bc ; Tira o BC da stack
ret ; Sai para o BASIC
INCLUDE "delay.asm"
INCLUDE "limpa.asm"
INCLUDE "texto.asm"
INCLUDE "scroll.asm"
end start

Binary file not shown.

View File

@ -1,24 +0,0 @@
; printa numeros de 0 a 9 na linha definida em A
printnumbers
ld b, a ; guarda o valor de A em B
ld a, $16 ; AT
rst $10
ld a, b ; Y = B
rst $10
ld a, $0 ; X = 0
rst $10
ld b, $20 ; 32 colunas
ld h, $30 ; chr "0"
printnumbers_loop
ld a, h ; printa o chr em H
rst $10
inc h ; Incrementa
ld a, h ; Guarda o valor em A
cp $3a ; Compara com chr ":" (a seguir ao "0")
jr nz, printnumbers_continue
ld h, $30 ; Volta a meter a "0"
printnumbers_continue
djnz printnumbers_loop
ret

View File

@ -1,91 +0,0 @@
scroll_addr db 0,0 ; Endereço da linha a scrollar - na coluna 0
linha_actual db 0 ; Linha actual
ultima_addr db 0,0 ; Endereço da coluna mais à direita da linha actual
; O endereço inicial tem de vir em HL
scroll
ld c, $8 ; Numero de vezes que a rotina vai correr
; 8 é o numero de linhas de pixeis a scrollar
ld a, $0
ld (linha_actual), a ; Começa na linha 0
; Loop1
scroll_loop
ld (scroll_addr), hl ; Guarda o valor de HL (argumento da rotina)
call scrolla_linha ; Scrolla uma linha
ld hl, (scroll_addr) ; Le o valor de tmp1 para HL
inc h ; Incrementa H, mas como estamos a trabalhar com um
; endereço de 16bits, na realidade vai adicionar
; $100 a HL
; Isto vai fazer com que a segunda rotina seja
; chamada com os seguintes endereços em tmp1
; videoAddr, videoAddr+$100 videoAddr+$200,
; ..., videoAddr+$700
ld a, (linha_actual) ; Incrementa a linha actual
inc a
ld (linha_actual), a
dec c ; Decrementa o contador C
jr nz, scroll_loop ; Se C != 0 corre novamente o Loop1
ret
; Scrolla a linha que estiver em scroll_addr
scrolla_linha
push bc
ld hl, (scroll_addr) ; Le linha a scrollar
ld bc, $1f ; Soma $1f ao endereço para começar
add hl, bc ; no fim da linha, tudo à direita
; Cada linha tem 32 bytes
ld (ultima_addr), hl ; Guarda o endereço do fim da linha
ld b, $20 ; Numero de vezes que vai correr
; Vai começar por fazer um rotate left à coluna mais à direita, e
; guarda o bit que se perde na carry, que vai ser usado como o
; bit 0 do proximo rotate left que for executado.
; Depois faz-se um rotate left à mesma linha do UDG#1 guardado na
; rotina do "scroll_text.asm".
; Se a carry estiver definida faz-se um OR ao bit 0 da coluna mais
; à direita da linha.
; Loop2
scrolla_linha_loop
ld a, (hl) ; Faz um rotate left aos 8 pixels no
rla ; endereço de video ram em HL, o bit
; perdido fica na carry
ld (hl), a ; Actualiza
dec hl ; Anda uma coluna para a esquerda
djnz scrolla_linha_loop ; Se ainda nao chegou ao fim, repete
; Já processou tudo ate à esquerda, vamos passar o resto do
; UDG#1
ld a, (linha_actual) ; Le a linha actual para A
ld d, $0 ; D = $0
ld e, a ; E = A
ld hl, udg_start ; Endereço onde começa o UDG#1
add hl, de ; Soma a linha actual
ld a, (hl) ; Le o valor da linha do #UDG#1
rla ; Rotate
ld (hl), a ; Actualiza
ld hl, (ultima_addr) ; Le o valor do endereço da coluna
ld a, (hl) ; mais à direita em A
; Se não tem carry significa que não perdeu pixel nenhum
; no ultimo rotate, então não é preciso passar nada para
; a coluna mais à direita porque já tem o bit 0 a 0 devido
; ao rotate inicial.
jr nc, scrolla_linha_fim ; Não tem carry? vai para o fim
; Se tem carry é porque se perdeu um pixel no ultimo
; rotate, então tem de se settar o bit 0 do coluna mais
; à direita a 1
or $1 ; bit 0 = 1
scrolla_linha_fim
ld (hl), a ; Actualiza
pop bc
ret

View File

@ -1,80 +0,0 @@
text db "\"SEM QUERER MAGOAR O MEU BENFICA SO SABE GANHAR VIVA O BENFICA\" \"DA TRAFARIA ATE AO JAMOR O MEU BENFICA MOSTRA SEMPRE O SEU ESPLENDOR VIVA O BENFICA\" \"MANHA DE NEVOEIRO TARDE DE SOL SOALHEIRO BENFICA SEMPRE O PRIMEIRO VIVA O BENFICA\" \"DUAS VIAGENS SEGUIDAS PARA A ITALIA DAQUI A BOCADO MAIS VALE ABRIR UM BARBAS EM TURIM VIVA O BENFICA\" ", 0
chars equ $5c36 ; Endereço 256 ($100) bytes abaixo da fonte (2 bytes)
; Contem $3c00 inicialmente
font_start equ $3c00 ; Endereço onde começa a fonte, acaba em $3fff
; Começa com o espaço e acaba no ©
; http://en.wikipedia.org/wiki/ZX_Spectrum_character_set
udg equ $5c7b ; Endereço do primeiro user-defined graphics (2 bytes)
; Contem $ff58 inicialmente
udg_start equ $ff58 ; User-defined characters, vai até $ffff
; São acessiveis com o caracter $90 até $a4
posicao_addr db 0,0 ; Contem o endereço da posição actual na string
reset_posicao db 1 ; Se estiver a 1 a posição é resetada a 0
obtem_proxima_letra
ld a, (reset_posicao)
cp $1 ; Se não for para meter a posição a 0 salta
jr nz, proxima_letra_sem_reset
; o reset_posicao está a 1, meter a posicao na string a 0
ld a, 0
ld (reset_posicao), a ; reset_posicao = 0
ld hl, text ; Endereço do primeiro chr
jr proxima_letra_loop
proxima_letra_sem_reset
; Usa a posição guardada em posicao_addr
ld hl, (posicao_addr)
proxima_letra_loop
; Por exemplo, a primeira letra é um L. No ASCII do
; Spectrum o valor dela é $4C e com esse valor pretendo
; chegar a $3E60 que é onde está a font dela
ld a, (hl) ; Le chr da string - $4C inicialmente
push hl ; Guarda a posição na string na stack
ld h,$0 ; H = $0
ld l,a ; L = A
add hl, hl ; $4C + $4C = $98
add hl, hl ; $98 + $98 = $130
add hl, hl ; $130 + $130 = $260
ld d, h
ld e, l ; DE = HL
ld hl, font_start
add hl, de ; $3C00 + $260 = $3E60
call proxima_letra_udg ; Copia a letra para o UDG#1
; O argumento para a rotina é o valor em HL
pop hl ; Tira a posição na string da stack
inc hl ; Anda para a frente
ld a, (hl) ; Le o proximo valor
cp $0 ; Se for 0 estamos no fim da string
jr z, proxima_letra_sem_reset ; Manda fazer reset à posição
jr proxima_letra_fim ; Senão continua
proxima_letra_sem_reset
ld a, $1 ; Manda meter a posicao a 0 na proxima
ld (reset_posicao), a ; iteração
proxima_letra_fim
ld (posicao_addr), hl ; Guarda a posição
ret
; copia a letra para o UDG#1
proxima_letra_udg
; Está a contar que o endereço de origem esteja em HL
ld b, $8 ; Copiar 8 bytes, cada letra são 8x8
ld de, udg_start ; Destino
proxima_letra_udg_loop
ld a, (hl) ; Le origem
ld (de), a ; Copia para destino
inc hl ; Incrementa ambos
inc de
djnz proxima_letra_udg_loop ; b--, se b != 0 salta
ret

View File

@ -1,31 +0,0 @@
zx-brainfuck
=========
ZX-Brainfuck é um interpretador de [Brainfuck] em Assembly no ZX Spectrum.
Requisitos
-----------
O unico realmente necessário é o Assembler, mas para ver o resultado convem tambem ter um emulador, os verdadeiros podem converter o ficheiro [tap] para audio, passar para um leitor de mp3 e ligar a um Spectrum real :-D
* [Pasmo] - Assembler de Z80, é Open Source e Cross Platform
* [ZX Spin] - Emulador de ZX Spectrum para Windows que inclui um Debugger
Instalação
--------------
```sh
git clone https://github.com/falsovsky/z80.git
cd z80/zx-brainfuck
pasmo -v --tapbas --err main.asm main.tap
```
Licença
----
BSD
[Brainfuck]:http://en.wikipedia.org/wiki/Brainfuck
[tap]:http://www.worldofspectrum.org/faq/reference/formats.htm
[Pasmo]:http://pasmo.speccy.org/
[ZX Spin]:http://www.zophar.net/sinclair/zx-spin.html

View File

@ -1,113 +0,0 @@
org 30000
tv_flag equ $5c3c ; Variavel das flags da tv
last_k equ $5c08 ; Contem a ultima tecla pressionada
OP_INC_DP equ ">"
OP_DEC_DP equ "<"
OP_INC_VAL equ "+"
OP_DEC_VAL equ "-"
OP_OUT equ "."
OP_IN equ ","
OP_JMP_FWD equ "["
OP_JMP_BCK equ "]"
;brainfuck db "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.", 0
brainfuck db "+++++++++++++++++++++++++++++++++.", 0
memory_pos db $0,$80
start ; Começa em $75a2
xor a ; O mesmo que LD a, 0
ld (tv_flag), a ; Faz com que o rst $10 envie output pra tv
push bc ; Guarda BC na stack
main
ld hl, brainfuck
read_bf
ld a,(hl)
push hl
; EOF
cp $0
jr z, end_main
; >
cp OP_INC_DP
jr z, F_INC_DP
; <
cp OP_DEC_DP
jr z, F_DEC_DP
; +
cp OP_INC_VAL
jr z, F_INC_VAL
; -
cp OP_DEC_VAL
jr z, F_DEC_VAL
; .
cp OP_OUT
jr z, F_OUT
; ,
cp OP_IN
jr z, F_IN
continue
pop hl
inc hl
jr read_bf
end_main
pop bc ; Tira o BC da stack
ret ; Sai para o BASIC
F_INC_DP
ld hl, (memory_pos)
inc hl
ld (memory_pos), hl
jr continue
F_DEC_DP
ld hl, (memory_pos)
dec hl
ld (memory_pos), hl
jr continue
F_INC_VAL
ld hl, (memory_pos)
ld a, (hl)
inc a
ld (hl), a
jr continue
F_DEC_VAL
ld hl, (memory_pos)
ld a, (hl)
dec a
ld (hl), a
jr continue
F_OUT
ld hl, (memory_pos)
ld a, (hl)
rst $10
ld (hl), a
jr continue
F_IN
ld a, $0
ld (last_k), a ; Limpa o valor da ultima tecla pressionada
F_IN_LOOP
ld a, (last_k) ; Se o valor da ultima tecla pressionada ainda
cp $0 ; for 0, é porque ainda não se pressionou nenhuma
jr z, F_IN_LOOP ; tecla, por isso... repete
ld hl, (memory_pos)
ld (hl), a
jr continue
end start

Binary file not shown.