› Foros › Retro y descatalogado › Consolas clásicas
Diskover escribió:Esta interesante para ver lo que se puede llegar a hacer, ¿pero por que no empezamos con algo mas sencillo como por ejemplo poner de colores la pantalla, que cambien, etc... para luego conseguir añadir un sprite, varios, hacer un fondo completo, etc...?
A modo de consejo, eh es que lo veo mas básico.
Diskover escribió:Si, me lo he bajado y ya lo he visto, pero desde luego para que te hagas una idea, viendo el código, no pillo nada.
Para tu primer ejemplo básico ya te digo: Si enseñas a cambiar el color de fondo de la pantalla, que es lo mas básico creo yo, empezaríamos bien. Luego puedes enseñar a poner un sprite en pantalla.
La cosa seria que explicaras paso a paso que hace cada linea, para que nos hagamos una idea
vid_enablePPU_CTRL_1(#valor)
vid_enablePPU_CTRL_1(#(BACKGRND_TABLE_0|SPRITE_TABLE_1))
//Cargamos la paleta de mario en el buffer 0
ldx #0
ldy #sizeof(PALENT)
while(not zero) {
lda marioPal, x
sta palletesBuffer, x
inx
dey
}
vid_setPalette(#0, #SPRITE_PALETTES.PAL_0);
int_queueNmiEventStart(#EFFECT.SET_PALENTRY)
int_queueNmiEventParam(#0)
int_queueNmiEventParam(#SPRITE_PALETTES.PAL_0)
int_queueNmiEventEnd()
socram8888 escribió:No se puede estropear. Lo único que ocurre si usas esos seis negros de la derecha es que son los llamados "ultranegros", y tienen un voltaje por debajo del rango aceptado con lo que algunas teles lo confunden con la señal de BLANK con lo que sale este típico efecto: http://www.youtube.com/watch?v=SIv78J3IaMk
wave escribió:Las Name Table
Son las que definen que tiles usar para confeccionar el escenario. De serie, la NES trae memoria para almacenar 2 Name tables, hay algun juego con configuracion 4-SCREEN que añade las dos restantes, pero lo obviaremos por ser poco frecuente.
wave escribió:La paleta de colores
La paleta de colores de guarda en $3F00-$3F1F, son 32 valores pero no todos son usables, ahora explicare por que.
La NES tiene 8 paletas, 4 para el fondo y 4 para los sprites.
wave escribió:Los indices de la paleta siguen esta imagen:
No esta recomendado utilizar los 6 colores negros de la derecha ya que podrian no funcionar bien en hardware real o incluso estropearlo.
Asi que tenemos 14*4 = 56 colores a nuestra disposicion.
Diskover escribió:Mmm, ¿que juegos tren esa configuración de 4-screen? ¿por que?
¿Se pueden cambiar o ampliar esas paletas desde el hardware de un cartucho de NES? Me refiero a si era posible ampliar el número de paletas, con colores nuevos desde algún mapper o algo así.
¿Por que existen entonces esos seis colores negros del final? ¿como que pueden romper la consola?
socram8888 escribió:Deberías saber si sabes de programación que un ordenador nunca se puede estropear desde el teclado xD
wave escribió:2- No se si es tecnicamente posible mediante un mapper pero ningun mapper de los oficiales tiene ampliacion del numero de paletas (el unico que hace algo remotamente parecido es el MMC5 al dejarte elegir una paleta en cada tile del escenario en vez de en cada bloque de 16x16 pixels, pero no aumenta el numero de colores totales)
Diskover escribió:wave escribió:2- No se si es tecnicamente posible mediante un mapper pero ningun mapper de los oficiales tiene ampliacion del numero de paletas (el unico que hace algo remotamente parecido es el MMC5 al dejarte elegir una paleta en cada tile del escenario en vez de en cada bloque de 16x16 pixels, pero no aumenta el numero de colores totales)
Mmm. Interesante.
La mayoría de los juegos de NES se nota que los sprites tienen solo 3 colores+transparente, dado que normalmente los dibujan a 16x16, y a veces se saltaban ese escollo dibujando un sprite encima de otro para dar sensación de que tenia mas colores, como por ejemplo, el sprite azul de Megaman que es independiente al sprite de la cara.
Realmente son 2 sprites colocados de tal manera que parecen uno, aprovechando el color transparente. Uno de ellos, el del cuerpo, tiene los colores negro+azul+azul oscuro+transparente y el otro sprite, el de la cara, tiene solo el color carne+blanco+transparente.
Pero no sabia yo que el MMC5 se saltaba este problema.
DarkRyoga escribió:Un tutorial muy interesante. Estoy con el primer ejemplo viendo que puedo sacar.
Diskover escribió:DarkRyoga escribió:Un tutorial muy interesante. Estoy con el primer ejemplo viendo que puedo sacar.
Flaman. La gente se empieza a animar
Mas cosas interesantes:
Megaman con visualización al acceso de memoria donde podemos ver las tablas de tiles y las de sonido.
http://www.youtube.com/watch?v=oPSERZz1PvU
Lo mismo con Metroid
http://www.youtube.com/watch?v=c8uPdDT4mfQ
socram8888 escribió:El FCEU de Cah4e3 es el mejor por la cantidad de cosas raras que soporta para hacer experimentos
bit PPU.STATUS
lda #3F
sta PPU.ADDRESS
lda #00
sta PPU.ADDRESS
lda #FE
sta PPU.IO
lda PPU.IO
int_queueNmiEventStart(#EFFECT.SET_PALENTRY)
int_queueNmiEventParam(#0)
int_queueNmiEventParam(#SPRITE_PALETTES.PAL_0)
int_queueNmiEventEnd()
Diskover escribió:Esto marcha.
Cuando tengamos ya lo básico ¿podrías hacer un pequeño tutorial de ejemplo paso a paso para poner la pantalla de color rojo, amarillo, azul, etc...?
Diskover escribió:Bien, bien. Eso es lo que mas quería para empezar. Luego ya meternos con sprite, etc... La demo tuya que pusiste es muy interesante. Pienso que solo le falta la detección de colisiones y ya seria bastante completa, pero vamos, de sobresaliente el curro que te pegas
Ya mas tarde, cuando quede claro lo de los colores en fondo de pantalla, cambiarlos con el mando, etc... podríamos ir a los sprites, que posiblemente sea mas complejo, pero base fundamental de todo, jaja
socram8888 escribió:Por fin he podido hacer una maldita rutina sin fallos
Es simplemente para leer el mando del puerto 2:lda *$02 ; Move last read
sta *$03
lda #1 ; Clock LATCH pin
sta $4017
lda #0
sta $4017
sta *$02 ; Clean new port read
ldx #8 ; Number of itinerations
readloop:
rol *$02 ; Rotate one bit left the current data
lda $4017 ; Load next bit
and #01 ; Delete garbage bits, ...
ora *$02 ; ... mix together, ...
sta *$02 ; ... and put back to $02
dex ; Decrement X and continue if not zero
bne readloop
inline inp_strobePorts() {
assignx(PORT_1_ADDR, #1)
assignx(PORT_1_ADDR, #0)
}
inline inp_readPort(addr) {
ldx #CONTROLLER_BUTTONS
do {
lda addr
lsr a
rol tmpPort
dex
} while(not zero)
}
Para leer el puerto 1:
inp_strobePorts()
inp_readPort(PORT_1_ADDR)
bit PPU.STATUS
lda #5
sta PPU.BG_SCROLL
lda #10
sta PPU.BG_SCROLL
lda buffer
sta PPU.CNT0
76543210
||||||||
|||||||+- Banco de tiles ($0000 o $1000)
+++++++-- Numero de tile del sprite superior (la parte inferior contiene el siguiente tile)
76543210
||||||||
||||||++- Paleta (4 a 7) del sprite
|||+++--- No hacen nada
||+------ Prioridad (0: delante del escenario; 1: detras del escenario)
|+------- Sprite rotado horizontalmente
+-------- Sprite rotado verticalmente
lda #03
sta PPU.SPR_DMA
int_setUpdateSprites()
76543210
||||||||
||||||++- Direccion base de la Nametable (para el scroll)
|||||| (0 = $2000; 1 = $2400; 2 = $2800; 3 = $2C00)
|||||+--- Incremento de la direccion de VRAM al leer/escribir desde la CPU
||||| (0: incrementar 1; 1: incrementar 32)
||||+---- Pattern table para los sprites
|||| (0: $0000; 1: $1000; se ignora en el modo de 8x16)
|||+------ Pattern table para el background (0: $0000; 1: $1000)
||+------- Tamaño de los sprites (0: 8x8; 1: 8x16)
|+-------- Seleccion de PPU master/esclava (no tiene efecto en la NES)
+--------- Generar una NMI al principio del VBLANK (0: no; 1: si)
76543210
||
|+- 1: Añade 256 a la posicion X del scroll
+-- 1: Añade 240 a la posicion Y del scroll
vid_getPPU_CTRL_1()
vid_setPPU_CTRL_1(valor)
vid_enablePPU_CTRL_1(mascara)
vid_disablePPU_CTRL_1(mascara)
CTRL_1.BCKGRND_TABLE_0
CTRL_1.BCKGRND_TABLE_1
CTRL_1.SPRITE_TABLE_0
CTRL_1.SPRITE_TABLE_1
CTRL_1.NAME_TABLE_0
CTRL_1.NAME_TABLE_1
CTRL_1.NAME_TABLE_2
CTRL_1.NAME_TABLE_3
CTRL_1.NMI
CTRL_1.SPRITE8x16
CTRL_1.ADDRINC32
//Sprites tabla 1 y background tabla 0
vid_setPPU_CTRL_1(
#(CTRL_1.BCKGRND_TABLE_0|CTRL_1.SPRITE_TABLE_1))
76543210
||||||||
|||||||+- Escala de grises (0: color normal; 1: display monocromo)
||||||+-- 1: Mostrar background en los 8 pixels a la izquierda de la pantalla; 0: ocultar
|||||+--- 1: Mostrar sprites en los 8 pixels a la izquierda de la pantalla; 0: ocultar
||||+---- 1: Mostrar background
|||+----- 1: Mostrar sprites
||+------ Intensificar rojo (y oscurecer el resto)
|+------- Intensificar verde (y oscurecer el resto)
+-------- Intensificar azul (y oscurecer el resto)
vid_getPPU_CTRL_2()
vid_setPPU_CTRL_2(valor)
vid_enablePPU_CTRL_2(mascara)
vid_disablePPU_CTRL_2(mascara)
CTRL_2.GREEN_BCKGRND
CTRL_2.BLUE_BCKGRND
CTRL_2.RED_BCKGRND
CTRL_2.SPRITES_NOCLIP
CTRL_2.BCKGRND_NOCLIP
CTRL_2.DISPLAY_MONO
CTRL_2.SPRITES_VISIBLE
CTRL_2.BCKGRND_VISIBLE
//Sprites y background visibles
vid_setPPU_CTRL_2(
#(CTRL_2.SPRITES_VISIBLE|CTRL_2.BCKGRND_VISIBLE))
//Activar display en monocromo
vid_enablePPU_CTRL_2(#CTRL_2.DISPLAY_MONO)
76543210
||||||||
|||+++++- Bits menos significativos del ultimo valor escrito a un registro de la PPU
||| (due to register not being updated for this address)
||+------ Sprite overflow. Activo cuando hay mas de 8 sprites en una scanline,
|| parece que el comportamiento exacto es algo mas complicado, no se suele usar.
|+------- Sprite 0 Hit. Activo cuando un pixel no transparente del sprite 0 se sobrepone
| con un pixel que no es del fondo del escenario, este bit se usa para partir
| la pantalla en 2 secciones por ejemplo en Super Mario Bros. la puntuacion y el escenario.
| (ya habra algun tutorial sobre esto porque tiene miga)
+-------- VBLANK iniciado (0: no en VBLANK; 1: en VBLANK)
vid_getPPU_STAT()
VBLANK_PERIOD
SPRITE_0_HIT
vid_getPPU_STAT()
and #SPRITE_0_HIT
if(true) {
//Hacer algo
}
ldx #01
stx $4016
dex
stx $4016
ldx #08
read: lda $4016
lsr a
rol buttons
dex
bne read
inp_update(#(PORT_1|PORT_2))
//Si acabamos de pulsar el boton
lda pads[CONTROLLER.PLAYER1].pressed
and #BUTTON.A
if(true) {
//Hacer algo
}
//Si es por lo menos el segundo frame en el que lo tenemos pulsado
lda pads[CONTROLLER.PLAYER1].mantained
and #BUTTON.A
if(true) {
//Hacer algo
}
//Si acabamos de soltar el boton
lda pads[CONTROLLER.PLAYER1].released
and #BUTTON.A
if(true) {
//Hacer algo
}
interrupt.start main()
{
//Inicializamos el sistema
nes_init(#0)
//Paramos el video
vid_stop()
//El background usara la tabla 0, los sprites la 1
vid_enablePPU_CTRL_1(#(CTRL_1.BCKGRND_TABLE_0|CTRL_1.SPRITE_TABLE_1));
//No activamos el clipping
vid_enablePPU_CTRL_2(#CTRL_2.BCKGRND_NOCLIP);
//Reseteamos el scroll
lda #1
sta scrX
sta scrY
//El modo de sprites sera de ignorar prioridad, para activar el OAM CYCLING
lda #1
sta _vidIgnorePriority
//Limpiamos los sprites
vid_clearSprites()
//Reiniciamos el video
vid_start();
//Bucle principal, se ejecutara siempre
forever {
doFrame()
}
}
inline doFrame() {
//Leemos el joypad 1
inp_update(#PORT_1)
ldand(pads[CONTROLLER.PLAYER1].pressed, #BUTTON.UP)
if(true) {
ldx backColor
inx
cpx #$0D
if(zero) {
inx
}
stx backColor
}
ldand(pads[CONTROLLER.PLAYER1].pressed, #BUTTON.DOWN)
if(true) {
ldx backColor
dex
cpx #$0D
if(zero) {
dex
}
stx backColor
}
int_queueNmiEventStart(#EFFECT.SET_BACKCOLOR)
int_queueNmiEventParam(backColor)
int_queueNmiEventEnd()
//Marcamos el final de la logica para que en la NMI se actualicen los cambios
nes_setGameLogicCompleted()
//Esperamos a que pase el VSYNC
int_waitVbl()
}
wave escribió:Primera demo: cambiando el color de fondo
Lo mejor es no mezclar esta version con la anterior del framework ya que tiene varios cambios, ire actualizandolo a medida que el tutorial avance intentando no romper nada, pero en esta version descomprimir en otra carpeta.
DESCARGA
Diskover escribió:wave escribió:Primera demo: cambiando el color de fondo
Lo mejor es no mezclar esta version con la anterior del framework ya que tiene varios cambios, ire actualizandolo a medida que el tutorial avance intentando no romper nada, pero en esta version descomprimir en otra carpeta.
DESCARGA
Megaupload dice que el archivo no está
wave escribió:Diskover escribió:wave escribió:Primera demo: cambiando el color de fondo
Lo mejor es no mezclar esta version con la anterior del framework ya que tiene varios cambios, ire actualizandolo a medida que el tutorial avance intentando no romper nada, pero en esta version descomprimir en otra carpeta.
DESCARGA
Megaupload dice que el archivo no está
Vaya, a mi si que me lo baja, a ver si con mediafire:
DESCARGA
Diskover escribió:A ver si es que estoy haciendo algo mal... pero... ¿que se supone que debería mostrarse en pantalla? Por que solo sale el color gris y no se puede cambiar con el mando.
wave escribió:Diskover escribió:A ver si es que estoy haciendo algo mal... pero... ¿que se supone que debería mostrarse en pantalla? Por que solo sale el color gris y no se puede cambiar con el mando.
Arriba y abajo cambian el color.
//Inicializamos el sistema
nes_init(#0)
//Paramos el video
vid_stop()
//Bucle principal, se ejecutara siempre
forever {
doFrame()
}
if(true) {
ldx backColor
inx
cpx #$0D
if(zero) {
inx
}
stx backColor
}
int_queueNmiEventStart(#EFFECT.SET_BACKCOLOR)
int_queueNmiEventParam(backColor)
int_queueNmiEventEnd()
//Marcamos el final de la logica para que en la NMI se actualicen los cambios
nes_setGameLogicCompleted()
//Esperamos a que pase el VSYNC
int_waitVbl()
socram8888 escribió:Menudo follón... Creo que lo ideal seria aprender o C o Assembler, pero este NESHLA me parece una chapuza
Diskover escribió://Inicializamos el sistema
nes_init(#0)
Inicializamos el sistema ¿por que pones #0? ¿que significa eso?
Probé a cambiar el 0 por otro valor y sigue funcionando con normalidad.
Diskover escribió://Paramos el video
vid_stop()
He probado a borrar esta linea y sigue funcionando con normalidad.
En un ejemplo real, con un juego ¿cual seria su función?
Etc... con el resto del código de inicio.
Diskover escribió://Bucle principal, se ejecutara siempre
forever {
doFrame()
}
Y esto es lo que hace que se ejecute, una y otra vez doFrame ¿no?
Me voy a liar mucho, pero... ¿debo dar por hecho que son simples valores estandar para arrancar el sistema? ¿que siempre van a ser así?
Diskover escribió:Mas cosas. Vamos con doFrame:
Entiendo que lo primero que hacemos es decirle que leemos el mando conectado en el puerto 1 poniendo inp_update(#PORT_1).
Luego pones ldand que exactamente no se que es... ¿algo así como un "cuando"? para que esté pendiente del mando 1 si se pulsa la cruceta hacia arriba.
lda valoruno
and valor2
Diskover escribió:Seguimos y le explicamos que debe de hacer cuando pulsamos en la cruceta hacia arriba mediante el IF, un bucle. Ok.if(true) {
ldx backColor
inx
cpx #$0D
if(zero) {
inx
}
stx backColor
}
Guardamos en X lo que halla en backColor.
Incrementamos X y luego copiamos lo que hay en esa misma X en la dirección de memoria #$0D ¿?
El siguiente IF no entiendo muy bien que hace ¿incrementa X pero bajo que condición?
Y luego, el stx backColor es para volver a leer backColor y empezar de nuevo?
El siguiente paso entiendo que es lo mismo pero haciéndolo al revés, cuando se pulsa hacia abajo bajando el valor de X.
Diskover escribió:Y este resto de código... ¿también es como un estándar? ¿algo que se debe poner siempre?int_queueNmiEventStart(#EFFECT.SET_BACKCOLOR)
int_queueNmiEventParam(backColor)
int_queueNmiEventEnd()
//Marcamos el final de la logica para que en la NMI se actualicen los cambios
nes_setGameLogicCompleted()
//Esperamos a que pase el VSYNC
int_waitVbl()
Gracias por tu paciencia
int_queueNmiEventStart(#EFFECT.SET_BACKCOLOR)
int_queueNmiEventParam(backColor)
int_queueNmiEventEnd()
Diskover escribió:P.D.: He modificado el código y siguiendo el tutorial, he conseguido que cambie los colores pero cambiando lo de arriba y abajo por botón A y botón B. Una tontería, pero sigo probando cosas.
Diskover escribió:socram8888 escribió:Menudo follón... Creo que lo ideal seria aprender o C o Assembler, pero este NESHLA me parece una chapuza
Mmm, no me parece tanto follón por ahora.
wave, tambien he usado lda pads[CONTROLLER.PLAYER1].mantained solo con el boton A para que cambien los colores mientras le dejo pulsado y al B lo he dejado como estaba.
socram8888 escribió:Me refiero al tema de usar mezcla de Assembler y C, no al comprenderlo. Normalmente se gasta Assembler para trabajar de forma rápida y C para general, pero por lo que veo en NESHLA es totalmente al reves: cosas simples como incrementar el acumulador se hacen en Asm (obviamente con ninguna ventaja de velocidad pero con el consiguiente aumento de codigo) y cosas mas complejas como leer los mandos, que es algo un pelin mas complejo, se gasta C
socram8888 escribió:Menudo follón... Creo que lo ideal seria aprender o C o Assembler, pero este NESHLA me parece una chapuza