Commodore manía
Commodore 64 => Desarrollo => Ensamblador => Mensaje iniciado por: riq en Julio 07, 2015, 23:14:51
-
¡Hola programadores!
Esto no pretende ser un curso de assembler, ni nada parecido.
Solo quiero compartir con Uds. las cosas que voy aprendiendo mientras desarrollo un jueguito. Nada de lo que les voy a contar es nuevo... todo respecto a la c64 ya esta descubierto y bien detallado en codebase64 y otros sitios. De hecho, es de ahí de donde yo aprendo casi todo de la c64.
¿Entonces por qué hago esto si ya esta todo descubierto? Bueno, porque no todo lo que esta en codebase64 se entiende facilmente. Creo que varios artículos presuponen que uno sabe ciertas cosas, y cuesta bastante seguirlos. Y además porque tengo ganas de hacerlo :)
Yendo al grano, mi primer aprendizaje es...
Cómo hacer un IRQ estable
Si alguna vez trataron de hacer un "raster bar", o un simple scroll fino usando IRQ, habrán notado que la primer linea del raster hace "flicker"... es como que se corre a veces un poco hacia la derecha, o la izquierda y no se sabe bien porque.
Lo que aprendí estos días, es saber porqué pasa eso, y como prevenirlo y de esa manera lograr efectos que se vean bien.
Así es como se ve la intro del jueguito que estoy haciendo:
(https://lh3.googleusercontent.com/-RvjtDMhKTq8/VZwfNp02USI/AAAAAAABTPQ/7Gg3Qc9FoSY/s640/the-race-aprendiendo.png)
Basicamente tiene 4 IRQs (Código https://github.com/ricardoquesada/c64-the-race/blob/ec5f2f6b6ec8e1b4c4ad32ca95834af1398aead2/src/intro.s#L108 (https://github.com/ricardoquesada/c64-the-race/blob/ec5f2f6b6ec8e1b4c4ad32ca95834af1398aead2/src/intro.s#L108) )
irq1: Pone una barrita violeta. Pone color gris de fondo. Comienza el scroll fino de arriba.
irq2: Pone una barrita violeta. Cambia los colores a negro. Termina el scroll fino.
irq3: Comienza el scroll fino de abajo y pone color gris de fondo.
irq4: Termina con el scroll fino y pone los colores a negro nuevamente.
Parece sencillo, pero para poner las barritas violetas me costó una eternidad.
El tema es que cuando uno esta dentro de una IRQ, el "raster beam" (o haz de luz... no se como se traduce) se sigue moviendo, entonces hay que cambiar los colores en los momentos justos.
(http://static1.squarespace.com/static/511651d6e4b0a31c035e30aa/t/5178e819e4b0bf1bde30ed23/1366878234203/dustlayer.com-screen-raster-cycles.png?format=1500w)
( Para saber bien qué es el raster y demás recomiendo leer este articulo: http://dustlayer.com/vic-ii/2013/4/25/vic-ii-for-beginners-beyond-the-screen-rasters-cycle )
Para simplificar las cosas, vamos a asumir que tenemos una c64 PAL (no NTSC).
Del gráfico se puede ver que el raster para hacer una linea entera tarda 63 ciclos de CPU. Y lo más interesante de todo que hay momentos en los que el raster no es visible.
Y es justamente en esos momentos cuando uno tiene que cambiar el color del fondo de pantalla... porque sino el color aparece cortado.
Ejemplo: Aca la barra violeta aparece "cortada"...y es que cambié el color mientras el "raster beam" estaba por la mitad.
(https://lh3.googleusercontent.com/-HnEeXrKFuww/VZwrBohX3kI/AAAAAAABTQI/HxItIECi78c/s800/the-race-raster-not-aligned.png)
Entonces la teoría es sencilla: cambiar el color cuando el "raster beam" esta invisible.
Ciclos, interrupciones y demás:
Cuando uno instala una interrupción raster, uno no puede saber con exactitud cuantos ciclos fueron ejecutados por la siguiente razón:
Supongamos que tengo mi IRQ instalado, y en estoy ejecutando en mi ciclo principal un código que hace algo.
Justo en ese momento se prende mi IRQ ("raster beam" esta en la posición deseada).
El tema es que como la CPU puede estar ejecutando una instrucción, hay que dejar que se termine de ejecutar esa instrucción para que se llama a mi IRQ. Y eso consume ciclos.
Y como hay instrucciones de hasta 7 ciclos, cuando se llama a mi IRQ yo no se cuantos ciclos entre 0 y 7 se ejecutaron de más.
Y es exactamente por este motivo que a veces los raster bars o efectos hacen "flicker"... ya que a veces estan corridos 0, 1, ... y hasta 7 ciclos hacia la "derecha".
Lo que aprendí es que hay varias técnicas para hacer el raster estable: http://codebase64.org/doku.php?id=base:making_stable_raster_routines (http://codebase64.org/doku.php?id=base:making_stable_raster_routines)
Pero la que yo estoy usando en la intro es la "doble IRQ": Basicamente uso una IRQ para lograr que la CPU esta ejecutando un NOP cuando se produzca la siguiente IRQ. Eso se logra poniendo varios NOPs dentro de la primera IRQ, y luego nunca volver (no usar "rti"). De esa manera me garantizo que solo va a haber entre 0 y 1 ciclos de diferencia (y no hasta 7 como antes)... y luego ese ciclo de "sobra" se arregla con una comparación.
Los detalles están aca: http://codebase64.org/doku.php?id=base:stable_raster_routine (http://codebase64.org/doku.php?id=base:stable_raster_routine) Si alguien no entiende algo de la técnica "Doble IRQ" con gusto lo explico.
Y eso... basicamente para poner esas 2 barras violetas, tuve que aprender a usar la "doble IRQ" y contar ciclos :)
-
En su momento jugué con el raster pero no a ese nivel.
Muchas gracias por colgar el código. Ahora toca estudiarlo. ;)
A ver si me animo a colgar algunas rutinas útiles para noveles como yo.
-
Este hilo va a ser MUY interesante :)
-
Las famosas "bad lines"
¿Qué carajo son las "bad lines"?
Algo que molesta mucho, pero al parecer se pueden hacer trucos muy buenos abusando de estas. Pero vamos a lo que nos importa:
Antes dije que el raster beam tardaba 63 ciclos en recorrer una linea de pantalla horizontalmente. Y eso sigue siendo verdad... pero cada 8 lineas, el VIC se consume como 40 ciclos para leer los punteros a los caracteres de esa linea. O sea que no siempre tenemos 63 ciclos por "raster line".
El algoritmo es:
// pseudo code
// puede que tenga que compara con 7 o 5 en vez de con 0... no hice muchas pruebas aún.
if (($d012 & scroll_fino_vertical) ==0)
tengo_23_ciclos();
else
tengo_63_ciclos();
¿y por qué molestan las Bad Lines? Basicamente si yo quiero cambiar el color de fondo en cada "raster line", lo que tengo que hacer es:
1) cambiar color
2) consumir los ciclos necesarios hasta llegar a 63
3) comparar si es el último color
4) si no, volver a 1)
Pero eso no funciona con las bad lines, porque cada 8 lines, solo tengo alrededor de 20 ciclos. Esto es lo que pasa:
(https://lh3.googleusercontent.com/-Bv21kZ6_bSE/VZyEyfxooQI/AAAAAAABTQw/r6sBpetjF24/s640/bad-lines.png)
Como pueden ver, cada 8 lineas, se desfasa todo porque estoy consumiendo 63 ciclos en vez de ~20.
Intenté comparar si estaba en una bad-line, y consumir solo ~20 ciclos... pero no me daban los ciclos ya que cada instrucción consume ciclos, y hacer todo ese calculo era muy caro.
Así que probé una rutinita distinta. Algo asi como esto:
; los ciclos consumidos estan a la derecha
; raster bars
ldx #0
: lda $d012 ; +4
cmp $d012 ; +4
beq *-3 ; +2
; wait for new raster line, change color then
lda raster_colors,x ; +4
sta $d021 ; +4
inx
cmp #$ff
bne :- ; +3
Y casi funciona bien...
(https://lh3.googleusercontent.com/-uvb40UWzEE8/VZyFDTKDywI/AAAAAAABTRA/-r7lzqyc6iw/s400/bad-lines2.png)
Pero si prestan atención cada 8 lineas se repite una linea (las malditas bad lines). Mucho mejor que el test anterior, pero molesto aún.
Todavía no se como solucionar este problema... lo que hice, es que en vez de modificar el color en cada linea, lo modifica cada 2, y así esta todo uniforme.
El código para dibujar cada 2 lineas es muy similar al anterior:
; raster bars
ldx #0
: lda $d012 ; +4
clc ; +2
adc #$02 ; +2
cmp $d012 ; +4
bne *-3 ; +2
; wait for new raster line, change color then
lda raster_colors,x ; +4
sta $d021 ; +4
inx ; +2
cmp #$ff ; +2
bne :- ; +3
El resultado final en la intro es algo así:
(https://lh3.googleusercontent.com/-KH5N3LYRLpI/VZyIeNJtRhI/AAAAAAABTRM/v2ep9fVOluk/s400/the-race-intro-colors.png)
La última versión del PRG siempre la van a poder bajar de aca: https://www.dropbox.com/s/x2grp14do6w4jyb/therace.prg?dl=0 (https://www.dropbox.com/s/x2grp14do6w4jyb/therace.prg?dl=0)
Y el código fuente siempre va a estar aca: https://github.com/ricardoquesada/c64-the-race (https://github.com/ricardoquesada/c64-the-race)
Muy buena información sobre las "bad lines" se puede encontrar aca: http://www.zimmers.net/cbmpics/cbm/c64/vic-ii.txt (http://www.zimmers.net/cbmpics/cbm/c64/vic-ii.txt)
-
No tenía ni pero ni idea de esto...
-
Desenrollando bucles
Ja ja... la solución era mucho más fácil de lo que creía :-)
El algoritmo que había presentado era el correcto, pero había que desenrollar el bucle. ¿Qué significa eso?
// pseudo código. Código enrollado:
for (int i=0;i<4;i++)
inc $d020
; Mismo algoritmo pero con el bucle desenrollado
; me ahorro las comparaciones. Ocupa más espacio, pero es más rápido.
inc $d020
inc $d020
inc $d020
inc $d020
Eso hace que uno se ahorra las comparaciones (recordemos que solo tengo ~20 ciclos), y si bien el código es más feo y ocupa más bytes, es más rápido.
Al final el código me quedó así. Son 3 "repeats" anidados:
; 9 lines per char
.repeat 9
; 7 "buenas" lineas: Tengo que consumir 63 ciclos
.repeat 7
inx ; +2
lda raster_colors,x ; +4
sta $d021 ; +4
.repeat 25
nop ; +2 * 30
.endrepeat
bit $00 ; +3 = 63 ciclos
.endrepeat
; 1 "linea mala": Tengo que consumir 20 ciclos
inx ; +2
lda raster_colors,x ; +4
sta $d021 ; +4
.repeat 5
nop ; +2 * 5 = 20 ciclos
.endrepeat
.endrepeat
Gracias al poder de las macros, el código no es tan horrible y el resultado visual el que quería: Un color por linea sin que haya lineas duplicadas y sin "desfasajes":
(https://lh3.googleusercontent.com/-Yh_hhNNb0e4/VZyrte5Hq-I/AAAAAAABTRg/b-LIXI41gy0/s400/unrolling-loop.png)
Creo recordar que en este video hablaban que había que desenrollar todo para tener velocidad en la c64: https://www.youtube.com/watch?v=po9IY5Kf0Mo (https://www.youtube.com/watch?v=po9IY5Kf0Mo)
Aclaración: Hacer "raster bars" en el borde ($d020) es más fácil que en el fondo ($d021) ya que no se nota el desfasaje por las "bad lines"... el desfasaje esta, pero no se nota.
-
Me mata no saber inglés :-[
Pero lo que explicas es "semicomprensible" para mi. Esta claro que tengo que practicar con ello para poder entenderlo del todo.
-
@maniako: cualquier duda que tengas, preguntá nomás.
-
Supongo que eso se podria traducir como "desenrrollando bucles", y deduzco que es una manera de ver al bucle como un rollo de papel que tiene tantas capas como iteraciones tiene el bucle, al desenrrollarlo queda un codigo mas largo con lo mismo repetido varias veces.
Y si, cuando se necesita velocidad o tiempos muy criticos o predecibles, se suele escribir el codigo repetido varias veces aunque los cambios entre una y otra repeticion sean minimos, por lo general solo parametros distintos.
-
@pastbytes:
gracias. corregido.
Disculpen si a veces uso algunas palabras en ingles, pero es que muchas veces no se cual es la palabra en español. No se bien porque, pero por alguna razón en Argentina se usan muchas palabras del ingles en el mundo de la programación, sumado que al comienzo (digamos hace 20 años) los libros de programación que se conseguian en Argentina eran todos en ingles.
-
Cargando un archivo Koala
Se pueden usar varios modos gráficos en la Commodore 64: http://www.studiostyle.sk/dmagic/gallery/gfxmodes.htm (http://www.studiostyle.sk/dmagic/gallery/gfxmodes.htm)
pero yo solo se usar los oficiales: o sea el "bitmap alta resolución" y el "bitmap multicolor".
Y parece que en la C64 había un programa de dibujo llamado Koala Paint que generaba un formato bastante sencillo para los archivos que generaba.
Basicamente primero guardaba la información del bitmap, luego la definición de los colores %01, %10, luego del color %11, y luego el color del fondo (%00).
- bitmap (160x200/4) = 8000 bytes. Son 2 bits por color. Y se define por "celdas" de 8x8.
- color %01 y %10: (40x25) = 1000 bytes
- color %11: (40x25) = 1000 bytes
- color %00: 1 byte.
Más información sobre este modo aca: http://dustlayer.com/vic-ii/2013/4/26/vic-ii-for-beginners-screen-modes-cheaper-by-the-dozen
La rutinita para poner los colores en su lugar es esta, bastante sencilla:
;--------------------------------------------------------------------------
; init_koala_colors(void)
;--------------------------------------------------------------------------
; Args: -
; puts the koala colors in the correct address
; Assumes that bimap data was loaded in the correct position
;--------------------------------------------------------------------------
.proc init_koala_colors
KOALA_BITMAP_DATA = __GFX_LOAD__
KOALA_CHARMEM_DATA = KOALA_BITMAP_DATA + $1f40
KOALA_COLORMEM_DATA = KOALA_BITMAP_DATA + $2328
KOALA_BACKGROUND_DATA = KOALA_BITMAP_DATA + $2710
; Koala format
; bitmap: $0000 - $1f3f = $1f40 ( 8000) bytes
; color %01 - %10: $1f40 - $2327 = $03e8 ( 1000) bytes
; color %11: $2328 - $270f = $03e8 ( 1000) bytes
; color %00: $2710 = 1 ( 1) byte
; total: $2710 (10001) bytes
ldx #$00
@loop:
; $0400: colors %01, %10
lda KOALA_CHARMEM_DATA,x
sta $0400,x
lda KOALA_CHARMEM_DATA+$0100,x
sta $0400+$0100,x
lda KOALA_CHARMEM_DATA+$0200,x
sta $0400+$0200,x
lda KOALA_CHARMEM_DATA+$02e8,x
sta $0400+$02e8,x
; $d800: color %11
lda KOALA_COLORMEM_DATA,x
sta $d800,x
lda KOALA_COLORMEM_DATA+$0100,x
sta $d800+$100,x
lda KOALA_COLORMEM_DATA+$0200,x
sta $d800+$200,x
lda KOALA_COLORMEM_DATA+$02e8,x
sta $d800+$02e8,x
inx
bne @loop
lda KOALA_BACKGROUND_DATA
sta $d021
rts
.endproc
El programa que estoy usando para generar imagenes Koalas es Timanthes: http://csdb.dk/release/?id=75871 Esta bueno, pero no es trivial como generar koalas validos.
En algún momento me gustaría aprender a generar y cargar imágenes avanzadas como la FLI y demás... pero sera en el futuro.
Mientras tanto estoy contento con el modo "160x200x16".
(https://lh3.googleusercontent.com/-T5EoWKFRW5U/VaNbp-FTiVI/AAAAAAABTV0/2L7yt4vX8p4/s400-Ic42/Screen%252520Shot%2525202015-07-12%252520at%25252011.21.06%252520PM.png)
Así va quedando la intro del jueguito.
-
El tema del Raster es algo que desconozco y que tengo que aprender a medio plazo si o si,..por desgracia ahora estoy incomunicado por un virus y muchos de los enlaces del hilo no puedo verlos,..pero el hilo se le ve interesantisimo..
Cuando tenga solucionado el problema prometo estudiarme el hilo porque aparte necesito por peles dominar ésta tecnica.
Chao-
-
Llevo ya dos semanas peleandome con este tema y esto es a lo que he llegado gracias a un libro en pdf.
;Escrito con CBM prg studio
; 10 SYS (4096)
*=$801
BYTE $0E, $08, $0A, $00, $9E, $20, $28, $34, $30, $39, $36, $29, $00, $00, $00
*=$1000
sei ;Stop IRQ's
lda #27
sta $D011 ;53265 Registro de contrl del VIC-II 00011011
lda<inte ;Guardando lobyte direccion del programa
sta$0314 ;Desviando al programa hibyte
lda>inte ;Guardando hibyte direccion del programa
sta$0315 ;Desviando al prorama lobyte
lda #127
sta $DC0D ;56333 Registro control CIA 01111111
lda#129
sta $D01A ;53274 Registro mascara IRQ 10000001
cli ;Start IRQ's
rts ;Vuelta al basic
inte LDA #$01
STA $D019 ;Bandera de registro de IRQ. Activa bit 0 para comparacion de barrido
LDX #$92 ;Altura del barrido para poner el negro
LDY #$02 ;06 ;Color primera mitad pantalla
LDA $D012 ;Valor de barrido para comparar en IRQ
BPL aa ;Si es positivo...(<127)
LDX #$32;01 32 justo empieza parte sup. pantalla ;Altura de barrido para la primera pantalla
LDY #$00 ;Color segunda mitad pantalla.
aa STX $D012 ;Nuevo valor de barrido para comparar en IRQ.
STY $D021 ;Color de fondo 0 o 2 segun sea.
LDA $DC0D ;Registro de control de la CIA
AND #$01 ;Bit interrupcion timer A.
BEQ bb ;Si no esta activado pasando
JMP $EA31 ;Rutina ROM interrupt.
bb JMP $FEBC ;Continua con lo suyo.
Es lo mas sencillo que he llegado a comprender al 70%. Lo que hace Riq es de otro universo paralelo para mi ;)
-
Pues fijate para un Carnicero,...en cualquier caso lo importante es EL HIERRO!!! y luchar y luchar y aunque perezcamos en la batalla moriremos combatiendo!!,...ja,j,aj,aj,ja
Tengo que probar todas estas rutinas,..buff se me acumula el trabajo, como siempre!!
saludos.
-
@maniako: Va bien eso. Una pequeña optimización que podes hacer, es en vez de esperar que el raster llegue a cierta linea, le podes decir que el IRQ se llame cuando el raster este en una linea determinada:
; irq raster que se llame en la linea $80
lda #$80
sta $d012
; setear la irq
lda #<inter
sta $0314
lda #>inter
sta $0315
una cosa que me llamó la atención es que estas haciendo:
;
lda #127
sta $dc0d
... probablemente sea correcto y este perfecto. Pero yo no lo había visto antes dentro la rutina de IRQ. Pero ojo, yo tampoco tengo mucha experiencia en esto asi que como dije, probablemente este perfecto llamarla.
-
Riq, a buen profesional le preguntas ;D ;D ;D
Buscaba una rutina comprensible y simple, sin paja y polvo para destriparla. Venia con un cargador en basic, abri el monitor del VICE y copié la rutina.
Como digo, no lo comprendo del todo y sigo dandole palos para ver por y para que es todo.
Esta rutina hace lo que comentas, pero si puedo hacerla mas simple mejor.
-
Pues fijate para un Carnicero,...en cualquier caso lo importante es EL HIERRO!!! y luchar y luchar y aunque perezcamos en la batalla moriremos combatiendo!!,...ja,j,aj,aj,ja
Tengo que probar todas estas rutinas,..buff se me acumula el trabajo, como siempre!!
saludos.
Me pasa igual. Solo tengo las noches para trastear y aprender. Por desgracia (o no), ser autodidacta consiste en encontrar las 1000 maneras diferentes de hacerlo mal para saber hacerlo bién. ;)
Por eso creé el hilo de rutinas mas o menos útiles. Con rutinas sencillas se aprende y yo las necesito muuuuuy simples ::)
-
La importancia de no saltar de página
La documentación del 6502/6510 dice que LDA $FFFF,x y STA $FFFF,x tardan 4 ciclos... salvo que se salta de página, y ahí tarda 5 ciclos.
( http://unusedino.de/ec64/technical/aay/c64/blda.htm )
La verdad que nunca le presté atención a ese detalle hasta hace unos días atras cuando noté que por alguna razón la "raster bar" no estaba sincronizada.
No entendia bien porque, hasta que me di cuenta que estaba haciendo el "salto de página" cuando accedia a esa memoria. Asi que lo único que tuve que hacer es poner los colores en la direccion para que haya salto de página.
El salto de página es algo así como:
*=$0800
ldx #00
loop:
lda colores,x
sta $d800,x
inx
cpx #16
bne loop
*=$5f8
colores: .byte 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
El color 8, salta de página... va la página $0500 a las $0600, y eso hace que esa operación tarde un ciclo más.
Respecto a esto, algo que aprendí a querer, son los segmentos del ca65... al principio me parecian que agregaban complejidad innecesaria, pero ahora que el proyecto se agrando, puedo mapear los segmentos a los lugares que necesito sin tener que cambiar el código. Asi es como se ven mis segmentos ahora, donde tengo en memoria 2 partes del juego: la pantalla del menu principal, y la pantalla del about
SEGMENTS {
SIDMUSIC: load = RAM, type = rw, start = $1000, optional = yes, define = yes;
#
# About:
# GFX $2000 - $2710 (Koala)
# CHARSET $4800 - $4fff
#
ABOUT_GFX: load = RAM, type = rw, start = $2000, optional = yes, define = yes;
ABOUT_CHARSET: load = RAM, type = rw, start = $4800, optional = yes, define = yes;
ABOUT_CODE: load = RAM, type = rw, start = $5000, optional = yes, define = yes;
ABOUT_DATA: load = RAM, type = rw, start = $6000, optional = yes, define = yes;
#
# Main Screen:
# SCREEN $8400 - $87FE
# CHARSET $8800 - $8FFF
#
MAIN_CODE: load = RAM, type = rw, start = $7000, optional = yes, define = yes;
MAIN_SCREEN: load = RAM, type = rw, start = $8400, optional = yes, define = yes;
MAIN_CHARSET: load = RAM, type = rw, start = $8800, optional = yes, define = yes;
}
de esta manera, si quiero cambiar la posición de algunos segmentos porque necesito usar la memoria de una manera diferente, solo tengo que editar un solo archivo en vez de editar varios.
-
Conversores de imagenes
Estuve usando Timanthes para convertir imágenes a formato Koala. Si bien el resultado estaba bien, Project One v0.5 es muy superior.
Project One no lo pude hacer andar en un Windows 8.1, pero me anduvo muy bien en una Mac con Wine instalado. El único truco es que hay que instalar gdiplus usando winetricks.
Y yo mucho más contento usando Wine que Windows ya que mi computadora principal es una Mac.
Asi me quedó el grafico luego de haberlo convertido con Project One:
(https://lh3.googleusercontent.com/-ffY6ZEI_p1c/VbUGNvmho5I/AAAAAAABTb4/3PtJxJx1gHk/s640-Ic42/Screen%252520Shot%2525202015-07-26%252520at%2525209.06.11%252520AM.png)
Project One tiene muchicismas más opciones para convertir imagenes y la el resultado es mucho mejor!
Downloads:
* Project One v0.5: http://csdb.dk/release/?id=39261
* Timanthes: http://csdb.dk/release/?id=75871
-
Comparandola con la otra si, se ve mucho mejor. Mas colorida y ahora se ve el monociclo.
Tengo un block de notas que no deja de crecer con recomendaciones.
-
La imagen mejoró muchísimo! quizás tiene demasiado gris de fondo.
A ver que tal ese Project One
-
Muchas gracias Riq por tan interesante aporte, soy cepecero (diría más bien que multisistemas en la actualidad) aunque me gustaría hacer algo para el C64 en un futuro.
-
Bancos de memoria: $1000 y $9000
Esto que voy a decir esta documentado en varios lados, pero yo por alguna razón me lo había prestado suficiente atención.
Como sabrán la C64 tiene 64k de RAM, pero el chip VIC solo puede ver 16k a la vez. Entonces para decirle al VIC que uso cierta parte de la memoria uno simplemente cambia el banco:
Por ejemplo, para usar el banco de $8000 - $BFFF se hace esto:
; Vic bank 2: $8000-$BFFF
lda $dd00
and #$fc
ora #1
sta $dd00
y eso hace que la pantalla, sprites y demas, que normalmente estan en el banco 0, ahora esten en el banco 2.
Pero si uno usa los bancos 0, 2 ($0000-$3FFFF y $8000-$BFFF) no se pueden usar la direcciones que estan entre $1000-$1FFF y $9000-$9FFFF para poner sprites, graficos y charsets. Cuando le dicen al VIC que use esas direcciones, los lee de la ROM en vez de la RAM.
El jueguito va tomando forma... aún no hay jueguito, pero al menos ahora tiene un menu principal y un "choose rider".
https://www.dropbox.com/s/x2grp14do6w4jyb/therace.prg?dl=0
-
Va tomando forma.
Me suena a Boulder Dash esa tipografía, ¿puede ser??
Sobre los bancos y lo de leer la ROM, ¿puede ser que haya algun truco para usar alguno de esos espacios? me suena algo el tema...
-
Si, bien ahí. Son los fonts del Boulderdash... estoy tratando de darle un look muy retro al jueguito. Lo que quiero hacer es un juego que se parezca a los juegos del '82 / '83.
Quiero poner graficos y efectos muy muy básicos... Estoy un poco cansado de los jueguitos del iPhone / Android que dicen ser retros... entonces lo que quiero hacer es un juego "retro retro"... es decir, hacer un juego en una plataforma retro (la c64), y que el juego en si mismo sea retro para esa plataforma.
Entonces cuando alguien me diga "mira el super jueguito retro que tengo para el iPhone"... yo les voy a decir "Y mira el jueguito retro retro que hice yo para la c-64" :-)
Si, esos espacios se usan para poner código, o música... de hecho el espacio $1000 generalmente se usa para música... pero no los uses para poner nada que requiera que VIC los lea.
-
Vaya motivos para hacer un juego!! :D :P
-
Si, bien ahí. Son los fonts del Boulderdash...
Es que soy un gran fan de ese juego.
estoy tratando de darle un look muy retro al jueguito. Lo que quiero hacer es un juego que se parezca a los juegos del '82 / '83.
A ver si lo consigues, los juegos de esa época tienen un sabor distinto.
-
... los juegos de esa época tienen un sabor distinto.
Ahora entiendo el porqué no conservais nada de esa época, OS LOS COMIAIS!!! :o
-
Capitán Literal al ataqueee! :-P
-
Vaya motivos para hacer un juego!! :D :P
Ja. La idea del juego fue mutando mucho... Desde hacer un juego de olimpiadas de monociclo par la PC, hasta a hacer el "muni race" en formato "retro retro" para la C64. Pero nada garantiza que es la idea final... quizas el mes que viene vuelva a cambiar de parecer :)
-
¿Porqué lo de "muni"?, mi cerebro está contaminado y al leer "muni" inmediatamente veo el diminutivo de Municipalidad...
-
¿Porqué lo de "muni"?, mi cerebro está contaminado y al leer "muni" inmediatamente veo el diminutivo de Municipalidad...
muni = Mountain Unicycle... es como Mountain Bike, pero para monociclos.
Y es un deporte real... no es un invento mio :)
https://www.google.com/search?q=google+images&es_sm=91&source=lnms&tbm=isch&sa=X&ved=0CAcQ_AUoAWoVChMIoOaaoYyDxwIV0qSICh1d6Qq3&biw=1435&bih=778#tbm=isch&q=mountain+unicycle
-
No tenía ni idea de este deporte!
En ese enlace he visto la foto que usaste, me parece que hay otras que se nota mejor que es un monociclo, por ejemplo esta:
(http://workinglife.org.au/wp-content/uploads/2013/02/unicycle.jpg)
-
gracias. es buena esa foto.
-
¿Mejor ahora?
(https://lh3.googleusercontent.com/-aUDoxnk5ez0/VbqEmBSLAEI/AAAAAAABTlQ/aF-XMyxj2tI/s400-Ic42/Screen%252520Shot%2525202015-07-30%252520at%2525201.09.24%252520PM.png)
Lo que me gustaba de la foto original, es que era yo el que estaba andado :-P
-
Lo que me gustaba de la foto original, es que era yo el que estaba andado :-P
Lo sabía, mi 9º bit me decía que usaste esa foto era por eso! :D
Tampoco la descartes tan rapidamente!
-
Viendo la foto original, tu conversión ha quedado muy parecida.
Bancos de memoria: $1000 y $9000
Pero si uno usa los bancos 0, 2 ($0000-$3FFFF y $8000-$BFFF) no se pueden usar la direcciones que estan entre $1000-$1FFF y $9000-$9FFFF para poner sprites, graficos y charsets. Cuando le dicen al VIC que use esas direcciones, los lee de la ROM en vez de la RAM.
No lo sabia. Creia que tenia acceso a toda la RAM.
Estas cosas son las que me matan a la hora de tratar con mi pequeñin. Nunca lo he leido en ningún libro de los que tengo asi que, ¿como lo averiguas cuando tu programa falla antes de pegarte un tiro?.
Me falta aun mucha practica y leer mucha documentación.
-
No lo sabia. Creia que tenia acceso a toda la RAM.
Vos podes usar toda la RAM, los 64k.
Pero el VIC no puede ver la RAM que esta entre $1000-$1FFF y $9000-$9FFF.
O sea, vos podes poner código en esos lugares. Pero no pongas sprites, graficos y charsets.
Para más info leer este articulo: http://www.zimmers.net/cbmpics/cbm/c64/vic-ii.txt
Ir a la sección 2.4.2
-
Parece ser un buen lugar para poner el código, no?
-
Vos podes usar toda la RAM, los 64k.
Pero el VIC no puede ver la RAM que esta entre $1000-$1FFF y $9000-$9FFF.
O sea, vos podes poner código en esos lugares. Pero no pongas sprites, graficos y charsets.
Para más info leer este articulo: http://www.zimmers.net/cbmpics/cbm/c64/vic-ii.txt
Ir a la sección 2.4.2
Vaale. La memoria de color no se mueve selecciones el banco que selecciones , el VIC accede a 16k de cada página pero las zonas 0 y 2 contienen los carcteres en ROM . Creo que voy pilandolo , aunque la ROM CHAR no se mueve, el VIC no lo sabe y sigue saltandose ese hueco ¿no?.
Las zonas 1 y 3 son 100% aprovechables.
Me estoy releyendo los libros que tengo para ponerme al dia y en el GUIA DE REFERENCIA DEL COMMODORE 64 de Microelectronica y control comentan los mapas y los huecos.
Grácias por el fichero DOC. Toda ayuda es poca ;)
-
Parece ser un buen lugar para poner el código, no?
Nada que empleé el VIC debe ser puesto en esas zonas . Codigo , sin problemas o eso interpreto.
-
A mi me tiene frito el tema interrupciones.
Hay como 100 maneras diferentes para hacerlo, aunque este listado (que adjunto al post) para mi es el mas coherente y temendamente estable.
Riq, tu lo tienes dominado, pero a mi se me resiste. Emplearlas es fácil, pero comprender al 100% el por qué funciona aún se me escapa.
Con lo fácil que son las interrupciones en un Arduino ... ::)
Te la dejo por si te sirve para el juego y por si puedes iluminarme un poco sobre este tema.
; CBM prg Studio
; 10 SYS (4096)
*=$801
BYTE $0E, $08, $0A, $00, $9E, $20, $28, $34, $30, $39, $36, $29, $00, $00, $00
;Aparece el sprite 0 en las dos mitades de la pantalla, pero solo es por probar la rutina.
;Los valores de pantalla de rastreo en zona visible , van de 50 a 250.
;150 es el centro. 250+50=300 300/2=150 .
superior=50 ;Primera pantalla. La superior
inferior=150 ;150 ;Segunda pantalla. Inferior
*=$1000
lda #255
sta 2040 ;Puntero sprite 0 en 255
lda #1
sta $d015 ;Sprite 0 activado
sei ; set interrupt disable flag
ldy #$7f ; $7f = %01111111
sty $dc0d ; Turn off CIAs Timer interrupts
sty $dd0d ; Turn off CIAs Timer interrupts
lda $dc0d ; cancel all CIA-IRQs in queue/unprocessed
lda $dd0d ; cancel all CIA-IRQs in queue/unprocessed
lda #$01 ; Set Interrupt Request Mask...
sta $d01a ; ...we want IRQ by Rasterbeam
lda #<irq ; point IRQ Vector to our custom irq routine
ldx #>irq
sta $314 ; store in $314/$315
stx $315
lda #superior ; trigger first interrupt at row zero
sta $d012
lda $d011 ; Bit#0 of $d011 is basically...
and #$7f ; ...the 9th Bit for $d012
sta $d011 ; we need to make sure it is set to zero
cli ; clear interrupt disable flag
rts
irq dec $d019 ; acknowledge IRQ
lda $d012
cmp #inferior
beq rojo ;Segunda mitad
lda #0
sta $d021 ;Color negro en pantalla
lda #inferior
sta $d012 ;Nuevo valor segnda pantalla
lda #80
sta $d000
sta $d001
jmp pasa
rojo lda #2
sta $d021 ;Color rojo en pantalla
lda #superior
sta $d012 ;nuevo valor primera mitad
lda #200
sta $d000
sta $d001
pasa jmp $ea31
-
y por si puedes iluminarme un poco sobre este tema.
en concreto, ¿qué dudas tenes sobre las interrupciones?
-
Como desviarlas no.
Es el por qué de como conseguir fluidez y estabilidad.
Veo muchas maneras de eliminar esos flicks que afean y dejar los cortes de cambio de color impecables, pero cada cual usa una manera distinta de manipular los registros del VIC para conseguirlo y eso me desorienta.
Usando las CIAS es sencillo conseguir que cada cierto tiempo se ejecute mi rutina, pero usando el RASTER para por ejemplo conseguir multiples SPRITES o diferentes modos graficos a la vez según donde esté la linea de barrido es mas lioso.
Cada cual usa técnicas que difieren unas de otras para conseguirlo.
Si por lo menos siguieran un patrón lo llegaria a comprender, pero hasta ahora solo coinciden en muy pocas cosas y contra mas rutinas leo, mas me confunden.
-
A mi me sirvió entender el porqué de la inestabilidad del raster para entender lo demás... así que empiezo por el principio:
¿por qué la IRQ del raster es inestable?
El barrido de la pantalla se hace unas 50 veces por segundo en PAL-B (la Commodore europea).
Y uno le puede decir a la commodore que te avise cuando empiece el barrido, y que te avise cuando el raster esta en cierta posición del barrido.
Supongamos que quiero que la interrupción me avise cuando el raster esta en la posición 50.
Entonces se hace lo tradicional de poner el vector $314 apuntando a donde queres, poner #50 en $d012, y demas.
Pero vas a ver que a veces sos llamado en el medio de la "scan line", o a veces al principio... como si fuera aleatorio.
Pero en verdad no es aleatorio, y sos llamado de acuerdo a lo siguiente:
a) Supongamos que el raster llega a la linea 50
b) La interrupción interrumpe lo que esta sucediendo en bucle principal
c) Para eso tiene que dejar terminar la instrucción que se este ejecutando
d) y luego pone en el stack A,X,Y, status y PC.
e) y luego te llama a tu código.
La unica incógnita es c)... no se sabe que instrucción se esta ejecutando... y hay instrucciones que tardan 2 ciclos y otras que pueden tardar 7.
Y esos 5 ciclos de diferencia es el "randomness" que ves en las "raster inestables".
¿Como prevenirlos?
Hay distintas técnicas. La que yo estoy usando es una llamada "doble IRQ" que esta muy bien explicada aca:
http://codebase64.org/doku.php?id=base:stable_raster_routine
La idea es la siguiente:
Como no sabes lo que pasa en c), la idea es poner una primera IRQ llena de NOPs y luego otra, con la idea de que la segunda IRQ se llame cuando se estan ejecutando los NOPs... y luego un truquito más que esta explicado en ese documento.
El código mencionado ahí lo puse en esta macro en format CA65:
https://github.com/ricardoquesada/c64-the-muni-race/blob/master/src/mymacros.mac
-
Que interesante. En algún momento me gustaría probar algo de esto.
-
Estudiandolo estoy.
Grácias Riq ;)
-
Que interesante. En algún momento me gustaría probar algo de esto.
Es muy interesante y útil. La cosa tiene su miga pero si consigues comprenderlo bién se pueden hacer virguerias. Llevo dias leyendo de todo para tratar de entenderlo. Soy duro de mollera ;)
-
Soy duro de mollera ;)
Me parece de muy mala educación contradecir a un compañero :P
Ahora mismo estoy metido cargando revistas y libros a Ri, que tenía curro atrasado. Al mismo tiempo cargando también cosas a CBMes, asi que dejo este tema un poquito aparcado, pero en algun momento me pica de nuevo y sigo donde estaba.
-
Me parece de muy mala educación contradecir a un compañero :P
Así me gusta. Pero no sé si os a pasado alguna vez que ante una cosa obvia que la tienes delante , no la ves y cuando te das cuenta , te das de collejas por no pillarlo a la primera.
Así estoy yo con el raster. Ya comprendo que hay que desconctar algunas cosas para que las interrupciones NMI no te toquen las narices.
Cuando lo tenga aclarado (lo más básico y necesario para que funcionen, nada de virguerias) lo colgare , aunque supongo que en "dudas en ensamblador", que creo que pertenecen las dudas que tengo sobre esto.
Ahora mismo estoy metido cargando revistas y libros a Ri, que tenía curro atrasado. Al mismo tiempo cargando también cosas a CBMes, asi que dejo este tema un poquito aparcado, pero en algun momento me pica de nuevo y sigo donde estaba.
No es una competición ;), pero siempre es agradable y divertido tener a más gente con niveles similares para ir evolucionando con los aportes e ideas de cada uno.
-
timers
La frecuencia de barrido de NTSC (commodore en EE.UU) es de 60 veces por segundo. La PAL-B (europa) es de 50-veces por segundo.
O sea, que el barrido en la NTSC es más rápido... asi que usar el raster-IRQ para tocar música no es muy buena idea.
Entonces ¿si queres hacer un jueguito que funcione en NTSC y PAL, y que la música corra a la misma velocidad que haces?
Podes cambiar el código de la música, pero algo más fácil es usar los timers de la CIA, y programar uno para que se ejecute 50 veces por segundo.
Programarlos es relativamente sencillo, pero lo que hay que tener en cuenta es que cuando el timer llega a 0, se genera una IRQ.
Entonces si uno ya tiene instalado un vector con el raster-IRQ, hay que diferenciar cuando la IRQ es de raster y cuando es de timer.
Es se puede hacer comprobando si $d019 esta en uno para saber si fue una interrupción por raster, o similar.
Si la IRQ es por timer, entonces solo ahí uno tiene que tocar la música... y de esa manera la música va a sonar a la misma velocidad tanto en NTSC como en PAL.
Quizás lo complicado es saber que valores hay que usar en el timer, porque la duración de un ciclo en NTSC y PAL son distintos... lo bueno es que todo esto ya fue hecho hace muchos años... entonces solo hay que usar, por ejemplo, estos números para programar el timer:
http://codebase64.org/doku.php?id=base:playing_music_on_pal_and_ntsc
Aca tengo código que lo usa (el scroller es el mismo del jueguito que estoy haciendo, pero fijense en la parte que dice "sync50hz" )
https://github.com/ricardoquesada/c64-casual-connect-15/blob/master/src/intro.s
y aca esta un .prg para que prueben
-
Que bueno todo... en serio.
-
Optimizaciones...
Detectar colisiones usando la funcionalidad que trae el VIC esta bien, pero cuando uno quiere hacer cosas más complejas no es muy útil.
Por ejemplo, si a mi me interesa saber si mi sprite colisiona con ciertos caracteres, pero quiero ignorar otros, ya no me sirve usar la IRQ de sprite-caracteres que trae el VIC.
Entonces para detectar eso, uno tiene que hacer una simple rutina de "bounding box"
Y si bien hacer un bounding_box() no es complicado, lo más importante es hacerlo rápido, ya que se va a ejecutar 1 vez por por sprite en cada loop.
En la rutina que estoy haciendo, lo más lento era una multiplicación por 40 que hacía.
// saber que char hay en (x,y)
int char_index = y * 40 + x;
// Y se puede optimizar con
int char_index = (y * 32) + (y *8) + x;
// que es lo mismo que esto, pero más rápido
int char_index = (y << 5) + (y << 3) + x;
// pero lo más rápido de todo es hacer una tabla de multiplicaciones
// la tabla solo ocupa 50 bytes (25 words) ya que solo multiplico por valores entre 0 y 24, ya
// que solo hay 25 columnas
int char_index = tabla_de_mulitplicacion_de_40[y] + x;
así que lo que hice fue una tablita... y para hacer la tablita me hice este tool:
https://github.com/ricardoquesada/c64-misc/blob/master/tools/mult_table_generator.py
A medida que voy avanzado con el jueguito, me estoy dando cuenta lo importante que es tener tablas de valores precalculados para todo, por dos simple razones:
- velocidad
- simplifica el código múchisimo :)
pero el problema es que las tablas hacen que consuma más memoria, lo cual puede ser un problema grande.
El jueguito va progresando poco a poco, todavía no tiene mucho, pero aunque ahora hay un "game scene" donde se puede mover el actor y hacerlo saltar y tiene detección de colisiones y salta bajo y alto. Se puede bajar de aca:
https://github.com/ricardoquesada/c64-the-muni-race/blob/master/bin/therace.prg?raw=true
-
Ya me gustaría llegar a ese nivel como para hacer una detección por boundingbox...
He mirado el prg, ¿tus personajes van desnudos? :D :D
-
Consejo: para empezar a jugar pon también que sirva el disparo, además de F1.
-
Me gusta el efecto de gravedad en el salto.
¿Has hecho exprofeso que en el primer hueco haya como un fondo y en el segúndo, caiga en un bucle infinito donde el monociclista alcanza velocidades supersónicas?.
Es divertido ver como se acelera y aparece el efécto estroboscópico ;D
Hacia la derecha desaparece y parece que sigue haciendo camino ya que tarda el mismo tiempo dedicado en volver como el que he invertido antes. Es curioso.
Pero tiene pinta de entretenido. Me gusta.
-
He mirado el prg, ¿tus personajes van desnudos? :D :D
Ahora que me fijo... tienes razón :D.
-
Ja. Andar en monociclo desnudo no es algo que yo recomiende :) Son más mis limitaciones como artista gráfico que otra cosa.
El código todavía esta muy crudo... le falta muchísimo, y voy avanzado poco a poco. Me concentré solamente en hacer un mini algoritmo de colisiones. Mi siguiente paso creo que es mejorar el editor de caracteres que estoy haciendo (vchar64) para poder hacer un mapa más o menos decente.
Ya agregaré mejores animaciones, mejores graficos, sonidos y demás... quizas en 5 años lo termine :)
-
Ja. Andar en monociclo desnudo no es algo que yo recomiende :)
Pués anda, que sin sillín... :D
Ya agregaré mejores animaciones, mejores graficos, sonidos y demás... quizas en 5 años lo termine :)
Veo que eres optimista. Si necesitas ayuda en el apartado gráfico, tenemos un artista en el foro , Errazking. Es un crack!! ;).
-
Pues aquí seguimos.
Estoy empezando un juego tipo Head On (por fin me he animado a intentar algo ::)) y se me a ocurrido ir poniendo las rutinas que voy creando para que si veis alguno como añadir mejoras, pues me encantará aplicarlas si esta en mis posibilidades entenderlo.
La verdad es que es complicado el jueguecito, el hacer que los enemigos se muevan hacia el carril donde estoy desde cualquier dirección y posición de la pantalla es malnacido.
Intentaré crear unas tablas para que estas cosas las haga de manera automática sin "if thens" o comprobaciones eternas que compliquen el seguir/crear el programa
Ya iré colgando por aquí los progresos ;)
;Creado en CBM prg STUDIO 3.6.0
;Pruebas para colocar sprite en pantalla partiendo de unas coordenadas de pantalla
;X de 0 a 39 e Y de 0 a 24
; 10 SYS4096
*=$801
BYTE $0B, $08, $0A, $00, $9E, $34, $30, $39, $36, $00, $00, $00
*=$1000 ;#4096
;Posición sprite en coordenadas X=0 e Y=0 de caracteres, en el sprite es X=#24 e Y=#50
;Formula de caracteres a sprites: Xcar*8+24 Ycar*8+50
facarg=$bc0c
intfac=$b391
sum=$b86a
res=$b853
mul=$ba2b
div=$bb12
facind=$bc9b
msb=$d010 ;Activar >255 sprites
posprites=$D000
spena=$D015
Posmemspr=$07f8 ;#2040
Xcar0=#30 ;Coordenada X coche 0 (el prota) 28*8=224 +24 de correccion=248.
;Es el máximo sin tener que activar el msb
Ycar0=#00 ;Coordenada Y coche 0 (elprota)
;Posicionando y conectando sprites
lda #1
sta spena ;Conecta sprite 0
lda #24+50
sta posprites ;CoordX
lda #50
sta posprites+1 ;CoordY
lda #192+2 ;#12288
sta Posmemspr ;Sprite en memoria
loop ;Inutil de momento, solo se ejecuta una vez
lda #00 ;Desactiva el msb antes del cálculo
sta msb ;es mejorable, solo es para la prueba.
;Multiplicando la coordenada X en caracteres para conseguir la coordenada X del sprite:
;Vale también para la coordenada Y. De hecho, se llamará a esta rutina para calcular
;cada eje de cada coche.
;ACU y Registro Y se pueden cargar antes de llamar a esta rutina. Aqui los cargo a
;continuación para las pruebas.
lda #00 ;HIBYTE LoHi Es 0 por que va de 0 a 0 XD
ldy #Xcar0 ;LOBYTE ;00XX coordenada X coche Va de 0 al 39
jsr intfac ;
jsr facarg ;
lda #00 ;HIBYTE LoHi
ldy #08 ;LOBYTE 0008 X8
jsr intfac
jsr mul ;Resultado en $64 y $65 HIBYTE y LOBYTE respectivamente
jsr facind
lda $64 ;Resultado HI de multiplicar Xcar x 8 bits
ldy $65 ;Resultado LO de multiplicar Xcar x 8 bits
jsr intfac
jsr facarg
lda #00
ldy #24 ;Corrección de la posición del sprite , ya que coordnada
;X o Y con valor 0, queda detrás del borde de la pantalla.
jsr intfac
jsr sum
jsr facind
ldy $65
clc ;Por si acaso XD
lda $64 ;Si el numero calculado sobrepasa los 255, el Hibyte no sera 0
beq sigue1 ;Si es cero, pasa de activar el msb
lda #01 ;Si es > de 0 , pasa a activar el msb
sta msb
sigue1 sty posprites ;posprites ;
rts ;Vuelta al basic
*=$3000 ;#12288 12288/64=192 primer sprite
; Derecha
BYTE 0,0,0
BYTE 118,0,0
BYTE 32,0,0
BYTE 63,0,0
BYTE 63,0,0
BYTE 32,0,0
BYTE 118,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0,0
; Izquierda
BYTE 0,0,0
BYTE 110,0,0
BYTE 4,0,0
BYTE 252,0,0
BYTE 252,0,0
BYTE 4,0,0
BYTE 110,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0,0
; Abajo
BYTE 0,0,0
BYTE 66,0,0
BYTE 126,0,0
BYTE 90,0,0
BYTE 24,0,0
BYTE 90,0,0
BYTE 90,0,0
BYTE 24,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0,0
; Arriba
BYTE 24,0,0
BYTE 90,0,0
BYTE 90,0,0
BYTE 24,0,0
BYTE 90,0,0
BYTE 126,0,0
BYTE 66,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0
BYTE 0,0,0,0
-
Si modificáis Xcar0 de 0 a 39 (eje X), el coche aparecerá justo encima de ese carácter.
-
¿Este es el juego, no?
https://www.youtube.com/watch?v=jkCycCMJWdo
-
Casi. Este se mueve como un comecocos, el Head On arcade se desplaza lateralmente hasta 2 o 3 carriles.
Ese va a "saltos" de 8 pixeles, por eso quiero usar un sprite para que se mueva suave.
-
GUAU!!!!
Animo Maniako,...super espectante me quedo!!,....es toda una alegria para mi ver como te lo curras!!!, me has dejado alucinado!!
Un saludazo!!
-
ahora que le agregué un editorcito de mapas al vchar64, pude recién seguir con el jueguito este que estoy haciendo. pero el juego es completamente distinto... creo que rescribí el 80% del código ya que decidí hacer un juego distinto al que pensé originalmente.
- este va a tener sprites super simplificados (extremadamente simplificados)
- no va a tener graficos bitmap
- no va a redifinir caracteres. todo va a ser petscii + sprites
- va a ser multijugador
- tiene nueva pantalla de inicio, nueva pantalla de scores, nueva pantalla para jugar
- saque el "about"... lo tengo que reemplazar por otro cosa
- no se llama más "the muni race", ahora se llama "the uni games".
- la idea es que tenga un look super super pedorro... cuanto más pedorro mejor... nada de efectitos copados ni nada de eso... bien pedorro.... un look bien "retro retro".
- y la idea es que se tenga que jugar con un monociclo de verdad (el uni-stick)... jugar con un joystick va a ser posible (es asi como lo estoy testeando), pero la posta es jugarlo con monociclo de verdad. más sobre esto en el futuro...
va a tener 3 o 4 eventos:
- saltar escaleras hacia arriba (boton del joy, ó saltar con el monociclo)
- 100 metros carrera llana (izq-der del joy, ó idling en el monociclo)
- 2k metros carrera llana (izq-der del joy, ó idling en el monociclo)
- 2k cross-country con obstaculos (izq-der + boton del joy, ó idling + saltar con el monociclo)
aca esta el último binario:
https://github.com/ricardoquesada/c64-the-muni-race/raw/master/bin/therace.prg
y 2 screenshots pedorros del código actual:
(https://lh3.googleusercontent.com/-G0U1Wbbfeo0/VvDxcWEVQKI/AAAAAAABdl4/MaAoyrS_QdQpx9NjH9B38FePe5-jgeQiwCCo/s640-Ic42/Screen%2BShot%2B2016-03-22%2Bat%2B12.16.05%2BAM.png)
(https://lh3.googleusercontent.com/-JPw87NTIzPw/VvDxcSKPFyI/AAAAAAABdl8/sFwRp2qILYg1zZEJ2BR2ZjIwzXb-CHrpgCCo/s640-Ic42/Screen%2BShot%2B2016-03-22%2Bat%2B12.16.34%2BAM.png)
-
pero en definitiva... ¿qué aprendí de nuevo estos meses?
Básicamente que si uno quiere velocidad, hay que usar tablas para tooooodo.
es como si un programase "off-line". Se hacen todos los calculos pesados en una o varias tablas, y luego se usan con algún indice.
Las tablas (con ayuda de macros) se pueden usar en cálculos sencillos, como multiplicar. Si uno sabe que va a multiplicar por 15 ciertos números, lo mejor es tener una tabla con ese precalculado. ej:
mult15:
.repeat 10,I
.byte 15*I
.endrepeat
lda mult15,8 ; multiplicar 8 * 15
hice estos dos toolcitos para generar distintos tipos de tablas:
- https://github.com/ricardoquesada/c64-misc/blob/master/tools/easing_table_generator.py
- https://github.com/ricardoquesada/c64-misc/blob/master/tools/mult_table_generator.py
y ademas fui descubriendo el poder de las macros del cc65. Muy poderoso, aunque supongo que los demas ensambladores son similares. ejemplo de macro que estoy usando:
ADDRESS0 = SCREEN_BASE+15*40 ; left eye
ADDRESS1 = SCREEN_BASE+15*40+2 ; right eye
ADDRESS2 = SCREEN_BASE+17*40 ; left arm
ADDRESS3 = SCREEN_BASE+17*40+2 ; right arm
ADDRESS4 = SCREEN_BASE+21*40+1 ; hub
ADDRESS5 = SCREEN_BASE+15*40+37 ; left eye
ADDRESS6 = SCREEN_BASE+15*40+39 ; right eye
ADDRESS7 = SCREEN_BASE+17*40+37 ; left arm
ADDRESS8 = SCREEN_BASE+17*40+39 ; right arm
ADDRESS9 = SCREEN_BASE+21*40+38 ; hub
addresses_lo:
.repeat 10,YY
.byte <.IDENT(.CONCAT("ADDRESS", .STRING(YY)))
.endrepeat
addresses_hi:
.repeat 10,YY
.byte >.IDENT(.CONCAT("ADDRESS", .STRING(YY)))
.endrepeat
basicamente esas macros me generan las direcciones "lo" y "hi" de las coordenadas que les paso... nada del otro mundo, pero me ahorran bastante tiempo.
creo que aprender las macros del ensablador es tan importante como aprender las instrucciones del 6502.
-
Cambio radical ;)
Veo que es pantalla partida. Estupendo para dos jugadores.
¿Vas a conectar un monociclo real al commodore? :o
Encoders, contadores y todo eso?.
-
voy avanzando poco a poco con el jueguito, pero creo que lo termino este año.
¿que aprendí ultimamente?
no mucho. pero hay dos que cosas que vale la pena mencionar:
- manejar el teclado de manera prolija es más complicado de lo que uno imagina.
- los sprites consumen "ciclos" en el rasterline... asi que cuando uno pone sprites, hay que hacer las cuentas nuevamente para tener un raster estable.
si alguien quiere probar el jueguito (version muy alpha aún, esta aca):
https://github.com/ricardoquesada/c64-the-uni-games/raw/master/bin/unigames.prg
-
Críticas:
- Cuando entras a SCORES (disparo) se tendría que poder volver con disparo.
- Jugarlo con las teclas en emulador es un poco complicado :D :D
- Los sprites de los protagonistas no son realistas
- En la pantalla de arriba, el barrido hace algunas cosas raras, supongo que a eso te referias con los ciclos.
-
gracias!
- Jugarlo con las teclas en emulador es un poco complicado :D :D
¿cómo? ¿no tenes un unijoysticle para jugarlo?
-
Vaya, ya he quedado obsoleto... :D
-
otra cosita útil:
Para no tener que cargar cosas de disquete, es útil tener las distintas escenas del juego comprimidos en memoria (en caso que uno tenga varias escenas).
uno reserva un pedazo de memoria para una escena... digamos de $2400 a $8000, y luego todas la esceneas que esten comprimidas de $8000 a $fff0.
comprimo todo con exomizer, y la descompresión la hago con el descrompresor de exomizer.
todo el código esta aca: https://github.com/ricardoquesada/c64-the-uni-games
es es lo que estoy haciendo en la última versión del "uni games" (adjuntada).
-
Eh!! El personaje es de Grog Revenge XD.
¿Es cosa mia o el salto se retrasa unos pocos milisegundos?, Cuando intento saltar alguno de los obstáculos, tarda en reaccionar y me la pego.
La velocidad en doble scroll es muy buena!!.
Le echaré un ojo al código a ver qué aprendo. :)
-
Eh!! El personaje es de Grog Revenge XD.
¿Es cosa mia o el salto se retrasa unos pocos milisegundos?, Cuando intento saltar alguno de los obstáculos, tarda en reaccionar y me la pego.
La velocidad en doble scroll es muy buena!!.
Le echaré un ojo al código a ver qué aprendo. :)
Si, en particular es el personaje de BC's Quest For Tires, que esta basado en el comic B.C.
Y existe un tipo de monociclo llamado la "rueda BC" que esta inspirado en eso.
El jueguito es un poco un homenaje a eso. En el About cuento un poco eso.
Respecto al salto debería ser inmediato, sino es un bug. pero tené en cuenta que no se puede saltar ni bien aterrizas. En el nivel "Cyclo Cross" debería saltar inmediatamente casi siempre.
-
Que buen hilo. Estoy tratando de aprender y me puse a buscar y llegue aqui. Muy bueno.
Una pregunta a ver si alguien me puede ayudar. Tengo la ultima version de Vine y del CBM prg Studio. Cuando uso lafuncion Ctr+F5 en CBM para probar un codigo assembly hay dos cosas que no se si en verdad se pueden solucionar:
1 - CBM abre una ventana que se llama Assembly Dump, esto se puede evitar?
2 - VINE carga el archivo, pero como es Assembly, tratar de hacer un run y no pasa nada, no hace el llamado usando SYS. Esto es normal se puede hacer que automaticamente haga el llamado con SYS?
Gracias!
-
Por aquí me suenan que @darro99 y @PacoBlog64 son los linuxeros que usan Wine.
*EDITO: acabo de ver que es VINE y no Wine...¿?