mirror of https://github.com/falsovsky/z80.git
Separar em projetos diferentes
This commit is contained in:
parent
1cf0517850
commit
2441814043
|
@ -17,9 +17,7 @@ Instalação
|
||||||
```sh
|
```sh
|
||||||
git clone https://github.com/falsovsky/z80.git
|
git clone https://github.com/falsovsky/z80.git
|
||||||
cd z80/scroller
|
cd z80/scroller
|
||||||
pasmo -v --tapbas --err main_first.asm main_first.tap
|
pasmo -v --tapbas --err main.asm main.tap
|
||||||
pasmo -v --tapbas --err main_second.asm main_second.tap
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Licença
|
Licença
|
Binary file not shown.
|
@ -0,0 +1,30 @@
|
||||||
|
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/scroller
|
||||||
|
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
|
|
@ -0,0 +1,45 @@
|
||||||
|
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
|
|
@ -0,0 +1,16 @@
|
||||||
|
; 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
|
Binary file not shown.
|
@ -0,0 +1,24 @@
|
||||||
|
; 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
|
|
@ -0,0 +1,79 @@
|
||||||
|
;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
|
|
@ -13,8 +13,8 @@ udg equ $5c7b ; Endereço do primeiro user-defined graphics (2 bytes)
|
||||||
udg_start equ $ff58 ; User-defined characters, vai até $ffff
|
udg_start equ $ff58 ; User-defined characters, vai até $ffff
|
||||||
; São acessiveis com o caracter $90 até $a4
|
; São acessiveis com o caracter $90 até $a4
|
||||||
|
|
||||||
letra_pos db 0,0
|
|
||||||
text_pos db 0,0
|
text_pos db 0,0
|
||||||
|
char_pos db 0
|
||||||
|
|
||||||
scroll_text
|
scroll_text
|
||||||
; Verificar se o valor de text_pos já foi alguma vez alterado
|
; Verificar se o valor de text_pos já foi alguma vez alterado
|
||||||
|
@ -52,14 +52,14 @@ scroll_text_loop
|
||||||
ld hl, font_start
|
ld hl, font_start
|
||||||
add hl, de ; $3C00 + $260 = $3E60
|
add hl, de ; $3C00 + $260 = $3E60
|
||||||
|
|
||||||
ld (letra_pos), hl ; Guarda o valor em letra_pos
|
|
||||||
|
|
||||||
call copia_para_udg ; Copia a letra para o UDG#1
|
call copia_para_udg ; Copia a letra para o UDG#1
|
||||||
|
; O argumento para a rotina é o valor em HL
|
||||||
|
|
||||||
ld a, $90 ; Imprime UDG#1
|
ld a, $90 ; Imprime UDG#1
|
||||||
rst $10
|
rst $10
|
||||||
|
|
||||||
pop hl ; Tira a posição na string da stack
|
pop hl ; Tira a posição na string da stack
|
||||||
inc hl ; Anda para a frente
|
inc hl ; Anda para a frente
|
||||||
|
|
||||||
ld a, (hl) ; Le o proximo valor
|
ld a, (hl) ; Le o proximo valor
|
||||||
cp 0 ; Se for 0 estamos no fim da string
|
cp 0 ; Se for 0 estamos no fim da string
|
||||||
jr z, reset ; Reset à posição
|
jr z, reset ; Reset à posição
|
||||||
|
@ -71,13 +71,13 @@ the_end
|
||||||
ret
|
ret
|
||||||
|
|
||||||
copia_para_udg
|
copia_para_udg
|
||||||
ld hl, (letra_pos) ; Posição da font da letra a copiar
|
; Está a contar que o endereço de origem esteja em HL
|
||||||
ld b, $8 ; Copiar 8 bytes, cada letra são 8x8
|
ld b, $8 ; Copiar 8 bytes, cada letra são 8x8
|
||||||
ld de, udg_start ; Destino
|
ld de, udg_start ; Destino
|
||||||
copia_para_udg_r
|
copia_para_udg_loop
|
||||||
ld a, (hl) ; Le origem
|
ld a, (hl) ; Le origem
|
||||||
ld (de), a ; Copia para destino
|
ld (de), a ; Copia para destino
|
||||||
inc hl ; Incrementa ambos
|
inc hl ; Incrementa ambos
|
||||||
inc de
|
inc de
|
||||||
djnz copia_para_udg_r ; b--, se b != 0 salta
|
djnz copia_para_udg_loop ; b--, se b != 0 salta
|
||||||
ret
|
ret
|
Loading…
Reference in New Issue