Que empecé a programar para cpc. He publicado dos juegos. Y ahora voy a empezar otro en c.
viernes, 18 de noviembre de 2022
martes, 23 de agosto de 2022
Automodificable
Ld a,#5;;1
Ld (valor), a
Ld a,#6;;2
Ld (valor),a
Valor=.+1
Ld a,#0
;; En primer caso, valor es 1
;;En segundo caso, valor es 2
sábado, 26 de junio de 2021
Subo a github
Intento tener el programa o juego en GitHub. Es lo más fácil que conozco para intercambiarlo.
jueves, 24 de junio de 2021
Más rápido comparar con 0?
Me pregunto , supongamos el caso de una entidad, con posición x, igual a 4.
Le vamos restando una unidad. Cuando llegue a 0, impedimos que se reste más, antes o en esta comprobación.
Si x llega a -1, se pone a 0. En un número U8(sin signo), esto no es posible.
En tal caso, en ensamblador¿ sería más óptimo comparar con 0(jz) o con Carry(JC).?
miércoles, 23 de junio de 2021
Ahora,en C
viernes, 12 de febrero de 2021
ECS mejorado en Ensamblador para CPC
Esta vez pongo un pequeño programa, como base para le expansion de un ECS. Esta creado en ensamblador. tiene pocos comentarios, espero os sirva.
.module cpct_functions.h.s
.globl cpct_disableFirmware_asm
.globl cpct_waitVSYNC_asm
.globl cpct_scanKeyboard_f_asm
.globl cpct_isKeyPressed_asm
.globl cpct_setVideoMode_asm
.globl cpct_drawSolidBox_asm
.globl cpct_getScreenPtr_asm
.globl cpct_drawSprite_asm
.module main.s
.include "cpctelera.h.s"
.include "cpct_functions.h.s"
.include "man/game.h.s"
.area _DATA
.area _CODE
_main::
;;desactiva firmware
call cpct_disableFirmware_asm
;;init game manager
call man_game_init
;loop forever
loop:
call man_game_update
;waitNVsyncs 2
call cpct_waitVSYNC_asm
call man_game_render
jr loop
martes, 8 de diciembre de 2020
creacion de entidades con un ECS usando CPCTelera
pequeñito ejemplo de como, usndo en entity component system (ECS), se crean dos entidades distintas, y se pintan en pantalla.
;;main.s
;; ejemplo de dibujado simple de cuadrados
.module main.s
.include "cpctelera.h.s"
.area _DATA
.area _CODE
;;declaracion de globales
.globl cpct_disableFirmware_asm
.globl cpct_getScreenPtr_asm
.globl cpct_drawSolidBox_asm
.globl cpct_waitVSYNC_asm
.globl entityman_create
.globl rendersys_update
.globl _entity_array
.globl _num_entities
.globl entityman_getEntityArray_IX
.globl rendersys_init
.globl entityman_getNumEntities_A
;;declaracion de etiquetas,constantes
;;x,y,ancho,alto,color,velocidad x,vy
player: .db 20,20,04,16,0xff,0,0
enemy: .db 30,30,06,16,0xf0,0,0
;;principal
_main::
;; Disable firmware to prevent it from interfering with string drawing
call cpct_disableFirmware_asm
;;INIT SYSTEMS
call rendersys_init
ld hl,#player
call entityman_create
ld hl,#enemy
call entityman_create
loop:
call entityman_getEntityArray_IX
call entityman_getNumEntities_A
call rendersys_update
jr loop
parate:
jp parate
domingo, 6 de diciembre de 2020
Dibujo cuadrado
rutina para dibujar unos sencillos cuadrados, incrementando x e y en 1 a cada paso
;;
;; ejemplo de dibujado simple de cuadrados
.module main.s
.include "cpctelera.h.s"
.area _DATA
.area _CODE
;;declaracion de globales
.globl cpct_disableFirmware_asm
.globl cpct_getScreenPtr_asm
.globl cpct_drawSolidBox_asm
.globl cpct_waitVSYNC_asm
;;declaracion de etiquetas,constantes
x: .db #20
y: .db #12
;;principal
_main::
;; Disable firmware to prevent it from interfering with string drawing
call cpct_disableFirmware_asm
;;dibujado de cuadrados en pantalla, incrementando x e y a cada paso
loop:
ld de,#0xc000 ;;principio memoria video
ld hl,#x ;;carga en hl el valor de x
ld b,(hl) ;;pasa a b
inc (hl) ;;el valor de hl, HL=HL+1
inc HL ;;hl=hl+1
ld c,(hl) ;;pasa a c
inc (hl) ;;valor de hl +1
call cpct_getScreenPtr_asm ;;funcio9n para localizar x e y en pantalla
ex de,HL ;;intercambia de y hl
ld a,#0xff ;;color cuadrado
ld bc,#0x0804 ;;tamaño cuadrado
call cpct_drawSolidBox_asm ;;funcion dibujado cuadrado
call cpct_waitVSYNC_asm ;;funcion espera a retrazado
;; Loop forever
jr loop ;;salta a bucle loop
lunes, 12 de octubre de 2020
Get key cpctelera
cpct_keyID getKey() {
// Traverse the keystatus vector from end to start, to help// the compiler better optimize this code
u8 i = 10, *keys = cpct_keyboardStatusBuffer + 9;
u16 keypressed;
// Wait for a keypress
do { cpct_scanKeyboard(); } while ( ! cpct_isAnyKeyPressed() );
// Analyse which key has been pressed and return its keycode
do {
// We analyse groups of keys byte by byte (8 by 8, 1 bit per key)
// If no single key is pressed in this group, all bits will be on, and the byte will be 0xFF
// Then, XORing the byte with 0xFF will result in 0 unless some key from this group is pressed
keypressed = *keys ^ 0xFF;
if (keypressed)
return (keypressed << 8) + (i - 1); // Convert to cpct_keyID format: 8 first bits = key mask, 8 next bits, keyboard row (0-9)
--keys;
} while(--i);
// No key was pressed
return 0;
}
cpct_keyID getKey() {
// Traverse the keystatus vector from end to start, to help// the compiler better optimize this code
u8 i = 10, *keys = cpct_keyboardStatusBuffer + 9;
u16 keypressed;
// Wait for a keypress
do { cpct_scanKeyboard(); } while ( ! cpct_isAnyKeyPressed() );
// Analyse which key has been pressed and return its keycode
do {
// We analyse groups of keys byte by byte (8 by 8, 1 bit per key)
// If no single key is pressed in this group, all bits will be on, and the byte will be 0xFF
// Then, XORing the byte with 0xFF will result in 0 unless some key from this group is pressed
keypressed = *keys ^ 0xFF;
if (keypressed)
return (keypressed << 8) + (i - 1); // Convert to cpct_keyID format: 8 first bits = key mask, 8 next bits, keyboard row (0-9)
--keys;
} while(--i);
// No key was pressed
return 0;
}
domingo, 11 de octubre de 2020
Includes en cpctelera
Fran Gallego:
include hace lo que todos los includes hacen en cualquier lenguaje
es lo mismo que si copiaras y pegaras el archivo que incluyes
Pero es que eso es idéntico en C y en C++
Por eso, se usa para incluir sólo declaraciones, no definiciones
Como en C
no pones en los ficheros de cabecera definiciones
sólo declaraciones
El concepto es el mismo
Todos los ficheros se compilan siempre por separado
ningún fichero sabe nada de que existan otros ficheros
Entonces, cuando quieres usar un símbolo que está en otro fichero
simplemente en el fichero que lo vas a usar, lo declaras
Para que el ensamblador sepa que ese símbolo existe, aunque no sepa cuánto vale
Es después, cuando el linker recoge todos los ficheros compilados intermedios y los junta
cuando mira dónde está cada símbolo
Si tienes dos ficheros F1 y F2
Con esta estructura de símbolos
F1
etiqueta1::
etiqueta2::
F2
otra1::
otra2::
F1 y F2 se ensamblan por separado, individualmente
ninguno sabe de la existencia del otro
Así que si quieres que F1 pueda usar la etiqueta "otra2", por ejemplo
harías esto
F1
.globl otra2
etiqueta1::
etiqueta2::
F2
otra1::
otra2::
Simplemente, le dices al ensamblador "existe un símbolo otra2, que es global"
Y lo usas
como lo que haces con las llamadas a las funciones de CPCtelera
que son etiquetas, que no están en tu código
Si ahora resulta que tienes una etiqueta "cpct_doGame", que vas a usar tanto en F1 como F2
harías esto
F1
.globl cpct_doGame
etiqueta1::
etiqueta2::
F2
.globl cpct_doGame
otra1::
otra2::
Pero eso ya es duplicar código
mientras sólo sea una etiqueta vale
pero si ahora resulta que quieres usar 4 símbolos en ambos ficheros, la cosa crece
F1
.globl cpct_doGame_1
.globl cpct_doGame_2
.globl cpct_doGame_3
.globl cpct_doGame_4
etiqueta1::
etiqueta2::
F2
.globl cpct_doGame_1
.globl cpct_doGame_2
.globl cpct_doGame_3
.globl cpct_doGame_4
otra1::
otra2::
Y si tienes que hacer lo mismo en 5 ficheros, va siendo más feo
y si luego necesitas en los 5 ficheros, añadir un símbolo nuevo
te toca acordarte de todos los ficheros y editarlos uno a uno
Para evitar hacer eso
creas un tercer fichero
Un fichero de cabecera
Y haces esto
FH
.globl cpct_doGame_1
.globl cpct_doGame_2
.globl cpct_doGame_3
.globl cpct_doGame_4
.globl cpct_doGame_5
F1
.include "FH"
etiqueta1::
etiqueta2::
F2
.include "FH"
otra1::
otra2::
Eso es exactamente igual que haberlo escrito en los ficheros F1 y F2
Pero la ventaja es que sólo lo escribes en un sitio y cuando lo edites lo cambias para todos los que necesitan esas declaraciones
Así puedes tener 20 ficheros que incluyan FH
y en ninguno de ellos incurres en ningún coste
es lo mismo que haberlo escrito en los 20
totalmente igual, pero más práctico
cuidado, eso sí
no pongas en FH nada que no sean directivas, como has visto
Las directivas .globl
Sólo son información para el programa ensamblador
no generan bytes en el binario resultante
no existen en código máquina
sólo es información para el ensamblador para saber cosas sobre sus símbolos, mientras ensambla
Si metes código o bytes en un fichero del que luego hagas include
como lo estás duplicando en todas partes donde haces include
en todas ellas se generará ese código o bytes
por eso hay que saber usarlo, y entender el proceso, como te cuento ahora
Porque include es eso
un copy/paste automatizado
Sumar decimales en asm
Fran Gallego:
@Kalandras Explicación fácil
Pones un número en el acumulador (A)
que en hexadecimal no tenga números mayores de 9
es decir, ambos números hexadecimales entre 0 y 9
como si fuera decimal, en vez de hexadecimal
a partir de ese momento
haces cualquier operación con el número
por ejemplo
add b
add #20
sub #15
lo que quieras
Si es puntuación, estás sumando puntos
pero después de cada operación aritmética
ejecutas la instrucción
DAA
Esa instrucción lo que hace es ajustar el resultado de la operación aritmética
como si los dígitos A-F no existieran, como si estuvieras usando números decimales
por ejemplo
ld a, #9
add #2
Da como resultado A = 0B
pero
ld a, #9
add #2
daa
Da como resultado A = 11
Como si hubieras sumado en decimal
DAA ajusta el resultado de la operación, para que sea como si fueran decimales
sábado, 10 de octubre de 2020
Imprimir scores en cpctelera
Fran Gallego:
Un ejemplo para un score de 4 dígitos
Si tienes el score en HL
y le sumas una puntuación que está en DE
ld hl, #0x4995
ld de, #0x0010
ld a, l
add e
daa
ld l, a
ld a, h
adc d
daa
ld h, a
con eso sumas y da 0x4995+ 0x10 = 0x5005
Es como si sumaras en decimal
Pues sacando cada dígito por separado
porque cada dígito está codificado en 4 bits
Son dígitos hexadecimales
Si tienes A = 0x95
Los primeros 4 bits son un 9 ( 1001 )
Los segundos 4 bits son un 5 ( 0101 )
Así que sólo tienes que hacer operaciones de bits para quedarte con cada parte
y luego sumarles 48 para convertirlos en ASCII
Por ejemplo, si A = 0x95 = 0b10010101
puedes hacer esto para imprimir el 5
and #0x0F
add #48
call cpct_drawCharM0_asm
Con el AND te quedas sólo con los 4 últimos bits (el 5 )
le sumas 48 y da 53 (carácter del 5 en ASCII)
y se lo pasas a drawChar para imprimir
Si quieres imprimir el 9 de A = 0x95
harías esto
rrca
rrca
rrca
rrca
and #0x0F
add #48
call cpct_drawCharM0_asm
Rotas los bits de A 4 veces para poner abajo los 4 bits de arriba
y haces lo mismo de antes
De hecho, igual este año lo comento en clase porque es algo que nunca he explicado y creo que puede ser útil
sábado, 22 de agosto de 2020
Escribir frases
Rutina de ejemplo para escribir frases predefinidas.
la he sacado del foro amstrad.es.
https://www.amstrad.es/forum/viewtopic.php?f=6&t=5591&p=77489&hilit=Message%3A+db+%27hola+mundo%21%27%2C255#p77489
org &4200 ;origen de la rutinaPrintchar equ &Bb5a ;instrucción para imprimir un caracter
ld hl,Message ;carga en hl la dirección de message
Call PrintString ;llama a la rutina printstring
ret ;vuelve desde donde le llamaron
PrintString: ;loop para imprimir
ld a,(hl) ;carga en a la dirección de memoria ubicada en hl
cp 255 ;compara si a es 255
ret z ; y vuelve si es asi
inc hl ;incrementa en uno la posición de memoria de hl
call PrintChar ;imprime el carácter ubicado en a
jr PrintString ;salta a printstring
Message: db 'hola mundo!',255 ;frase de ejemplo,termina en ,255 para control
Rutina detección teclado
un ejemplo de rutina de detección de teclado. dar las gracias a artaburu por su permiso para poder publicarla.
Aquí cuelgo las rutinas que uso para detectar el teclado sin usar las opciones del firmware. Como ejemplo incluyo la detección de las teclas del cursor y del escape.
CÓDIGO: SELECCIONAR TODO
; -----------------------------------------------------------------------------
; |Rutinas para detección de teclado leyendo diréctamente el hardware del CPC |
; |Raúl Simarro (Artaburu) 2006 |
; -----------------------------------------------------------------------------
;_______________________________________________________________________________
; Ejemplo
;_______________________________________________________________________________
ORG &4000
xor a
ld (salir),a
_bucle_teclado
call detecta_teclas_hardware
ld a,(salir)
cp 1 ;termina al pulsar esc
jp nz,_bucle_teclado
ret
salir db 0
;______________________________________________________________________________
detecta_teclas_hardware ; cada vez que se quieran detectar
di ; las teclas pulsadas se debe
call comprobacion_teclas_pulsadas ; ejecutar esta rutina
ei
ld a,(teclado)
;_________________________________________________
; movimientos extras
;_________________________________________________
;cp %00000101
;jr z,arriba_derecha
;cp %00000110
;jr z,arriba_izquierda
;cp %0001001
;jr z,arriba_corto_derecha
;cp %00001010
;jr z,arriba_corto_izquierda
;_________________________________________________
cp %00000100
jp z, tecla_arriba
cp %00001000
jp z, tecla_abajo
cp %00000010
jp z, tecla_izquierda
cp %00000001
jp z, tecla_derecha
ret
comprobacion_teclas_pulsadas
xor a
ld (teclado),a ;Reinicia a 0 la vble teclado
ld hl,tecla_izquierda_x+1
ld a,(HL)
ld (linea_a_buscar+1),a ;cambia la línea a explorar
XOR A
call detecta_teclado_x ; esta rutina lee la línea del teclado correspondiente
DEC hl ; pero sólo nos interesa una de las teclas.
and (HL) ;para filtrar por el bit de la tecla (puede haber varias pulsadas)
CP (hl) ;comprueba si el byte coincide
call z,tecla_izquierda_pulsada
ld hl,tecla_derecha_x+1
ld a,(HL)
ld (linea_a_buscar+1),a
XOR A
call detecta_teclado_x
DEC hl
and (HL)
CP (hl)
call z,tecla_derecha_pulsada
ld hl,tecla_arriba_x+1
ld a,(HL)
ld (linea_a_buscar+1),a
XOR A
call detecta_teclado_x
DEC hl
and (HL)
CP (hl)
call z,tecla_arriba_pulsada
ld hl,tecla_abajo_x+1
ld a,(HL)
ld (linea_a_buscar+1),a
XOR A
call detecta_teclado_x
DEC hl
and (HL)
CP (hl)
call z,tecla_abajo_pulsada
; Comprueba si se ha pulsado ESC
ld a,8
ld (linea_a_buscar+1),a
XOR A
di
call detecta_teclado_x
ei
cp 4
jp z, esc_pulsado
ret
esc_pulsado
ld a,1
ld (salir),a
ret
tecla_izquierda_pulsada
ld a,(teclado)
or %00000001
ld (teclado),a
ret
tecla_derecha_pulsada
ld a,(teclado)
or %00000010
ld (teclado),a
ret
tecla_arriba_pulsada
ld a,(teclado)
or %00000100
ld (teclado),a
ret
tecla_abajo_pulsada
ld a,(teclado)
or %00001000
ld (teclado),a
ret
detecta_teclado_x ;Tomado de las rutinas básicas que aparecen
;en los documentos de Kevin Thacker
ld bc,&f7*256+%10000010
out (c),c ;PPI A OUT. RESET.
ld bc,&f400+14 ;Registro 14 del PSG (Puerta A)
out (c),c ;(contains keyboard line data)
ld b,&f6 ;PSG control
ld c,%11000000 ;Select Register 14 for use
out (c),C ;send
ld c,0 ;PSG inactive
out (c),c ;send
ld b,&f7 ;8255 PPI control
ld c,%10010010 ;Port A and Port C (upper) - Operating mode 0
;Port A input, Port C (upper) output.
;Port B and Port C (lower) - Operating mode 0
;Port B input, Port C (lower) output
out (c),c ;send control byte
;;READ KEYBOARD LINE
ld b,&F6 ;PSG control + keyboard line wanted
ld a,%01000000 ;PSG control - read
; >> linea a buscar <<
linea_a_buscar
; >> linea a buscar <<
or 1 ;keyboard line 1 ;Cambio esta línea para explorar distintas
;líneas del teclado.
out (c),a ;send it
ld b,&F4 ;Port to get PSG port A (register 14) data
in a,(c) ;Keyboard data from keyboard line 9
cpl
ret
teclado db 0 ;Este byte indicará qué teclas han sido pulsadas
;después de un ciclo de exploración
linea db 0
bte db 0
tecla_0 dw &0204
;teclado_usable ; teclas del cursor, cada tecla está definida por su bit y su línea.
tecla_izquierda_x dw &0002 ; bit 0, línea 2
tecla_derecha_x dw &0101 ; bit 1, línea 1
tecla_arriba_x dw &0001 ; bit 0, línea 1
tecla_abajo_x dw &0004 ; bit 0, línea 4
tecla_arriba
;operaciones
ld a,65
call &bb5a ; como ejemplo, imprime la letra A,
; &BB5A es la rutina del firmware que escribe un caracter en pantalla.
ret
tecla_abajo
;operaciones
ld a,66
call &bb5a ; como ejemplo, imprime la letra B
ret
tecla_izquierda
;operaciones
ld a,67
call &bb5a ; como ejemplo, imprime la letra C
ret
tecla_derecha
;operaciones
ld a,68
call &bb5a ; como ejemplo, imprime la letra D
retArta
Rutinas cpc ensamblador
Aquí voy a ir poniendo rutinas creo y espero que útiles para el micro cpc de amstrad.
Son recopilatorios de varios sitios
lunes, 1 de junio de 2020
Instalar samba en raspbian
Instrucciones a seguir
sudo apt-get install samba samba-common-bin
sudo cp /etc/samba/smb.conf smb.old
sudo nano -w /etc/samba/smb.conf
[pi 16GB]
comment = USB Share
path = /media/16GB
writeable = Yes
create mask = 0777
directory mask = 0777
browseable = Yes
valid users @users
force user = pi
sudo smbpasswd -a pi
sudo /etc/init.d/smbd restart
jueves, 28 de mayo de 2020
Lento, al abrir Firefox y la página de winape es un suplicio.
Todo porque me gusta probar cosas en la pi, y le instalo muchas cosas que luego no se sacarles provecho. Y no se desinstalarla o configurarlos bien
Me paso con boinc( aprovechar el tiempo muerto de la CPU para investigación del coronavirus).
El pihole, para quitar publicidad al navegar por internet ( no noto mejoría ninguna)
uTorrent, que por gui se configura y no sirve para configurar por terminal.
Winape, que me gusta trastear con los cpc, estoy intentando aprender ensamblador , y no logro ejecutarlo
Bueno, por ahora es todo.
lunes, 13 de abril de 2020
Mucho tiempo
Uso una Raspberry,peleándome con ella. Uso raspbian, intento poner amule,torrent,jdownloader y plex server. Y a veces funciona.
Iré poniendo ideas de cómo manejarlo todo.