Repository navigation
DEZ80: Nivel 1
- Introducción
-
Nivel 1: Práctica
- Vídeo 1.P01: Introducción al nivel 1
- Vídeo 1.P02: Instalación de Winape en Ubuntu Linux
- Vídeo 1.P03:Ejemplo: Reto 1.1: Pintar un pixel rojo en pantalla
- Video 1.P04: Jugando con el código
- Vídeo 1.P05: Ejecutando Paso a paso
- Video 1.P06: Reto: Utilizar los colores
- Video 1.P07: Ejemplo. De 2 en 2
- Video 1.P08: Reto: Domina el formato
- Vídeo-1.P09: Pintando por la pantalla
- Video-1.P10: Reto: Pinta por la pantalla
- Video-1.P11: Domina la memoria de vídeo
- Video-1.P12: Desafio: Pinta un sprite
- Descripción del contenido del curso:
- Programar en código máquina
- Binario y hexadecimal
- Memoria principal y procesador
- Desafío: Pintar un Sprite en código ḿáquina
- Objetivo: Instalar y poner en funcionamiento el emulador del Amstrad CPC. Se utiliza el WinApe. Es una aplicación para Windows, pero se ejecuta perfectamente en Linux a través de Wine
- Observaciones: La instalacion de wine en Ubuntu 20.04 es mucho más fácil (El vídeo se hizo en el 2017 para Ubuntu 17.04)
Aunque esto no es de este nivel, para instalar y arrancar Winape más fácilmente he utilizado CPCtelera
Para instalarlo en Ubuntu 20.04 hay que seguir estos pasos:
- Instalar las dependencias
sudo apt install gcc g++ make bison flex mono-complete libboost-dev libfreeimage-dev wget unzip
-
Instalar wine
-
Descargar: cpctelera-1-4-2.zip
-
Descomprimir el archivo de cpctelera. En mi caso lo tengo en este directorio:
/home/obijuan/Bin/cpctelera-1.4.2 -
Ejecutar setup.sh:
Dentro del directorio cpctelera-1.4.2 hay un archivo llamado setup.sh
obijuan@corellia:~/Bin/cpctelera-1.4.2$ ls
cpctelera examples GPL-LICENSE LICENSE README.md setup.sh
Al ejecutarse se comprueban las dependencias y se instala cpctelera:
./setup.sh
- Cerrar el terminal
Cuando abramos otro terminal ya se tendrá acceso a todos los scripts y utilidades de cpctelera (se ha modificado el path en la instalación)
Para instalar winape ejecutar el siguiente script desde cualquier directorio:
obijuan@corellia:~$ cpct_winape
%%%%%%%%%%%%%%%%%%%%%%%%%
%% WinAPE laucher script
%%%%%%%%%%%%%%%%%%%%%%%%%
[Warning] WinAPE is not configured for your system yet.
Proceeding to install/configure WinAPE on your system.
Do you already have WinAPE installed (y/n)?n
[...]
La primera vez se detecta que winape NO está instalado y si le indicamos que no lo tenemos instalado lo descarga automáticamente, lo instala y lo ejecuta
Si ya está instalado winape, bastará con ejecutar este script:
cpct_winape
Winape arrancará directamente
Para configurar WinApe para trabajar en el curso vamos a la opción Settings/Display:

Así es como deben quedar las opciones:

Las opciones señaladas por flechas rojas son las que se han cambiado:
- Hide mouse pointer: DESMARCADA. Queremos que se vea el cursor del ratón al pasarlo por la ventana del emulador
- Directx strech: DESMARCADA. Para evitar problemas con la visualización en wine
- PAL emulation: DESMARCADA. La pantalla del emulador la veremos con más nitidez
- On Screen Drive LED: MARCADA
- Show Drive Cylinders: MARCADA
- Código máquina:
3E 88 32 00 C0 18 FE - Almacenado en dirección
0x4000 - Explicación: Almacenar el valor 0x88 en la dirección 0xC000 (Memoria de video). Esto hace que aparezca un pixel rojo en la esquina superior izquierda
- Resultado de la ejecución:

En esta imagen ampliada se puede ver mejor el pixel que aparece:

- Programa desensamblado:
LD A,#88
LD (#C000),A
JR #4005
Vamos a realizar varios experimentos para irnos familiarizando con el código máquina, el emulador y el funcionamiento de la memoria de vídeo. Como explica Fran, vamos a aprender por nuestra cuenta. Vamos a practicar y a experimentar. Y luego visualizaremos los vídeos de teoría para comprender perfectamente el funcionamiento
La memoria del CPC es de bytes. En cada posición de memoria se almacena un byte. En un byte hay 8 bits. El objetivo de este experimento es escribir valores que tengan sólo un bit a 1 y el resto a 0, para descubrir el significado de cada bit
Así, los valores que vamos a escribir en binario son: 1000000, 01000000, 00100000, 00010000, 0000100, 00000100, 00000010 y 00000001, que en hexadecimal se corresponden con estos números: 80, 40, 20, 10, 08, 04, 02 y 01
El programa para guardar el valor 88 en la dirección c000 ya lo conocemos. Bastará con sustituir 88 por los nuevos valores y ver qué ocurre:
- Valor 80 en C000
- Código máquina:
3E 80 32 00 c0 18 FE - Programa desensamblado:
ld a,#80
ld (#c000),a
jr #4005- Resultado: Se dibuja un pixel amarillo en la primera posicion

En esta imagen se ve ampliado:

- Valor 40 en C000
- Código máquina:
3E 40 32 00 c0 18 FE - Programa desensamblado:
ld a,#40
ld (#c000),a
jr #4005- Resultado: Se dibuja un pixel amarillo en la segunda posición (justo a continuación de la posición del pixel de la prueba anterior)
Para comprobar la posición del nuevo pixel respecto al anterior hacemos una captura y la alineamos con la captura de la prueba anterior. Vemos que el nuevo pixel está en la misma horizontal que el anterior, y que en la vertical está desplazado exactametne un pixel a la derecha

- Valor 20 en C000
- Código máquina:
3E 20 32 00 c0 18 FE - Programa desensamblado:
ld a,#20
ld (#c000),a
jr #4005- Resultado: Se dibuja un pixel amarillo en la tercera posición (Desplazado dos píxeles con respeto al pixel de la prueba 1)

- Valor 10 en C000
- Código máquina:
3E 10 32 00 c0 18 FE - Programa desensamblado:
ld a,#10
ld (#c000),a
jr #4005- Resultado: Se dibuja un pixel amarillo en la cuarta posición (Desplazado tres píxeles con respeto al pixel de la prueba 1)

- Valor 08 en C000
- Código máquina:
3E 08 32 00 c0 18 FE - Programa desensamblado:
ld a,#08
ld (#c000),a
jr #4005- Resultado: Se dibuja un pixel cyan en la primera posición (Misma posición que el pixel amarillo de la prueba 1)

Esta es la imagen ampliada

Y en este dibujo se comprueba que efectivamente es la misma posición que el pixel amarillo de la prueba 1

- Valor 04 en C000
- Código máquina:
3E 04 32 00 c0 18 FE - Programa desensamblado:
ld a,#04
ld (#c000),a
jr #4005-
Resultado: Se dibuja un pixel cyan en la segunda posición
-
Prueba 7
-
Valor 02 en C000
-
Código máquina:
3E 02 32 00 c0 18 FE -
Programa desensamblado:
ld a,#02
ld (#c000),a
jr #4005-
Resultado: Se dibuja un pixel cyan en la tercera posición
-
Prueba 8
-
Valor 01 en C000
-
Código máquina:
3E 01 32 00 c0 18 FE -
Programa desensamblado:
ld a,#01
ld (#c000),a
jr #4005- Resultado: Se dibuja un pixel cyan en la cuarta posición
Los resultados de las pruebas 5,6,7 y 8 se representan en esta figura:

Las posiciones son las mismas que en las pruebas 1,2,3 y 4, pero el pixel es cyan en vez de amarillo
TODO
Experimento 3: Localizar posiciones de memoria de las lineas
Experimento 4: Localizar posicion de memoria de la linea 2
Experimento 5: Pintar una bandera
Bandera:
ld A,#FF
ld (#C000),A
ld (#C800),A
ld A,#F0
ld (#D000),A
ld (#D800),A
ld (#E000),A
ld (#E800),A
ld A,#FF
ld (#F000),A
ld (#F800),A
Código máquina: 3E,FF,32,00,C0,32,00,C8,3E,F0,32,00,D0,32,00,D8,32,00,E0,32,00,E8,3E,FF,32,00,F0,32,00,F8,18,FE
-
Resumen: Para depurar nuestros programas utilizamos la ejecución paso a paso. Pulsando la tecla F7 hacemos que el procesador ejecuta una única instrucción y que se pare. Esto nos permite comprobar qué es lo que va sucediendo. Para editar nuestros programas en código máquina podemos hacer copy & paste en la memoria. No hay ninguna opción para hacerlo gráficamente. Hay que usar las típicas teclas de cortar y pegar: Ctr-C (Copiar), Ctr-V (Pegar), Ctrl-X (Cortar)
-
Programa inicial de pruebas: Se quiere sacar por la pantalla un total de 8 píxeles, por lo que hay que escribir dos valores, uno en la dirección C000 y otro en la C001. El programa inicial propuesto (que no funciona, pero que vamos a depurar) es este:
- Código máquina:
3E 88 3E 93 32 00 C0 18 FE - Programa desensamblado:
- Código máquina:
LD A, #88
LD A, #93
LD (#C000),A
JR #4007- Depuración: Al ejecutar el programa paso a paso vemos que el registro A se carga con el valor 88 y en el siguiente paso se escribe uno nuevo: 93, machacando el valro anterior. En la posición de memoria C000 se escribe por tanto sólo el valor 93
-
Solución: Lo que se quiere es que salgan 8 píxeles por lo que habrá que escribir el valor 88 en C000 y el valor 93 en C001. El número código (que ya funciona) es este:
- Código máquina:
3E 88 32 00 C0 3E 93 32 01 C0 18 FE - Programa desensamblado:
- Código máquina:
LD A, #88
LD (#C000),A
LD A, #93
LD (#C001),A
JR #400AY este es el resultado obtenido al ejecutarlo:

En esta imagen se pueden ver los píxeles ampliados:

-
En este reto hay que realizar 4 actividades:
- Actividad 1: Pinta el primer pixel en amarillo (¡OJO! Debe haber sólo un pixel, y tiene que ser el primero)
- Actividad 2: Pintar el mismo pixel en Cyan
- Actividad 3: Pintar el mismo pixel en Rojo
- Actividad 4: Pintar el mismo pixel en color del fondo (para que no se vea)
-
Truco: Para distinguir si el pixel pintado es el primero ponemos el borde negro utilizando este comando en basic
border 0
La pantalla nos quedará así:

Por los experimentos realizados en el vídeo 1.P04 y por los vídeos de teoría, sabemos que cada byte que se escribe en la memoria de video hay 4 pixeles codificados. Para cada pixel se usan 2 bits, lo que nos permite establecer 4 colores diferentes:
- 00: Color del fondo
- 01: Cyan
- 10: Amarillo
- 11: Rojo
Cada posición de memoria de vídeo la podemos representar como 2 nibbles (4 bits) uno encima de otro (el nibble superior encima). Cada Columna representa un pixel: P1, P2, P3 y P4. El que tenemos que pintar en este reto es el Pixel 1. Así por ejemplo, el valor 88 (que ya hemos usado y que sabemos que produce un color rojo) en binario es: 10001000. Y si lo dibujamos como nibbles tendría esta estructura:
| P1 | P2 | P3 | P4 |
|---|---|---|---|
| 1 | 0 | 0 | 0 |
| 1 | 0 | 0 | 0 |
| Rojo | Fondo | Fondo | Fondo |
- Objetivo: Pintar en amarillo el pixel P1
Para pintar en amarillo los dos bits del pixel 1 deben ser 10:
| P1 | P2 | P3 | P4 |
|---|---|---|---|
| 1 | 0 | 0 | 0 |
| 0 | 0 | 0 | 0 |
| Amarillo | Fondo | Fondo | Fondo |
Es decir, que hay que escribir el valor (binario) 10000000 en la posición C000. Este valor es 0x80 en hexadecimal
-
Codigo máquina:
3E 80 32 00 C0 18 FE - Programa desensamblado:
LD A,#80
LD (#C000),A
JR #4005
- Resultado:

En esta imagen está ampliado:

- Objetivo: Pintar en cyan el pixel P1
Para pintar en cyan los dos bits del pixel 1 deben ser 01:
| P1 | P2 | P3 | P4 |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 1 | 0 | 0 | 0 |
| Cyan | Fondo | Fondo | Fondo |
Es decir, que hay que escribir el valor (binario) 00001000 en la posición C000. Este valor es 0x08 en hexadecimal
-
Codigo máquina:
3E 08 32 00 C0 18 FE - Programa desensamblado:
LD A,#08
LD (#C000),A
JR #4005
- Resultado:

En esta imagen está ampliado:

- Objetivo: Pintar en rojo el pixel P1
- Codificación del byte
| P1 | P2 | P3 | P4 |
|---|---|---|---|
| 1 | 0 | 0 | 0 |
| 1 | 0 | 0 | 0 |
| Rojo | Fondo | Fondo | Fondo |
- Valor binario: 10001000
- Valor hexadecimal: 88
-
Codigo máquina:
3E 88 32 00 C0 18 FE - Programa desensamblado:
LD A,#88
LD (#C000),A
JR #4005
- Resultado:


- Objetivo: Pintar el Pixel 1 de color del fondo
- Codificación del byte
| P1 | P2 | P3 | P4 |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 0 | 0 | 0 | 0 |
| Rojo | Fondo | Fondo | Fondo |
- Valor binario: 00000000
- Valor hexadecimal: 00
-
Codigo máquina:
3E 00 32 00 C0 18 FE - Programa desensamblado:
LD A,#00
LD (#C000),A
JR #4005
- Resultado:

Para probarlo primero hay que ejecutar alguno de los programas anteriores, y a continuación este, que borrará el pixel 1
-
Resumen: Introducción de dos nuevas instrucciones en código máquina: 21 y 22, que permite usar el registro HL de 16 bits tanto para almacenar un valor en él como para guardarlo en dos posiciones de memoria
-
Instrucción 21:
LD HL, #### -
Instrucción 22:
LD (####),HL
-
Instrucción 21:
Este ejemplo almacena los valores 88 en C000 y 88 en C001 lo que provoca que aparezcan dos píxeles rojos. El resto de píxeles tienen el color de fondo (en cada byte tenemos codificados 4 píxeles)
-
Código máquina:
21 88 88 22 00 C0 18 FE - Programa desensamblado:
LD HL,#8888
LD (#C0000),HL
JR #4006
- Resultado: Aparecen dos píxeles rojos separados por 3 píxeles


| Instrucción | Código máquina | Tamaño | Descripción |
|---|---|---|---|
| LD A, ## | 3E ## | 2 bytes | Cargar un valor en el registro A |
| LD (####),A | 32 ## ## | 3 bytes | Almacenar A en la posición de memoria indicada |
| LD HL, #### | 21 ## ## | 3 bytes | Cargar un valor en el registro HL |
| LD (####),HL | 22 ## ## | 3 bytes | Almacenar HL en las posiciones #### y #### + 1 |
| JR ## | 18 FE | 2 bytes | Bucle infinito |
En este reto hay 5 actividades. Hay que pintar píxeles de varios colores
Los 4 primeros píxeles hay que ponerlos todos de color rojo
- Codificación del byte
| P1 | P2 | P3 | P4 |
|---|---|---|---|
| 1 | 1 | 1 | 1 |
| 1 | 1 | 1 | 1 |
| Rojo | rojo | rojo | rojo |
- Valor binario: 11111111
- Valor hexadecimal: FF
-
Código máquina:
3E FF 32 00 C0 18 FE - Programa desensamblado:
LD A, #FF
LD (#C000),A
JR #4005
- Resultado:


- Descripción: Dibujar 24 pixeles en total, en grupos de 4, usando todos los colores. Pero todos los píxeles del grupo deben ser del mismo color
- Bonus: Usar la instrucción 21
Dado que los 4 píxeles ocupan un byte, tendremos en total 24/4 = 6 bytes. Hay que escribir información en las posiciones de memoria C000 - C005
Los valores a escribir para pintar 4 píxeles del mismo color son:
- 4 pixeles rojos: 0xFF (Actividad anterior)
- 4 pixeles cyan: 0x0F
| P1 | P2 | P3 | P4 |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 1 | 1 | 1 | 1 |
| Cyan | Cyan | Cyan | Cyan |
- 4 pixeles amarillos: 0xF0
| P1 | P2 | P3 | P4 |
|---|---|---|---|
| 1 | 1 | 1 | 1 |
| 0 | 0 | 0 | 0 |
| Amarillo | Amarillo | Amarillo | Amarillo |
- Patrón de 24 píxeles: El patrón que voy a utilizar es Cyan-amarillo-Cyan-Rojo-Amarillo-Rojo. Por tanto los valores a escribir en la memoria son los siguientes:
| C000 | C001 | C002 | C003 | C004 | C005 |
|---|---|---|---|---|---|
| cyan | Amarillo | Cyan | Rojo | Amarillo | Rojo |
| 0F | F0 | 0F | FF | F0 | FF |
- Código máquina:
21 0F F0 22 00 C0 21 0F FF 22 02 C0 21 F0 FF 22 04 C0 18 FE - Programa desensamblado:
LD HL,F00F
LD (C000),HL
LD HL,FF0F
LD (C002),HL
LD HL,FFF0
LD (C004),HL
JR #4012
- Resultado:

- Descripción: Dibujar 12 pixeles en total, en grupos de 2, usando todos los colores. Pero todos los píxeles del grupo deben ser del mismo color
- Bonus: Usar las instrucciones 3E y 21
- Patrón de 12 píxeles a mostrar: El mismo de antes, pero con grupos de 2 pixeles: cyan-amarillo-cyan-rojo-amarillo-rojo
Como ahora son 12 píxeles, y hay 4 pixeles en un byte, necesitamos en total 12/4 = 3 bytes. Vamos a ver la codificación necesaria:
| C000 | C001 | C002 |
|---|---|---|
| P1 P2 P3 P4 | P1 P2 P3 P4 | P1 P2 P3 P4 |
| Cyan Amarillo | cyan rojo | amarillo rojo |
| 0 0 1 1 | 0 0 1 1 | 1 1 1 1 |
| 1 1 0 0 | 1 1 1 1 | 0 0 1 1 |
A partir de esta tabla, sacamos los bytes a guardar en cada una de las posiciones:
| C000 | C001 | C002 |
|---|---|---|
| 3C | 3F | F3 |
-
Código máquina:
3E 3C 32 00 C0 3E 3F 32 01 C0 3E F3 32 02 C0 18 FE - Programa desensamblado:
LD A,#3C
LD (#C000),A
LD A,#3F
LD (#C001),A
LD A,#F3
LD (#C002),A
JR #400F
- Resultado:


-
BONUS:
-
Código máquina:
3E 3C 32 00 C0 21 3F F3 22 01 C0 18 FE -
Programa desensamblado:
ld a,#3C
ld (#C000),A
ld HL, #F33F
ld (#c100),HL
JR #400B
- Descripción: Dibujar 8 pixeles en total usando todos los colores
- Patrón de 8 píxeles a mostrar: cyan-amarillo-cyan-rojo-amarillo-rojo-cyan-amarilllo
Como ahora son 8 píxeles, y hay 4 pixeles en un byte, necesitamos en total 8/4 = 2 bytes. Vamos a ver la codificación necesaria:
| C000 | C001 |
|---|---|
| P1 P2 P3 P4 | P1 P2 P3 P4 |
| C A C R | A R C A |
| 1 0 1 1 | 0 1 1 0 |
| 0 1 0 1 | 1 1 0 1 |
| Valor: 5B | Valor: D6 |
-
Código máquina:
3E 5B 32 00 C0 3E D6 32 01 C0 18 FE - Código desensamblado:
ld a,#5B
ld (#c000),A
ld a,#D6
ld (#c001),A
jr #400a
- También se puede hacer con el registro HL. Código máquina:
21 5B D6 22 00 C0 18 FE - Desensamblado
ld HL,#D65B
ld (#c000),HL
jr #4006
- Resultado:


- Patrón de 80 bits a pintar: RRRRRRRR-AAAAAAAA-CCCCCCCC-RRRR-AAAA-CCCC-RR-AA-CC-F-RR-F-AA-F-CC-F-R-F-A-F-C-FF-R-FF-A-FF-C-FFFR-FFF-A-FFF-C-F-R
En total hay 80 píxeles --> 20 bytes. Desde la dirección C000 hasta C013
| C000 | C001 | C002 | C003 | C004 | C005 | C006 | C007 | C008 | C009 | Cantidad |
|---|---|---|---|---|---|---|---|---|---|---|
| RRRR | RRRR | AAAA | AAAA | CCCC | CCCC | RRRR | AAAA | CCCC | RRAA | 40 pixeles |
| FF | FF | F0 | F0 | 0F | 0F | FF | F0 | 0F | FC | 10 bytes |
| C00A | C00B | C00C | C00D | C00E | C00F | C010 | C011 | C012 | C013 | Cantidad |
|---|---|---|---|---|---|---|---|---|---|---|
| CCFR | RFAA | FCCF | RFAF | CFFR | FFAF | FCFF | FRFF | FAFF | FCFR | 40 pixeles |
| 1D | B8 | CC | CD | 19 | 20 | 04 | 44 | 40 | 15 | 10 bytes |
-
Código máquina:
21 FF FF 22 00 C0 21 F0 F0 22 02 C0 21 0F 0F 22 04 C0 21 FF F0 22 06 C0 21 0F FC 22 08 C0 21 1D B8 22 0A C0 21 06 A8 22 0C C0 21 19 20 22 0E C0 21 04 44 22 10 C0 21 40 15 22 12 C0 18 FE -
Programa desensamblado:
ld hl,#FFFF
ld (#c000),hl
ld hl,#F0f0
ld (#c002),hl
ld hl,#0f0f
ld (#c004),hl
ld hl,#f0ff
ld (#c006),hl
ld hl,#fc0f
ld (#c008),hl
ld hl,#b81d
ld (#c00a),hl
ld hl,#a806
ld (#c00c),hl
ld hl,#2019
ld (#c00e),hl
ld hl,#4404
ld (#c010),hl
ld hl,#1540
ld (#c012),hl
JR #403C
- Resultado:


- La memoria de vídeo es de 16K, y va desde las direcciones C000 hasta la FFFF
- La pantalla tiene un acho de 320 píxeles. Cada línea son 80 bytes (80 * 4 = 320)
- Por tanto, la primera posición es la C000 y la última de esa línea es C000 + (80 - 1). El valor 80 es 50 en hexadecimal así que los últimos 4 píxeles de la primera línea están en C04F
- La segunda línea empieza en C050 y llega hasta C09F
- La siguiente en pieza en C0A0 y llega hasta C0EF
Para ir la posición central hay que escribir en los bytes 39 y 40 (que en hexadecimal son 27 y 28). Para llegar al centro sólo hay que sumar a la posición de memoria del extremo izquierdo de la línea el valor 0x27 y pintar 8 píxeles
Este programa imprime los 4 primeros píxeles y los 4 últimos pixeles de las líneas 1, 2 y 3. Además, pone 8 píxeles en el centro de cada una de ellas
-
Código máquina:
3E FF 32 00 C0 32 4F C0 32 50 C0 32 9F C0 32 A0 C0 32 EF C0 21 FF FF 22 27 C0 22 77 C0 22 C7 C0 18 FE - Programa desensamblado:
la A, #ff
ld (#c000),A
ld (#c04F),A
ld (#c050),A
ld (#c09F),A
ld (#c0A0),A
ld (#c0EF),A
ld hl,#ffff
ld (#c027),hl
ld (#c077),hl
ld (#c0c7),hl
jr #4020
- Resultado:

- En este reto hay 4 actividades:
- Actividad 1: Pintar un pixel rojo en una posición concreta de la pantalla, entre dos letras
- Actividad 2: Pintar tres pixeles de colores diferentes en la misma fila y debajo de 3 letras
- Actividad 3: Pintar cinco píxeles de distintos colores formando una columna
- Actividad 4: Pintar tres columnas de 4 píxeles cada una, en distintos bytes
- Posición a pintar: En la primera línea de la frase "Amstrad Microcomputer", entre las letras M e i
Contando caracteres vemos que está en la segunda file (empieza en C050) y hasta la M hay 10 caracteres. Como cada caracter tiene 8 pixeles, en total hay 80 píxeles --> 80/4 = 20 bytes. La posición es C050 + 0x14 = C064 (0x14 es 20)
En la posición 0xC064 escribimos por ejemplo el valor 0x44
-
Código máquina:
3E 44 32 64 C0 18 FE - Programa desensamblado:
ld A,#44
ld (#C064),A
JR #4005
- Resultado:


-
Posición a pintar: Debajo de las letras e, a y d de
Ready
Contando caracteres con el cursos, el primero punto está en el carácter (x,y)=(1,11). La cuenta a realizar es C000 + 80*11. Con esto llegamos a la línea debajo de R. Para llegar a la 3 hay 12 píxeles hasta la mitad, pero nos vamos al otro byte, por lo que sumamos 3. La posición final es:
-
Punto rojo debajo de
e: Dirección: 0xC000 + 11*80 + 3 = 0xC373 -
Punto amarillo debajo de a: Sumamos 1 byte: 0xC374
-
Punto cyan debajo de d: Sumamos 2 bytes: 0xC376
-
Código máquina:
3E 88 32 73 C3 3E 10 32 74 C3 3E 01 32 76 C3 18 FE -
Programa desensamblado:
ld A,#88
ld (#C373),A
ld A,#10
ld (#c374),A
ld A,#01
ld (#c376),A
JR #400F
- Resultado:


- Posición de partida: 0xC0FC
Para pasar a la línea de abajo hay que sumar 0x800. Dirección pixel inferior: 0xC0FC + 0x800 = 0xC8FC
Línea 3: 0xC0FC + 2 * 0x800 = 0xC0FC + 0x1000 = D0FC
Linea 4: 0xC0FC + 3 * 0x800 = D8FC
Línea 5: 0xC0FC + 4 * 0x800 = E0FC
-
Código máquina:
3E 11 32 FC C0 32 FC C8 3E 10 32 FC D0 32 FC D8 3E 01 32 FC E0 18 FE - Programa desensamblado:
ld A,#11
ld (#c0fc),A
ld (#c8fc),A
ld A,#10
ld (#D0fc),A
ld (#D8fc),A
ld A,#01
ld (#E0fc),A
JR #4015
- Resultado:


-
Los patrones de las columnas son estos (en veritcal):
- Columna 1: CACRA
- Columna 2: RRARR
- Columna 3: CCACC
-
Posición: A continuación de
BASIC 1.1. Posición en caracteres: (10,8) -
Posición inicial en memoria: 0xC0000 + 8 * 80 + 10 * 2 + 1 = 0xC295
-
Resto de posiciones:
- Linea 1: 0xC295
- Línea 2: 0xC295 + 0x800 = 0xCA95
- Línea 3: 0xC295 + 0x800*2 = 0xd295
- Línea 4: 0xC295 + 0x800*3 = 0xDA95
- Línea 5: 0xC295 + 0x800*4 = 0xE295
| Col1 | valor | Col2 | valor | Col3 | valor |
|---|---|---|---|---|---|
| 0xC295 | 08 | 0xC296 | 11 | 0xC298 | 04 |
| 0xCA95 | 80 | 0xCA96 | 11 | 0xCA98 | 04 |
| 0xD295 | 08 | 0xD296 | 10 | 0xD298 | 40 |
| 0xDA95 | 88 | 0xDA96 | 11 | 0xDA98 | 04 |
| 0xE295 | 80 | 0xE296 | 11 | 0xE298 | 04 |
-
Código máquina:
3E 08 32 95 C2 3E 80 32 95 CA 3E 08 32 95 D2 3E 88 32 95 DA 3E 80 32 95 E2 3E 11 32 96 C2 3E 11 32 96 CA 3E 10 32 96 D2 3E 11 32 96 DA 3E 11 32 96 E2 3E 04 32 98 C2 3E 04 32 98 CA 3E 40 32 98 D2 3E 04 32 98 DA 3E 04 32 98 E2 18 FE - Programa desensamblado:
ld a,#08
ld (#C295),a
ld a,#80
ld (#CA95),a
ld a,#08
ld (#D295),a
ld a,#88
ld (#DA95),a
ld a,#80
ld (#E295),a
ld a,#11
ld (#C296),a
ld a,#11
ld (#CA96),a
ld a,#10
ld (#D296),a
ld a,#11
ld (#DA96),a
ld a,#11
ld (#E296),a
ld a,#04
ld (#C298),a
ld a,#04
ld (#CA98),a
ld a,#40
ld (#D298),a
ld a,#04
ld (#DA98),a
ld a,#04
ld (#E298),a- Resultado:


En este reto hay 4 actividades
- Actividad 1: Filas de colores
- Actividad 2: Subrayado de Ready con filas de colores
- Actividad 3: Rectángulo alrededor de la versión de Basic
- Actividad 4: Dibujar un dado
-
Descripcíon: Dibujar en el carácter de la esquina superior izquierda 8 filas de 4 píxeles (4x8), de diferentes colores
-
El patrón de líneas a dibujar es el siguiente: CFRARFCA
-
Valores a almacenar en las diferentes direcciones
| Linea | Dir | Color | Valor |
|---|---|---|---|
| 1 | C000 | Cyan | 0F |
| 2 | C800 | Fondo | 00 |
| 3 | D000 | Rojo | FF |
| 4 | D800 | Amar | F0 |
| 5 | E000 | Rojo | FF |
| 6 | E800 | Fondo | 00 |
| 7 | F000 | Cyan | 0F |
| 8 | F800 | Amar | F0 |
-
Código máquina:
3E 0F 32 00 C0 3E 00 32 00 C8 3E FF 32 00 D0 3E F0 32 00 D8 3E FF 32 00 E0 3E 00 32 00 E8 3E 0F 32 00 F0 3E F0 32 00 F8 18 FE -
Programa desensamblado:
ld a,#0F
ld (#C000),a
ld a,#00
ld (#C800),a
ld a,#FF
ld (#D000),a
ld a,#F0
ld (#D800),a
ld a,#FF
ld (#E000),a
ld a,#00
ld (#E800),a
ld a,#0F
ld (#F000),a
ld a,#F0
ld (#F800),a
- Resultado:


-
Descripcíon: Dibujar 8 filas de 40 pixeles (40x8) debajo de la palabra "Ready", en diferentes colores
-
El patrón de líneas a dibujar es el siguiente: CFRARFCA (Mismo que en la actividad anterior)
-
Posición inicial: El carácter está en la posición 11, por tanto la memoria inicial es: 0xC0000 + 11 * 80 = 0xC370
Esta es la tabla con los primeros 4 pixeles de las 8 líneas.
| Linea | Dir | Color | Valor |
|---|---|---|---|
| 1 | C370 | Cyan | 0F |
| 2 | CB70 | Fondo | 00 |
| 3 | D370 | Rojo | FF |
| 4 | DB70 | Amar | F0 |
| 5 | E370 | Rojo | FF |
| 6 | EB70 | Fondo | 00 |
| 7 | F370 | Cyan | 0F |
| 8 | FB70 | Amar | F0 |
En total son 40 pixeles --> 40/4 = 10 Bytes. Desde la dirección base hasta base + 9. Haciendo escrituras de 16 bits, necesitamos 5 operaciones (instrucciones 21 y 22) por línea en las direcciones base + 0, +2, +4, +6, +8
-
Código máquina:
21 0F 0F 22 70 C3 22 72 C3 22 74 C3 22 76 C3 22 78 C3 21 00 00 22 70 CB 22 72 CB 22 74 CB 22 76 CB 22 78 CB 21 FF FF 22 70 D3 22 72 D3 22 74 D3 22 76 D3 22 78 D3 21 F0 F0 22 70 DB 22 72 DB 22 74 DB 22 76 DB 22 78 DB 21 FF FF 22 70 E3 22 72 E3 22 74 E3 22 76 E3 22 78 E3 21 00 00 22 70 EB 22 72 EB 22 74 EB 22 76 EB 22 78 EB 21 0F 0F 22 70 F3 22 72 F3 22 74 F3 22 76 F3 22 78 F3 21 F0 F0 22 70 FB 22 72 FB 22 74 FB 22 76 FB 22 78 FB 18 FE -
Programa desensamblado:
ld HL,#0F0F
ld (#C370),HL
ld (#C372),HL
ld (#C374),HL
ld (#C376),HL
ld (#C378),HL
ld HL,#0000
ld (#CB70),HL
ld (#CB72),HL
ld (#CB74),HL
ld (#CB76),HL
ld (#CB78),HL
ld HL,#FFFF
ld (#D370),HL
ld (#D372),HL
ld (#D374),HL
ld (#D376),HL
ld (#D378),HL
ld HL,#F0F0
ld (#DB70),HL
ld (#DB72),HL
ld (#DB74),HL
ld (#DB76),HL
ld (#DB78),HL
ld HL,#FFFF
ld (#E370),HL
ld (#E372),HL
ld (#E374),HL
ld (#E376),HL
ld (#E378),HL
ld HL,#0000
ld (#EB70),HL
ld (#EB72),HL
ld (#EB74),HL
ld (#EB76),HL
ld (#EB78),HL
ld HL,#0F0F
ld (#F370),HL
ld (#F372),HL
ld (#F374),HL
ld (#F376),HL
ld (#F378),HL
ld HL,#F0F0
ld (#FB70),HL
ld (#FB72),HL
ld (#FB74),HL
ld (#FB76),HL
ld (#FB78),HL
- Resultado:


-
Descripción: Rectángulo en 2 colores de 2 píxeles de ancho sin modificar el texto 1.1
-
Bonus: Programa más corto
-
Línea horizontal superior: La dirección base la calculamos así: 0xC000 + 80 * 7 + 7*2 = 0xC23E. Es la dirección de la primera fila del caracter encima del primer 1. Sobre esta dirección base hay que obtener la dirección de la líena 7 del carácter: 0xC23E + 0x800 * 7 =
0xFA3e. Y la anterior es: 0xF23E
La línea debe tener una longitud de 3 caracteres: 3*8 = 24 píxeles. Es decir, 6 bytes. Para que el programa sea lo más corto posible (Bonus) utilizamos las instrucciones 21 y 22
El código máquina para dibujar las dos líneas superiores es: 21 FF FF 22 3E FA 22 40 FA 22 42 FA 22 3E F2 22 40 F2 22 42 F2 18 FE
- Línea horizontal inferior: Dirección base: 0xC000 + 80 * 9 + 7*2 (Dos caracteres más abajo) = 0xC2DE. La siguiente línea es: 0xC2DE + 0x800 = 0xCADE
Código máquina: 22 DE C2 22 E0 C2 22 E2 C2 22 DE CA 22 E0 CA 22 E2 CA
-
Línea vertical izquierda: Dirección base: 0xC000 + 80 * 8 + 6*2 + 1 = 0xC28D Líneas inferiores en direcciones 0xCA8D, 0xD28D, 0xDA8D, 0xE28D, 0xEA8D, 0xF28D, 0xFA8D
-
Esquina superior izquierda: En el byte encima de la línea izquierda hay que escribir 2 líneas de 2 pixeles. Las direcciones son: 0xC000 + 80 * 7 + 62 + 1 + 0x8006 = 0xF23D y 0xFA3D (0xF23D + 0x800)
-
Esquina inferior izquierda: La dirección base es la de la línea vertical izquierda más 0x800: 0xC28D + 80 = 0xC2DD. La otra es 0xC2DD + 0x800 = 0xCADD
El código máquina es el siguiente. Primero Metemos los dos bytes de la esquina superior izquierda:
3E 03 32 3D F2 32 3D FA
Ahora añadimos la línea vertical:
32 8D C2 32 8D CA 32 8D D2 32 8D DA 32 8D E2 32 8D EA 32 8D F2 32 8D FA
Y la esquina inferior izquierda:
32 DD C2 32 DD CA
-
Código máquina línea vertical izquierda:
3E 03 32 3D F2 32 3D FA 32 8D C2 32 8D CA 32 8D D2 32 8D DA 32 8D E2 32 8D EA 32 8D F2 32 8D FA 32 DD C2 32 DD CA 18 FE
- La esquina superior derecha tiene la dirección base de la esquina superior izquierda + 4 caracteres (7 bytes). Por tanto las direcciones son: 0xF23D y 0xFA3D a las que les sumamos 8 bytes: 0xFA44 y 0xF244
3E 0C 32 44 FA 32 44 F2
- La línea vertical derecha tiene como dirección base la misma que la izquierda + 7 bytes: 0xC28D + 7 = 0xC294. Las siguientes son esta más los 0x800: CA94, D294, DA94, E294, EA94, F294, FA94
32 94 C2 32 94 CA 32 94 D2 32 94 DA 32 94 E2 32 94 EA 32 94 F2 32 94 FA
- La esquina inferior derecha tiene las direcciones base: 0xC2DD y 0xCADD a las que se le suman 7 bytes: C2E4 y CAE4
32 E4 C2 32 E4 CA
- Código máquina para dibujar la línea vertical derecha:
3E 0C 32 44 FA 32 44 F2 32 94 C2 32 94 CA 32 94 D2 32 94 DA 32 94 E2 32 94 EA 32 94 F2 32 94 FA 32 E4 C2 32 E4 CA
-
Código máquina final:
3E 03 32 3D F2 32 3D FA 32 8D C2 32 8D CA 32 8D D2 32 8D DA 32 8D E2 32 8D EA 32 8D F2 32 8D FA 32 DD C2 32 DD CA 3E 0C 32 44 FA 32 44 F2 32 94 C2 32 94 CA 32 94 D2 32 94 DA 32 94 E2 32 94 EA 32 94 F2 32 94 FA 32 E4 C2 32 E4 CA 21 FF FF 22 3E FA 22 40 FA 22 42 FA 22 3E F2 22 40 F2 22 42 F2 22 DE C2 22 E0 C2 22 E2 C2 22 DE CA 22 E0 CA 22 E2 CA 18 FE -
Programa desensamblado:
LD A,#03
LD (#F23D),A
LD (#FA3D),A
LD (#C28D),A
LD (#CA8D),A
LD (#D28D),A
LD (#DA8D),A
LD (#E28D),A
LD (#EA8D),A
LD (#F28D),A
LD (#FA8D),A
LD (#C2DD),A
LD (#CADD),A
LD A,#0C
LD (#FA44),A
LD (#F244),A
LD (#C294),A
LD (#CA94),A
LD (#D294),A
LD (#DA94),A
LD (#E294),A
LD (#EA94),A
LD (#F294),A
LD (#FA94),A
LD (#C2E4),A
LD (#CAE4),A
LD HL,#FFFF
LD (#FA3E),HL
LD (#FA40),HL
LD (#FA42),HL
LD (#F23E),HL
LD (#F240),HL
LD (#F242),HL
LD (#C2DE),HL
LD (#C2E0),HL
LD (#C2E2),HL
LD (#CADE),HL
LD (#CAE0),HL
LD (#CAE2),HL
JR #4073
- Resultado:


- Descripción: Dibujar un dado de 8x7 (8 pixeles de ancho y 7 de alto) en el centro de la pantalla. El número del dado puede ser cualquiera. Yo eligo el 5
- Bonus: Programa más corto
La pantalla del amstrad tiene 40x25 caracteres. Cada caracter son de 8x8. Por tanto, la pantalla (en este modo) tiene 320 x 200 píxeles
En coordenadas de carácter, el centro está en las posiciones x = 19, x=20, y=13. Utilizamores por tanto estas dos posiciones de caracter para pintar el pixel: (19,13) y (20,13)
La dirección base del byte superior izquierdo está dado por: `Base = 0xC000 + (y-1)*80 + (x-1)*2' + 1 = 0xC3E5
El script en python es este:
x,y = 19,13
base = 0xC000 + (y-1)*80 + (x-1)*2 + 1
print(hex(base))Tabla con las direcciones a rellenar
| Linea | Dir | Valor |
|---|---|---|
| 1 | C3E5 | F0F0 |
| 2 | CBE5 | F6F6 |
| 3 | D3E5 | F0F0 |
| 4 | DBE5 | F1F8 |
| 5 | E3E5 | F0F0 |
| 6 | EBE5 | F6F6 |
| 7 | F3E5 | F0F0 |
Las direcciones se pueden calcular con este script en python:
[hex(base + 0x800*i) for i in range(7)]El código máquina se calcula fácilmente así. Cada línea deposita un valor en su dirección correspondiente:
21 F0 F0 22 E5 C3
21 F6 F6 22 E5 CB
21 F0 F0 22 E5 D3
21 F1 F8 22 E5 DB
21 F0 F0 22 E5 E3
21 F6 F6 22 E5 EB
21 F0 F0 22 E5 F3
-
Código máquina:
21 F0 F0 22 E5 C3 21 F6 F6 22 E5 CB 21 F0 F0 22 E5 D3 21 F1 F8 22 E5 DB 21 F0 F0 22 E5 E3 21 F6 F6 22 E5 EB 21 F0 F0 22 E5 F3 18 FE -
Programa desensamblado:
LD HL,#F0F0
LD (#C3E5),HL
LD HL,#F6F6
LD (#CBE5),HL
LD HL,#F0F0
LD (#D3E5),HL
LD HL,#F8F1
LD (#DBE5),HL
LD HL,#F0F0
LD (#E3E5),HL
LD HL,#F6F6
LD (#EBE5),HL
LD HL,#F0F0
LD (#F3E5),HL
JR #402A
- Resultado:


-
Desafío: Pintar un sprite de 16x16 en el centro de la pantalla usando todos los colores
-
Dirección base: Base = 0xC000 + (y-1)*80 + (x-1)*2' =
0xC3E4
Como el sprinte es de 16x16 píxeles, tendremos por cada línea 16/4 = 4 bytes. Hay que hacer 2 escriburas de 16 bits para cada fila. En total hay 16 filas. El script para calcular las direcciones es este:
[hex(base + 0x800*i) for i in range(8)] | Linea | Dir | Valor1 | Dir | Valor 2 |
|---|---|---|---|---|
| 1 | C3E4 | 00 00 | C3E6 | 00 00 |
| 2 | CBE4 | 00 00 | CBE6 | 00 00 |
| 3 | D3E4 | 00 00 | D3E6 | 07 00 |
| 4 | DBE4 | 00 00 | DBE6 | 0F 00 |
| 5 | E3E4 | 00 01 | E3E6 | 0F 00 |
| 6 | EBE4 | 00 03 | EBE6 | 0B 00 |
| 7 | F3E4 | 00 07 | F3E6 | 03 00 |
| 8 | FBE4 | 00 02 | FBE6 | 03 00 |
La dirección base de la parte inferior es C3E4 + 80 = C434. Aplicando el script anterior obtenemos las direcciones: c434, cc34, d434, dc34, e434, ec34, f434, fc34
| Linea | Dir | Valor1 | Dir | Valor 2 |
|---|---|---|---|---|
| 9 | C434 | 60 00 | C436 | 03 00 |
| 10 | CC34 | 10 80 | CC36 | 03 00 |
| 11 | D434 | 00 00 | D436 | 03 00 |
| 12 | DC34 | 70 80 | DC36 | 33 00 |
| 13 | E434 | 00 00 | E436 | 44 88 |
| 14 | EC34 | 10 80 | EC36 | 44 44 |
| 15 | F434 | 60 10 | F436 | 88 44 |
| 16 | FC34 | 00 10 | FC36 | 00 60 |
-
Código máquina:
21 00 00 22 E4 C3 22 E6 C3 22 E4 CB 22 E6 CB 22 E4 D3 21 07 00 22 E6 D3 21 00 00 22 E4 DB 21 0F 00 22 E6 DB 21 00 01 22 E4 E3 21 0F 00 22 E6 E3 21 00 03 22 E4 EB 21 0B 00 22 E6 EB 21 00 07 22 E4 F3 21 03 00 22 E6 F3 21 00 02 22 E4 FB 21 03 00 22 E6 FB 21 60 00 22 34 C4 21 03 00 22 36 C4 21 10 80 22 34 CC 21 03 00 22 36 CC 21 00 00 22 34 D4 21 03 00 22 36 D4 21 70 80 22 34 DC 21 33 00 22 36 DC 21 00 00 22 34 E4 21 44 88 22 36 E4 21 10 80 22 34 EC 21 44 44 22 36 EC 21 60 10 22 34 F4 21 88 44 22 36 F4 21 00 10 22 34 FC 21 00 60 22 36 FC 18 FE -
Programa desensamblado:
LD HL,#0000
LD (#C3E4),HL
LD (#C3E6),HL
LD (#CBE4),HL
LD (#CBE6),HL
LD (#D3E4),HL
LD HL,#0007
LD (#D3E6),HL
LD HL,#0000
LD (#DBE4),HL
LD HL,#000F
LD (#DBE6),HL
LD HL,#0100
LD (#E3E4),HL
LD HL,#000F
LD (#E3E6),HL
LD HL,#0300
LD (#EBE4),HL
LD HL,#000B
LD (#EBE6),HL
LD HL,#0700
LD (#F3E4),HL
LD HL,#0003
LD (#F3E6),HL
LD HL,#0200
LD (#FBE4),HL
LD HL,#0003
LD (#FBE6),HL
LD HL,#0060
LD (#C434),HL
LD HL,#0003
LD (#C436),HL
LD HL,#8010
LD (#CC34),HL
LD HL,#0003
LD (#CC36),HL
LD HL,#0000
LD (#D434),HL
LD HL,#0003
LD (#D436),HL
LD HL,#8070
LD (#DC34),HL
LD HL,#0033
LD (#DC36),HL
LD HL,#0000
LD (#E434),HL
LD HL,#8844
LD (#E436),HL
LD HL,#8010
LD (#EC34),HL
LD HL,#4444
LD (#EC36),HL
LD HL,#1060
LD (#F434),HL
LD HL,#4488
LD (#F436),HL
LD HL,#1000
LD (#FC34),HL
LD HL,#6000
LD (#FC36),HL
JR #40B4
- Resultado:


El Sprite creado es un bit a 1 corriendo, inspirado en la constante bit 1 utilizada en los bloques de la colección iceK de Icestudio
¡¡NIVEL COMPLETADO!! 😀️











