Commodore manía

Commodore 64 => Desarrollo => Ensamblador => Mensaje iniciado por: Laddh en Marzo 01, 2026, 19:23:33

Título: Movimiento de sprites dentro de un scroll de chars
Publicado por: Laddh en Marzo 01, 2026, 19:23:33
Una pregunta a los coders del foro, os pongo en situación, tengo un mapa de 4 pantallas en horizontal, hago un scroll izquierda y derecha, y quiero poner sprites enemigos en diversas plataformas y la pregunta es como  sincronizas el movimiento de los sprites para que vaya acorde al movimiento de la pantalla ( se mantengan en su plataforma, desaparezcan cuando esa parte del mapa no este en pantalla, etc ).
Alguna teoría, algoritmo o ejemplos sobre el tema? He buscado y no encuentro nada.
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: josepzin en Marzo 01, 2026, 20:24:13
Es una buena pregunta y tiene que haber tratados sobre eso.

Yo me imagino dos tipos de escenarios:
- Permanente: todos los sprites están vivos, moviendose por el mapa según su programación aunque el mapa esté en memoria
- Efímero: los enemigos se activan cuando están a X pixels de aparecer en pantalla y al salir de ese rango se reinician

Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: PacoBlog64 en Marzo 01, 2026, 21:39:38
Una pregunta a los coders del foro, os pongo en situación, tengo un mapa de 4 pantallas en horizontal, hago un scroll izquierda y derecha, y quiero poner sprites enemigos en diversas plataformas y la pregunta es como  sincronizas el movimiento de los sprites para que vaya acorde al movimiento de la pantalla ( se mantengan en su plataforma, desaparezcan cuando esa parte del mapa no este en pantalla, etc ).
Alguna teoría, algoritmo o ejemplos sobre el tema? He buscado y no encuentro nada.

Pues es algo que no he hecho nunca (al menos horizontalmente), pero a bote pronto se me ocurre guardar las coordenadas en X de cada sprite y de la pantalla actual de caracteres en formato 16bits, e ir comprobando si cada sprite tiene que mostrarse en la ventana gráfica actual. Con esta solución se debería traducir la dirección en 16bits o "absoluta" a la dirección de lo que se ve en pantalla (relativa al marco izquierdo de la pantalla), cuando un sprite tenga que salir en pantalla. No sé si me he explicado bien...
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: SingletonJohn en Marzo 01, 2026, 23:24:30
Una pregunta a los coders del foro, os pongo en situación, tengo un mapa de 4 pantallas en horizontal, hago un scroll izquierda y derecha, y quiero poner sprites enemigos en diversas plataformas y la pregunta es como  sincronizas el movimiento de los sprites para que vaya acorde al movimiento de la pantalla ( se mantengan en su plataforma, desaparezcan cuando esa parte del mapa no este en pantalla, etc ).
Alguna teoría, algoritmo o ejemplos sobre el tema? He buscado y no encuentro nada.

A las contestaciones de @PacoBlog64 y de @josepzin, que son MUY correctas, te recuerdo además que los sprites se pueden ocultar por detrás del borde, con lo cual su entrada y salida en pantalla es gradual. Es decir, para dibujar sus coordenadas en pantalla tienes que tener en cuenta que salen/se meten 24 pixels antes/después en horizontal y 50 pixels antes/después en vertical. La posición de coordenadas menores con el total de un sprite en pantalla es de (24,50) para la esquina superior izquierda
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: josepzin en Marzo 02, 2026, 03:30:11
De todos modos, seguramente laddh está buscando algo mas técnico y específico.
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: SingletonJohn en Marzo 02, 2026, 10:33:30
Yaaa....yo es por no estropearle la "peleilla". ;D
Las ideas principales son:
- El sprite tiene que tener una velocidad horizontal de la misma magnitud que la pantalla, pero en dirección opuesta. Por lo tanto, la velocidad del sprite en x es Vxsprite - Vxpantalla. Hayq ue tener en cuenta el signo de la velocidad, por supuesto, ya que si ambas velocidades tiene la misma dirección las maginitudes SE SUMARÁN y si son opuestas se restarán. Eso ya te lo da la fórmula. Para los enemigos estáticos, cuya Vxsprite = 0, su velocidad en PANTALLA será -Vxpantalla por lo tanto. Es lo que se llama una velocidad relativa a la pantalla. La velocidad en y del sprite será la propia del sprite, ya que NO HAY SCROLL VERTICAL
- Con esa velocidad, la coordenada del sprite sera X=X+Vx e Y=Y+Vy...eso como siempre
- Para situar las coordenadas del Sprite "en el mundo" yo empezaría por asignarle coordenadas del Tile correspondiente a la esquina superior izquierda del sprite. Para que aparezca en pantalla antes o después hay que tener en cuenta su tamaño. SI tienes sprites de diferentes tamaños, yo no me liaría y usaría siempre las mismas dimensiones, las estandar:24x21. Como el scroll es horizontal, tienes que tener en cuenta el borde de la pantalla(los sprites se representan por debajo de él) y ponerlos con una X=0 cuando queden 3 tiles para que "salgan" (3 tiles x 8 pixels/tile = 24, que es la anchura estándar del sprite y de los bordes derecho e izquierdo). No tienes que pensar nada parecido en vertical.
-Como los sprites se "PINTAN" debajo del borde, hay que tener en cuenta que desaparecen con una coordenada 0(por la izquierda, que es el "borde izquierdo bajo el borde izquierdo) o 24+40*8+1= 345, (que es cuando su esquina superior izquierda queda bajo el borde derecho). En ambos casos no hay ningún pixel del sprite en pantalla (salvo que no tengan puesto el x2 en X o en Y...o que no sean multisprite....en cualquiera de estos casos especiales, dinos y te ayudamos
-Las buenas prácticas con sprites de C64 te dicen que NO apagues el sprite...que los dejes bajo el borde y lo recicles para evitar ciclos perdidos y tirones
-Cómo se traducen las coordenadas del sprite desde coordenadas de tiles?Pues teniendo en cuenta el sistema diferente de coordenadas de los sprites (ya que su cero es distinto y se mueven al pixel).Las fórmulas serían Xsprite=24+8*Xtile Ysprite=50+8*Ytile(ya que los bordes superior e inferior son de 50 pixels.Una vez "conectado" el sprite, es más fácil ir operando con la velocidad de la pantalla, que es unica para todos, y la velocidad del propio sprite(que será cero si está "anclado al suelo"), que traducir las coordenadas, que es más lento. el sprite quedaría "desactivado" si su x se sale del rango [0,344). En Y su rango visible es desde 50-24 = 26 hasta 26+25*8+1 = 227, es decir [26, 227)
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: SingletonJohn en Marzo 02, 2026, 10:54:39
cómo se traduce "cuando queden 3 tiles para que salga el Sprite"? Pues fácil. pongamos que las coordenadas de la pantalla en el mundo son (20,0) (la coordenada Y de la pantalla SIEMPRE SERÁ cero en tu caso, porque la altura del mundo es de 1 pantalla).En pantalla se pintarán las columnas 20 a 59 del mundo.si hay sprites en los tiles de la columna 20-3 = 17, deberán asociarse a un sprite con una X=0 y su Y correspondiente -> Ysprite=50+8*Ytile (ya que los bordes supeior e inferior tienen 50 pixels de anchura en lo que a sprites se refiere)...et voilá!

Esto es más lío de explicar que de hacer....cualquier duda que vayas teniendo cuenta
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: Laddh en Marzo 02, 2026, 11:09:27
Vaya.., gracias por todas estas anotaciones, me las apunto y a ver si las puedo aplicar.
El tema tiles sigue siendo una de mis asignaturas pendientes, aún no ha caído en mis manos un source que me explique claro (no soy bueno con la teoría, solo aprendo cuando veo un ejemplo práctico que expone y se ve lo que hace)
Voy con la "peleilla"  ;)
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: SingletonJohn en Marzo 02, 2026, 11:13:04
Para las multiplicaciones en ensamblador. Lo vemos con las fórmulas de las coordenadas del sprite en funcióna de las del tile:
Xsprite = 24 + 8*Xtile => Xsprite = 8*3 + 8*Xtile ; Xsprite = 8*(Xtile + 3); Xsprite = 3ASL(Xtile + 3).
Es decir en ensamblador

LDA Xtile
CLC
ADC #$3
ASL
ASL
ASL


y ya tienes la X del sprite!
(NOTA: Multiplicar por dos equivale a una rotación de 1 BIT a la izquierda en binario. Por eso 8*=2*2*2=3ASL

(estamos hablando de tiles de 8x8 pixels, of course. Si fueran de 2x2 chars, sustituir el 8 inicial por un 16 ,esto es Xsprite=24+16*Xtile, y ver cómo simplificar la operación en ensamblador)
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: SingletonJohn en Marzo 02, 2026, 11:22:49
Vaya.., gracias por todas estas anotaciones, me las apunto y a ver si las puedo aplicar.
El tema tiles sigue siendo una de mis asignaturas pendientes, aún no ha caído en mis manos un source que me explique claro (no soy bueno con la teoría, solo aprendo cuando veo un ejemplo práctico que expone y se ve lo que hace)
Voy con la "peleilla"  ;)
El tema Tiles está tirado. EL C64 en modo "normal" está preparado para textos, luego puedes definir un juego de caracteres que sean los tiles del juego(256 diferentes simultáneos). La pantalla será entonces una matriz de 25*40 bytes (1000 bytes) y en cada uno de esos bytes te cabe un número entre 0 y 255, que es la posición del tile en el charset: posición 0->@, posición 1->A, etc ,etc...este número es el ScreenCode del Char

Es decir, aunque suene ANTINATURAL, para escribir una Z en la esquina zuperior izquierda de la pantalla tienes que pokear:Poke1024,26. La pantalla estándar está en $400->1024 y la Z es el screen code 26

Los colores de cada char están en $D800 y también son 1000 bytes porque la correspondencia es 1 a 1 con la pantalla....es un "gemelo" de la pantalla con el valor de sus colores (colores de pixels sólo, no de fondo). Es decir, el byte cero de la pantalla tiene un color representado en el byte cero de la ColorRam($D800 o 55.296). Vamos, que si quieres pintar la Z de antes de color blanco, tienes que poner POKE55296,1

Esta es la base de los tiles...pero puedes tener diferentes modos de tile además del "por defecto"....tienes el tile multicolor y el modo "con color de fondo extendido" que básicamente funcionan igual, pero con "ciertas peculiaridades"
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: Laddh en Marzo 02, 2026, 11:31:05
El tema Tiles está tirado. EL C64 en modo "normal" está preparado para textos, luego puedes definir un juego de caracteres que sean los tiles del juego(256 diferentes simultáneos). La pantalla será entonces una matriz de 25*40 bytes (1000 bytes) y en cada uno de esos bytes te cabe un número entre 0 y 255, que es la posición del tile en el charset: posición 0->@, posición 1->A, etc ,etc...este número es el ScreenCode del Char

Es decir, aunque suene ANTINATURAL, para escribir una Z en la esquina zuperior izquierda de la pantalla tienes que pokear:Poke1024,154. La pantalla estándar está en $400->1024 y la Z es el screen code 154

Huumm, esto que explicas es para el manejo de chars normales, no? Los tiles son grupos de chars (2*2,3*3,etc) que es lo que aun no se aplicar
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: SingletonJohn en Marzo 02, 2026, 11:45:25
Es lo mismo, pero tienes que definir el TileSet de 2x2(por ejemplo) con la misma filosofía del charset.
Es decir, defines en memoria un lugar para esos tiles y los pones todos seguidos (lo mismo que el charset). Apuntarás por ejemplo, que el tile 0 es "abcd"....bueno, mejor dicho"1,2,3,4"...y así con todos uno tras otro
Tu pantalla de tiles tendrá ahora un tamaño de 20x12=240 bytes (procura no tener MáS de 255 tiles diferentes), que es MUCHO menos de 1000 bytes....es decir, se comprime la imagen

También tendrás que tener unas rutinas de pintado que cuando vean un cero, vayan a la tabla de tiles y lean"1,2,3,4"...y pinten en pantalla
AB
CD
...y tengan en cuenta que la pantalla de tiles tiene ahora 20 columnas y 12 filas

Esto es la base....pero puedes modificarla a conveniencia....por ejemplo....imagina que sólo tienes 16 tiles diferentes de 2x2. En cada Byte te caben 2 tiles, por lo que la definición de cada pantalla ahora será de 240/2 = 120 bytes, aunque la operativa de la "recuperación" se complica algo (no demasiado, para el espacio que se gana)
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: SingletonJohn en Marzo 02, 2026, 11:50:53
un tile de 3x3 yo JAMÁS lo definiría.....porque un ordenador "piensa" y almacena en binario, que es la matemática del 2,4,8,16, etc

Un 3x3=9 es MUCHO MAS complicado de gestionar porque los datos quedan totalmente "desalineados"...o si no, pierdes memoria metiendo ceros para "alinearlos"...y multiplicar por 3 o por 9 es mucho más complicado que por 2 o por 4

resumiendo..haría tiles de 1x1, 2x2, 4x4, 8x8, 4x2, etc
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: SingletonJohn en Marzo 02, 2026, 11:57:57
Es lo mismo, pero tienes que definir el TileSet de 2x2(por ejemplo) con la misma filosofía del charset.
Es decir, defines en memoria un lugar para esos tiles y los pones todos seguidos (lo mismo que el charset). Apuntarás por ejemplo, que el tile 0 es "abcd"....bueno, mejor dicho"1,2,3,4"...y así con todos uno tras otro...

Una vez que tienes claro esto y lo manejas con soltura (y siguiendo el ejemplo del tileSet de 2x2), YA CREAS EL CHARSET con el orden correcto: para el primer tile, el cero, defines en los 8x4=32 bytes el "dibujo de la A, la B, la C y la D"....y ya no tienes por qué tener un charset y un tileset "en paralelo"....tu programa en ensamblador verá el charset de 32 en 32 bytes y lo  pintará en el orden y coordenadas correctas con los scripts definidos antes, ya que para la rutina de pintar, los chars son de 32 bytes y la definición de pantalla es de 20x12

Esto son ideas...si te interesa tener a la vez tiles de diferentes tamaños, no te queda otra que definir un tileset por tamaño....aunque el tamaño de 4x4, es en realidad de 2x2 de tiles de 2x2....jejeje...parece un trabalenguas, pero ahorras MUCHO espacio

Con varios tilesets de diferentes tamaños, ahora sólo te queda idear una manera de marcarlos de alguna manera en la definición de la pantalla para poder recuperarlos....para esto hay muchas técnicas diferentes y dependerá del número de tiles en cada tileset, de cuantos bits te quedan libres en cada byte para poder usarlos de FLAG o de marcador de tamaño de tile, etc...o quizás uses un criterio POSICIONAL, es decir, los 20 primeros tiles son de 2x2, los 20 siguientes de 8x8, etc

En esto de la informática, yo te aconsejo que vayas de lo fácil a lo difícil, es decir, intenta probar a definir un tileset de 2x2 sobre el charset estándar del C64 (para empezar)  y vas creando poco a poco las rutinas y las vas complicando a medida que entiendes y dominas la base...yo te puedo soltar el chorizo de ensamblador y de fórmulas y de timings y no te enterarás de nada si te dan eso de salida

Aquí te podemos ayudar bastante en el proceso si vas sacando las dudas
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: Laddh en Marzo 02, 2026, 14:36:44
Pues muchas gracias, haré mis pinitos en cuanto a los tiles con tus indicaciones, aparte de seguir con lo que estaba, me has dado faena  ;D
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: SingletonJohn en Marzo 02, 2026, 16:00:39
Otra cosa importante, para cuando tengas que "definir" o "dibujar" el charset base de los tiles.
Hay dos rangos de memoria en el que no podrías meterlo, ya que el "cableado" del charset estándar te lo taparía, aunque el charset esté oculto (que es como está normalmente). Estos rangos son:
-$1000 a $1FFF (es decir el cableado del charset en el banco 0 del VIC)
-$9000 a $9FFF (es decir, el cableado del charset en el banco 2 del VIC)

Si te fijas, ambos cableados están en la posición relativa +$1000 y tienen $1000 bytes de tamaño, esto es 4096 bytes->4k->2k del charset "modo dibujo" y 2k del charset "máquina de escribir". Por lo tanto las posiciones 2 y 3 de las 8 posibles en el banco 0 y el banco 2, están PROHIBIDAS para la definición base del tileset. Tendrías que coger la 0,1,4,5,6 o 7 ....o usar otro banco

Observa que digo "prohibidas para un charset", ya que el cableado sólo afecta al charset que el VIC ve, en esas posiciones puedes poner código o definiciones de sprites o lo que sea, que puedes acceder a ello sin problemas

Esto aparece comentado el la Guía Oficial del Programador del C64 en 3.PROGRAMMING GRAPHICS - Graphic Locations - Character Memory (página 104)
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: Laddh en Marzo 02, 2026, 16:08:33
No hay problema, ya hace tiempo me acostumbre a que el VIC apunte siempre al banco 1, así pongo los chars editados que necesite donde quiera dentro de ese banco
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: SingletonJohn en Marzo 02, 2026, 16:13:36
Apunta siempre al banco 0->0000 a 16384. Recuerda que el charset estándar está cableado entre 4096 a 8191 (posiciones 2 y 3  del VIC, de las 8 posibles)
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: SingletonJohn en Marzo 02, 2026, 16:18:24
a esto me refiero...

Y recuerda que en el banco 0, no debes poner el charset en la posición cero (ya que está la página cero, la pila y la pantalla en posición estándar). Y en la posición 1 tampoco (o con mucho cuidado y dejando sin definir los primeros chars), ya que en $800 (2048) se inicia el basic, por lo que si usas un cargador, ojo con no pisarle hasta que se haya ejecutado
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: SingletonJohn en Marzo 02, 2026, 16:55:27
jajaja....estoy constantemente corrigiendo....hablo de memoria y al mirar los papeles veo que he metido el cuezo!

Perdona por el caos
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: SingletonJohn en Marzo 12, 2026, 08:18:12
Cómo lo llevas @Laddh ?

Qué tal va la cosa, has avanzado algo?
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: Laddh en Marzo 12, 2026, 11:48:54
Hola, pues de lo que pregunté y los tiles aún no he llegado, primero tengo que acabar de pulir el scroll de un bigmap de 4 pantallas en horizontal que ya he conseguido que los chars los muestre bien pixel a pixel pero no se porque el color me falla y produce unos destellos, y eso que hago doble buffer y no apunto a la pantalla hasta que esta hecho, te pongo el .prg para que lo veas, es más fácil de ver que explicar.
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: javierglez en Marzo 12, 2026, 12:30:05
No sigo muy bien el tema pero la memoria de color no tiene doble bufer. Para cambios en la memoria de color, si tienes alguna interrupción raster, quizá cambiando el orden de ejecucion de los distintos bloques de código.
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: SingletonJohn en Marzo 12, 2026, 16:00:34
Hola, pues de lo que pregunté y los tiles aún no he llegado, primero tengo que acabar de pulir el scroll de un bigmap de 4 pantallas en horizontal que ya he conseguido que los chars los muestre bien pixel a pixel pero no se porque el color me falla y produce unos destellos, y eso que hago doble buffer y no apunto a la pantalla hasta que esta hecho, te pongo el .prg para que lo veas, es más fácil de ver que explicar.

Efectivamente @javierglez tiene razón: sólo hay una Color Ram en 55296 ($D800, ahí está toda la info del color, a no ser que estés en modo multicolor o enhanced background color o Bitmap(o cualquier modo "no oficial"). La manera correcta de proceder es ir pintando el siguiente fotograma en el dobble buffer (mientras usas el scroll hardware te suele dar tiempo), y, en el momento en que toque, hacer el scroll de la Color RAM (que los colores acompañen a los tiles) y redireccionar el VIC al nuevo frame. Hay que hacer un movimiento de 1000 bytes en la Color Ram, por lo que le da tiempo de sobra al 6510. La clave es CUANDO

Los 1000 bytes del color da tiempo de sobra a moverlos desde que el raster entra en la primera línea del borde inferior hasta que vuelve a entrar por la primera línea superior de la pantalla (la primera tras el borde superior). EL cambio de VIC al buffer es casi inmediato, eso si, como es casi inmediato hay que hacerlo cuando el raster esta saliendo por el borde inferior de la pantalla. Yo he hecho las dos cosas sin problema. Eso si, conviene al inicio del juego, coordinar las interrupciones por tiempo (las que tengas para música, sonido, lectura del teclado, etc) con las del raster, y darles la misma frecuencia.

Esta coordinación se puede hacer al arrancar el juego, y sería tan "sencillo" como programar una interrupción de raster en la primera línea del borde inferior, y justo en esa interrupción, cambiar la frecuencia de la interrupción por tiempo a la del Raster y poner el "cronómetro" a cero y eliminar la interrupción por raster (esto NO ES DEL TODO EXACTO, pero si ves que cada cierto tiempo hay flickering, puedes ir corrigiéndolo, en las muertes, en los cambios de fase, etc...) De esta manera, en cada interrupción puedes hacer lo que sea necesario, tanto de gráficos como de cualquier otra cosa (sonido, animaciones, movimiento de sprites, etc)

@Laddh , si puedes pásanos mejor el código fuente o un archivo .d64 con los binarios (aunque esto último es más incómodo, ya que habría que descompilar, etc... si optas por archivo binario, no estaría de más un archivo de etiquetas o un mapa de memoria del juego etc...para que se puede entender bien el desensamblado


Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: SingletonJohn en Marzo 12, 2026, 17:16:52
Veo que la rutina del movimiento de bytes está en $8c0 y que usas el modo de direccionamiento indirecto indexado. Veo además que intentas pintar el buffer y mover el color A LA VEZ, y por eso el raster te pillla enseguida. La mejor estrategia es pintar los tiles en el buffer en momentos en los que el procesador "está libre" mientras usas el scroll hardware (tienes más de un frame para hacerlo). Y en el momento que el Raster toca el borde inferior, hacer el scroll SOLO del color y cambiar de pantalla a buffer y vuelta a empezar.

También veo que debes tener dos espacios de 1000 bytes para mover el color: uno un buffer de lectura (puntero en $f7) y el otro de escritura en el D800 (puntero $f9)....a ver creo que sólo necesitas leer el buffer de color para la línea de tiles que entra. El resto de bytes YA ESTAN EN LA PANTALLA, con lo que los puedes mover de una forma mucho más rápida que con el indirect indexed....la Color RAM SIEMPRE está en $D800, no te hace falta una Indirect Indexed, ya que tienes que coger un tile en la color ram, pongamos que en $D805 y ponerlo en $D804 (o viceversa, según el scroll se mueva a derecha o izquierda) y repetirlo 1000 veces.

Si no quieres cambiar la rutina de mover el color, lo que si puedes hacer es empezar a mover el color Justo cuando el ráster entre en la primera fila de pixels de la segunda línea de tiles ($D828) e ir POR DETRÁS DE ÉL...con lo que tendrás MUUUUCHO mas tiempo que esperando a que esté en el borde inferior. Sólo deberías esperar a este momento justo para cambiar pantalla por buffer, ya que tarda unos 5 ciclos de reloj (el tiempo que tardas en cambiar el valor  del screen pointer)
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: Laddh en Marzo 12, 2026, 17:25:11
Je, te me has adelantado, te estaba escribiendo esto:

Te he aislado el programa solo con la parte que concierne al scroll para clarificar mejor.
Las rutinas importantes son las Bigmap, que escriben la pantalla entera en $4400 o $6400 (trabajo con el banco 1) después del scroll por hardware y a la de color.
Con el JOY 2 te mueves izq y der.
En $a000 esta en mapa de 4 pantallas de chars creado con el charpad y en $b000 el mapa de color, en $7000 los chars.
Código: [Seleccionar]
; 10 SYS (2064)

*=$0801

        BYTE    $0E, $08, $0A, $00, $9E, $20, $28,  $32, $30, $36, $34, $29, $00, $00, $00

*=$0810

zp=$f9
zs=$fb
screen=$4400
screen2=$6400
maptab=$a000

zpc=$f7
zc=$fd
colortab=$b000
color=$d800

screen_control_register1 = $d011
screen_control_register2 = $d016


        lda 1   ;quita el basic
        and #%11111110
        sta 1

        jsr PANCHAR
        jsr pantalla
        jsr int

init    jsr bigmap1
        jsr bigmap2
        LDA $D018
        AND #15
        ORA #144  ;POSICIÓN PANTALLA DENTRO DEL BANCO1 $6400
        STA $D018

        LDA screen_control_register2
        AND #$F7    ;38 columnas
        STA screen_control_register2

lg      jsr raster_wait ;Loop game
        jsr PlayerControl
        jmp lg

PlayerControl
                  lda #4      ;Read LEFT on joystick port 2
                  bit $dc00
                  bne NotDENLeft
        jsr right ;muevecajai

NotDENLeft                 
                  lda #8      ;Read RIGHT on joystick port 2
                  bit $dc00
                  bne NotDENRight
        jsr left ;muevecajad
NotDENRight   
      rts

bigmap1
        lda #<maptab
        sta zp 
        lda #>maptab
        sta zp+1

        lda #<colortab
        sta zpc 
        lda #>colortab
        sta zpc+1

fixcol  lda cornrx
        clc
        adc zp
        sta zp
        lda #0
        adc zp+1
        sta zp+1
       
        lda cornrx
        clc
        adc zpc
        sta zpc
        lda #0
        adc zpc+1
        sta zpc+1

        lda #<screen
        sta zs
        lda #>screen
        sta zs+1

        lda #<color
        sta zc
        lda #>color
        sta zc+1

        lda lines
        sta countr
storlp  ldy cols
inloop  lda (zp),y
        sta (zs),y

        lda (zpc),y
        sta (zc),y

        dey
        bpl inloop
           
        clc
        lda zp
        adc width
        sta zp
        lda #0
        adc zp+1
        sta zp+1
        clc
        lda zs
        adc #40
        sta zs
       
        clc
        lda zpc
        adc width
        sta zpc
        lda #0
        adc zpc+1
        sta zpc+1
        clc
        lda zc
        adc #40
        sta zc

        bcc fdg
        inc zs+1
        inc zc+1

fdg     dec countr
        bpl storlp

        rts

bigmap2
        lda #<maptab
        sta zp 
        lda #>maptab
        sta zp+1

        lda #<colortab
        sta zpc 
        lda #>colortab
        sta zpc+1

fixcol2  lda cornrx
        clc
        adc zp
        sta zp
        lda #0
        adc zp+1
        sta zp+1
       
        lda cornrx
        clc
        adc zpc
        sta zpc
        lda #0
        adc zpc+1
        sta zpc+1

        lda #<screen2
        sta zs
        lda #>screen2
        sta zs+1

        lda #<color
        sta zc
        lda #>color
        sta zc+1

        lda lines
        sta countr
storlp2  ldy cols
inloop2  lda (zp),y
        sta (zs),y

        lda (zpc),y
        sta (zc),y

        dey
        bpl inloop2
           
        clc
        lda zp
        adc width
        sta zp
        lda #0
        adc zp+1
        sta zp+1
        clc
        lda zs
        adc #40
        sta zs
       
        clc
        lda zpc
        adc width
        sta zpc
        lda #0
        adc zpc+1
        sta zpc+1
        clc
        lda zc
        adc #40
        sta zc

        bcc fdg2
        inc zs+1
        inc zc+1

fdg2     dec countr
        bpl storlp2

sale2   rts

left   
        ldx cornrx
        cpx maxx
        beq sale2
    LDX screen_offset
    DEX
    STX screen_offset
    CPX #$FF
    BEQ continue
    JMP end
continue
    LDX #$07
    STX screen_offset
        jsr move_rows_left
end     
    LDA screen_control_register2
    AND #$F8
    ORA screen_offset
    STA screen_control_register2
    rts

move_rows_left
        inc cornrx
        jsr swap_bigmap
        jsr swap_video
sale3   rts
screen_offset byte $07

right
        ldx cornrx
        beq sale3
    LDX screen_offset_r
    inx
    STX screen_offset_r
    CPX #8
    Beq continuer
    JMP endr
continuer
    LDX #$00
    STX screen_offset_r
        jsr move_rows_right
endr 
    LDA screen_control_register2
    AND #$F8
    ORA screen_offset_r
    STA screen_control_register2
@sal        rts

move_rows_right
        dec cornrx
        jsr swap_bigmap
        jsr swap_video
        rts
screen_offset_r byte $00

swap_video
        lda cp
        beq pantalla1
        bne pantalla2
        rts
pantalla1
        LDA $D018
        AND #15
        ORA #16  ;POSICIÓN PANTALLA DENTRO DEL BANCO1 $4400
        STA $D018
        lda #1
        sta cp
        rts
pantalla2
        LDA $D018
        AND #15
        ORA #144  ;POSICIÓN PANTALLA DENTRO DEL BANCO1 $6400
        STA $D018
        lda #0
        sta cp
        rts
cp      byte 0

swap_bigmap
        lda bm
        beq bm1
        bne bm2
        rts
bm1
        jsr bigmap1
        lda #1
        sta bm
        rts
bm2
        jsr bigmap2
        lda #0
        sta bm
        rts
bm      byte 0

raster_wait               ;espera línea raster
l         LDA  #$ff
          CMP  $D012
          BNE  l
          BIT  $d011
          BMI  l
          rts

PANCHAR   LDA  56578
          ORA  #3        ;PREPARAMOS PARA SELECCIONAR EL @@@
          STA  56578
          LDA  56576
          AND  #252
          ORA  #2        ; @@@ BANCO DE VIDEO 1 (16384)
          STA  56576
; COMO MEMORIA PANTALLA SE QUEDA EN SU POSICIÓN POR DEFECTO, NO LA CAMBIAMOS
;        LDA $D018
;        AND #15
;        ORA #16  ;POSICIÓN PANTALLA DENTRO DEL BANCO
;        STA $D018
; SI QUISIERAMOS EL CURSOR
;        LDA #68 ;CURSOR PANTALLA EN BANCO 1
;        STA 648

          LDA  $D018
          AND  #240      ;ESTABLECEMOS EL MODO CARACTER
          ORA  #12       ;BUSCA CARACTERES A PARTIR DE 12288 + DIR BANCO 1
          STA  $D018
;        LDA $D016
;        ORA #16  ;MODO CARACTER MULTICOLOR
;        STA $D016
         RTS

pantalla
        lda #11
        sta $d020
        sta $d021
        lda #8
        sta $d022
        lda #10
        sta $d023
        rts

INT     sei
         lda #<n1
        sta $0314
        lda #>n1
        sta $0315
;        lda #$00
;        jsr $1000 ;Initialize music
         lda #$7f
         sta $dc0d
         sta $dd0d
 
         lda #$01  ;IRQ speeder
         sta $d01a
        cli
        RTS

N1      asl $d019 ; IRQ speeder again
        lda $dc0d
        sta $dd0d ; Stabilize CIA

;        jsr $1003;Play the music
        jmp $ea31 ;7e

width   byte 160
height  byte 22 ;25 normal total lineas pantalla vertical
lines   byte 21;22-1
cols    byte 39 ;40-1

cornrx  byte 0
cornry  byte 0
maxx    byte 120 ;160-40 total mapa x menos pantalla (40 carac)
maxy    byte 0   ;25-25 total mapa y menos pantalla (25 carac)
countr  byte 0
countr2  byte 0


*=$7000  ;28672 ;CARACTERES EN BANCO 1 (12288 + 16384)
incbin    "chars2.bin"

*=$a000
incbin"map.bin"
*=$b000
incbin"colormap.bin"
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: SingletonJohn en Marzo 12, 2026, 17:52:30
Varias ideas que te pueden ayudar:

-Pon música e interrupciones raster en la misma rutina de interrupción y coordínalas. Eso es mejor que esperar al raster, que tienes al procesador ocioso esperando el momento (raster_wait). De esta forma, coordinando ambas cosas, no pierdes tiempo. Si al entrar en la rutina de interrupción ves que hay que hacer el scroll de color y cambiar pantalla por buffer, pues lo haces. Si no, pues no....usando las variables que tienes mismamente lo podrías hacer

-Para hacer el scroll de color VE POR DETRÁS del raster...es decir, cuando el ráster esté pintando la segunda fila de tiles, empieza a mover el color de la primera fila....ganarás un tiempo enorme. Y justo al final del scroll de color, cambia el pointer de la pantalla. Lo más seguro es que se haga con el raster fuera de pantalla y no se note. Esto es ya es cuestión de AJUSTE FINO (o de renunciar a un fps de 60. Hasta 21 fps la percepción del scroll es suave).Por lo tanto, me desdigo del rollo anterior y sincroniza las interrupciones con el ráster entrando en la segunda fila de chars.

-Ve pintando el buffer con el frame siguiente mientras usas el scroll hardware. Por ejemplo, si pintas 1/3 de pantalla cada vez, lo tienes listo en 3 frames y luego el procesador está libre para otras cosas

-Investiga o intenta crear una rutina de movimiento de color/tiles más eficiente que una indirecta indexada...si vas ganando 1 ciclo en cada pixel, cada 4 pixels te sale uno de gratis. Por ejemplo, en vez de usar indirect indexed, puedes probar una absoluta que se vaya automodificando (y ganas 1 ciclo por cada operación de lectura o de escritura)....como vas a mover 1000 bytes, necesitas hacer 1000 operaciones de lectura y 1000 de escritura.....la diferencia es NOTABLE. Además es una rutina CRUCIAL. En un rato te pongo un ejemplo

 
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: SingletonJohn en Marzo 12, 2026, 18:48:05
Mira esta rutina, que es una rutina de esas que son bucles "desenrollados". Tómalo como un ejemplo, fijo que hay rutinas mucho mejores

La primera columa es la dirección de memoria en la que se aloja. La segunda columna los bytes que ocupa. La tercera columna es el tiempo que tarda (en ciclos de procesador). La cuarta no influye...es el número de línea

Cada par de LDA/STA es una línea, luego este bloque se repetirá 25 veces y ocupa 6 bytes. Entonces tienes una rutina de 25*6 + 2 + 6 = 158 bytes...es asumible en términos de espacio.

cada bloque de LDA/STA tarda unos 10 ciclos. por lo tanto 25 líneas tardarán 250 ciclos. Como la rutina se repite 38 veces (ldy #39 estaría mal), tarda en moverte los 1000 bytes de color = 38 * 250 = 9500 ciclos
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: SingletonJohn en Marzo 12, 2026, 18:58:44
Analicemos ahora la tuya, teniendo en cuenta sólo que movemos color:

En términos de espacio ocupa $947- $91D = $2A = 42 bytes....ahorro importante de espacio

Analicemos el tiempo:

el bloque $920-925 se repite 39 veces por línea. Una ejecución tarda 18 ciclos, luego una línea tarda 18*39 = 702. Como son 25 líneas de color, ese bloque tarda 25*702 = 17550 ciclos.

el otro bloque se repite 24 veces (1 por línea). Como el bloque tarda unos 44 ciclos aprox -> 44 *24 = 1056 ciclos.

Por lo tanto, en mover 1000 bytes tardas 1056 + 17550 = 18606

es decir, tardamos 18606 ciclos frente a 9500....es algo menos del doble de tiempo....creo que puede compensar si no andas PILLADÍSIMO de espacio
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: SingletonJohn en Marzo 12, 2026, 19:09:34
Ahora vamos a hacer un cálculo "poco fino".
El raster tarda en cada frame 1/60 segundos                                          = 0,0167   segundos
Tu rutina inicial tarda en ejecutarse 18606 ciclos/1000000 ciclos/segundo = 0,0186   segundos (te pilla)
Con la rutina "Desenrollada" tardas 9500 ciclos/1000000                         = 0,0095 segundos (te libras y tienes tiempo de sobra de meter la nueva columna de color por la derecha o por la izquierda)

Luego compensa sacrificar 158*2 = 316 bytes (158 en scroll left y 158 en scroll right)
O puede que no.....que andes pillado de memoria y prefieras sacrificar framerate...
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: SingletonJohn en Marzo 12, 2026, 19:39:21
Otra buena opción es coger la rutina "desenrollada" y probar a convertirla en una rutina Automodificable. Es decir, cada 38 repeticiones del bloque, sumas 40 a $801 y lo sobreescribes. Le restas uno y lo sobreescibes a $800 y vuelves a lanzar el blucle....así 25 veces

La rutina será algo más lenta (aún así más rápida que una indirect indexed, me atrevería a decir) pero ocupará MUCHO MENOS de los 158 bytes

 
...y antes de ejecutar la rutina, tienes que volver a poner $801 en la memoria $94B-$94C y 800 en $94E-$94F (para hacer eso pondrías etiquetas). Por ejemplo

source:
lda $801,y
target:
sta $800,y


el Low byte de $801 estaría en source+1($01) y el high byte en source+2($08) (ya que las instrucciones del 6510 son de 1 byte). Lo mismo para $800 (target+1($00) y target+2($08))
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: SingletonJohn en Marzo 12, 2026, 19:50:08
Y si desarrollas en PC...pues te aconsejo que aprendas a manejar el C64 debugger.....es ULTRAPOTENTE y puedes ver en directo todas estas cosas

Un artículo que habla de él y te da los links de descarga

https://programacion-retro-c64.blog/2022/08/07/c64-debugger/

Usándolo, te puedo decir que el raster te pilla en la tercera línea de tiles cada vez que haces scroll....por eso se ven esas cosas raras cuando mueves bytes
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: SingletonJohn en Marzo 12, 2026, 21:57:22
Otra cosa que no sé si sabes @Laddh!

Algo tan inocente como esto que pongo en la imagen...lo compilo y....MIRA EL TAMAÑO. Te lo digo porque lo he visto en tu main.prg, que vas metiendo sprtiteSheet, charset, etc, en distintos lugares con la etiqueta *=

entre el LDA #4 y el LDA #5, el programa llena todo de ceros....es decir tenemos un programa de 4 bytes útiles, y el resto de los 47.107 son ceros que van a la cinta/diskette y luego van a la memoria.
Si quieres cargar cosas diferentes en diferentes bloques sin llenar de ceros todo lo de enmedio, hay que hacer varios files en binario y un loader que los  vaya cargando
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: SingletonJohn en Marzo 12, 2026, 22:08:05
Aquí se puede ver el archivo con la BURRADA en todo su esplendor: 47K de ceros (salvo 6 bytes)

Los dos primeros(01 08, recuadrados en morado) que es la dirección en donde va a meter el programa al cargar ($801), los dos segundos (a9, 04, que es LDA #$04).....luego un montón de ceros y los dos ultimos bytes, 47 K de ceros después (a9, 05, que es LDA #$5)

Así que OJO!!!
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: Jeff en Marzo 12, 2026, 23:10:32
Estos programas tipo ICU64 y el retrodebuguwr y el C64Debuguer…. No me tiran en condiciones.
Además… me parecen muy complicados para entender lo que sucede.
A veces los empleo para ver donde se van cargando los bloques de memoria, de manera visual, pero en cuando empieza a ejecutarse el programa… ya es un lío para seguimos.
Habría que hacer un programa en YouTube de cómo usarlos y sacarles un poco de jugo.
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: Laddh en Marzo 12, 2026, 23:31:03
Buuuffff! Que porrón de información..., tengo que releerme con tranquilidad todo el hilo y ver si lo puedo ir aplicando.
Gracias  @SingletonJohn, de verdad, tengo entretenimiento para rato  ;)
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: Laddh en Marzo 12, 2026, 23:35:28
Ah! en cuanto a lo del espacio vacío entre una cosa y otra, no hay problema, se que lo voy a llenar!
Título: Re:Movimiento de sprites dentro de un scroll de chars
Publicado por: SingletonJohn en Marzo 12, 2026, 23:36:57
Estos programas tipo ICU64 y el retrodebuguwr y el C64Debuguer…. No me tiran en condiciones.
Además… me parecen muy complicados para entender lo que sucede.
A veces los empleo para ver donde se van cargando los bloques de memoria, de manera visual, pero en cuando empieza a ejecutarse el programa… ya es un lío para seguimos.
Habría que hacer un programa en YouTube de cómo usarlos y sacarles un poco de jugo.

El C64Debugger lo conozco bien y es una PASADA. Pero hay que dedicarle tiempo. Coger el manual, cargar el debugger (a ser posible con programas hechos por ti o alguno sencillo) y ponerse a cacharrearlo

Ah! en cuanto a lo del espacio vacío entre una cosa y otra, no hay problema, se que lo voy a llenar!
:):):)