PCW: RSX para acceder al banco de pantalla

Programando el Amstrad en Ensamblador.
Reglas del Foro
Debido a que hay varios temas pidiendo ayuda para programar en ensamblador máquinas distintas al Amstrad CPC, con micro distinto al Z80 y que incluso dependen del sistema operativo, nos vemos en la necesidad de poner por escrito que estos posts son bienvenidos pero que no es el lugar adecuado ya que por estos lares nos dedicamos más al ensamblador del Z80, un microprocesador de 8 bits que tuvo su gran auge en ordenadores y consolas de los años 80.

De todas formas, esto no quita que alguien que sepa del asunto pueda postear alguna respuesta pero es más fácil encontrar foros dedicados a programar en ensamblador en Windows o MS-DOS que ayudarán más que nosotros:
http://www.lawebdelprogramador.com/news ... nsamblador
Avatar de Usuario
FloppySoftware
Megaforero
Megaforero
Mensajes: 237
Registrado: Mié 26 Oct , 2011 2:07 pm
Ubicación: Spain
Contactar:

PCW: RSX para acceder al banco de pantalla

Mensajepor FloppySoftware » Jue 19 Dic , 2013 10:52 pm

Hola,

Para animar un poquito esto, y como veo que el PCW no es muy frecuente en esta sección, pego aquí el código ensamblador de una RSX muy sencillita, con dos funciones básicas:

- Escribir bytes en una dirección del banco de memoria donde están los datos de pantalla y demás.
- Leer bytes de ... idem ...

El tamaño del buffer es de 720 bytes (el mismo tamaño que una fila de carácteres en pantalla), pero se puede modificar fácilmente.

La RSX ha de estar dentro del banco común de memoria (por encima de 0xC0000), lo que suele ser tan sencillo como adosarla a un archivo COM y ya está. Esto lo haríamos con GENCOM.

Por lo demás, el código se puede ensamblar con M80 de Micro$oft, y linkar con LINK de Digital Research.

Dentro de su sencillez, éstas dos rutinas nos permiten hacer muchísimas cosas:

- Redefinir el juego de carácteres.
- Dibujar en la pantalla (sprites, etc.).
- Leer imágenes de la pantalla.
- ...

Tan sólo hay que utilizarlas con imaginación.

Son un buen complemento a cualquier programa en MESCC, pero se puede utilizar desde prácticamente cualquier lenguaje de programación, incluido ensamblador, por supuesto.

Parámetros:

- env_adr: Dirección en el banco de memoria de pantalla.
- tpa_adr: Dirección en el banco de memoria "normal" de nuestro programa.
- length: Número de bytes que queremos mover.

Bueno, ahí os dejo el código.

Saludos.

PD: Veréis que hay algunas definiciones que no se utilizan. Son cositas heredadas de otro código, que no he eliminado por si las utilizo más tarde. Tampoco molestan tanto...

Código: Seleccionar todo

;PutScrEnv(env_adr, tpa_adr, length)
;GetScrEnv(env_adr, tpa_adr, length)

   .Z80

RAMScroll   EQU   0B600H
RAMChars   EQU   0B800H
RAMScreen   EQU   05C00H

USERF      EQU   0FC5AH
SCRRUN      EQU   0E9H

BDOS_PCW   EQU   255   ;New BDOS function for this RSX

PCW_PUTENV   EQU   0
PCW_GETENV   EQU   1

MAXFUNC   EQU   12      ;Max. defined subfunctions
MAXPARS   EQU   10      ;Max. size of parameters in bytes

   cseg

   defb   0,0,0,0,0,0   ;SERIAL NUMBER
   jp   SysTrap      ;JUMP TO RSX
Cont:   jp   0      ;JUMP TO NEXT RSX
   defw   0      ;ADDRESS OF PREVIOUS RSX
   defb   255      ;REMOVE FLAG (0 == PERMANENT)
   defb   0      ;NON BANK ONLY FLAG
   defb   'PcwEnv00'   ;RSX name (8 bytes)
   defb   0      ;LOADER FLAG
   defw   0      ;RESERVED

SysTrap:

 ld a,c
 cp BDOS_PCW
 jr nz,Cont

 ld a,(de)

 ex de, hl
 ld de, fun
 ld bc, 8
 ldir

 cp PCW_PUTENV
 jp z, PutScrEnv
 cp PCW_GETENV
 jp z, GetScrEnv
 ret

fun:     defw 0
env_adr: defw 0
tpa_adr: defw 0
length:  defw 0

buffer:  defs 720

PutScrEnv:

 ld hl, (tpa_adr)
 ld de, buffer
 ld bc, (length)
 ldir

 ld bc, BufToEnv
 call USERF
 defw SCRRUN
 ret

BufToEnv:

 ld hl, buffer
 ld de, (env_adr)
 ld bc, (length)
 ldir
 ret

GetScrEnv:

 ld bc, EnvToBuf
 call USERF
 defw SCRRUN

 ld hl, buffer
 ld de, (tpa_adr)
 ld bc, (length)
 ldir
 ret

EnvToBuf:

 ld hl, (env_adr)
 ld de, buffer
 ld bc, (length)
 ldir
 ret

   end

Guspan
Me voy lanzando
Me voy lanzando
Mensajes: 81
Registrado: Mar 20 Dic , 2011 1:53 pm

Re: PCW: RSX para acceder al banco de pantalla

Mensajepor Guspan » Mié 09 Mar , 2016 11:43 am

Buenos días FloppySoftware, llevo tiempo intentando aprender la parte de ASM (estoy haciéndolo con pasmo), y ahora me he puesto con este listado y me han surgido dudas de como "adaptarlo" o ponerme a trabajar con ello, podrias poner un ejemplo de uso "fácil" para principiantes, para tratar de entenderlo.

Muchas Gracias.

Avatar de Usuario
FloppySoftware
Megaforero
Megaforero
Mensajes: 237
Registrado: Mié 26 Oct , 2011 2:07 pm
Ubicación: Spain
Contactar:

Re: PCW: RSX para acceder al banco de pantalla

Mensajepor FloppySoftware » Sab 16 Abr , 2016 12:28 am

Hola Guspan,

Lo primero, disculpa la tardanza en contestar. ](*,) Si no he visto tu pregunta antes, ha sido porque tenía este post en el olvido (es de diciembre de 2013, y nadie le hizo el menor caso en todo este tiempo <XX ).

Esta RSX la hice en su día por tener un par de rutinas básicas para todos mis programas, pero al final acabé haciendo lo que es XPCW, unas librerías gráficas que hacen uso de una RSX más compleja. De hecho, quiero darle un meneo, y crear algunas funciones específicas para sprites, etc., aunque la funcionalidad básica ya está allí.

En cualquier caso, a mi entender esta RSX sigue siendo un buen método para aprender cosas acerca de las peculiaridades de la pantalla del PCW y, dentro de lo básica que es, proporciona un par de métodos con los que se puede hacer casi de todo.

Pero mejor, intento explicarlo desde el principio, y que me corrija algún compañero si la lío en algo. :lol:

Una RSX de CP/M Plus, es una Resident System eXtension (no confundir con las RSX de los CPC bajo AMSDOS, porque se llaman igual y tienen funciones similares, pero no tienen nada que ver en su implementación). Dicho pronto y mal, una RSX permite ampliar / modificar / capturar las llamadas al BDOS de CP/M Plus; las funciones del sistema, vaya. #-o

Por otra parte, la memoria de pantalla del PCW reside en un banco distinto al del programa que el usuario esté ejecutando (la TPA), y eso da bastantes quebraderos de cabeza. #-o

Como la memoria desde 0C000h hasta 0FFFFh es común para todos los bancos, se puede utilizar para transferir datos desde un banco a otro, y es ahí donde una RSX viene muy bien para el caso. :D

CP/M Plus carga las RSX en la memoria alta, por lo que suelen estar por encima de 0C000h (puede darse el caso de que esto no sea así, si hay más RSX cargadas, pero es rarísimo que ocurra [-X ).

De esta manera, utilizamos la RSX como intermediaria.

¿Cómo creamos una RSX?

Esto por sí sólo ya necesitaría un post dedicado, en el caso de que entrásemos en profundidad, porque las RSX dan para mucho.

En este caso, comentaré que al ser reubicables, necesitan un formato binario especial, no es un simple ensamblado: el formato PRL (Page ReLocatable).

Para esto, suelo utilizar M80 (ensamblador nativo de CP/M) y LINK (también nativo), pero creo que PASMO también puede crear PRLs, aunque la sintaxis del código es algo distinta. A veces también utilizo ZMAC para Windows.

En cualquier caso, una vez se tenga el archivo PRL, se renombra a RSX, y se adjunta al fichero COM ejecutable que sea, con el comando GENCOM de CP/M Plus:

GENCOM fichero.COM fichero.RSX

Con esto, ya tendríamos un fichero ejecutable con la RSX adosada. :)

Evidentemente, necesitaríamos hacer creado y ensamblado el fichero COM que hiciese uso de la RSX.

¿Qué se puede hacer con estas 2 rutinas?

Para empezar, necesitamos conocer 3 direcciones de memoria en el banco de pantalla del PCW:

Código: Seleccionar todo

RAMScroll   EQU   0B600H
RAMChars    EQU   0B800H
RAMScreen  EQU 05930h


RAMScroll y RAMScreen van de la mano, pero su explicación y uso son complejos; lo dejaremos para otro día. 8-[

Por cierto, en el listado que puse en su día, RAMScreen está mal. ](*,)

En cuanto a RAMChars (los nombres son míos, no son estándar), es la dirección de comienzo de la fuente de pantalla.

Como son 256 caracteres (del 0 al 255), que ocupan 8 bytes cada uno, hacen un total de 2048 bytes (2 Kb de toda la vida).

Por lo tanto, es muy sencillo calcular la posición en memoria de un caracter:

0B800H + caracter * 8

Ahora, vamos con las 2 rutinas de la RSX:

Código: Seleccionar todo

;PutScrEnv(env_adr, tpa_adr, length)
;GetScrEnv(env_adr, tpa_adr, length)


Ambas necesitan los mismos parámetros:

env_adr = dirección de memoria de pantalla del PCW
tpa_adr = dirección de memoria "normal" en la que está ejecutándose nuestro programa
length = nº de bytes a leer o escribir

Para llamar a la RSX, utilizamos una llamada normal al BDOS, cargando en el registro C el código que filtrará la RSX:

Código: Seleccionar todo

BDOS_PCW   EQU   255   ;New BDOS function for this RSX


Y en el par de registros DE, le pasaríamos el código de la rutina, y los parámetros indicados.

Ejecutaríamos la rutina llamando al BDOS (posición 00005h).

Los códigos de las rutinas son:

Código: Seleccionar todo

PCW_PUTENV   EQU   0  ; Escribir en la memoria de pantalla
PCW_GETENV   EQU   1  ; Leer de la memoria de pantalla


Por ejemplo, para leer la definición del carácter espacio (código 32 decimal), podríamos llamar a la RSX así:

Código: Seleccionar todo

 LD   C, 255
 LD   DE, lee
 CALL 5
 
 ...
 
lee:  DEFW 1                ; GET
      DEFW 0B800H + 32 * 8  ; DIRECCIÓN CARACTER ESPACIO
     DEFW espacio          ; DONDE ESTARÁN LOS DATOS
     DEFW 8                ; SON 8 BYTES
    
espacio:
      DEFS 8


En condiciones normales, debería devolver 8 bytes CERO en 'espacio'. [-o<

Para definir el carácter por un bloque verde, podríamos hacer:

Código: Seleccionar todo

 LD   C, 255
 LD   DE, escribe
 CALL 5
 
 ...
 
escribe:  DEFW 0                ; PUT
      DEFW 0B800H + 32 * 8  ; DIRECCIÓN CARACTER ESPACIO
     DEFW espacio          ; DONDE ESTÁN LOS DATOS
     DEFW 8                ; SON 8 BYTES
    
espacio:
      DEFB 255, 255, 255, 255, 255, 255, 255, 255


Como puedes ver, los parámetros que se le pasan a la RSX son 2 BYTES (1 WORD).

Dicho lo cual, espero haberte aclarado algo, en lugar de liarte más. [-o<

La RSX no es nada del otro mundo y no está muy optimizada que digamos, pero puede servir de partida para investigar más.

En cualquier caso, si estás interesado en el tema, podrías echarle un vistazo a XPCW y los ejemplos en C que le acompañan, pues el sistema es el mismo: fichero ejecutable COM + fichero RSX.

Saludos.


Volver a “Ensamblador”

¿Quién está conectado?

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

La Comunidad Española
ESP Soft, juegos para tu CPC Foro de Amstrad CPC Todos los juegos para CPC en un CD El portal del CPC Web dedicada al Amstrad CPC (utilidades) Información útil para el CPC (talleres) El sitio del Amstrad CPC Mundo CPC Pree Play then any Key CPC Basic