Commodore manía
Commodore 64 => Desarrollo => Ensamblador => Mensaje iniciado por: Maniako en Julio 08, 2015, 00:49:44
-
Buenas.
Como veo interes en aprender ensamblador (yo el que mas) , ire colgando por aquí las rutinas
que en su dia aprendí o me enseñaron. "Trasteocódigos" los llamaba (era un crio).
Me encantaria crear una colección con los aportes de todos para tener un lugar de consulta rápida ante esos momentos "¿y ahora como demonios hago esto?" .
Aqui van mis primeros aportes. Utilizo la ROM del basic para las operaciones. Ya se que no es lo mas rápido, pero la facilidad de uso ayudará (o eso espero) a los noveles como yo.
___________________________________________________________________________________
Este permite hacer calculos de 16bit. y los muestra en pantalla. Suma, resta, divide y multiplica enteros.
Muy útil para manejarse en la memoria de pantalla usando coordenadas por ejemplo.
;Creado en CBM prg Studio
; 10 SYS (4096)
*=$801
BYTE $0E, $08, $0A, $00, $9E, $20, $28, $34, $30, $39, $36, $29, $00, $00, $00
*=$1000 ;inicio programa
facarg=$bc0c
intfac=$b391
sum=$b86a
res=$b853
mul=$ba2b
div=$bb12
facind=$bc9b
intasc=$bdcd
lda #$01 ;hibyte 1ª cifra a calcular
ldy #$18 ;lobyte 1ª cifra a calcular
jsr intfac ;
jsr facarg ;
lda #$04 ;hibyte 2ª cifra a calcular
ldy #$00 ;lobyte 2ª cifra a calcular
jsr intfac ;
jsr sum ;OPERACION ELEGIDA
jsr facind ;
ldx $65 ;Resultado lobyte leido de $65
lda $64 ;Resultado hibyte leido de $64
jsr intasc ;Imprimir resultado en pantalla (X=lobyte/Acu=Hibyte)
rts
___________________________________________________________________________________
Aqui lo mismo pero usando la pagina cero (zeropage) para pokear el puntito dentro de las coordenadas que pongais en cordx y cordy.
Primero calculo la coordenada Y*40 para saltar a la columna a la que apunte y después le sumo 1024 al resultado.
La coordenada X, simplemente usando STA indirecto indizado por Y que contiene el valor de cordx...
;Creado en CBM prg Studio
;----------------------------------------------------------------------------------------
;Este bloque separado genera una linea basic para arrancar el programa
; 10 SYS (4096)
*=$801
BYTE $0E, $08, $0A, $00, $9E, $20, $28, $34, $30, $39, $36, $29, $00, $00, $00
;-----------------------------------------------------------------------------------------
*=$1000 ;inicio programa SYS4096
;Direcciones de las rutinas del basic necesarias.
facarg=$bc0c
intfac=$b391
sum=$b86a
res=$b853
mul=$ba2b
div=$bb12
facind=$bc9b
;Aqui están las coordenadas X e Y para que juguéis con ellas y poner el punto
;donde os apetezca.
cordx=#05 ;Coordenada X de pantalla. De 0 a 39
cordy=#24 ;Coordenada Y de pantalla. De 0 a 24
;Aqui el programa en cuestión.
lda #00 ;hybyte
ldy #cordy ;lobyte la coordenada Y no pasa de 24
jsr intfac ;
jsr facarg ;
lda #00 ;hibyte
ldy #40 ;lobyte #40-$28. En la memoria de pantalla para bajar una linea se suma 40 ;)
jsr intfac ;
jsr mul ;Multiplica cordy * #40
jsr facind ;
lda $64 ;Carga el hibyte resultado del calculo en el ACU
ldy $65 ;Carga el lobyte resultado del calculo en Y
jsr intfac ;
jsr facarg ;
lda #$04 ;La memoria de pantalla va de 0400 hasta 07E7
ldy #$00 ;hibyte en ACU y lobyte en Y
jsr intfac ;
jsr sum ;Suma 0400 al resultado de (cordy*40)
jsr facind ;
lda $64 ;Carga ACU con el hibyte resultado.
ldx $65 ;Carga X con el lobyte resultado.
sta $FC ;Guarda hibyte en la zeropage.
stx $FB ;Guarda lobyte en la zeropage.
ldy #cordx ;Carga Y con el valor de cordx.
lda #81 ;Carga ACU con el valor 81 (puntito).
sta ($FB),y ;Lo muestra en pantalla
rts ;Volver al BASIC
;Puede que no sea una forma muy rápida para hacer los calculos, pero si es más comprensible
;para usuarios noveles. Siempre estaré agradecido a JAVIER CANTERO por las ayudas que me
;brindo a la hora de programar en CM.
;Se puede usar para mover multitud de objetos en la memoria de pantalla.
Espero la ayuda de todos con correcciones , mejoras y vuestros trasteocódigos con los que aprendisteís o aprendeis. ;)
___________________________________________________________________________________
Mostrar texto en pantalla en las coordenadas que se deseén
Aportado por R.Internacional en este hilo http://retroinvaders.com/commodoremania/foro/index.php/topic,1080.msg17747.html#msg17747 (http://retroinvaders.com/commodoremania/foro/index.php/topic,1080.msg17747.html#msg17747)
* = $1000 ; SYS 4096.
LDX #$01 ; Carga X con #$01, que corresponde a la línea 1.
LDY #$0A ; Carga el Y #$0A, que corresponde a la columna 10.
JSR $E50C ; Salta a la subrutina en ROM $E50C, que sitúa el cursor en las coordenadas dadas en los valores de X e Y.
LDA #<CADENA ; Carga A con el byte bajo de la posición donde empieza el texto.
LDY #>CADENA ; Carga Y con el byte alto de la posición donde empieza el texto.
JSR $AB1E ; Salta a la subrutina en ROM $AB1E, que imprime una cadena de caracteres.
RTS ; Retorna al BASIC.
CADENA .TEXT "HOLA A TODOS!!!" ; Texto.
.BYTE $00
___________________________________________________________________________________
Rutina multiplicación rápida
Aportado por Lobogris en el hilo: http://retroinvaders.com/commodoremania/foro/index.php/topic,637.msg9662.html#msg9662 (http://retroinvaders.com/commodoremania/foro/index.php/topic,637.msg9662.html#msg9662)
/*
*************************************************************************************
RUTINA DE MULTIPLICACION RAPIDA * 320
ENTRADAS:
$fa = numero multiplicador (1 byte, rango efectivo = 0 < 204)
SALIDAS:
$fb-$fc = resultado del multiplicador * 320 (precisión 16 bits)
DETALLES:
Num. de ciclos = 51 (+12 contando ciclos del JSR/RTS)
Tamaño en memoria = 29 bytes
Max resultado teorico = 255 * 320 = 81600 ($013EC0)
(no cabe en 16 bits, habria que adaptar resultado a 3 bytes)
Max. resultado efectivo = 204 * 320 = 65280 ($FF00)
Si se quiere optimizar para menor tamaño, se pueden incluir las rotaciones
como una parte iterada dos veces por un bucle. Pero perdemos ciclos asi...
FECHA CREACION: 05-03-13 , ULT. REV.: 05-03-13 (LOBOGRIS)
***************************************************************************************
*/
fastMUL320:
// Descomponiendo, resultado de n * 320 = (256 * n) + (64 * n)
// ahora vamos a calcular 64*numero
// esto se consigue poniendo numero en la parte alta del resultado para obtener numero*256
// y desplazaremos (todos los 16 bits) de resultado a la derecha 2 veces para
// conseguir numero*64...
lda numero
clc // Primera rotacion lógica a la derecha (16 bits)
lsr
sta resultado+1 // Num. en parte alta resultado = multiplicar Num. * 256)
lda resultado
ror
sta resultado // Tras 1a rotación, resultado = 128 * numero
clc // 2a rotacion a la derecha (16 bits)
lda resultado+1
lsr
sta resultado+1
lda resultado
ror
sta resultado // aqui resultado = 64 * numero
// Ahora haremos resultado = (numero * 256) + (numero * 64)
lda numero // Recupera numero. Al ponerlo parte alta = numero * 256
adc resultado+1 // se añade a resultado*64 (parte alta es la única afectada)
sta resultado+1 // ¡Ahora resultado = 320 * numero!
rts
-
Reservado para futuros listados
-
gracias! y muy buena la idea de ir poniendo rutinas aca.
-
Me encantaria crear una colección con los aportes de todos para tener un lugar de consulta rápida ante esos momentos "¿y ahora como demonios hago esto?" .
Seguramente existe pero en inglés...
Quizás más adelante podemos hacer un hilo índice con chincheta, que enlace a esto que estais haciendo.
-
Seguramente existe pero en inglés...
Quizás más adelante podemos hacer un hilo índice con chincheta, que enlace a esto que estais haciendo.
Mi intención es recopilar todas las rutinas que se han posteado en el foro donde se enseñe a hacer algo dificil o lo mismo pero de maneras diferentes y poner las nuevas aportaciones para tener un punto de referencia desde donde empezar.
Ya me imagino que en inglés estara todo, pero si lo tenemos en castellano mejor. A mi el inglés me dificulta el aprendizaje. Puedo leerlo pero según como lo redacten se me cruzan los cables y no lo puedo traducir coerentemente y si uso el google translator... me desescojono con las traducciones .
-
¿Cómo piensas hacerlo? organicemos así queda bien accesible :)
-
¿Cómo piensas hacerlo? organicemos así queda bien accesible :)
Pues a base de copypaste y poner el link donde está publicado.
Una vez recopiladas ,las ordenaria por orden alfabetico o crearia un índice de consulta con lo que hay recopilado.
¿Alguna sugerencia?.
-
gracias! y muy buena la idea de ir poniendo rutinas aca.
Gracias a vosotros por colgar vuestros trabajos para que nos peleémos con ellos.
Cuando tu programa para manejo de interrupciones esté terminado, lo colgare aqui también.
Si lo documentas con comentarios que faciliten su comprensión mucho mejor ;)
-
Si quieres puedes ir haciendolo directamente en un hilo del foro y le pongo chincheta.
-
Si quieres puedes ir haciendolo directamente en un hilo del foro y le pongo chincheta.
Posteado a las 5:22:11... me lo parece a mi o los que tenemos un commodore no dormimos mucho?... :-\
Somos como vampiros chupa 8 bits ;D
Que susto me has dado, pensaba que estaba posteando en el privado.
Seguire posteando aqui las rutinas recopiladas y si teneís a bién cambiar algo o chinchetearlo , pues adelante.
-
Posteado a las 5:22:11... me lo parece a mi o los que tenemos un commodore no dormimos mucho?... :-\
Somos como vampiros chupa 8 bits ;D
Es que por la noche es cuando hay TRANQUILIDAAAADDDD... eso desde siempre de toda la vida, pero con mujer y cría se nota más.
Y además tener en cuenta que estoy en otro uso horario, hemisferio, continente y universo paralelo...
-
Quizas tenga sentido poner estas rutinas en macros de ensamblador, y ponerlas todas en un solo archivo.
De esa manera para usuarlas, solo hay que usar ese archivo en tu juego y listo.
La pregunta del millón es que ensamblador usar, ya que cada uno tiene su propio formato de macro :)
Y se podria poner en github ese archivo.
-
Las rutinas que he ido colgando (excepto las de Lobogris) son muy sencillas , solo hacen lo que hacen e implementarlas en un programa usando una macro sin adaptar antes el código no lo veo útil.
Naturalmente , los programas que si se puedan usar como macro si que se podria hacer lo que comentas.
Si alguién mas experto que yo (casi todos ;) ) puede modificarlas para ese uso, estaré encantado.
El tema de ensamblador A, B o C si que es un lio. En mis códigos siempre pogo el assembler que he utilizado, arriba del todo. Aunque con práctica, creo que al final los reconoceremos a simple vista, como en Matrix ;D ;D ;D
-
Sere bobo. Con lo que me enseñastes ayer (Riq) , convertirlas para usar como macro es facil .
El problema es la disparidad de ensambladores , pero cada cual se lo tendra que adaptar.
No hay peor ciego que el que no sabe ver. ::)
-
Y se podria poner en github ese archivo.
Eso ya es terreno semi-desconocido para mi, pocas veces he tenido que usar algo de esto (subversion) asi que no puedo hacer...
-
Hace tiempo que no colgaba nada por aquí y ya tocaba XD.
Gracias a Riq y a sus ejemplos de código he llegado entender como usar las interrupciones (o eso creo XD).
Aquí dejo el código fuente esperando que alguíen me muestre los fallos y como mejorar la rutina.
Es lo más básico necesario para hacerlas funcionar. Solo hace algo raro cuando provocas un ?syntax error, se "clava" un poco y vuelve a la normalidad. Después, por muchos ?Syntax error que hagas, ni se inmuta.
Hacer un NEW antes de introducir lineas basic, si no, se reseteará. ;)
;CBM prg studio.
; 10 SYS32768
*=$0801
BYTE $0B, $08, $0A, $00, $9E, $33, $32, $37, $36, $38, $00, $00, $00
*=$8000 ;Coloco el programa aquí para que no se desplace al
;entrar lineas de basic.
vector=vect;$0400
ldx#0
sta vector
; jsr$ff81 ;Limpiar pantalla
sei
lda #%00011011 ;27 original. 26 no flickea.Hibyte del raster pero
sta $D011 ;si no es 27 aparecen "pelos" en los bordes pantalla.
lda #<irq1
sta $0314
lda #>irq1
sta $0315
lda #%00000001 ;#127 en el ejemplo. Basta con activar el timer A #1
sta $DC0D ;Registro control de la cia
lda #1
sta $D01A ;Registro mascara IRQ activada. IRQ ON.
cli
rts ;Salida al basic para pruebas.
main ;El programa empezaria aquí.
jmp main
irq1
lda $D019 ;Reset bandera de registro reescribiendo encima su
sta $D019 ;propio valor de nuevo.Si no, se queda activado y falla.
ldx vector
ldy linea,x
sty $d012
ldy color,x
sty $d020
lda linea+1,x ;Siguente nuevo valor
cmp #255
beq salt0
inc vector
jmp $FEBC ;Saltar a restaurar a partir de la rutina NMI.
salt0
lda #0
sta vector
jmp $EA31 ;Rutina interrupcion normal Leer teclado y demás.
linea byte $32,$3A,$42,$4A,$52,$5A,$62,$6A,$72,$7A,$82,$8A,$92,$9A,$A2,$AA,$C8,$ff
color byte $00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$0a,$0b,$0c,$0d,$0e,$0f,$00
vect
-
Ese Maniako interruptor :-)
-
Esa!
No recuerdo haber visto mucho el "JMP $FEBC", pero esta bien lo que haces. Es lo mismo que hacer "JMP $EA81"... nada más que el EA81 es más popular que el FEBC.
El "LDA $D019; STA $D019" lo podes reemplazar por "LDA $D019"... creo que no hace falta el "STA $D019"... solo lo tenes que leer para hacer el "ack" de la interrupción.
-
Entonces están bien así?. No sabes la ilusión que me hace poder utilizarlas por fin jejeje.
Hay que escribir en D019 para limpiar la bandera de la interrupción. Si no, no funciona.
Pasa lo mismo que con los sprites creo recordar.
He probado con $EA81 y funciona igual. Usaré EA81 ya que es más fácil de recordar.
$EA31 y $EA81.
NMI no dar de comer al 3.
IRQ dar de comer al 3.
;D
Ahora a hacer scroll fuera del barrido de pantalla o mover los caracteres justo cuando el barrido sobrepase la zona donde se muestren para ganar tiempo de proceso.
Me queda aun mucho trabajo.
-
Ese Maniako interruptor :-)
No queriais programadores?. Pues en eso estoy. :P
Cuando domine todas estas cosas y me vea preparado, veremos si podemos modificar los juegos multicarga y pasarlos a lo que se necesite. Aún me queda mucho trabajo. :-[
-
Hay que escribir en D019 para limpiar la bandera de la interrupción. Si no, no funciona.
Pasa lo mismo que con los sprites creo recordar.
Si, creo que tenez razón. Me estaba confundiendo con limpiar los timers CIA.
Yo uso "ASL $D019" en vez de "LDA $D019; STA $D019", y me sirve también para saber si la IRQ fue generada por raster o no.
Viendo código viejo mio (el de los 90s), veo que también usaba el "LDA $D019; STA $D019;".
-
Despues de muchas pruebas con scroll de pantalla (sin scroll fino), he comprobado que al pobrecillo C64 le cuesta mucho esfuerzo mover 1000 caracteres de un sitio a otro.
Se pueden hacer rutinas cortas usando bucles, pero este modo crea frenos ya que hay que modificar valores, hacer comparaciones y saltar de nuevo para seguir trasladando caracteres.
Otra manera (para mi la mejor) es UNLOOP´ear XD. Riq me aconsejo sobre ello pero hasta que no hice pruebas, no me dí cuenta de lo que come en tiempo de proceso.
Aquí dejo tres ejemplos de código, uno con LOOPS y dos sin.
***********************************************************************
LOOPS:
;CBM prg STUDIO
;Scroll linea a linea . Solo mueve una linea cada vez que se llama.
;Intento de hacer scroll moviendo la linea que el raster acaba de mostrar
;para asi, aprovechar al máximo
;Lo le he puesto interrupciones por que aún es mas lento XD
; 10 SYS (4096)
*=$801
BYTE $0E, $08, $0A, $00, $9E, $20, $28, $34, $30, $39, $36, $29, $00, $00, $00
*=$1000
;
reset lda #25
sta ctrlinea
loop ldx #39 ;#39 es el valor correcto
poke1 lda $0401
poke2 sta $0400
jsr recoloca ;Pasamos al siguiente caractera leer y pokear
pasa1 dex
bne poke1
;Como es final de linea, dejamos lista la siguiente...
lda poke2+1
sta poke3+1
lda poke2+2
sta poke3+2
lda $d012 ;Datos aleatorios tomados del raster
poke3 sta $0400 ;Y pokeados el final de la fila
jsr recoloca ;... deja lista la siguiente linea XD
;Una vez terminada la última linea de pantalla, puesta a cero de los vectores y vuelta a empezar.
;Puede ir fuera en la memoria normal. (fuera de la pag cero)
dec ctrlinea
bne fin
lda #04
sta poke1+2 ;HI
sta poke2+2 ;HI
lda #00
sta poke2+1 ;LO
lda #01
sta poke1+1 ;LO
jmp reset
fin jmp loop ;Deberia ser un RTS si la usas con JSR. En esta prueba
;lo puse en loop continuo
;Rutina aumenta vectores de lectura/escritura de los caracteres de la linea.
recoloca
inc poke1+1 ;LO
bne pasa2
inc poke1+2 ;HI
pasa2 inc poke2+1 ;LO
bne pasa3
inc poke2+2 ;HI
pasa3 rts
ctrlinea
*******************************************************************
UNLOOP:
;CBM prg STUDIO
;Esta forma es mucho mas rápida que un loop. Mucho mas.
; 10 SYS (4096)
*=$801
BYTE $0E, $08, $0A, $00, $9E, $20, $28, $34, $30, $39, $36, $29, $00, $00, $00
*=$1000
;Moviendo de der a izq.
main ldx #01
ldy #00
loop1 jsr move
inx
iny
txa
cmp #40
beq fin
jmp loop1
fin jsr chars
;loop2 lda $d012 ;Bucle freno
; bne loop2
jmp main ;rts
;Rutina mover 8x8 pixels
move ;X=Lectura. Y=Escritura.
lda $0400,x
sta $0400,y
lda $0428,x
sta $0428,y
lda $0450,x
sta $0450,y
lda $0478,x
sta $0478,y
lda $04a0,x
sta $04a0,y
lda $04c8,x
sta $04c8,y
lda $04f0,x
sta $04f0,y
lda $0518,x
sta $0518,y
lda $0540,x
sta $0540,y
lda $0568,x
sta $0568,y
lda $0590,x
sta $0590,y
lda $05b8,x
sta $05b8,y
lda $05e0,x
sta $05e0,y
lda $0608,x
sta $0608,y
lda $0630,x
sta $0630,y
lda $0658,x
sta $0658,y
lda $0680,x
sta $0680,y
lda $06a8,x
sta $06a8,y
lda $06d0,x
sta $06d0,y
lda $06f8,x
sta $06f8,y
lda $0720,x
sta $0720,y
lda $0748,x
sta $0748,y
lda $0770,x
sta $0770,y
lda $0798,x
sta $0798,y
lda $07c0,x
sta $07c0,y
rts
;Rutina poner caracteres aleatorios a la derecha de la mantalla para ver como se desplaza
chars
lda $d012
sta $0427
sta $044f
sta $0477
sta $049f
sta $04c7
sta $04ef
sta $0517
sta $053f
sta $0567
sta $058f
sta $05b7
sta $05df
sta $0607
sta $062f
sta $0657
sta $067f
sta $06a7
sta $06cf
sta $06f7
sta $071f
sta $0747
sta $076f
sta $0797
sta $07bf
sta $07e7
rts
**********************************************************************
UNLOOPS con IRQ:
;CBM prg STUDIO
;Pruebas de scroll de caracteres de la pantalla.El color negro es el tiempo que lleva
;ejecutar el desplazamiento de los caracteres un caracter hacia la izquierda.
;En lugar de desplazar la pantalla desde la misma interrupción, uso la interrupción para
;dar permiso al programa para desplazar los caracteres.
;No sé si me explico bién XD. Si es incorrecto hacerlo así, no lo se, pero alargar el
;tiempo de la interrupción me parece incorrecto.
;De toda manera es un experimento para mejorar y aprender. A trastear señor@s.
;Si alguno averigua como acelerar esto aun más, que no se corte y lo diga. Grácias.
; 10 SYS (4096)
*=$801
BYTE $0E, $08, $0A, $00, $9E, $20, $28, $34, $30, $39, $36, $29, $00, $00, $00
permiso=$FB ;Usando pag cero para ahorrar ciclos (1) XD
*=$1000 ;Coloco el programa aquí para que no se desplace al
;entrar lineas de basic.
jsr $ff81 ;Limpiar pantalla.
sei ;Desactivando interrupciones.
lda #%00011011 ;27 original. 26 no flickea.Hibyte del raster pero
sta $D011 ;si no es 27 aparecen "pelos" en los bordes pantalla.
lda #<irq1
sta $0314
lda #>irq1
sta $0315
lda #%00000001 ;#127 en el ejemplo. Basta con activar el timer A #1
sta $DC0D ;Registro control de la cia
lda #1
sta $D01A ;Registro mascara IRQ activada. IRQ ON.
cli ;Conectando interrupciones.
lda #230 ;#230 Linea del raster que activara el movimiento scroll
sta $d012
jsr random ;Activa el SID para generar numeros aleatorios
main
lda permiso ;Tengo permiso para scroll?
beq main ;No, pues a esperar...
ldx #02 ;De derecha a izq, no hace falta dibujar el ultimo caracter
ldy #01 ;ya que queda por detras de el marco en pantalla de 38 caracteres.
lda #0 ;Color negro para visionar tiempo
sta $d020 ;es borrable 100% y ganamos ciclos.
loop1
jsr move ;Moviendo toda una columna
inx
iny
cpx #40
beq fin
jmp loop1
fin
jsr newchars
lda #2 ;Color rojo para visionar tiempo
sta $d020 ;Es borrable 100% y ganamos ciclos.
lda #0 ;Desconectando el scroll .
sta permiso
jmp main ;Vuelta al ruedo XD
irq1
asl $D019 ;Reset IRQ.ASL es consejo de Riq.Si no, se queda activado y falla.
bcc salt0 ;Acarreo OFF? Salt0
sigue
lda #1 ;Activando scroll desde las interrupciones para que se
sta permiso ;ejecuten fuera de las mismas.
jmp $EA81 ;FEBC ;Saltar a restaurar a partir de la rutina NMI.
salt0
jmp $EA7b ;$EA31 ;Rutina interrupcion normal Leer teclado, cursor y demás.
;Rutina mover un caracter a la izq. Se puede usar en ambas direcciones jugando
;con X e Y.
move ;X=Lectura. Y=Escritura.
;Aqui estan desconectadas las lineas que no interesan.
;Conectad y desconectad a placer para experimetar.
;Podreis ver lo que llega a consumir el mover 1000 caracteres.
; lda $0400,x ;Primera linea
; sta $0400,y ;Primera linea
lda $0428,x ;Segunda linea
sta $0428,y ;Segunda linea
lda $0450,x ;Tercera linea
sta $0450,y ;Tercera linea
lda $0478,x ;etc...
sta $0478,y
lda $04a0,x
sta $04a0,y
lda $04c8,x
sta $04c8,y
lda $04f0,x
sta $04f0,y
lda $0518,x
sta $0518,y
lda $0540,x
sta $0540,y
lda $0568,x
sta $0568,y
lda $0590,x
sta $0590,y
lda $05b8,x
sta $05b8,y
lda $05e0,x
sta $05e0,y
lda $0608,x
sta $0608,y
lda $0630,x
sta $0630,y
lda $0658,x
sta $0658,y
lda $0680,x
sta $0680,y
lda $06a8,x
sta $06a8,y
lda $06d0,x
sta $06d0,y
lda $06f8,x
sta $06f8,y
lda $0720,x
sta $0720,y
lda $0748,x
sta $0748,y
lda $0770,x
sta $0770,y
; lda $0798,x
; sta $0798,y
; lda $07c0,x
; sta $07c0,y
rts
;Rutina poner caracteres aleatorios a la derecha de la pantalla para ver como se desplaza.
newchars
;Leer valor aleatorio creado por el SID. Esto seria el siguiente caracter a mostrar del
;nivel del juego que andeis haciendo. Yo uso basura para ahorrar trabajo durante las pruebas XD
LDA $D41B ;Leyendo random del SID
;Aqui estan desconectadas las lineas que no interesan.
;Conectad y desconectad a placer para experimentar.
; sta $0427 ;Primera linea.
sta $044f ;Segunda linea.
sta $0477 ;Tercera linea.
sta $049f ;etc...
sta $04c7
sta $04ef
sta $0517
sta $053f
sta $0567
sta $058f
sta $05b7
sta $05df
sta $0607
sta $062f
sta $0657
sta $067f
sta $06a7
sta $06cf
sta $06f7
sta $071f
sta $0747
sta $076f
sta $0797
; sta $07bf
; sta $07e7
rts
;Activar random usando el SID
random LDA #$FF ; maximum frequency value
STA $D40E ; voice 3 frequency low byte
STA $D40F ; voice 3 frequency high byte
LDA #$80 ; noise waveform, gate bit off
STA $D412 ; voice 3 control register
RTS
Como podeis ver, sin loops hace que el programa crezca en tamaño, pero la velocidad bién lo vale.
Dejo los programas ya compilados para que podais abrirlos todos a la vez y apreciar la gran diferencia. Lo interesante es la que usa IRQ, mover la pantalla sin deformidades es esencial para cualquier juego y para eso, hay que moverla cuando el barrido de pantalla no esté un la "zona visual".
Si se desea mover toda la pantalla, se pueden usar técnicas de doble buffer como la descrita en este link:
http://1amstudios.com/2014/12/07/c64-smooth-scrolling/ (http://1amstudios.com/2014/12/07/c64-smooth-scrolling/)
En este otro link en el parrafo Loop Unrolling hay una explicación con calculos de tiempo de procesos que lo deja bien claro.
http://www.antimon.org/code/Linus/demo_prog.html#SECTION000121000000000000000 (http://www.antimon.org/code/Linus/demo_prog.html#SECTION000121000000000000000)
Pero hasta que no haga pruebas con el double buffering, no comento XD.
Espero que os sea útil y didactico. Mi intención es incentivaros a trastear en CM y echar una mano para aprender comprendiendo, para mí algo esencial.
-
¿El último parece ser el que va mejor no?
-
Se ve mejor por que uso las IRQ para que no haga extraños , no como en el segundo ejemplo UNLOOP que no usa interrupciones y se ven los flicks. Va más deprisa moviendo pero se vé mal.
-
Yastoyotravez.
Una vez le vas cogiendo el gusanillo a programar, cuesta dejarlo.
Reconozco que me ha costado arrancar y recordar métodos y demás técnicas para crear los programas.
Aquí dejo otra pequeña rutina donde muevo un mapa de 64 caractéres, del 0 al 63.
Uso un tamaño de mapa que me premita controlar los limites con un simple AND#63, de esta manera consigues devolver a 0 el vector de lectura del mapa.
Basta de rollos, aquí dejo la rutina para que la destripeís y la mejoreís ahí donde no llego o no veo.
;CBM prg STUDIO
;Scroll de una pantalla de 64 caracteres (0-63) en multicolor.
;Sin scroll fino. Solo probando tamaños de mapas para futuras pantallas de 127 o 256
;caracteres.
;En $3800 estan los caracteres programables
;En $4000 el mapa en sí.
;Para encontrar el principio de cada linea, solo hay que ir sumandole #64 cada
;vez para poder leerla sin problemas.
;He escogido este tamaño para con simplemente un AND poder controlar el bucle sin fin.
;El mapa y los caracteres se han editado con VChar64 0.013. Muy practica.
;La proxima le meto scroll fino y a la siguiente, moverse en ambas direcciones en el eje X.
; 10 SYS4096
*=$0801
BYTE $0B, $08, $0A, $00, $9E, $34, $30, $39, $36, $00, $00, $00
vectscroll byte $00 ;Vector de lectura para el mapa.
*=$1000
jsr $ff81 ;Limpiar pantala
lda #15+16 ;Cambio vector punteros programables $3800
sta $D018 ; #53272
lda $d016 ;Multicolor ON
ora #16
sta $d016 ; #53270
lda #0 ;Fondo negro
sta $d021
lda #9 ;Color 1 marrón
sta $d022 ;#53282
lda #13 ;Color 2 verde claro
sta $d023 ;#53283
lda #5 ;Verde coscuro
sta $d800 ;#55296
;Ram de color. Solo una vez ya que no altero su valor.
lda #13
ldx #39
buc4 sta $da08,x
sta $da30,x
sta $da58,x
sta $da80,x
sta $daa8,x
sta $dad0,x
sta $daf8,x
sta $db20,x
sta $db48,x
sta $db70,x
dex
bpl buc4
loop2 ldy vectscroll ;Se va sumando hasta llegar al final del mapa y vuelta a empezar
ldx #0 ;Escritura en ram de pantalla.
loop1
;Ram pantalla
lda $4000,y
sta $0608,x
lda $4040,y
sta $0630,x
lda $4080,y
sta $0658,x
lda $40c0,y
sta $0680,x
lda $4100,y
sta $06a8,x
lda $4140,y
sta $06d0,x
lda $4180,y
sta $06f8,x
lda $41c0,y
sta $0720,x
lda $4200,y
sta $0748,x
lda $4240,y
sta $0770,x
iny ;Al registro Y lo pongo a cero cuando llega al final del mapa
tya ;y así, empieza a leer desde el principio otra vez.
and #63
tay
inx
cpx #40 ;He llegado al final de la pantalla?
bne loop1 ;No, pues a seguir
inc vectscroll ;Como he llegado al final, incremento el vector de lectura
lda vectscroll ;Y le hago un AND 63 para devolverlo a 0
and #63 ;si es mayor que 63
sta vectscroll ;y lo guardo.
pasa0 lda $d012 ;Bucle de raster.
bne pasa0 ;para frenar esto un poco y eliminar flick sin usar interrupciones de la manera clasica XD
jmp loop2
*=$3800 ;Caracteres programables.
BYTE $3C,$66,$6E,$6E,$60,$62,$3C,$00,$18,$3C,$66,$7E,$66,$66,$66,$00,$7C,$66
BYTE $66,$7C,$66,$66,$7C,$00,$3C,$66,$60,$60,$60,$66,$3C,$00,$78,$6C,$66,$66,$66,$6C
BYTE $78,$00,$7E,$60,$60,$78,$60,$60,$7E,$00,$7E,$60,$60,$78,$60,$60,$60,$00,$3C,$66
BYTE $60,$6E,$66,$66,$3C,$00,$66,$66,$66,$7E,$66,$66,$66,$00,$3C,$18,$18,$18,$18,$18
BYTE $3C,$00,$1E,$0C,$0C,$0C,$0C,$6C,$38,$00,$66,$6C,$78,$70,$78,$6C,$66,$00,$60,$60
BYTE $60,$60,$60,$60,$7E,$00,$63,$77,$7F,$6B,$63,$63,$63,$00,$66,$76,$7E,$7E,$6E,$66
BYTE $66,$00,$3C,$66,$66,$66,$66,$66,$3C,$00,$7C,$66,$66,$7C,$60,$60,$60,$00,$3C,$66
BYTE $66,$66,$66,$3C,$0E,$00,$7C,$66,$66,$7C,$78,$6C,$66,$00,$3C,$66,$60,$3C,$06,$66
BYTE $3C,$00,$7E,$18,$18,$18,$18,$18,$18,$00,$66,$66,$66,$66,$66,$66,$3C,$00,$66,$66
BYTE $66,$66,$66,$3C,$18,$00,$63,$63,$63,$6B,$7F,$77,$63,$00,$66,$66,$3C,$18,$3C,$66
BYTE $66,$00,$66,$66,$66,$3C,$18,$18,$18,$00,$7E,$06,$0C,$18,$30,$60,$7E,$00,$3C,$30
BYTE $30,$30,$30,$30,$3C,$00,$0C,$12,$30,$7C,$30,$62,$FC,$00,$3C,$0C,$0C,$0C,$0C,$0C
BYTE $3C,$00,$00,$18,$3C,$7E,$18,$18,$18,$18,$00,$10,$30,$7F,$7F,$30,$10,$00,$00,$00
BYTE $00,$00,$00,$00,$00,$00,$18,$18,$18,$18,$00,$00,$18,$00,$66,$66,$66,$00,$00,$00
BYTE $00,$00,$66,$66,$FF,$66,$FF,$66,$66,$00,$18,$3E,$60,$3C,$06,$7C,$18,$00,$62,$66
BYTE $0C,$18,$30,$66,$46,$00,$3C,$66,$3C,$38,$67,$66,$3F,$00,$06,$0C,$18,$00,$00,$00
BYTE $00,$00,$0C,$18,$30,$30,$30,$18,$0C,$00,$30,$18,$0C,$0C,$0C,$18,$30,$00,$00,$66
BYTE $3C,$FF,$3C,$66,$00,$00,$00,$18,$18,$7E,$18,$18,$00,$00,$00,$00,$00,$00,$00,$18
BYTE $18,$30,$00,$00,$00,$7E,$00,$00,$00,$00,$00,$00,$00,$00,$00,$18,$18,$00,$00,$03
BYTE $06,$0C,$18,$30,$60,$00,$3C,$66,$6E,$76,$66,$66,$3C,$00,$18,$18,$38,$18,$18,$18
BYTE $7E,$00,$3C,$66,$06,$0C,$30,$60,$7E,$00,$3C,$66,$06,$1C,$06,$66,$3C,$00,$06,$0E
BYTE $1E,$66,$7F,$06,$06,$00,$7E,$60,$7C,$06,$06,$66,$3C,$00,$3C,$66,$60,$7C,$66,$66
BYTE $3C,$00,$7E,$66,$0C,$18,$18,$18,$18,$00,$3C,$66,$66,$3C,$66,$66,$3C,$00,$3C,$66
BYTE $66,$3E,$06,$66,$3C,$00,$00,$00,$18,$00,$00,$18,$00,$00,$00,$00,$18,$00,$00,$18
BYTE $18,$30,$0E,$18,$30,$60,$30,$18,$0E,$00,$00,$00,$7E,$00,$7E,$00,$00,$00,$70,$18
BYTE $0C,$06,$0C,$18,$70,$00,$3C,$66,$06,$0C,$18,$00,$18,$00,$EF,$FE,$55,$55,$55,$55
BYTE $55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$03,$03,$03,$03,$03,$03,$03,$03,$C0,$C0
BYTE $C0,$C0,$C0,$C0,$C0,$C0,$FE,$BF,$FB,$EF,$BD,$75,$55,$55,$BE,$FB,$BF,$FB,$7E,$5F
BYTE $55,$55,$00,$03,$0D,$0D,$35,$35,$35,$D5,$C0,$F0,$F0,$70,$7C,$57,$57,$57,$5F,$5F
BYTE $5F,$5C,$5C,$7C,$7C,$FC,$00,$00,$00,$E0,$F0,$38,$18,$18,$18,$18,$1C,$0F,$07,$00
BYTE $00,$00,$18,$18,$38,$F0,$E0,$00,$00,$00,$C0,$C0,$C0,$C0,$C0,$C0,$FF,$FF,$C0,$E0
BYTE $70,$38,$1C,$0E,$07,$03,$03,$07,$0E,$1C,$38,$70,$E0,$C0,$FF,$FF,$C0,$C0,$C0,$C0
BYTE $C0,$C0,$FF,$FF,$03,$03,$03,$03,$03,$03,$00,$3C,$7E,$7E,$7E,$7E,$3C,$00,$00,$00
BYTE $00,$00,$00,$FF,$FF,$00,$36,$7F,$7F,$7F,$3E,$1C,$08,$00,$60,$60,$60,$60,$60,$60
BYTE $60,$60,$00,$00,$00,$07,$0F,$1C,$18,$18,$C3,$E7,$7E,$3C,$3C,$7E,$E7,$C3,$00,$3C
BYTE $7E,$66,$66,$7E,$3C,$00,$18,$18,$66,$66,$18,$18,$3C,$00,$06,$06,$06,$06,$06,$06
BYTE $06,$06,$08,$1C,$3E,$7F,$3E,$1C,$08,$00,$18,$18,$18,$FF,$FF,$18,$18,$18,$C0,$C0
BYTE $30,$30,$C0,$C0,$30,$30,$18,$18,$18,$18,$18,$18,$18,$18,$00,$00,$03,$3E,$76,$36
BYTE $36,$00,$FF,$7F,$3F,$1F,$0F,$07,$03,$01,$00,$00,$00,$00,$00,$00,$00,$00,$F0,$F0
BYTE $F0,$F0,$F0,$F0,$F0,$F0,$00,$00,$00,$00,$FF,$FF,$FF,$FF,$FF,$00,$00,$00,$00,$00
BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$C0,$C0,$C0,$C0,$C0,$C0,$C0,$C0,$CC,$CC
BYTE $33,$33,$CC,$CC,$33,$33,$03,$03,$03,$03,$03,$03,$03,$03,$00,$00,$00,$00,$CC,$CC
BYTE $33,$33,$FF,$FE,$FC,$F8,$F0,$E0,$C0,$80,$03,$03,$03,$03,$03,$03,$03,$03,$18,$18
BYTE $18,$1F,$1F,$18,$18,$18,$00,$00,$00,$00,$0F,$0F,$0F,$0F,$18,$18,$18,$1F,$1F,$00
BYTE $00,$00,$00,$00,$00,$F8,$F8,$18,$18,$18,$00,$00,$00,$00,$00,$00,$FF,$FF,$00,$00
BYTE $00,$1F,$1F,$18,$18,$18,$18,$18,$18,$FF,$FF,$00,$00,$00,$00,$00,$00,$FF,$FF,$18
BYTE $18,$18,$18,$18,$18,$F8,$F8,$18,$18,$18,$C0,$C0,$C0,$C0,$C0,$C0,$C0,$C0,$E0,$E0
BYTE $E0,$E0,$E0,$E0,$E0,$E0,$07,$07,$07,$07,$07,$07,$07,$07,$FF,$FF,$00,$00,$00,$00
BYTE $00,$00,$FF,$FF,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$FF,$FF,$03,$03
BYTE $03,$03,$03,$03,$FF,$FF,$00,$00,$00,$00,$F0,$F0,$F0,$F0,$0F,$0F,$0F,$0F,$00,$00
BYTE $00,$00,$18,$18,$18,$F8,$F8,$00,$00,$00,$F0,$F0,$F0,$F0,$00,$00,$00,$00,$F0,$F0
BYTE $F0,$F0,$0F,$0F,$0F,$0F,$C3,$99,$91,$91,$9F,$99,$C3,$FF,$E7,$C3,$99,$81,$99,$99
BYTE $99,$FF,$83,$99,$99,$83,$99,$99,$83,$FF,$C3,$99,$9F,$9F,$9F,$99,$C3,$FF,$87,$93
BYTE $99,$99,$99,$93,$87,$FF,$81,$9F,$9F,$87,$9F,$9F,$81,$FF,$81,$9F,$9F,$87,$9F,$9F
BYTE $9F,$FF,$C3,$99,$9F,$91,$99,$99,$C3,$FF,$99,$99,$99,$81,$99,$99,$99,$FF,$C3,$E7
BYTE $E7,$E7,$E7,$E7,$C3,$FF,$E1,$F3,$F3,$F3,$F3,$93,$C7,$FF,$99,$93,$87,$8F,$87,$93
BYTE $99,$FF,$9F,$9F,$9F,$9F,$9F,$9F,$81,$FF,$9C,$88,$80,$94,$9C,$9C,$9C,$FF,$99,$89
BYTE $81,$81,$91,$99,$99,$FF,$C3,$99,$99,$99,$99,$99,$C3,$FF,$83,$99,$99,$83,$9F,$9F
BYTE $9F,$FF,$C3,$99,$99,$99,$99,$C3,$F1,$FF,$83,$99,$99,$83,$87,$93,$99,$FF,$C3,$99
BYTE $9F,$C3,$F9,$99,$C3,$FF,$81,$E7,$E7,$E7,$E7,$E7,$E7,$FF,$99,$99,$99,$99,$99,$99
BYTE $C3,$FF,$99,$99,$99,$99,$99,$C3,$E7,$FF,$9C,$9C,$9C,$94,$80,$88,$9C,$FF,$99,$99
BYTE $C3,$E7,$C3,$99,$99,$FF,$99,$99,$99,$C3,$E7,$E7,$E7,$FF,$81,$F9,$F3,$E7,$CF,$9F
BYTE $81,$FF,$C3,$CF,$CF,$CF,$CF,$CF,$C3,$FF,$F3,$ED,$CF,$83,$CF,$9D,$03,$FF,$C3,$F3
BYTE $F3,$F3,$F3,$F3,$C3,$FF,$FF,$E7,$C3,$81,$E7,$E7,$E7,$E7,$FF,$EF,$CF,$80,$80,$CF
BYTE $EF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$E7,$E7,$E7,$E7,$FF,$FF,$E7,$FF,$99,$99
BYTE $99,$FF,$FF,$FF,$FF,$FF,$99,$99,$00,$99,$00,$99,$99,$FF,$E7,$C1,$9F,$C3,$F9,$83
BYTE $E7,$FF,$9D,$99,$F3,$E7,$CF,$99,$B9,$FF,$C3,$99,$C3,$C7,$98,$99,$C0,$FF,$F9,$F3
BYTE $E7,$FF,$FF,$FF,$FF,$FF,$F3,$E7,$CF,$CF,$CF,$E7,$F3,$FF,$CF,$E7,$F3,$F3,$F3,$E7
BYTE $CF,$FF,$FF,$99,$C3,$00,$C3,$99,$FF,$FF,$FF,$E7,$E7,$81,$E7,$E7,$FF,$FF,$FF,$FF
BYTE $FF,$FF,$FF,$E7,$E7,$CF,$FF,$FF,$FF,$81,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$E7
BYTE $E7,$FF,$FF,$FC,$F9,$F3,$E7,$CF,$9F,$FF,$C3,$99,$91,$89,$99,$99,$C3,$FF,$E7,$E7
BYTE $C7,$E7,$E7,$E7,$81,$FF,$C3,$99,$F9,$F3,$CF,$9F,$81,$FF,$C3,$99,$F9,$E3,$F9,$99
BYTE $C3,$FF,$F9,$F1,$E1,$99,$80,$F9,$F9,$FF,$81,$9F,$83,$F9,$F9,$99,$C3,$FF,$C3,$99
BYTE $9F,$83,$99,$99,$C3,$FF,$81,$99,$F3,$E7,$E7,$E7,$E7,$FF,$C3,$99,$99,$C3,$99,$99
BYTE $C3,$FF,$C3,$99,$99,$C1,$F9,$99,$C3,$FF,$FF,$FF,$E7,$FF,$FF,$E7,$FF,$FF,$FF,$FF
BYTE $E7,$FF,$FF,$E7,$E7,$CF,$F1,$E7,$CF,$9F,$CF,$E7,$F1,$FF,$FF,$FF,$81,$FF,$81,$FF
BYTE $FF,$FF,$8F,$E7,$F3,$F9,$F3,$E7,$8F,$FF,$C3,$99,$F9,$F3,$E7,$FF,$E7,$FF,$FF,$FF
BYTE $FF,$00,$00,$FF,$FF,$FF,$F7,$E3,$C1,$80,$80,$E3,$C1,$FF,$E7,$E7,$E7,$E7,$E7,$E7
BYTE $E7,$E7,$FF,$FF,$FF,$00,$00,$FF,$FF,$FF,$FF,$FF,$00,$00,$FF,$FF,$FF,$FF,$FF,$00
BYTE $00,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$00,$00,$FF,$FF,$CF,$CF,$CF,$CF,$CF,$CF
BYTE $CF,$CF,$F3,$F3,$F3,$F3,$F3,$F3,$F3,$F3,$FF,$FF,$FF,$1F,$0F,$C7,$E7,$E7,$E7,$E7
BYTE $E3,$F0,$F8,$FF,$FF,$FF,$E7,$E7,$C7,$0F,$1F,$FF,$FF,$FF,$3F,$3F,$3F,$3F,$3F,$3F
BYTE $00,$00,$3F,$1F,$8F,$C7,$E3,$F1,$F8,$FC,$FC,$F8,$F1,$E3,$C7,$8F,$1F,$3F,$00,$00
BYTE $3F,$3F,$3F,$3F,$3F,$3F,$00,$00,$FC,$FC,$FC,$FC,$FC,$FC,$FF,$C3,$81,$81,$81,$81
BYTE $C3,$FF,$FF,$FF,$FF,$FF,$FF,$00,$00,$FF,$C9,$80,$80,$80,$C1,$E3,$F7,$FF,$9F,$9F
BYTE $9F,$9F,$9F,$9F,$9F,$9F,$FF,$FF,$FF,$F8,$F0,$E3,$E7,$E7,$3C,$18,$81,$C3,$C3,$81
BYTE $18,$3C,$FF,$C3,$81,$99,$99,$81,$C3,$FF,$E7,$E7,$99,$99,$E7,$E7,$C3,$FF,$F9,$F9
BYTE $F9,$F9,$F9,$F9,$F9,$F9,$F7,$E3,$C1,$80,$C1,$E3,$F7,$FF,$E7,$E7,$E7,$00,$00,$E7
BYTE $E7,$E7,$3F,$3F,$CF,$CF,$3F,$3F,$CF,$CF,$E7,$E7,$E7,$E7,$E7,$E7,$E7,$E7,$FF,$FF
BYTE $FC,$C1,$89,$C9,$C9,$FF,$00,$80,$C0,$E0,$F0,$F8,$FC,$FE,$FF,$FF,$FF,$FF,$FF,$FF
BYTE $FF,$FF,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$FF,$FF,$FF,$FF,$00,$00,$00,$00,$00,$FF
BYTE $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$00,$3F,$3F,$3F,$3F,$3F,$3F
BYTE $3F,$3F,$33,$33,$CC,$CC,$33,$33,$CC,$CC,$FC,$FC,$FC,$FC,$FC,$FC,$FC,$FC,$FF,$FF
BYTE $FF,$FF,$33,$33,$CC,$CC,$00,$01,$03,$07,$0F,$1F,$3F,$7F,$FC,$FC,$FC,$FC,$FC,$FC
BYTE $FC,$FC,$E7,$E7,$E7,$E0,$E0,$E7,$E7,$E7,$FF,$FF,$FF,$FF,$F0,$F0,$F0,$F0,$E7,$E7
BYTE $E7,$E0,$E0,$FF,$FF,$FF,$FF,$FF,$FF,$07,$07,$E7,$E7,$E7,$FF,$FF,$FF,$FF,$FF,$FF
BYTE $00,$00,$FF,$FF,$FF,$E0,$E0,$E7,$E7,$E7,$E7,$E7,$E7,$00,$00,$FF,$FF,$FF,$FF,$FF
BYTE $FF,$00,$00,$E7,$E7,$E7,$E7,$E7,$E7,$07,$07,$E7,$E7,$E7,$3F,$3F,$3F,$3F,$3F,$3F
BYTE $3F,$3F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F,$F8,$F8,$F8,$F8,$F8,$F8,$F8,$F8,$00,$00
BYTE $FF,$FF,$FF,$FF,$FF,$FF,$00,$00,$00,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$00
BYTE $00,$00,$FC,$FC,$FC,$FC,$FC,$FC,$00,$00,$FF,$FF,$FF,$FF,$0F,$0F,$0F,$0F,$F0,$F0
BYTE $F0,$F0,$FF,$FF,$FF,$FF,$E7,$E7,$E7,$07,$07,$FF,$FF,$FF,$0F,$0F,$0F,$0F,$FF,$FF
BYTE $FF,$FF,$0F,$0F,$0F,$0F,$F0,$F0,$F0,$F0
*=$4000 ;Mapa a mostrar 63x10 caracteres
BYTE $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20
BYTE $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20
BYTE $20,$20,$20,$20,$20,$20,$20,$20,$46,$45,$44,$47,$20,$20,$20,$20,$20,$20,$20,$20
BYTE $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20
BYTE $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20
BYTE $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$46,$41,$41,$41,$41,$47,$20,$20,$20
BYTE $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20
BYTE $20,$20,$20,$20,$20,$46,$44,$47,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20
BYTE $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$46,$41,$41,$41,$41,$41
BYTE $41,$47,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20
BYTE $20,$20,$20,$20,$20,$20,$20,$20,$42,$41,$41,$41,$47,$20,$20,$20,$20,$20,$20,$20
BYTE $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$46,$41,$41
BYTE $41,$41,$41,$41,$41,$41,$47,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20
BYTE $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$46,$40,$41,$41,$41,$48,$20,$20,$20
BYTE $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20
BYTE $46,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$47,$20,$20,$20,$20,$20,$20,$20,$20
BYTE $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$42,$41,$41,$41,$41,$48
BYTE $20,$20,$20,$20,$20,$20,$20,$46,$45,$47,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20
BYTE $20,$20,$20,$46,$41,$41,$41,$41,$41,$41,$41,$41,$44,$44,$44,$44,$44,$44,$47,$20
BYTE $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$46,$40,$40,$41
BYTE $41,$41,$48,$20,$20,$20,$20,$20,$20,$20,$46,$41,$41,$41,$47,$20,$20,$20,$46,$40
BYTE $47,$20,$20,$20,$20,$20,$42,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41
BYTE $41,$41,$48,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$42
BYTE $41,$41,$41,$41,$41,$48,$20,$20,$20,$20,$20,$20,$46,$40,$41,$41,$41,$41,$41,$47
BYTE $20,$46,$41,$41,$41,$47,$20,$20,$20,$20,$46,$41,$41,$41,$41,$41,$41,$41,$41,$41
BYTE $41,$41,$41,$41,$41,$41,$47,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20
BYTE $20,$20,$20,$42,$41,$41,$41,$41,$41,$47,$20,$20,$20,$20,$20,$46,$41,$41,$41,$41
BYTE $41,$41,$41,$41,$44,$41,$41,$41,$41,$41,$47,$20,$20,$46,$41,$41,$41,$41,$41,$41
BYTE $41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$47,$20,$20,$20,$20,$20,$20,$44,$45
BYTE $44,$45,$44,$44,$44,$45,$44,$45,$44,$45,$44,$45,$44,$45,$44,$45,$44,$44,$44,$45
BYTE $44,$45,$45,$45,$44,$45,$44,$45,$44,$45,$44,$44,$45,$45,$44,$45,$44,$44,$44,$45
BYTE $44,$45,$44,$45,$44,$45,$44,$45,$45,$45,$44,$45,$44,$45,$44,$45,$44,$45,$44,$45
BYTE $44,$45
Seguiré colgando mis avances. Espero que le sea util a alguién XD
-
Solo hace algo raro cuando provocas un ?syntax error, se "clava" un poco y vuelve a la normalidad. Después, por muchos ?Syntax error que hagas, ni se inmuta.
He leido que eso lo hace al recolocar la memoria basic, al parecer reclama espacio. No se el por qué si ya sabe el tamaño de la única linea de basic.
-
Maniako,
Comentas que:
Lo interesante es la que usa IRQ, mover la pantalla sin deformidades es esencial para cualquier juego y para eso, hay que moverla cuando el barrido de pantalla no esté un la "zona visual".
Corrigeme si me equivoco: lo que no debe pasar, es que el raster intercepte una zona de la pantalla que se está cambiando en ese momento, cierto?
Es decir, si hablamos de caracteres: una vez que el raster ha pasado por la primera fila de caracteres, debería ser posible cambiarla sin que hubiera flicker. Mientras el raster no "alcance" a nuestro código, y nuestro código no "adelante" al raster, no debería haber problemas..
O sea, si se pusiera 1 interrupción en cada badline a partir de la primera, en esa interrupción se podría repintar los caracteres de la línea anterior.
Si esto es así, el tiempo disponible para repintar la pantalla, no es sólo el tiempo en el que el raster está en el borde, sino cualquier momento, siempre que el raster ni adelante, ni alcance al código..
Es esto así?
-
Maniako,
Comentas que:Corrigeme si me equivoco: lo que no debe pasar, es que el raster intercepte una zona de la pantalla que se está cambiando en ese momento, cierto?
Exacto. una vez el raster ha pasado la zona en la que deseas que haya cambios, los haces.
Es decir, si hablamos de caracteres: una vez que el raster ha pasado por la primera fila de caracteres, debería ser posible cambiarla sin que hubiera flicker. Mientras el raster no "alcance" a nuestro código, y nuestro código no "adelante" al raster, no debería haber problemas..
Eso seria lo ideal, pero la rutina que uses en ese intervalo de linea, no debe durar más tiempo que hasta la siguiente linea que vayas a cambiar.
Si tu rutina de movimiento consume 9 o más lineas del raster, a la siguiénte interrupción para movel la siguiente linea (8 lineas) ya no lllegas a tiempo y empiezan los fallos.
O sea, si se pusiera 1 interrupción en cada badline a partir de la primera, en esa interrupción se podría repintar los caracteres de la línea anterior.
El tiempo disponible hasta la siguiente linea a mover es el límite.
En la rutina de arcoirirs, se ve perfecta por que no hago más que cambiar el color Se podria poner toda la pantalla a barras , queda bonito, pero ya se captaba lo que queria compartir.
Tengo pendiente algo como lo que comentas pero como experimento.
Prefiero aprender a usar el doble bufer, una segunda pantalla donde aplicar los cambios según donde tengas el scroll fino. Tengo que leermelo más y probarlo.
Si esto es así, el tiempo disponible para repintar la pantalla, no es sólo el tiempo en el que el raster está en el borde, sino cualquier momento, siempre que el raster ni adelante, ni alcance al código..
Es esto así?
Si , correcto. Hay gente que hace maravillas y me encantaria llegar a ese nivel ;)
Hasta que no empecé con las interrupciones no me dí cuenta de lo importante que es el optimizar el código al máximo y contar los ciclos .
De todas maneras no soy un gurú en estas lides. llevo bastante tiempo documentandome y revisando códigos para encontrar como funcionan. No me gusta poner código sin entender para qué sirve.
Gracias a Riq, empece a enterarme un poco de como funcionaban realmente.
-
Por fin con algo de tiempo libre.
Me he puesto a hacer pruebas aprovechando la rutina de arcoiris para que podais comprobar los efectos de pasarse en tiempo entre las interrupciones y tratar de hacer más comprensible el "misterio" las IRQ.
;CMB prg STUDIO
; 10 SYS36864
*=$801
BYTE $0B, $08, $0A, $00, $9E, $33, $36, $38, $36, $34, $00, $00, $00
*=$9000 ;Coloco el programa aquí para que no se desplace al
;entrar lineas de basic.
vector=vect
ldx #0
stx vector
jsr $ff81 ;Limpiar pantalla
sei
lda #%00011011 ;27 original. 26 no flickea.Hibyte del raster pero
sta $D011 ;si no es 27 aparecen "pelos" en los bordes pantalla.
lda #<irq1
sta $0314
lda #>irq1
sta $0315
lda #%00000001 ;#127 en el ejemplo. Basta con activar el timer A #1
sta $DC0D ;Registro control de la cia
lda #1
sta $D01A ;Registro mascara IRQ activada. IRQ ON.
cli
rts ;Salida al basic para pruebas.
main ;El programa empezaria aquí.
inc $D021
jmp main
irq1
;Reset bandera de registro IRQ manipulando su valor.
asl $D019 ;asl es consejo de Riq.Si no, se queda activado y falla.
ldx vector
ldy linea,x
sty $d012
ldy color,x
sty $d020 ;Color marco
lda linea+1,x ;Siguente nuevo valor
cmp #255
beq salt0
inc vector
;Bucle de freno para test de tiempo disponible
ldx #24 ;Alterad este valor para pruebas de des-sincronismo
looop lda $d012 ;Valor "aleatorio" del raster
sta $0400,x ;Lo pokeo en pantalla
dex
bne looop ;Sigue el bucle hasta que X=0
jmp $EA81 ;FEBC ;Saltar a restaurar a partir de la rutina NMI.
salt0
lda #0
sta vector
jmp $EA31 ;Rutina interrupcion normal Leer teclado y demás.
linea byte $32,$3A,$42,$4A,$52,$5A,$62,$6A,$72,$7A,$82,$8A,$92,$9A,$A2,$AA,$C8,$ff
color byte $00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$0a,$0b,$0c,$0d,$0e,$0f,$00
vect byte $00
freno byte $00
He añadido un bucle para que podais experimentar aumentando o disminuyendo el tiempo del mismo. Este bucle representa el trabajo de mover una linea nada más acabe de pasar el raster (tal y como sugirió Dashiad) u otra cosa.
Mientras el tiempo del bucle sea menor al tiempo entre llamadas de interrupción, todo permanecerá estable.
En cuanto el tiempo del bucle sea mayor...
La verdad es que hay más tiempo del que creia, sin bucles , quizás de tiempo a mover toda una linea completa... Lo dejo para el que quiera trastear con este tema ;)
Otra idea. Usando esta rutina, se podria mostrar una linea de texto con dos colores a la vez e incluso hacer deslizar los dos colores arriba y abajo creando un efecto curioso.
A ver quién se anima.
EDITO:
Se puede ganar algo de tiempo si en vez de saltar a $EA31 donde se lee la tecla STOP y el parpadeo del cursor , saltamos a $EA61 saltandonos un buén cacho de código del sistema. Ando leyendo el listado de la ROM.
No es mucho, pero estas pequeñas ayudas pueden ser valiosas.
Está claro que el cursor dejará de parpadear y la tecla RUN/STOP deja de actuar a nivel del BASIC, pero generalmente no se suele trastear con el BASIC mientras juegas XD
Otro ahorro de tiempo es eliminando jmp$EA81 y pegando este código que es el mismo que se ejecuta en $EA81
pla
tay
pla
tax
pla
rti
Entre $EA61 y esto último se consigue algo mas de estabilidad .
Es cuestión de rascar ciclos.
Otra vez editando jajajaja. Esto engancha.
Si no necesitais el datasete, podeis saltar a $EA7B. Aun se consigue mas estabilidad. Desaparecen casi todos los flicks con el bucle a #28. Por lo menos es lo que aprecio con el VICE.
-
Otra chorrada de las mias ::).
Generalmente hacer que un personaje de un juego salte con cierta "elegancia" a veces no es sencillo. Suele acabar saltando en angulos de 45 grados y personalmente nunca me ha gustado demasiado.
Se puede hacer uso de tablas para hacer el salto algo más natural o "redondo" (y para muchisimas otras cosas interesantes).
Aquí dejo este pequeño ejemplo, como siempre lo más sencillo que sé hacerlo (tampoco llego a mucho más XD) para una fácil comprensión.
;CMB prg STUDIO 3.8.0
;Usando tablas para saltar.
;He usado para el calculo de la trayectoria del salto el programa SINUS CREATOR.
;Es excelente para estos menesteres.
; 10 SYS4096
*=$0801
BYTE $0B, $08, $0A, $00, $9E, $34, $30, $39, $36, $00, $00, $00
*=$1000
sprites=$D000
;Activando sprite.
lda eje
sta sprites ;Coordenada X sprite.
sta sprites+1 ;Coordenada Y sprite.
lda #1
sta sprites+21 ;Conecta sprite 1
lda #128
sta $07f8 ;Puntero direccion sprite
ldy #00
main
;Bucle de freno para poder ver como salta.
bu2 dec freno0
bne bu2
lda #10 ;Disminuyendolo acelera. Aumentandolo frena
sta freno0
bu3 dec freno1
bne bu2
;Fin bucle de freno0
;Aqui empieza el programa en sí.
inc sprites ;Muevo sprite en X un pixel a la derecha.
inc sprites ;Muevo sprite en X un pixel a la derecha otra vez.
lda eje ;Eje Y del sprite. Aqui lo tengo en un valor fijo.
sec ;Activar acarreo antes de restar.
sbc salty,y ;Le resto el valor del salto que hay en la tabla.
sta sprites+1 ;Y coloco el sprite en su nueva posicion.
iny ;aumento en uno el vector de lectura.
cpy #16 ;Es =16?
bne pasa0 ;No?. Pues pasando.
ldy #00 ;Si es =16, lo pongo a 0 y vuelve a leer la tabla de salto.
pasa0
jmp main ;Vuelta a empezar.
;Tabla datos salto usando Y como vector de lectura.
salty byte 2,4, 6, 8, 11, 14, 18, 19,19,19, 18, 15, 11, 6, 3, 0
;Si el salto no es de vuestro gusto, podeis ajustarlo a ojo.
*=$2000 ;Sprite puntero 128*64 =#8192-$2000
BYTE 0,124,0,0,68,0,0,66,0,0,100,0,0,24,0,1,248,96,3,30
BYTE 192,2,27,128,0,25,128,0,24,0,0,24,0,0,24,0,0,24,0,0
BYTE 24,0,0,30,0,0,27,0,0,49,0,3,225,0,3,1,0,2,1,128
BYTE 2,1,192,0
;Variables
eje byte 100 ;Valor fijo de la posición del sprite.
freno0 byte 0 ;Para el freno
freno1 byte 0 ;Para el freno
Como se puede ver , he usado una herramienta para crear la tabla del salto. Se llama SINUS CREATOR. Es muy sencilla de usar . CBM prg STUDIO 3.8.0 lleva una herramienta similar pero tengo que aprender a usarla.
El programa se explica por si mismo, pero cualquier duda, ya sabeis donde estamos.
-
Yo odio esos saltos angulares!
-
Yo odio esos saltos angulares!
Yo también XD.
Pero no sirve solamente para hacer saltos , sirve también para mover enemigos con más naturalidad y muchas otras cosas. El límite es vuestra imaginación.
-
Hola de nuevo gente.
Otra chorradilla que espero os sea de interes y sobre todo, útil.
;CBM prg STUDIO
; 10 SYS (4096)
*=$0801
BYTE $0E, $08, $0A, $00, $9E, $20, $28, $34, $30, $39, $36, $29, $00, $00, $00
;-----------------------------------------------------------------------------------------
;BLoque cabecera cartucho
;$8000 el LOBYTE del arranque del programa. Arranque en frio.
;$8001 el HIBYTE del arranque del programa normalmente $8009.
;$8002 el LOBYTE de la direccion de RESET o EXIT INTERRUPT. Arranque en caliente.
;$8003 el HIBYTE de la direccion de RESET o EXIT INTERRUPT normalmente $FEBC
;$8004 Caracter C $C3
;$8005 Caracter B $C2
;$8006 Caracter M $CD
;$8007 Caracter 8 $38
;$8008 Caracter 0 $30
;$8009 El progama empieza aqui.
*=$8000
byte $09,$80,$20,$80,$c3,$c2,$cd,$38,$30
*=$8009
;Al pulsar RESET salta a esta rutina.
main inc $d021 ;fondo
jmp main
*=$8020 ;AL pulsar RUNSTOP+RESTORE o RESTORE, salta a esta rutina
main2 inc $D020 ;marco
jmp main2
*=$1000 ;Programa principal.
;Incrementa los colores de fondo y marco.
main3 inc $d020
inc $d021
jmp main3
Al colocar en la dirección $8000 (es la que una un cartucho cuando está insertado) la cabecera de un cartucho, podemos controlar lo que hacer cuando alguíen pulsa RESET, RESTORE o RUNSTOP/RESTORE cambiando los vectores.
Podeis o bién, volver a arrancar vuestro programa o poner un aviso de "esto no se toca,piratilla" o lo que deseéis.
Como siempre, creo que el programa en si se explica solo a base de los comentarios.
Ahora a dormir que ya son las 2:37h.
-
Ahora a dormir que ya son las 2:37h.
Esas horas en que mejor rinde uno :)
-
Se puede hacer uso de tablas para hacer el salto algo más natural o "redondo" (y para muchisimas otras cosas interesantes).
Aquí dejo este pequeño ejemplo, como siempre lo más sencillo que sé hacerlo (tampoco llego a mucho más XD) para una fácil comprensión.
Buenisimo, grandes progresos.
Hice un toolcito para hacer tablas también... no es nada del otro mundo, pero anda. Para los curiosos, esta aca: https://github.com/ricardoquesada/c64-misc/blob/master/tools/easing_table_generator.py
-
Python, ese lenguaje... ;-)
-
Buenisimo, grandes progresos.
Hice un toolcito para hacer tablas también... no es nada del otro mundo, pero anda. Para los curiosos, esta aca: https://github.com/ricardoquesada/c64-misc/blob/master/tools/easing_table_generator.py
Gracias!! Ando probando mil cosas mientras aprendo.
Me he bajado el PY , instalado el cliente 2.7.16 , lo abro con el shell ¿IDLE? y no arranca.
¿Que hay que hacer para compilar python? XD
-
No es un interprete? Me parece que hay que llamar a python con el nombre del .py como parametro, no?
-
Si, es como dijo pastabytes.
Abrí una terminal (el cmd.exe en Windows), y hacé:
c:> python easing_table_generator.py
-
OK. Text mode ;).
Bajo windows es un asco, no se instala el path hacia el bin y hay que ir hasta la carpeta donde esta.
-
Python desde Windows es incomodo, hay que instalar cosas y liarse...
-
No uso windows, pero usé Windows durante varios años y si mal no recuerdo el instalador de python te ponia todo en el path... quizas cambió.
más allá de eso, aprender un lenguaje script es muy util. desde esta boludez de poder generar tablitas para los saltos, hasta para parsear ciertos archivos SIDs, o manipular sprites, o lo que uno necesite.
las herramientas que hay para la c64 estan buenas, pero a veces no tiene lo que uno necesita... y ahí es donde python (o agregar cualquier otro lenguaje script) ayuda y mucho.
-
Yo pase de XP a Linux no hace tanto, pero el otro dia tuve que instalar un juego hecho en python en un PC Windows, y el instalador no agregaba python al path, pero daba la opcion de hacerlo, solo que habia que chequear una opcion que viene desactivada por defecto. Esta visible en la primera pantalla si no recuerdo mal, cuando se elige donde instalarlo, pero el que no lee y cliquea ok a todo no lo ve. :D
Seguramente se puede asignar el tipo de archivo .py a python y luego solo se abririan los programas con doble click, yo hice un acceso directo del .py llamando a python porque solo me interesaba correr eso. En Linux solo hago doble click en los .py y abren.
-
Cierto, a eso me refería. Algo que en otros SO es tan natural como abrir una imagen, en Windows se complica.
-
Aquí estamos de nuevo, todavía trasteando en ensamblador para tratar de que mi cerebro acabe de arrancar de una vez y me sea más fluido el programar, el tiempo que ha pasado desde que lo dejé, ha causado estragos :(.
En esta ocasión he creado un programa que permite mover una nave en 16 direcciones diferentes manejándola con el JOY en port 2. Mi intención es usar esto en un futuro juego donde intentaré hacer que la nave tenga inercias al girar y se le aplique gravedad para alterar su trayectoria y así, hacer las cosas más difíciles en el juego (y en la programación XD ).
Utilizo interrupciones para mover la nave y así, regular su velocidad de desplazamiento sin bucles de freno que consuman ciclos inútilmente, pero las utilizo solo para activar algunas rutinas en el tiempo de ejecución fuera de las interrupciones para mover los gráficos.
Es decir, no consumo tiempo de proceso durante las interrupciones, si no durante el proceso normal con la ventaja de evitar flicks al mover gráficos ya que se da el permiso justo cuando ha terminado de dibujar la pantalla .
Hago uso de tablas para manejar todo el cotarro usando el puntero del sprite a mover para tomar todas las decisiones necesarias. Seguro que había otra manera más complicada de hacerlo, pero no di con ella ;D
La creé y pulí durante los 4 días que duro RetroBarcelona, a ratos libres.
Las variables MovX0 y MovY0, son las que controlan la cantidad de veces a esperar antes de desplazar un eje o el otro para conseguir que se desplace en 16 direcciones diferentes .
DEjeX0 y DEjeY0 contienen la dirección hacia donde mover la nave. 0=nada, 1=positivo (incrementa eje) , 2=negativo (decrementa eje).
La barrita de color que aparece por debajo de la pantalla, en el marco inferior , indica el tiempo de ejecución de las rutinas dentro del tiempo de IRQ pero fuera del mismo , no sé si ha quedado claro con mi explicación anterior XD.
Como siempre, he intentado comentarlo todo lo que me ha sido posible , así que aquí os dejo el código. De seguro es muy mejorable, pero es una buena introducción a otra manera de hacer las cosas.
Aquí lo tenéis. Destripadlo, trastearlo, en fin, lo que os apetezca. También he hecho que se active o desactive el MSB del sprite0 para poder navegar por toda la pantalla sin problemas.
;CBM PRG STUDIO 3.8.0
;CONSTANTES UNIVERSALES
; $D000-$D010 SPRITE HORIZONTAL AND VERTICAL POSITION REGISTERS
SP0X = $D000 ; SPRITE 0 X POSITION
SP0Y = $D001 ; SPRITE 0 Y POSITION
SP1X = $D002 ; SPRITE 1 X POSITION
SP1Y = $D003 ; SPRITE 1 Y POSITION
SP2X = $D004 ; SPRITE 2 X POSITION
SP2Y = $D005 ; SPRITE 2 Y POSITION
SP3X = $D006 ; SPRITE 3 X POSITION
SP3Y = $D007 ; SPRITE 3 Y POSITION
SP4X = $D008 ; SPRITE 4 X POSITION
SP4Y = $D009 ; SPRITE 4 Y POSITION
SP5X = $D00A ; SPRITE 5 X POSITION
SP5Y = $D00B ; SPRITE 5 Y POSITION
SP6X = $D00C ; SPRITE 6 X POSITION
SP6Y = $D00D ; SPRITE 6 Y POSITION
SP7X = $D00E ; SPRITE 7 X POSITION
SP7Y = $D00F ; SPRITE 7 Y POSITION
MSIGX = $D010 ; MSB'S OF SPRITES 0-7 HORIZONTAL POSITIONS
; POINTER SPRITES
POINSP0 = $07F8 ; POINTER 2040 SPRITE O
POINSP1 = $07F9 ; POINTER 2041 SPRITE 1
POINSP2 = $07FA ; POINTER 2042 SPRITE 2
POINSP3 = $07FB ; POINTER 2043 SPRITE 3
POINSP4 = $07FC ; POINTER 2044 SPRITE 4
POINSP5 = $07FD ; POINTER 2045 SPRITE 5
POINSP6 = $07FE ; POINTER 2046 SPRITE 6
POINSP7 = $07FF ; POINTER 2047 SPRITE 7
; $D011-$D012 SCROLL & RASTER
SCROLY = $D011 ; VERTICAL FINE SCROLLING AND CONTROL REGISTER
RASTER = $D012 ; READ CURRENT RASTER SCAN LINE/WRITE LINE TO COMPARE
; FOR RASTER IRQ
SPENA = $D015 ; SPRITE ENABLE REGISTER
SCROLX = $D016 ; HORIZONTAL FINE SCROLLING AND CONTROL REGISTER
YXPAND = $D017 ; SPRITE VERTICAL EXPANSION REGISTER
VMCSB = $D018 ; VIC-II CHIP MEMORY CONTROL REGISTER
VICIRQ = $D019 ; VIC INTERRUPT FLAG REGISTER
IRQMSK = $D01A ; IRQ MASK REGISTER
SPBGPR = $D01B ; SPRITE TO FOREGROUND DISPLAY PRIORITY REGISTER
SPMC = $D01C ; SPRITE MULTICOLOR REGISTERS
XXPAND = $D01D ; SPRITE HORIZONTAL EXPANSION REGISTER
; $D01E-$D01F SPRITE COLLISION DETECTION REGISTERS
SPSPCL = $D01E ; SPRITE TO SPRITE COLLISION REGISTER
SPBGCL = $D01F ; SPRITE TO FOREGROUND COLLISION REGISTER
; $D020-$D026 VIC-II COLOR REGISTER
EXTCOL = $D020 ; BORDER COLOR REGISTER
BGCOL0 = $D021 ; BACKGROUND COLOR 0
SPMC0 = $D025 ; SPRITE MULTICOLOR 0
SPMC1 = $D026 ; SPRITE MULTICOLOR 1
; $D027-$D02E SPRITE COLOR REGISTERS
SP0COL = $D027 ; SPRITE 0 COLOR
SP1COL = $D028 ; SPRITE 1 COLOR
SP2COL = $D029 ; SPRITE 2 COLOR
SP3COL = $D02A ; SPRITE 3 COLOR
SP4COL = $D02B ; SPRITE 4 COLOR
SP5COL = $D02C ; SPRITE 5 COLOR
SP6COL = $D02D ; SPRITE 6 COLOR
SP7COL = $D02E ; SPRITE 7 COLOR
; $D02F-$D03F NOT CONNECTED
; $D040-$D3FF VIC-II REGISTER IMAGES
; $D419-$D41A GAME PADDLE INPUTS
; $D41D-$D41F NOT CONNECTED
; $D420-$D7FF SID REGISTER IMAGES
; $D800-$DBFF COLOR RAM
COLRAM = $D800
; $DC00-$DC0F CIA #1
CIAPRA = $DC00 ; DATA PORT REGISTER A
CIAPRB = $DC01 ; DATA PORT REGISTER B
CIDDRA = $DC02 ; DATA DIRECTION REGISTER A
CIDDRB = $DC03 ; DATA DIRECTION REGISTER B
CIASDR = $DC0C ; SERIAL DATA PORT
CIAICR = $DC0D ; INTERRUPT CONTROL REGISTER
CIACRA = $DC0E ; CONTROL REGISTER A
CIACRB = $DC0F ; CONTROL REGISTER B
; $DC10-$DCFF CIA #1 REGISTER IMAGES
; $DD00-$DD0F CIA #2
; $DD10-$DDFF CIA #2 REGISTER IMAGES
LECOL = $0286 ; LETTER COLOR
GETIN = $FFE4
;------------------------------------------------------------
; 10 SYS4096
*=$0801
BYTE $0B, $08, $0A, $00, $9E, $34, $30, $39, $36, $00, $00, $00
;------------------------------------------------------------
*=$1000
;Conectando y colocando sprite para pruebas
lda #1
sta SPENA
lda #192 ;$3800 ...#12288 $3000
sta POINSP0
lda #99
sta SP0X
sta SP0Y
lda #0 ;Fondo negro
sta $d021
lda #1 ;Multicolor ON sprite 1
sta SPMC
lda #1 ;Blanco
sta SP0COL
lda #2 ;Rojo
sta SPMC0
lda #6 ;Azul
sta SPMC1
;Activando interrupciones
sei
lda #%00011011 ;27 original. 26 no flickea.Hibyte del raster pero
sta $D011 ;si no es 27 aparecen "pelos" en los bordes pantalla.
lda #<irq
sta $0314
lda #>irq
sta $0315
lda #%00000001 ;#127 en el ejemplo. Basta con activar el timer A #1
sta $DC0D ;Registro control de la cia
lda #1
sta $D01A ;Registro mascara IRQ activada. IRQ ON.
lda #250 ;Altura del barrido
sta $d012
cli
jmp PREMAIN ;Pasamos al programa normal saltandonos la rutina de irq.
IRQ ;Programa ejecutado a cada interrupción.
lda $d019 ;Reset bandera irq
sta $d019 ;asi se desactiva la bandera y funcionan bien.
lda #1 ;Activando permiso de ejecucion fuera de pantalla (IRQ)
sta Permiso ;XD
jmp $EA81 ;Rutina interrupcion normal Leer teclado y demás.
;EA81 ;FEBC ;Saltar a restaurar a partir de la rutina NMI.
;------------------------------------------------------------
;RESERVA DE VARIABLES EN EL PROGRAMA.
;El programa empieza aquí.
PREMAIN lda #0
sta Dspr0 ;Pongo la nave en direccion hacia arriba (pruebas).
clc
adc #192
sta POINSP0 ;Cambio el puntero sprite.
jsr ResetEjeNaveX ;Iniciando valores X
jsr ResetEjeNavey ;Iniciando valores Y
;DESPLAZAMIENTO NAVE RESPETANDO IRQ.
MAIN
lda Permiso ;El raster esta a mas de 250?
bne sigue0 ;Si=1 activado. Salta a ejecutar las rutinas irq dentro del tiempo de programa normal.
jmp PASODEIRQ ;Si=0 desactivado. Me largo a ejecutar los programas fuera de las IRQ.
sigue0
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.
inc $d020 ;Testigo de la rutina (Borrable)Cambia el color del marco para ver cuanto tiempo ocupan los procesos.
;Leer joy2
dec frenjoy ;Freno joystick. Solo leé una vez cada 3 IRQ.
bne paso3 ;No=0, paso de leer
lda #3 ;Una vez cada 3 IRQ. Reconectar el freno. A mayor cifra, mayor arco decribe la nave.
sta FrenJoy ;xx ciclos antes de leeeer joy2
lda CIAPRA ;Leer joy2
and #15 ;Solo movimiento der e izq.
cmp #07 ;Derecha.
bne paso1 ;No es derecha, paso a izq.
clc ;Borrar bandera de acarreo.
inc DSpr0
lda DSpr0 ;Comprobando si pasa limite 15. La animación va del 0 al 15
cmp #16
bne paso2 ;Si no lo sobrepasa, pasa XD.
lda #00 ;como si lo sobrepara, lo pone a 0
sta DSpr0 ;y lo almacena.
jmp paso2
paso1 clc
cmp #11 ;Izquierda.
bne paso3 ;No es izquierda?. Paso de todo.
dec DSpr0
lda DSpr0 ;Comprobando si pasa del limite <0 (255)
cmp #255
bne paso2
lda #15 ;Le doy el nuevo valor para mostrar el ciclo correcto.
sta DSpr0
paso2 jsr ResetEjeNaveX ;Como se ha "movido", inicializo de nuevo los valores de movimiento y dirección
jsr ResetEjeNavey ;de X e Y.
paso3 ;Se acabo joys
lda DSpr0 ;Cojo su nuevo valor y cambio el sprite.
clc
adc #192 ;Le sumo el valor de puntero del primer sprite de la animación.
sta POINSP0
;Mover eje X
lda MovX0Temp ;Ciclos a esperar para mover el eje X
beq PasoEjeX0 ;Sin decrementar la variable. 0=No mover.
dec MovX0Temp
bne PasoEjeX0 ;Si aún no es =0, paso de mover.
lda DEjeX0Temp ;Dirección hacia donde mover la nave.
beq PasoEjeX0 ;Si=0, no mueve este eje.
cmp #01 ;1=Incrementa eje. 0=Decrementa eje.
bne DecEjeX0
lda SP0X
clc ;Desactiva la bandera de acarreo antes de sumar.
adc #01
bcc paso4 ;Hay desbordamiento?
tax ;Si lo hay: Guardo el valor de la coordenada.
jsr msbx0 ;Salto a activar el MSB del sprite0
txa ;Recupero el valor de la coordenada.
paso4 sta SP0X ;y la pongo en el eje X
jsr ResetEjeNaveX ;Como se ha movido el eje, paso a reiniciar los valores de freno y dirección.
jmp PasoEjeX0 ;Saltar hasta la rutina de mover eje Y
DecEjeX0
lda SP0X
sec ;Para restar hay que activar la bandera de acarreo.
sbc #01
bcs paso5 ;Sigue activado el acarreo?. =Si.Pasando de tocar el MSB.
tax ;Guardo el valor de la coordenada.
jsr msbx0 ;Salto a desactivar el MSB.
txa
paso5
sta SP0X
jsr ResetEjeNaveX ;Como se ha movido el eje, paso a reiniciar los valores de freno y dirección.
PasoEjeX0
;Mover eje Y. Lo mismo que con X pero al no tener que activar/desactivar el MSB, uso INC o DEC.
lda MovY0Temp
beq PasoEjeY0 ;Sin decrementar la variable. 0=No mover.
dec MovY0Temp
bne PasoEjeY0 ;Si aún no es =0, paso de mover.
lda DEjeY0Temp
beq PasoEjeY0 ;Si=0, no mueve este eje.
cmp #01
bne DecEjeY0
inc SP0Y
jsr ResetEjeNaveY
jmp PasoEjeY0
DecEjeY0
dec SP0Y
jsr ResetEjeNavey
PasoEjeY0
dec $d020 ;Testigo de la rutina (Borrable). Este debe ejecutarse al terminar con las rutinas que usen IRQ.
PASODEIRQ ;Final rutinas que usen IRQ.
;A PARTIR DE AQUÍ, SOLO RUTINAS LIBRES QUE SE EJECUTEN EL 100% DE CICLOS.
nop
nop
nop
jmp MAIN
;SUBRUTINAS .
;Cargar direccion de la nave y almacenar valores de dirección y bucles espera en sus respectivas variables.
ResetEjeNaveX
clc
ldx DSpr0 ;Carga direccion actual de la nave.
lda MovX0,x ;cargo valor fijo segun direccion
sta MovX0Temp ;y la guardo en el control de freno movimiento temporal X.
lda DEjeX0,x ;Cargo si suma o resta
sta DEjeX0Temp ;y la guardo en el control de dirección X.
rts
ResetEjeNavey
clc
ldx DSpr0 ;Carga direccion actual de la nave
lda MovY0,x ;cargo valor fijo segun dirección
sta MovY0Temp ;y la guardo en el control de freno movimiento temporal Y.
lda DEjeY0,x ;Cargo si suma o resta
sta DEjeY0Temp ;y la guardo en el control de dirección Y.
rts
;Activar o desactivar MSB sprite0
msbx0 clc
lda MSIGX
eor #01 ;ON/OFF byte 1
sta MSIGX
rts
MovX0 byte $00,$02,$01,$01,$01,$01,$01,$02,$00,$02,$01,$01,$01,$01,$01,$02 ;bucles de espera antes de desplazar eje sprite0
MovY0 byte $01,$01,$01,$02,$00,$02,$01,$01,$01,$01,$01,$02,$00,$02,$01,$01 ;Idem
DEjeX0 byte $00,$01,$01,$01,$01,$01,$01,$01,$00,$02,$02,$02,$02,$02,$02,$02 ;Direccion ejes para saber si restar o sumar ese eje. 0=resta / 1=Suma / 255=nada
DEjeY0 byte $02,$02,$02,$02,$00,$01,$01,$01,$01,$01,$01,$01,$00,$02,$02,$02 ;Idem
MovX0Temp byte $00 ;Variable
MovY0Temp byte $00 ;Variable
DEjeX0Temp byte $00 ;Variable
DEjeY0Temp byte $00 ;Variable
DSpr0 byte $00 ;DireccionSprite0
FrenJoy byte $10 ;Freno lectura joystick
Permiso byte $00 ;Ejecutar o no rutinas por IRQ
;-------------------------------------------------------------------------------------------------------------------------------------
*=$3000 ;Los 16 sprites de la nave (0-15). sprites V2 #192-#203
;12288/64=192
BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$08,$00,$00,$19,$00,$00,$0A,$00,$00,$36,$00,$00,$36,$00,$00,$3A,$00,$00,$EA,$80,$00,$F6,$80,$00,$D1,$80,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$81
BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$04,$00,$00,$02,$00,$00,$0D,$40,$00,$36,$00,$00,$FA,$00,$00,$EA,$00,$00,$56,$00,$00,$06,$00,$00,$06,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$81
BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$01,$00,$00,$02,$80,$00,$5D,$80,$00,$DD,$40,$00,$DB,$00,$00,$DA,$00,$00,$1A,$00,$00,$18,$00,$00,$08,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$81
BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$E0,$40,$00,$EA,$80,$00,$6D,$80,$00,$1D,$40,$00,$1A,$00,$00,$68,$00,$00,$60,$00,$00,$C0,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$81
BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$C0,$00,$00,$E1,$00,$00,$69,$00,$00,$36,$80,$00,$36,$80,$00,$69,$00,$00,$E1,$00,$00,$C0,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$81
BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$10,$00,$00,$E0,$00,$00,$68,$40,$00,$6A,$40,$03,$6D,$80,$03,$6D,$80,$03,$AA,$80,$00,$01,$00,$00,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$81
BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$18,$00,$00,$18,$00,$00,$1A,$00,$00,$5A,$40,$02,$FD,$00,$00,$BD,$80,$00,$2B,$80,$00,$02,$80,$00,$04,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$81
BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$02,$00,$00,$06,$00,$00,$16,$00,$00,$FA,$00,$00,$FA,$00,$00,$3D,$00,$00,$0D,$40,$00,$02,$00,$00,$04,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$81
BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$D1,$80,$00,$F6,$80,$00,$EA,$80,$00,$3A,$00,$00,$36,$00,$00,$36,$00,$00,$08,$00,$00,$19,$00,$00,$08,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$81
BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$34,$00,$00,$34,$00,$00,$39,$40,$00,$3A,$80,$00,$36,$80,$00,$36,$00,$00,$58,$00,$00,$20,$00,$00,$04,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$81
BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0D,$00,$00,$3D,$00,$00,$39,$00,$00,$29,$40,$00,$DA,$80,$00,$5A,$80,$00,$9A,$00,$00,$A0,$00,$00,$10,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$81
BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$03,$00,$00,$0E,$00,$00,$0D,$00,$00,$39,$00,$00,$69,$00,$00,$D9,$00,$03,$5A,$40,$02,$AA,$80,$00,$40,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$81
BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$03,$00,$00,$4B,$00,$00,$69,$00,$02,$D8,$00,$02,$D8,$00,$00,$6D,$00,$00,$4F,$00,$00,$03,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$81
BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$40,$00,$02,$AA,$80,$03,$5A,$40,$00,$D9,$00,$00,$69,$00,$00,$39,$00,$00,$0D,$00,$00,$0E,$00,$00,$03,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$81
BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$10,$00,$00,$A0,$00,$00,$9A,$00,$00,$5A,$80,$00,$DA,$80,$00,$29,$40,$00,$39,$00,$00,$3D,$00,$00,$0D,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$81
BYTE $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$04,$00,$00,$20,$00,$00,$58,$00,$00,$36,$00,$00,$36,$80,$00,$3A,$80,$00,$39,$40,$00,$34,$00,$00,$34,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$81
*=$4000 ;Pantalla de pruebas
;Desde #1104 hasta #2023 ($0450 hasta $07E7)
-
Superinteresante!!! ya lo miraré a ver que tal!
-
Mola la mosca :)
Pero más me gustaría poder mirar y entender tu código!
-
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.
-
Buenísima la explicación, parece una buena forma de plantear el esqueleto de un juego.
-
Muy bueno!!,...ademas al "sintaxis" que utilizas conecta mucho conmigo,..dame tiempo para compilarla, estudiarla y destriparla, hay cosas que me interesan.
Saludos Ferreos!
-
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.
-
He encontrado un error en mi código.
Ya lo he editado y solucionado.
;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.
-
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:
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
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.
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
-
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:
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)
; 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: