¡Overscan con el señor Syx!

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
Mode 2
Master of The Forum
Master of The Forum
Mensajes: 1967
Registrado: Lun 10 Oct , 2005 8:01 pm
Ubicación: Sevilla, años 80.

¡Overscan con el señor Syx!

Mensajepor Mode 2 » Vie 01 Ago , 2014 2:03 pm

Buenas,

Acá estoy '¡chalao perdio!' seguir el código de ese titán llamado Syx (ya me veo a Mauri pensando/diciendo: "Pisha, pero si son tres Outs de naaaá!!"). Así que me gustaría preguntarle algunas cosillas al respecto. Sea usted bueno conmigo, caballero, tanto en la forma de expresar ciertas cosas que son nuevas para mi como en lo de preguntar ciertas cosas, pero es que llevo un buen tiempo liado con la comprensión del código. ¡Asias! :wink:

¡Hay que ver lo ordenadito que programas!, tío. =D>


Código: Seleccionar todo

    ORG  $1180
; ---------------------------------------------------------------------------
inicio
    ; Tomamos el control del sistema
    DI
    IM   1
    LD   HL,$C9FB       ; EI ($FB) + RET ($C9)
    LD   ($0038),HL     ; Habría un retardo de 4 NOPs al responder a las interrupciones
    LD   SP,inicio      ; Inicializamos la pila
    EI

Entiendo más o menos, o eso creo, lo que hace las lineas que toma el control del sistema pero serías tan amable de explicarmelo con tus palabras.



Código: Seleccionar todo

; ---------------------------------------------------------------------------
; Esperamos el refresco vertical
; ---------------------------------------------------------------------------
espera_refresco
    LD   B,HIGH PPI_B
.bucle_espera_refresco
    IN   A,(C)
    RRA
    JR   NC,.bucle_espera_refresco
    RET

Entiendo que HIGH especifica el byte alto de PPI_B, ¿no?, aunque es una instrucción que nunca había visto o eso creo recordar, ¿de dónde la saco vos?
Veo que lees en en A el 'contenido' de la puerta/puerto (C) sin haber primero especificado un valor para C, es como si supieses al
empezar el programa que valor va a tener. ¿Puedes aclararlo?.


Código: Seleccionar todo

   ; Tintas a negro
    LD   C,INK + NEGRO
    XOR  A
.bucle_apagon
    OUT  (C),A
    OUT  (C),C
    INC  A
    CP   $11
    JR   NZ,.bucle_apagon

Al poner una de las tintas a 0, tenemos que hacer un OUT con el valor de INK y NEGRO para volver a poner a 0 la próxima número de tinta y así sucesivamente con todas, ¿no?.



Código: Seleccionar todo

   
; Dimensiones y centrado de la pantalla para el CRTC
    LD   HL,valores_crtc
    LD   A,6
    LD   BC,$BDBE       ; (>CRTC_SELECT + 1) * 256 + (>CRTC_WRITE + 1) VASM Syntax Rulez!!! :P
.bucle_define_pantalla
    OUTI
    LD   B,C
    OUTI
    DEC  A
    JR   NZ,.bucle_define_pantalla
    RET

valores_crtc
    DEFB REG_01,ANCHO_PANTALLA_CRTC
    DEFB REG_06,ALTO_PANTALLA_CRTC
    DEFB REG_02,DESPLAZAMIENTO_HORIZONTAL ; POKE &11D1,&32
    DEFB REG_07,DESPLAZAMIENTO_VERTICAL   ; POKE &11D3,&24
    DEFB REG_0C,VRAM_P2 + VRAM32           
    DEFB REG_0D,OFFSET_PANTALLA_CRTC

Acá tenemos la madre del cordero,lo esencial. Por mucho que haga mentalmente lo que hace el código de arriba, no entiendo porque 'juegas' con $BD y $BE.

Consultando dicha información me encuentro esto:

The CRTC has a total of 18 8-bit registers controlling all aspects of the video timings.
It's clock frequency on the Amstrad CPC/Plus is 1MHz (so the CRTC updates itself every microsecond).
Four I/O ports are assigned to it :
&BC00 (Write only): to select an internal register.
&BD00 (Write only): to write to the currently selected internal register.

&BE00 (Read only) : to read the Status register (only available on CRTC type 1).
&BF00 (Read only) : to read the value of the currently selected internal register (but not all of them can be read)


Y viendo lo que pusiste en BASIC en el propio artículo:

Código: Seleccionar todo

OUT &BDBE,1: OUT &BEBE,48: REM R1 = 48
OUT &BDBE,6: OUT &BEBE,34: REM R6 = 34
OUT &BDBE,2: OUT &BEBE,50: REM R2 = 50
OUT &BDBE,7: OUT &BEBE,35: REM R7 = 36   
OUT &BDBE,12:OUT &BEBE,35:REM R12 = 44   
OUT &BDBE,13:OUT &BEBE,35:REM R13 = 16   

No lo comprendo, ¿no deberías de usar &BC y &BD?. ¡¡¡Aquí es donde tengo la mayor duda del programa!!! #-o


Un saludaco.
BUSCO: VideoPac+, Jaguar Saturn, Micromanía 1 y 25, Amstrad Semanal, MicroHobby, juegos especialmente CPC y Vectrex, Aquarius, Sam Copé, 520 ST, Everdrive SNES, manual +3, manual CPC664.

Avatar de Usuario
syx
Master of The Forum
Master of The Forum
Mensajes: 1300
Registrado: Mié 02 Sep , 2009 9:55 am

Re: ¡Overscan con el señor Syx!

Mensajepor syx » Vie 01 Ago , 2014 5:41 pm

Nas! :)

Mode 2 escribió:Entiendo más o menos, o eso creo, lo que hace las lineas que toma el control del sistema pero serías tan amable de explicarmelo con tus palabras.
Pues tal como dice, tomamos el control de la máquina :mrgreen:

Para ello establecemos el modo 1 de interrupciones del Z80, que lo que hace es que cada vez que se reciba un interrupción el Z80 salta a $0038, y en dicho lugar ponemos una rutina de interrupciones que no hace nada (EI + RET) ó sino saltaría a la rutina de manejo de interrupciones del firmware. Además de eso, situamos la pila en un sitio que no nos moleste y con suficiente espacio ($1180 en ese caso).

A modo de anécdota esa es una deformación de cuando programaba en Amiga, que lo primero que se hacía era desactivar la multitarea y las interrupciones del sistema operativo, así como situar la pila donde queríamos, y así empezar a hacer lo que nos diese la gana con el hardware... pues en este caso igual, desconectamos el firmware para que no nos moleste, aunque podrías hacerlo compatible con el firmware pero eso añadiría más complejidad, algo que en un tutorial de iniciación para una revista no era necesario.

Mode 2 escribió: LD B,HIGH PPI_B
IN A,(C)

Entiendo que HIGH especifica el byte alto de PPI_B, ¿no?, aunque es una instrucción que nunca había visto o eso creo recordar, ¿de dónde la saco vos?
Eso no es una instrucción, sino una directiva del ensamblador, y como uno ha programado para muchas CPUs, entre ellas el 6502, en donde esa directiva HIGH ó > y LOW ó < resultan de lo más cómodas. Por eso cuando empecé a usar pasmo, fue mi primera sugerencia al autor, porque para mí me ayuda a hacer el código más legible.

Mode 2 escribió:Veo que lees en en A el 'contenido' de la puerta/puerto (C) sin haber primero especificado un valor para C, es como si supieses al empezar el programa que valor va a tener. ¿Puedes aclararlo?.
Quéééé?!?!?! Esto no es el spectrum ó el msx :mrgreen: , en el CPC los puertos de e/s son de 16 bits, osea se usa BC al completo... y esa es la razón porque los OTIR e INIR no valen para nada en nuestas máquinas.

Por supuesto, si miras como se decodifican los puertos internamente en el CPC verás que no se hacen decodificaciones completas de los 16 bits (que ya sabemos como se las gastaba el Sugar a la hora de recortar gastos).

Por ejemplo, para el PPI B que es $F500 solo se prueban los siguientes bits %xxxx 0x01 xxxx xxxx, así que da igual si mandas a $F500 ó $F5FF ó $0100 ó ...

Es decir, que para empezar el byte bajo importa poco y luego del byte alto solo tienes que tener en cuenta 3 bits... usando este truco puedes acceder a varios dispositivos del CPC simultaneamente, pero también puedes desgraciar varias cosas simultaneamente :mrgreen: :mrgreen: :mrgreen:

Así que para el tutorial, use lo más común, emplear solo el byte de más peso, el cual logicamente va en B. De hecho en CPC más que hablar de IN x,(C) y OUT (C),x sería más correcto referirse a ellas como IN x,(B) y OUT (B),x. De la misma manera que tampoco tiene mucho sentido hablar de JP (HL) cuando lo más lógico sería decir JP HL, pero como Zilog lo documentó de esa manera, pues hay que tragar con ello ó hacerte tu propio ensamblador :P

Y en cierto modo este parece ser tu gran problema con este programa, quizás di por sentado que todo el mundo que programa en ensamblador para CPC sabe que los puertos de E/S son de 16 bits, pero que no todos esos bits se usan y para la mayor parte de ellos con usar el byte de más peso nos sobra, por lo que podemos usar C con toda libertad para meter valores como el color ó un índice de la paleta ó la página de RAM a activar ó valores para el CRTC ó ...

Mode 2 escribió:Al poner una de las tintas a 0, tenemos que hacer un OUT con el valor de INK y NEGRO para volver a poner a 0 la próxima número de tinta y así sucesivamente con todas, ¿no?.
Si, eso es lo que hace el código poner la paleta a negro usando un bucle. Pero eso no quiere decir que tengas que hacerlo en ese orden, puedes usar el orden que te de la gana. La verdad es que no entiendo muy bien tu pregunta, jejeje.

Mode 2 escribió: LD BC,$BDBE
OUTI
LD B,C
OUTI

Acá tenemos la madre del cordero,lo esencial. Por mucho que haga mentalmente lo que hace el código de arriba, no entiendo porque 'juegas' con $BD y $BE.

No lo comprendo, ¿no deberías de usar &BC y &BD?. ¡¡¡Aquí es donde tengo la mayor duda del programa!!! #-o
Y no estoy usando $BCxx y $BDxx, porque eso es lo que yo veo :P

Primero, no se que versión del artículo tienes pero el pedazo en Basic es:

Código: Seleccionar todo

OUT &BC00,1:OUT &BD00,48:REM R1 = 48
OUT &BC00,6:OUT &BD00,34:REM R6 = 34
OUT &BC00,2:OUT &BD00,50:REM R2 = 50
OUT &BC00,7:OUT &BD00,35:REM R7 = 35

En cuanto para entender lo que ocurre en el trozo en ensamblador, acabamos de decir que el CPC usa puertos de E/S de 16 bits, ahora lo que hace falta es coger el manual de Z80 y ver que hace la instrucción OUTI (una de mis favoritas y que suelo usar en practicamente todo programa que uso).

OUTI envía al puerto en BC, el valor apuntado por HL, incrementa HL y decrementa B. Con la salvedad que ese decremento de B es lo primero que se realiza. En pseudocodigo sería:

Código: Seleccionar todo

B--
Port[BC] = (HL)
HL++

Tenemos dos OUTIs en ese bucle, en el primero BC vale $BDBE, pero mientras se escribe en el puerto BC vale $BCBE. En el segundo BC vale $BEBE, pero mientras se escribe en el puerto BC vale $BDBE y vuelta a empezar.

Es por eso que puse el comentario "(>CRTC_SELECT + 1) * 256 + (>CRTC_WRITE + 1)", porque en el ensamblador que ya usaba por aquel entonces, puedes usar esas expresiones tan complejas directamente.

Vamos que no hay ningún misterio a parte del uso de OUTI, quizás las cosas me salieron más optimizadas de la cuenta, seguramente de haber continuado la revista el nivel de la sección se habría adecuado a los lectores... pero es que eres el primero en escribir acerca del artículo y hace 3 años que se publicó.

Avatar de Usuario
Mode 2
Master of The Forum
Master of The Forum
Mensajes: 1967
Registrado: Lun 10 Oct , 2005 8:01 pm
Ubicación: Sevilla, años 80.

Re: ¡Overscan con el señor Syx!

Mensajepor Mode 2 » Lun 04 Ago , 2014 11:05 am

Buenas Mauri,

Muchísimas gracias por tu pronta respuesta, la pude ver este finde. :wink:

Sí, ya sé que los puertos de E/S son de 16 bits pero me costó verlo, ¡es que eso de out (c),c despista!. Una vez que vi en un sitio que out (c),c = out (bc),c ya lo tuve claro. :wink:

En cuanto a lo de los registros usados, pues la verdad es que el lío ha venido de mirar lo de la instrucción OUTI en un sitio donde decrementaba b al final y no antes, ¡figurate el cacao!. Es más, en mi mensaje anterior te iba a preguntar si OUTI funcionaba como había leído. Así que, todo aclarado. Por cierto, lo que comentas de cómo se interpreta lo de los puertos es muy esclarecedor. :wink:

Curiosamente estoy siguiendo el código fuente de un juego foráneo, adaptación de un juego de Atari 2600 para más pistas, y cuando he llegado a cosillas que hace en común con tu rutina, como lo de las tintas a negro usando el mismo método, gracias a la comprensión de tu código he podido ver la redundancia de éste y la posibilidad que tiene de optimización, pero mucha. Lo dicho, eres un referente. ¡Esto marcha! :mrgreen:

Por cierto Mauri, ¿que se ha usado para dibujar el vkiller.scr y sacar el .pal? ¿con que has pasado el vkiller.scr a vkiller.bin y para qué?



Muchas gracias, bestia parda. :wink:
BUSCO: VideoPac+, Jaguar Saturn, Micromanía 1 y 25, Amstrad Semanal, MicroHobby, juegos especialmente CPC y Vectrex, Aquarius, Sam Copé, 520 ST, Everdrive SNES, manual +3, manual CPC664.

Avatar de Usuario
syx
Master of The Forum
Master of The Forum
Mensajes: 1300
Registrado: Mié 02 Sep , 2009 9:55 am

Re: ¡Overscan con el señor Syx!

Mensajepor syx » Lun 04 Ago , 2014 3:30 pm

Mode 2 escribió:Por cierto Mauri, ¿que se ha usado para dibujar el vkiller.scr y sacar el .pal? ¿con que has pasado el vkiller.scr a vkiller.bin y para qué?
Un programa de dibujo, no se si photoshop ó incluso el paint, ni idea, la verdad, cada dibujante usa las herramientas con las que se siente más comodo.

Lo importante es recibir el png correspondiente y pasarlo por una herramienta (cada cual tiene su propia preferencia, en mi caso s un script en python) que te genera dos ficheros, uno con la paleta en formato CPC y los datos de la imagen en "crudo".

Dichos datos de la imagen los puedes organiar como mejor te convengan, puede ser línea tras línea de la pantalla (para el caso en que vas a usar una rutina para pintar la pantalla, como si fuese un sprite) ó puedes tenerla con la misma organización de la memoria de vídeo del CPC (para el caso en que vas a descomprimir los datos directamente en su destino, pero ten en cuenta que esto deja huecos) ó omo te salga del alma porque tu programa los necesite de una forma específica.

Susso
Lechoncillo
Lechoncillo
Mensajes: 23
Registrado: Jue 13 Nov , 2014 6:13 pm

Re: ¡Overscan con el señor Syx!

Mensajepor Susso » Mar 18 Nov , 2014 12:54 am

Disculpadme mi ignorancia, pero...
¿PPI_B?
No he leído semejante palabro, ¿es algo de interrupciones del vblank?

Urusergi
Megaforero
Megaforero
Mensajes: 301
Registrado: Sab 25 Feb , 2006 5:45 pm

Re: ¡Overscan con el señor Syx!

Mensajepor Urusergi » Mar 18 Nov , 2014 3:21 pm

Susso escribió:Disculpadme mi ignorancia, pero...
¿PPI_B?
No he leído semejante palabro, ¿es algo de interrupciones del vblank?


PPI significa "Programmable Peripheral Interface" y se refiere al circuito 8255 que está dentro del cpc.
Como este PPI tienes 3 puertos se identifican como _A _B y _C

Susso
Lechoncillo
Lechoncillo
Mensajes: 23
Registrado: Jue 13 Nov , 2014 6:13 pm

Re: ¡Overscan con el señor Syx!

Mensajepor Susso » Mié 19 Nov , 2014 12:03 am

Urusergi escribió:
PPI significa "Programmable Peripheral Interface" y se refiere al circuito 8255 que está dentro del cpc.
Como este PPI tienes 3 puertos se identifican como _A _B y _C


Ok!! voy a tener que investigar, te agradezco mucho!


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