Impresión rápida de caracteres con ZX Basic

Soporte técnico sobre los lanzamientos de MojonTwins y comentarios sobre los güegos. Ofrecemos soporte técnico con Fourspriter, te ayudamos con ZX Basic o Z88DK, te damos pistas some cómo saltarse un bicho y cosas así.

Moderador: na_th_an

Avatar de Usuario
Imanolea
Mensajes: 6
Registrado: Sab, 18 Ene 2014, 00:48

Impresión rápida de caracteres con ZX Basic

Mensajepor Imanolea » Lun, 03 Feb 2014, 15:49

Aupa. Este es mi primer post, me presento rápido. Soy Imanol, y pesar de no haber tocado un ZX Spectrum en mi vida, ando desarrollando para él porque me gusta.

Antes de comentar la duda me gustaría agradecer a los Mojon Twins el acercar (y hacerlo bien) el desarrollo para este tipo de sistemas a todo el mundo a través de sus tutoriales y su filosofía de software libre. Una postura digna de admirar.

El tema es que empecé un juego siguiendo los tutoriales de ZX Basic + Fourspriter. Una vez entendí las peculiaridades de las herramientas, me fue más o menos viable el tema de hacer que el juego fuera tomando su propio rumbo. El juego en concreto es una especie de aventura/puzle, aquí tenéis un historial del desarrollo para los interesados: http://imanoleasgames.blogspot.com.es/search/label/The%20Subject

El problema llega cuando llegados a la parte final del desarrollo y seguimos teniendo un pintado "lento" de los tiles que le quita cierto encanto al resultado. Este y otros problemas los compartí en otro foro y con la colaboración de un usuario fui abordándolos. Este es el tema del que hablo http://www.fasebonus.net/foro/index.php?topic=27446.0 en el que también se tratan problemas de un proyecto anterior. Precisamente en este tema el usuario Bubu ha compartido un programa para pintar tiles en código máquina pero por peculiaridades de ZX Basic (suponemos) no termina de compilar.

Por eso acudo a vosotros, en busca de directrices para elaborar una rutina en ensamblador capaz de pintar tiles y que compile en ZX Basic. Si ya se adaptara al código de los tutoriales mencionados sería la leche.

De nuevo, gracias y a seguir así.
Avatar de Usuario
radastan
Mensajes: 692
Registrado: Vie, 20 Ago 2010, 12:54
Contactar:

Re: Impresión rápida de caracteres con ZX Basic

Mensajepor radastan » Lun, 03 Feb 2014, 15:52

Hombre, teóricamente puedes usar las rutinas en ensamblador que hay en este foro para pintar en baja resolución. Son rápidas y no requieren interrupciones ni cosas raras. Incluso las de scroll.
Avatar de Usuario
na_th_an
Mensajes: 26413
Registrado: Vie, 09 Ene 2009, 12:18

Re: Impresión rápida de caracteres con ZX Basic

Mensajepor na_th_an » Lun, 03 Feb 2014, 16:02

Pon por aquí la rutina mapeadora y le echamos un vistazo. He integrado ensamblador en ZX Basic y a lo mejor puedo echar una mano en reparar esto y hacerla funcionar. Y si no, lo que dice Radas :)

Y bienvenidor :)
Como diría Rorshach: "Urm..."
Avatar de Usuario
angel
Mensajes: 23213
Registrado: Vie, 09 Ene 2009, 13:04
Ubicación: Torreznolandia
Contactar:

Re: Impresión rápida de caracteres con ZX Basic

Mensajepor angel » Lun, 03 Feb 2014, 16:04

Aupa Imanol! me alegro que hayas podido acceder, hablamos! :D

PD: voy a alcahuetear el juego que estás haciendo :boots:
(_\_) (_|_) (_/_) (_|_) ILLO KE HEHEHEHEHEHEEEHEHEHEH!

¡Activa tu rainbow pechónico!
Avatar de Usuario
na_th_an
Mensajes: 26413
Registrado: Vie, 09 Ene 2009, 12:18

Re: Impresión rápida de caracteres con ZX Basic

Mensajepor na_th_an » Lun, 03 Feb 2014, 16:05

Oye, el juego tiene una pinta impresionante :O Lo veo super original!
Como diría Rorshach: "Urm..."
Avatar de Usuario
Imanolea
Mensajes: 6
Registrado: Sab, 18 Ene 2014, 00:48

Re: Impresión rápida de caracteres con ZX Basic

Mensajepor Imanolea » Lun, 03 Feb 2014, 16:21

Sobre el tema de rutinas posteadas, les echo un vistazo. Aunque no tengo mucha idea en general de código ensamblador.

Esta viene a ser la rutina sin adaptar.

Autor: Bubu
$this->bbcode_second_pass_code('', 'ORG $6000

;Constantes
ATTR_ADDR EQU $5800
PAPER_BLUE EQU 1*8
INK_YELLOW EQU 6


ld ix, tile_01
call prn_tile
noend: jr noend



; Imprime en pantalla un tile monocromo
; El tile presenta la siguiente estructura:
; dirección del tileset, fila, columna, ancho, alto, color, t1, t2, ...
; IN: ix = puntero al tile a imprimr

tile_01:
DEFW fonts
DEFB 5, 10, 16, 2, PAPER_BLUE + INK_YELLOW
DEFB "HOLA IMANOLEA "
DEFB "SOY BUBU, JAJAJA"

prn_tile:
; Colorea el rectángulo
ld h, (ix +2)
ld l, (ix +3)
call calc_attr
ld b, (ix +4)
ld c, (ix +5)
ld a, (ix +6)
call color_square

; Imprime una fila
ld h, (ix +2)
ld e, (ix +5)

push ix
pop iy
ld bc, 7
add iy, bc

ld c, (ix +0)
ld b, (ix +1)

prn_tile_02:
ld d, (ix +4)
ld l, (ix +3)

prn_tile_01:
ld a, (iy)
call prn_tilechar
inc l
inc iy
dec d
jr nz, prn_tile_01
inc h
dec e
jr nz, prn_tile_02

ret



prn_tilechar:
; Imprime en pantalla un carácter de un tile
; IN: a=carácter a imprimir
; bc=dirección del tileset
; hl=posición (fila, col)


push af
push bc
push de
push hl
call calc_vram

ld l, a
ld h, 0
add hl, hl
add hl, hl
add hl, hl
add hl, bc

ld b, 8
prn_tilechar_01:
ld a, (hl)
ld (de), a
inc d
inc hl
djnz prn_tilechar_01
pop hl
pop de
pop bc
pop af
ret

calc_attr:
; Calcula la dirección de atributos
; IN: hl = posición (fila, col)
; OUT: hl = dirección ATTR
ld e, l
ld d, 0
ld l, h
ld h, 0
add hl, hl
add hl, hl
add hl, hl
add hl, hl
add hl, hl
add hl, de
ld de, ATTR_ADDR
add hl, de
ret


; Colorea un recuadro
; IN: hl=dir. atributos
; b=ancho, c=alto
; a=color
color_square:

ld de, $20
color_square_02:
push bc
push hl
color_square_01:
ld (hl), a
inc hl
djnz color_square_01
pop hl
add hl, de
pop bc
dec c
jr nz, color_square_02
ret


calc_vram:
; Calcula la posición de vídeoRAM dadas una fila y columna
; IN: hl=posición (fila, col)
; OUT: de=posición en la vídeomemoria

push af
push hl
ld a, h
and 7
rrca
rrca
rrca
or l
ld e, a
ld a, h
and $18
or $40
ld d, a
pop hl
pop af
ret




fonts:
DEFS 384, 0x00
incbin "fonts.bin"

END $6000')

La salida del compilador es esta:

(En la línea de call color_square)
Error: Syntax error. Unexpected token ')' [RP]
Avatar de Usuario
na_th_an
Mensajes: 26413
Registrado: Vie, 09 Ene 2009, 12:18

Re: Impresión rápida de caracteres con ZX Basic

Mensajepor na_th_an » Lun, 03 Feb 2014, 16:25

Básicamente lo primero siempre es meter el código dentro de un contenedor para que "no moleste", por ejemplo dentro de un Sub. Luego puedes "hablar" directamente con él o crearte funciones de interfaz.

A ver si encuentro rato y le doy un tiento, pero necesitaría alguna que otra indicación. Según veo lo que hace es imprimir bloques de caracteres. ¿Cómo se integraría esto con el resto?
Como diría Rorshach: "Urm..."
antoniovillena
Mensajes: 494
Registrado: Jue, 24 Oct 2013, 15:52

Re: Impresión rápida de caracteres con ZX Basic

Mensajepor antoniovillena » Lun, 03 Feb 2014, 16:27

ZXBasic se lleva muy mal con los guiones bajos. También sería buena idea que indentaras el código ensamblador.

También puedes ponerte en contacto con el autor del compilador, es español y muy buena gente y a mí me está resolviendo algunas dudas en este hilo.

http://foro.speccy.org/viewtopic.php?f=6&t=3728
Avatar de Usuario
Imanolea
Mensajes: 6
Registrado: Sab, 18 Ene 2014, 00:48

Re: Impresión rápida de caracteres con ZX Basic

Mensajepor Imanolea » Lun, 03 Feb 2014, 22:56

na_th_an: En principio el programa tiene como objetivo tomarse como ejemplo para investigar luego como adaptarlo a la estructura del juego en basic. El problema es que ni llegó a compilar, aunque sí, el tema de conseguir imprimir los tiles del juego en sí ya es otra historia. Ahora mismo usar valores de variables declaradas en basic para rutinas de ensamblador es un misterio para mí.

antoniovillena: Gracias por la información, no descarto pasarme por allí para consultar las dudas con el propio boriel.
Avatar de Usuario
na_th_an
Mensajes: 26413
Registrado: Vie, 09 Ene 2009, 12:18

Re: Impresión rápida de caracteres con ZX Basic

Mensajepor na_th_an » Mar, 04 Feb 2014, 09:54

Lo primero que hay que hacer para que compile, es meter el código en un contenedor. En principio, entre un "Asm" y un "End Asm", pero además conviene meterlo en un Sub que no se llame en ningún momento para tenerlo aislado:

$this->bbcode_second_pass_code('', 'Sub myCodeContainer
Asm
rutina:
; Aquí va el código Asm
xor a
ld (hl), a
ret
End Asm
End Sub')

Y eso se puede llamar desde cualquier sitio con

$this->bbcode_second_pass_code('', 'Asm
call rutina
End Asm')

Luego, para pasar valores de la parte BASIC a la parte Asm hay varias formas, pero creo que la más sencilla e intuitiva para quien haya programado en cualquier BASIC antes es usar Poke.

Como sabrás, Poke recibe una dirección y un valor que poner en esa dirección. La dirección de memoria podemos "calcularla" en tiempo de compilación usando el operando @. Lo que hacemos es poner una etiqueta BASIC justo en el punto donde queremos escribir. Sería algo así:

$this->bbcode_second_pass_code('', 'Sub myCodeContainer
Asm
rutina:
; Aquí va el código Asm
ld a, (dato)
ret
End Asm
datosRutina:
Asm
dato:
db 0
End Asm
End Sub')

Fíjate como "datosRutina" es una etiqueta BASIC: Está fuera de los bloques Asm. rutina y dato son etiquetas Asm, porque están dentro del bloque Asm.

Podemos poner un valor en "dato" pokeando en datosRutina, porque estas etiquetas apuntan al mismo sitio. Haciendo un

$this->bbcode_second_pass_code('', 'Poke @datosRutina, 7')

Pondremos un 7 en la posición de memoria apuntada por esa rutina, que viene a ser el espacio de un byte que se ha reservado con el db 0. Desde dentro del código Asm se puede referenciar ese dato también, porque hay una etiqueta Asm (dato).

También podemos usar valores de 16 bits...
$this->bbcode_second_pass_code('', 'Sub myCodeContainer
Asm
rutina:
; Aquí va el código Asm
ld a, (dato)
ret
End Asm
datosRutina:
Asm
dato:
dw 0
End Asm
End Sub

Poke uInteger @datosRutina, 16384')

O varios valores:

$this->bbcode_second_pass_code('', 'Sub myCodeContainer
Asm
rutina:
; Aquí va el código Asm
ld a, (dato)
ret
End Asm
datosRutina:
Asm
dato:
db 0
db 0
defw 0
db 0
End Asm
End Sub

Poke @datosRutina, 5
Poke 1 + @datosRutina, 7
Poke uInteger 2 + @datosRutina, 16384
Poke 4 + @datosRutina, 9 ' aquí contamos dos bytes más porque el anterior dato ocupa 2 bytes')

Con esto se puede hacer prácticamente de todo. Si te fijas en el código de Fourspriter o Subaco, verás como toda la interfaz Asm<->BASIC está hecha así.
Como diría Rorshach: "Urm..."

Volver a “Ayuda”

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 22 invitados