ZX-Uno - kit de programación modo Radastaniano

Sinclair QL, ZX81, +2, +3, 128K ...
Avatar de Usuario
Haplo
MSX Turbo R
MSX Turbo R
Mensajes: 278
Registrado: 14 Abr 2014, 22:24
Sistema Favorito: PC
primer_sistema: Spectrum +2
consola_favorita: Sony PlayStation 1
Primera consola: Nintendo NES/Clónica
Ubicación: Ciudad Real
Gracias dadas: 33 veces
Gracias recibidas: 5 veces

Re: ZX-Uno - kit de programación modo Radastaniano

Mensajepor Haplo » 26 May 2015, 17:36

Pues a ver, no consigo dar con la tecla, las demos radastanianas se ven bien pero mi adaptación sale tal que asi:
rad2.JPG
rad2.JPG (45.17 KiB) Visto 5116 veces


Por cierto, tengo que correr ANTES alguna demo radastaniana para que muestre esto, porque si nó sólo me sale la pantalla en negro :?:

Si uso el mismo cargador que las demás demos, me aparece esto:

rad.JPG
rad.JPG (75.88 KiB) Visto 5116 veces


Juas, me acabo de dar cuenta que soy un máquina colgando spectrums!

Voy a limpiar un poco el código de basura y lo subo para que le echéis un ojo si estáis aburridos.

-- Actualizado 26 May 2015, 19:49 --

Por cierto, hay una línea que no sé traducirla a zxbasic:
#pragma output STACKPTR=65000

Juraría que tiene que ver con la pila, pero no sé si es necesaria o no, igual vienen por ahí los tiros...

Os adjunto lo que me ha salido traduciendo a pelo el código de Radastán, empiezo por motorzxuno.h (ahora motorzxuno.bas):

Código: Seleccionar todo

' motorzxuno.bas

' Los bits del color de paleta van en forma GGGRRRBB
' Los pixels en cada byte van invertidos, el segundo es el primero (al ser los bits de menos peso)
' Es decir 22221111 es el formato de los bits de pixel en cada byte


' Funciones:

' ___________________________________________
' Borra la pantalla a un color
' ___________________________________________

SUB borra (color AS UBYTE)

   ASM
      ld hl,2         ;pasamos la variable de entrada al acumulador
      add hl,sp
      ld a, (hl)
      rla            ;rotamos 4 bits a la izquierda
      rla
      rla
      rla            ;ya tenemos el color del primer pixel
      add a, (hl)      ;añadimos el color del segundo pixel
      ld hl, 16384
      ld de, 16385
      ld bc, 6143
      ld (hl), a
      ldir
   END ASM
   
END SUB


' ___________________________________________
' Delay, produce una pausa en el programa
' ___________________________________________

SUB delay (pausa AS UINTEGER)

   ASM
      ld hl,2
      add hl,sp
      ld c, 0
      ld b, 2
uno:   ld e, (hl)      ;operando base
      ld d, 0
dos:   halt
      dec de
      ld a,d
      or e
      jp nz,dos
      dec bc
      ld a,b
      or c
      jp nz,uno
   END ASM
   
END SUB

' ___________________________________________
' Función para sacar un dato por un puerto
' ___________________________________________

SUB portOut (port AS UINTEGER, value AS UBYTE)

   ASM
      ld hl,2
      add hl,sp
      ld a, (hl)
      inc hl
      inc hl
      ld c, (hl)
      inc hl
      ld b, (hl)
      out (c),a
   END ASM

END SUB

' ___________________________________________
' Definir paleta de color
' ___________________________________________

SUB escribePaleta (indice AS UBYTE, color AS UBYTE)

   ' Los bits del color van en forma GGGRRRBB
   portOut (48955, indice)
   portOut (65339, color)

END SUB


' ___________________________________________
' Función para leer un puerto
' ___________________________________________

SUB portIn (port AS UINTEGER)

   ASM
      ld   b, h
      ld   c, l
      ld   h, 0
      in   l, (c)
   END ASM

END SUB


' ___________________________________________
' Espera interrupción y para la CPU
' ___________________________________________

SUB waitInt ()

   ASM
      halt
   END ASM

END SUB

' ___________________________________________
' Posiciona un Sprite de 8x8 a color
' ___________________________________________

SUB putSpritex8 (posicion AS UINTEGER, x AS UBYTE, y AS UBYTE)

   ' -------------------------------------------
   ' RUTINA DE IMPRESION DE UN SPRITE 8x8 PIXELS
   ' EN CUALQUIER POSICION DE BYTES (cada byte dos pixels horizontales)
   ' ENTRADAS:
   ' D será la posición del cursor vertical en pixels
   ' E será la posición del cursor horizontal en parejas de pixels
   ' HL es la posición de memoria donde tenemos el sprite
   ' SALIDAS: se escribe en el mapa de pantalla
   ' ADVERTENCIAS: no comprueba límites de pantalla
   ' -------------------------------------------
   
   ASM
      ld hl,2      ; Pasamos la variable de entrada al acumulador
      add hl,sp
      ld d, (hl)   ; D es el valor Y
      inc hl
      inc hl
      ld e, (hl)   ; E es el valor X
      inc hl
      inc hl
      ld a, (hl)
      inc hl
      ld h, (hl)
      ld l, a      ; HL es el puntero al sprite
      ld a, d      ; recuperamos el valor vertical
      rrca
      rrca      ; rotamos para dejar su valor en múltiplos de 64 (linea, de dos en dos pixels)
      and 192      ; borramos el resto de bits por si las moscas
      or e      ; sumamos el valor horizontal
      ld e, a      ; e preparado
      ld a, d      ; cargamos el valor vertical
      rrca
      rrca      ; rotamos para quedarnos con los bits altos
      and 63      ; borramos el resto de bits
      or 64      ; nos posicionamos a partir de 16384 (16384=64+0 en dos bytes)
      ld d, a      ; d preparado, ya tenemos la posición en pantalla
      ld b,8      ; Indicamos que vamos a pintar 8 líneas
draw:   ld c,4      ; dibujamos 8 pixels (4 bytes) e indicamos que vamos a pintar 4 pares de pixels
      ldi
      ldi
      ldi
      ldi
      ld a,e
      add a,60   ; incrementamos una línea y retornamos los pixels dibujados
      ld e,a
      jr nc, sigue
      inc d      ; incrementamos D si sale acarrero al incrementar E en 64 bytes
sigue:   djnz draw
         
   END ASM
END SUB


juego.c (juego.bas):

Código: Seleccionar todo

' juego.bas
' Esqueleto de juegos de Radastan "traducido" a ZX Basic
' version 0.1 beta

#include "sprites.bas"
#include "lib\motorzxuno.bas"

'#pragma output STACKPTR=65000 ' <<<<<< ni idea de cómo usar esto en ZX Basic, sirve para algo?

DIM paleta(15) As UByte => {0,1,7,99,4,116,12,24,13,31,64,132,180,252,221,255}

DIM i As UByte

SUB main ()
   borra (3)
   ' Inicializamos el modo Radastaniano
   
   portOut (48955,64)
   portOut (65339,3)
   
   ' Definimos la paleta
   
   for i=0 to 15
   
      escribePaleta (i, paleta(i))

   next i
   
   ' Limite sprites x=60 e y=88
   
   for i=0 to 60 step 4
   
      putSpritex8 (@spriteTile3,i,80)
      putSpritex8 (@spriteTile1,i,88)
   next i
      putSpritex8 (@spriteTile2,24,72)
      putSpritex8 (@spriteTile3,28,72)
      putSpritex8 (@spriteTile4,32,72)
end sub

BORDER 2
main ()


y para acabar sprites.h (sprites.bas):

Código: Seleccionar todo

' sprites.bas

spriteTile0:

ASM
   DEFB   51, 51, 51, 51
   DEFB   51, 51, 51, 51
   DEFB   51, 51, 51, 51
   DEFB   51, 51, 51, 51
   DEFB   51, 51, 51, 51
   DEFB   51, 51, 51, 51
   DEFB   51, 51, 51, 51
   DEFB   51, 51, 51, 51
END ASM

spriteTile1:

ASM
   DEFB   68, 68, 68, 68
   DEFB   68, 68, 68, 68
   DEFB   68, 68, 68, 68
   DEFB   68, 68, 68, 68
   DEFB   68, 68, 68, 68
   DEFB   68, 68, 68, 68
   DEFB   68, 68, 68, 68
   DEFB   68, 68, 68, 68
END ASM

spriteTile2:

ASM
   DEFB   58, 187, 187, 170
   DEFB   171, 187, 187, 186
   DEFB   187, 164, 75, 68
   DEFB   164, 68, 68, 68
   DEFB   68, 68, 68, 68
   DEFB   68, 68, 68, 68
   DEFB   68, 68, 68, 68
   DEFB   68, 68, 68, 68
END ASM

spriteTile3:

ASM
   DEFB   170, 170, 170, 170
   DEFB   171, 186, 171, 186
   DEFB   75, 180, 68, 180
   DEFB   75, 68, 68, 68
   DEFB   68, 68, 68, 68
   DEFB   68, 68, 68, 68
   DEFB   68, 68, 68, 68
   DEFB   68, 68, 68, 68
END ASM

spriteTile4:

ASM
   DEFB   170, 187, 187, 163
   DEFB   171, 187, 187, 186
   DEFB   68, 187, 74, 187
   DEFB   68, 75, 68, 171
   DEFB   68, 68, 68, 68
   DEFB   68, 68, 68, 68
   DEFB   68, 68, 68, 68
   DEFB   68, 68, 68, 68

END ASM

spriteZulu:

ASM
   DEFB   243, 63, 243, 63, 243, 51
END ASM


Y ya para mayor comodidad el zip con los tres archivos
Adjuntos
codigozxbas.zip
(2.53 KiB) Descargado 217 veces

Avatar de Usuario
mcleod_ideafix
Amiga 2500
Amiga 2500
Mensajes: 5316
Registrado: 06 Oct 2009, 04:12
Sistema Favorito: Spectrum 16Kb/48Kb
primer_sistema: Spectrum 16Kb/48Kb
consola_favorita: Vectrex
Primera consola: TV Games/Pong Clone
Ubicación: Jerez de la Frontera
Gracias dadas: 12 veces
Gracias recibidas: 53 veces
Contactar:

Re: ZX-Uno - kit de programación modo Radastaniano

Mensajepor mcleod_ideafix » 26 May 2015, 20:29

Haplo escribió:Por cierto, hay una línea que no sé traducirla a zxbasic:
#pragma output STACKPTR=65000


Es para establecer la cima de la pila. En ZX Basic sería equivalente a un CLEAR 65000

Por otra parte, lo que te pasa parece que tiene que ver con los puertos de E/S. Parece que tus OUTs y tus INs no funcionan. Como en ZX Basic ya existe una instrucción IN y OUT, no tienes que volver a definirlas. En lugar de PortOut y PortIn usa sencillamente OUT e IN como en el BASIC de siempre.

Lo que me da pie a preguntar: el paso de parámetros entre ZX Basic y el ensamblador, ¿cómo lo estás haciendo exactamente? ¿El paso de parámetros es de derecha a izquierda como parece deducirse de tu implementación de PortOut?
Recuerda: cada vez que se implementa un sistema clásico en FPGA, Dios mata a un purista

Avatar de Usuario
Haplo
MSX Turbo R
MSX Turbo R
Mensajes: 278
Registrado: 14 Abr 2014, 22:24
Sistema Favorito: PC
primer_sistema: Spectrum +2
consola_favorita: Sony PlayStation 1
Primera consola: Nintendo NES/Clónica
Ubicación: Ciudad Real
Gracias dadas: 33 veces
Gracias recibidas: 5 veces

Re: ZX-Uno - kit de programación modo Radastaniano

Mensajepor Haplo » 27 May 2015, 01:50

Gracias McLeod, efectivamente el tema del IN y OUT funciona con las propias de basic asíque eso ya no es problema, (por cierto, esos comandos no los he visto en la wiki de zxbasic)
Como bien apuntas, el traspaso de parámetros a los registros en las funciones parece que tiene mucho que ver con mis cuelgues, ya estuve mirando cómo iva el tema y es algo lioso porque tienes que lidiar con la pila para extraer datos sin corromperla de paso. Como soy muy bruto y al no encontrar un esquema claro de cómo funciona, me he puesto a hacer ensayo y error y algunas veces he conseguido que me pinte los bloques enteros (8x8) pero desordenados. En todos los casos seguido de reseteos o congelamientos ](*,)

Al final voy a tener que hacerme un programa sencillo para averiguar cómo funciona esto de los parámetros en las funciones...

Avatar de Usuario
na_th_an
Amiga 1200
Amiga 1200
Mensajes: 1273
Registrado: 10 Oct 2012, 11:17
Sistema Favorito: (Otro)
primer_sistema: Spectrum +2
consola_favorita: Sony PlayStation 1
Primera consola: Sega Master System
Gracias dadas: 18 veces
Gracias recibidas: 15 veces

Re: ZX-Uno - kit de programación modo Radastaniano

Mensajepor na_th_an » 27 May 2015, 08:28

También puedes preguntárselo a Boriel en el foro de ZX Basic, creo que será más rápido :D

Avatar de Usuario
radastan
Amiga 2500
Amiga 2500
Mensajes: 4542
Registrado: 11 Jun 2007, 19:29
Sistema Favorito: Spectrum 16Kb/48Kb
primer_sistema: Spectrum 16Kb/48Kb
consola_favorita: Sega Genesis/Megadrive
Primera consola: TV Games/Pong Clone
Ubicación: Córdoba
Gracias dadas: 9 veces
Gracias recibidas: 40 veces
Contactar:

Re: ZX-Uno - kit de programación modo Radastaniano

Mensajepor radastan » 27 May 2015, 09:20

na_th_an escribió:También puedes preguntárselo a Boriel en el foro de ZX Basic, creo que será más rápido :D


Fecundo la moción, Boriel te va a guiar mejor que nadie.
Yo tengo una máquina del tiempo, se llama ZX Spectrum, siempre me devuelve a los buenos momentos.
(\.../) (\.../) (\.../) (\.../)
( *.*) ('.'= ) ('.'= ) ('.'= )
(")_(") (")_(") (")_(") (")_(")
╔═══╦═══╦═══╦══╦══╗
║╔═╗║╔═╗║╔═╗╠╣╠╩╣╠╝
║║─║║╚══╣║─╚╝║║─║║
║╚═╝╠══╗║║─╔╗║║─║║
║╔═╗║╚═╝║╚═╝╠╣╠╦╣╠╗
╚╝─╚╩═══╩═══╩══╩══╝

Avatar de Usuario
mcleod_ideafix
Amiga 2500
Amiga 2500
Mensajes: 5316
Registrado: 06 Oct 2009, 04:12
Sistema Favorito: Spectrum 16Kb/48Kb
primer_sistema: Spectrum 16Kb/48Kb
consola_favorita: Vectrex
Primera consola: TV Games/Pong Clone
Ubicación: Jerez de la Frontera
Gracias dadas: 12 veces
Gracias recibidas: 53 veces
Contactar:

Re: ZX-Uno - kit de programación modo Radastaniano

Mensajepor mcleod_ideafix » 27 May 2015, 09:29

Sinclair y yo estuvimos hablando por PM de estas cuestiones. Él ha estado haciendo programas en ZX Basic que además acceden a rutinas del +3E. Ahora mismo no tengo tiempo de mirar los correos que nos intercambiamos, pero luego lo haré y te cuento como va exactamente el tema de los parámetros. Te adelanto que yo no uso HL, sino IX, para indexar los parámetros más rapidamente (y más comodamente)
Recuerda: cada vez que se implementa un sistema clásico en FPGA, Dios mata a un purista

Avatar de Usuario
na_th_an
Amiga 1200
Amiga 1200
Mensajes: 1273
Registrado: 10 Oct 2012, 11:17
Sistema Favorito: (Otro)
primer_sistema: Spectrum +2
consola_favorita: Sony PlayStation 1
Primera consola: Sega Master System
Gracias dadas: 18 veces
Gracias recibidas: 15 veces

Re: ZX-Uno - kit de programación modo Radastaniano

Mensajepor na_th_an » 27 May 2015, 10:22

En el código de las diferentes bibliotecas que ha publicado Britlion podemos ver cómo lo hace él. Es un stack frame simple, pelao, y mondao. Cuando se llama a una función, hay varias cosas que se almacenan en la pila, en este orden:

- parámetro N
- parámetro N - 1
...
- parámetro 2
- parámetro 1
- dirección de retorno <-- stack pointer.

Lo que se suele hacer es POP BC para obtener la dirección de retorno, hacer POP de todos los parámetros y almacenarlos donde sea, y luego hacer PUSH BC para meter la dirección de retorno de nuevo en la pila. De este modo el SUB o el FUNCTION podrá volver al final.

También se puede hacer como dice McLeod, con IX, teniendo en cuenta que ZX Basic siempre coloca IX apuntando a la ventana dentro de la pila reservada para parámetros, que los parámetros se apilan al revés, que la pila crece hacia abajo, y que cada parámetro ocupa dos bytes en la pila (porque la pila sólo se puede llenar de 16 en 16 bits), tenemos que:

Código: Seleccionar todo

Sub miSub (a as uByte, b as uByte, c as uInteger)


Tendrá a en IX+5, b en IX+7 y c en IX+9. Obviamente, para leer 'a' y 'b' usaremos un registro de 8 bits, y para leer c usaremos uno de 16.

Esta es la forma más sencilla aunque supongo que si se emplea un stack frame de toda la vida el acceso será levemente más rápido... Aunque en estas circunstancias creo que básicamente da igual.

Para funciones sencillas con un parámetro puedes usar FASTCALL: http://www.boriel.com/wiki/en/index.php ... C:FastCall ... Básicamente si el parámetro es de tamaño 1 byte se mete automáticamente en A y si es de 2 bytes se mete en HL.

Si usas FASTCALL con más de un parámetro, el resto de los parámetros se mete en la pila y los iríamos POPeando en el mismo orden usual: dirección de retorno, parámetro 2, parámetro 3...

Avatar de Usuario
mcleod_ideafix
Amiga 2500
Amiga 2500
Mensajes: 5316
Registrado: 06 Oct 2009, 04:12
Sistema Favorito: Spectrum 16Kb/48Kb
primer_sistema: Spectrum 16Kb/48Kb
consola_favorita: Vectrex
Primera consola: TV Games/Pong Clone
Ubicación: Jerez de la Frontera
Gracias dadas: 12 veces
Gracias recibidas: 53 veces
Contactar:

Re: ZX-Uno - kit de programación modo Radastaniano

Mensajepor mcleod_ideafix » 27 May 2015, 10:58

na_th_an escribió:Lo que se suele hacer es POP BC para obtener la dirección de retorno, hacer POP de todos los parámetros y almacenarlos donde sea, y luego hacer PUSH BC para meter la dirección de retorno de nuevo en la pila. De este modo el SUB o el FUNCTION podrá volver al final.

No lo recuerdo ahora pero... ¿en ZX Boriel no es la función llamante la que retira los parámetros de la pila? Porque si es así, al retirarlos tú desde la función llamada, armarás un pifostio en la pila cuando se vuelva a la función llamante. Volver, volverá, pero la función llamante destrozará su propio stack frame (acuérdate de TPBN ;) )
Recuerda: cada vez que se implementa un sistema clásico en FPGA, Dios mata a un purista

Avatar de Usuario
na_th_an
Amiga 1200
Amiga 1200
Mensajes: 1273
Registrado: 10 Oct 2012, 11:17
Sistema Favorito: (Otro)
primer_sistema: Spectrum +2
consola_favorita: Sony PlayStation 1
Primera consola: Sega Master System
Gracias dadas: 18 veces
Gracias recibidas: 15 veces

Re: ZX-Uno - kit de programación modo Radastaniano

Mensajepor na_th_an » 27 May 2015, 11:21

mcleod_ideafix escribió:
na_th_an escribió:Lo que se suele hacer es POP BC para obtener la dirección de retorno, hacer POP de todos los parámetros y almacenarlos donde sea, y luego hacer PUSH BC para meter la dirección de retorno de nuevo en la pila. De este modo el SUB o el FUNCTION podrá volver al final.

No lo recuerdo ahora pero... ¿en ZX Boriel no es la función llamante la que retira los parámetros de la pila? Porque si es así, al retirarlos tú desde la función llamada, armarás un pifostio en la pila cuando se vuelva a la función llamante. Volver, volverá, pero la función llamante destrozará su propio stack frame (acuérdate de TPBN ;) )


Tienes razón, eso que digo es sólo válido para FASTCALL en ZX Basic. Micropunto negativo :D Supongo que ZX Basic, en modo "FASTCALL", hace lo menos posible y deja toda la tarea de deshacer el stack frame al programador. Documentado aquí: http://www.boriel.com/wiki/en/index.php ... C:FastCall

Ah, TPBN :) Cuando cursé esa materia era el primer año que se daba, creo, en el curso 1999/2000. Claudio hizo un buen trabajo, dadas las circunstancias ;) Recuerdo que apliqué los conocimientos en hacer un jueguecillo de recoger gotas con un paraguas que ocupaba 1Kb :lol:

Avatar de Usuario
mcleod_ideafix
Amiga 2500
Amiga 2500
Mensajes: 5316
Registrado: 06 Oct 2009, 04:12
Sistema Favorito: Spectrum 16Kb/48Kb
primer_sistema: Spectrum 16Kb/48Kb
consola_favorita: Vectrex
Primera consola: TV Games/Pong Clone
Ubicación: Jerez de la Frontera
Gracias dadas: 12 veces
Gracias recibidas: 53 veces
Contactar:

Re: ZX-Uno - kit de programación modo Radastaniano

Mensajepor mcleod_ideafix » 27 May 2015, 13:53

na_th_an escribió:Ah, TPBN :) Cuando cursé esa materia era el primer año que se daba, creo, en el curso 1999/2000. Claudio hizo un buen trabajo, dadas las circunstancias ;) Recuerdo que apliqué los conocimientos en hacer un jueguecillo de recoger gotas con un paraguas que ocupaba 1Kb :lol:


Algunos (ya supongo que ex-alumnos) les resultaba curioso eso de que su profe de prácticas posteara comentarios en sus blogs...
https://ubunturoot.wordpress.com/2008/0 ... /#comments

Otros se tomaron con mucha filosofía y humor su paso por TPBN...
Imagen

No todos los que han pasado por la asignatura han opinado igual. Eso de trastear con el ensamblador que produce un código C, y luego más tarde, cuando yo entré en la asignatura, escribir código C de bajo nivel para hacer drivers para Linux, "mató" a muchos de ellos. Tanto, que en los últimos años de la asignatura, cuando más quemado andaba el personal, se crearon páginas en las redes sociales del tipo "Yo odio a TPBN"...
https://www.facebook.com/groups/205837042778222/
Recuerda: cada vez que se implementa un sistema clásico en FPGA, Dios mata a un purista


Volver a “Sinclair/Spectrum”

¿Quién está conectado?

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