Autor Tema: Rutinas en CM mas o menos útiles  (Leído 23339 veces)

josepzin

  • Administrador
  • Commodore Master
  • *****
  • Mensajes: 12983
  • Commodoreador web
    • Ver Perfil
    • Mi blog
Re:Rutinas en CM mas o menos útiles
« Respuesta #45 en: Octubre 11, 2016, 23:24:09 »
Superinteresante!!! ya lo miraré a ver que tal!

josepzin

  • Administrador
  • Commodore Master
  • *****
  • Mensajes: 12983
  • Commodoreador web
    • Ver Perfil
    • Mi blog
Re:Rutinas en CM mas o menos útiles
« Respuesta #46 en: Octubre 12, 2016, 00:02:49 »
Mola la mosca :)

Pero más me gustaría poder mirar y entender tu código!

Maniako

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 1013
  • SYS 8*4096
    • Ver Perfil
Re:Rutinas en CM mas o menos útiles
« Respuesta #47 en: Octubre 12, 2016, 12:33:13 »
De aquí a un mes diré lo mismo XD, a ver si puedo explicarlo paso a paso.

Los tres primeros bloques se explican por si mismo.
             Constantes universales.
             Línea de BASIC para el arranque del programa.
             Conectando el sprite en modo multicolor y activar las interrupciones.
 
IRQ
             Aquí esta el programa que se ejecutará a cada interrupción por barrido.
             Este, lo único que hace es activar el permiso para que las rutinas que trabajarán
             dentro del tiempo de barrido fuera de la pantalla se ejecuten.
             ¿Con esto qué consigo?. Aparte de complicarme la vida XD, dejo que el código de 
             mover gráficos lo haga fuera de las interrupciones en tiempo normal de ejecución del   
             programa. ¿Para qué sirve?. Pues para que durante una interrupción se puedan leer
             teclado o joystick ya que en mis pruebas con las interrupciones, no podía leer ninguna
             entrada durante las mismas (o no sé hacerlo bién), además de un ejercicio para
             re-aprender a seguir un programa comprendiendo como piensa el commodore64 .

PREMAIN
            Coloco el puntero que indica el sprite a mostrar que a su vez, hace que el programa
            sepa hacia donde mover la nave gracias a las tablas que veremos más abajo.
            ResetEjeNaveX y ResetEjeNaveY , son subrutinas que dan los valores adecuados a las
            variables de trabajo. Veréis que hay redundancia, es por las futuras ampliaciones.

MAIN
            Aquí empieza el programa que se va a repetir en bucle.
            Las 3 primeras líneas comprueban si las interrupciones han dado su permiso para ejecutar
            el código. Si no es así, salta a ejecutar código "normal" fuera de las interrupciones.

        lda #0              ;Desconecto el permiso de ejecución por IRQ
        sta Permiso      ;para evitar su ejecución constante. Si lo poneis a 1, vereis el programa a toda
                               mecha XD.
            Una vez se permite la ejecución del código , anulo ese permiso para evitar que se ejecute
            constantemente. Debe ejecutarse solo a cada IRQ.

LEER JOY 2

            Esto no tiene misterio, si el valor es joy derecha o izquierda , incrementa o decrementa
            el valor del puntero del sprite0 y después compruebo si se sale del limite. Si es así, le
            otorgo el valor correcto y el ciclo continua.
           
MOVER EJE X

            Aquí empieza lo divertido.
            Mover una nave en 16 direcciones diferentes implica mover los ejes en tiempos variables.
            Desplazarse en ángulos rectos es sencillo, INC ejeX o ejeY.
            Las diagonales igual INC ejeX e INC ejeY a la vez. Pero esta manera solo consigue
            8 direcciones diferentes y hace los giros muy bruscos (para mi gusto).
            Pero las direcciones intermedias entre estos ángulos (8 más) , necesitan que uno de los
            ejes se ejecute dos veces mientras que el otro solo una vez, ahí
            entran las tablas y las comprobaciones para conseguirlo.
            MovX0Temp contiene el freno para el ejeX
            MovY0Temp contiene el freno para el ejeY.
            Si es 0 directamente, pasa, es decir, no mueve ese eje.
            Si no es 0, pasa a decrementar su valor hasta que sea 0 pero en el segundo paso,
            solo entonces se moverá ese eje.

             DEjeX0Temp contiene la dirección hacia donde se ha de mover el eje X.
             DEjeY0Temp contiene la dirección hacia donde se ha de mover el eje Y.

             Una vez movidos cada eje o cambiado el puntero del sprite0 , hago que se devuelvan
             los valores de nuevo para repetir el ciclo otra vez usando el puntero del sprite
             como guía para la lectura de las tablas.
             Para eso uso las subrutinas ResetEjeNaveX y ResetEjeNaveY.

PASODEIRQ

             A partir de aquí van las rutinas que se ejecutarán normalmente a cada ciclo sin importar
             las interrupciones (puntuación, detección de choques , lo que sea...).

MSBX0

            Activa o desactiva el MSB (bit más significativo) del eje X del sprite 0.
            Esta rutina solo se llama cada vez que hay desbordamiento al sumar o restar 1 (o 2 o 3 o...)
            al eje X.

Espero que esto ayude un poco a comprender su funcionamiento.
Esta rutina no solo vale para mover al protagonista, si no que también sirve para hacer mover enemigos siguiendo una tabla o patrón que le permitiría hacer giros bonitos (XD) antes de atacar o lo que vuestra imaginación os permita.

                 
« última modificación: Octubre 12, 2016, 14:02:08 por Maniako »
LDA #$50
STA $0400
RTS
Lloré cuando conseguí hacer esto con el monitor del FC1.

josepzin

  • Administrador
  • Commodore Master
  • *****
  • Mensajes: 12983
  • Commodoreador web
    • Ver Perfil
    • Mi blog
Re:Rutinas en CM mas o menos útiles
« Respuesta #48 en: Octubre 12, 2016, 13:50:26 »
Buenísima la explicación, parece una buena forma de plantear el esqueleto de un juego.

R. INTERNATIONAL

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 923
  • THE NEW IRON AGE HAS COME!!
    • Ver Perfil
Re:Rutinas en CM mas o menos útiles
« Respuesta #49 en: Octubre 12, 2016, 21:07:25 »
 Muy bueno!!,...ademas al "sintaxis" que utilizas conecta mucho conmigo,..dame tiempo para compilarla, estudiarla y destriparla, hay cosas que me interesan.

    Saludos Ferreos!

Maniako

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 1013
  • SYS 8*4096
    • Ver Perfil
Re:Rutinas en CM mas o menos útiles
« Respuesta #50 en: Octubre 13, 2016, 12:14:10 »
Muy bueno!!,...ademas al "sintaxis" que utilizas conecta mucho conmigo,..dame tiempo para compilarla, estudiarla y destriparla, hay cosas que me interesan.

    Saludos Ferreos!

Todo el tiempo que quieras ;)

Seguiré trabajando y colgando lo que vaya aprendiendo.
LDA #$50
STA $0400
RTS
Lloré cuando conseguí hacer esto con el monitor del FC1.

Maniako

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 1013
  • SYS 8*4096
    • Ver Perfil
Re:Rutinas en CM mas o menos útiles
« Respuesta #51 en: Octubre 14, 2016, 23:42:57 »
He encontrado un error en mi código.
Ya lo he editado y solucionado.

Código: [Seleccionar]
;Leer joy2
        dec frenjoy     ;Freno joystick. Solo leé una vez cada 3 IRQ.
        bne paso3       ;No=0, paso de leer

Antes enviaba a paso2 y era un error. Ahora está corregido.
Sorry.
« última modificación: Octubre 14, 2016, 23:46:43 por Maniako »
LDA #$50
STA $0400
RTS
Lloré cuando conseguí hacer esto con el monitor del FC1.

josepzin

  • Administrador
  • Commodore Master
  • *****
  • Mensajes: 12983
  • Commodoreador web
    • Ver Perfil
    • Mi blog
Re:Rutinas en CM mas o menos útiles
« Respuesta #52 en: Noviembre 14, 2016, 15:31:57 »
Esto es publicidad del curso de programación que están haciendo, pero igual es interesante. Multiplicando en código máquina.

Have you ever wondered how to multiply two numbers on Commodore 64?

Unfortunately it doesn't look like this:

Código: [Seleccionar]
lda #42
mul #5
The 6510 processor does not have a built in multiplication instruction.

Unless you are multiplying by a power of two.

In that case you can simply shift bits

Código: [Seleccionar]
lda #42
asl // a = a * 2 = 84
asl // a = a * 2 = 168
But in a general case we can't do that.

So what can we do?

Well, instead of multiplying forty-two by five, we can add forty-two five times.

Código: [Seleccionar]
  lda #0
  clc
  ldx #5
loop:
  adc #42
  dex
  bne loop
This get's the job done, but it's not very efficient (adding five forty two times would be even worse).

Can we improve this algorithm?

Sure, if we notice that

42 * 5 = 42 * 4 + 42

We can optimise the process using bit shifting operations.

Believe it or not, but the general version of this algorithm has been popular among...

Russian peasants...

few centuries ago...

Crazy right?

Anyway, if you want to learn how to apply this algorithm on the Commodore 64, take a look at the episode #067 - Multiplication.

You can also get it for free along with 13 other episodes.
https://gumroad.com/l/64bites

riq

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 567
    • Ver Perfil
    • From the C64 until today, a developer's perspective
Re:Rutinas en CM mas o menos útiles
« Respuesta #53 en: Noviembre 14, 2016, 17:17:54 »

42 * 5 = 42 * 4 + 42

We can optimise the process using bit shifting operations.

eso. y aunque multiplicar por 42 no es muy común, multiplicar por 320 si lo es, ya que es el ancho de la pantalla. y multiplicar por 320 se vuelve bastante sencillo ya que es:

Código: [Seleccionar]
320 = 256 + 64     en hexa sería: $140 = $100 + $40
320 = 2 ** 8 + 2 ** 6

pero 2 ** 8 es $100. O sea que multiplicar por 256 es super fácil. No hay que hacer nada.
y multiplicar por 64 es equivalente a hacer "valor << 6" (desde el LSB)... ó  "valor >> 2"  (desde el MSB).

entonces, y como ejemplo, supongamos que hay que multiplicar $bb * $140 (esta en hexa)

Código: [Seleccionar]
; multiplico por 256 ($100)
    lda #0
    sta resultado1_lo
    lda #$bb
    sta  resultado1_hi         ; no hay que hacer nada!, solo lo pongo en el MSB     

; multiplico por 64 ($40)
    lda #$bb
    lsr                                ; "dos shift rights" es más eficiente que hacer "seis shift left"
    ror resuldado2_lo
    lsr
    ror resuldado2_lo
    sta resultado2_hi

    ; y ahora tengo que hace la suma de 16-bit de resultado1 + resultado2

.byte resultado1_hi:
.byte resultado1_lo:
.byte resultado2_hi:
.byte resultado2_lo: