Registrarse

[RH - ASM] [DUDA] Rutinas ASM

Estado
Cerrado para nuevas respuestas.

Rasputin

Usuario de platino
Buenas noches. Lo primero decir que esta es la primera vez en mi vida que pregunto algo en un foro, por lo que si esto no va aquí o no está bien planteado espero que un moderador lo mueva o haga lo conveniente.

Llevo desde Noviembre modificando el Pokemon Esmeralda version Española (si, soy masoca :p) y hace unos dias he empezado a crear mis propias rutinas.
Pongo la rutina y explico mi problema:

.thumb
.align 2

main:
push {r0-r1,lr}
ldrb r0, .sprite_posx
ldrb r1, .var_800D
strb r0, [r1]
pop {r0-r1,pc}



.align 2
.sprite_posx: .word 0x02020694
.var_800D: .word 0x020375F0


".var_800D" creo que no haga falta explicar que es la direccion de esa variable en la RAM.

".sprite_posx" hace referencia a un offset en la RAM que contiene un byte (a mi parecer) con la posicion de un sprite en pantalla, en mi caso, un sprite de piedra que se mueve con "fuerza". Sea o no sea, me vale como referente para lo que quiero hacer asi que tampoco hay que darle mas vueltas jejeje.


Lo que quiero es que coja el valor del byte que contenga el offset "sprite_posx" y lo meta en el offset ".var_800D" para que apartir de ahi lo pueda administrar un script.


El problema es que no puedo guardar el valor que contiene el offset ".sprite_posx" en ".var_800D", ya que cuando ejecuto la rutina este guarda el valor "94" en el offset de ".var_800D" en vez del valor que contiene el offset, es decir:

-Interpreta "sprite_posx" como valor hexadecimal en vez de como offset y coge el ultimo byte ("94") de 0x02020694

-Mete el byte 0x94 como valor para el offset "var_800D".

NOTA: funciona si solo cargo un offset en un registro, un valor hex en otro registro y lo guardo, es decir:

ldrb r0, .sprite_posx
mov r1, #0xAD
strb r1, [r0]


Por lo que entiendo que lo que en verdad hace es guardar el valor como tal del registro y no el que tenga el offset guardado en ese registro.

La finalidad es saber si la piedra esta en una posicion del mapa concreta (un agujero) y hacer que desaparezca. Tambien se donde encontrar el referente a la posicion "y" en la RAM y tengo otra rutina mas desarrollada (que tampoco funciona xD) pero para poder explicarme mejor he puesto esta que es lo mismo pero simplificada.

Lo mas seguro es que no haya entendido bien algunos conceptos, y por eso me esta dando problemas. Lo he podido hacer con scripts y 20 compare farbytetobyte, pero quiero hacerlo en rutina para poder utilizarla en mas mapas sin tener que copiar el mismo script.

Se que alomejor no esta bien planteado, pero a mi me vale y solo pido que me ayuden si es posible a como guardar valores entre offsets.

Bueno, creo que he expuesto todo lo que he ido averiguando para intentar afinar lo mas posible la explicacion a mi problema.



MUCHISIMAS GRACIAS a quien se tome la molestia de leer esta biblia y aun más a quien intente ayudarme a solucionarlo.

Un saludo gente! :):)
 

CompuMax

Discord: CompuMax#0425
Miembro insignia
El problema es que tienes una confusión (común) con el funcionamiento del comando LDR. A ver te explico:

Código:
LDR R0, R1   @;Carga en R0 la dirección de R1
LDR R0, [R1] @;Carga en R0 el valor que contiene R1
Aquí te explico el funcionamiento de tu rutina:

Código:
.thumb
.align 2

main:
push {r0-r1,lr}
ldrb r0, .sprite_posx @;Carga el primer byte de la dirección de sprite_posx en R0
ldrb r1, .var_800D    @;Carga el primer byte de la dirección de la variable var_800D en R1
strb r0, [r1]         @;Guarda en la dirección R0 el primer byte contenido en R1 (F0 en 0x00000094)
pop {r0-r1,pc}

.align 2
.sprite_posx: .word 0x02020694
.var_800D: .word 0x020375F0
Está mal por donde se le vea. De hecho dudo que te esté cargando 0x94 en var_800D. Ya que 0x00xxxxxx corresponde al BIOS y no a la WRAM; y que de estar bien programada la rutina, al ejecutar strb r0, [r1] estarías mandando a guardar el valor de var_800D en sprite_posx y no al revés.

Luego para hacer lo que deseas, guardar el valor de sprite_posx en var_800D basta con hacer lo siguiente:

Código:
.thumb
.align 2

main:
push {lr}
ldr r0, .sprite_posx @;Carga la dirección de sprite_posx en R0
ldrb r0, [r0]        @;Carga el primer byte encontrado en la dirección sprite_posx en R0
ldr r1, .var_800D    @;Carga la dirección de la variable var_800D en R1
strb r1, [r0]        @;Guarda en la dirección R1 el primer byte contenido en R0 (sprite_posx en var_800D)
pop {pc}

.align 2
.sprite_posx: .word 0x02020694
.var_800D: .word 0x020375F0
Ahora si lo que deseas es guardar el valor de var_800D en sprite_posx basta con cargar var_800D en R0 y sprite_posx en R1.

Para finalizar no hace falta popear ni pushear los registros R0, R1, R2 y R3 ya que son de propósitos generales, a menos que los vayas a seguir usando en sub rutinas que dependan de ésta. Y es recomendable que le coloques notas a tus rutinas, así se te hará más fácil interpretar lo que hace a futuro, sobretodo cuando son rutinas más largas y/o complejas.
 

Rasputin

Usuario de platino
Buenas noches!!

No me esperaba que nadie respondiera tan rapido y ademas con la resolucion de los problemas, de verdad que me habeis dejado impresionado jejejeje

Lo primero dar las gracias a CompuMax por las explicaciones, los ejemplos y la resolucion, y a Kakaroto por su resolución tambien, ambas me han servido para entender mucho mejor esta forma de programacion y crear esta pequeña rutina que para mi me da la vida jejeje




Código:
--------------- RUTINA ------------------

.thumb
.align 2


@;############################
@;# funcion MAIN (PRINCIPAL) #
@;############################

main:
	push {lr}			@;Saca de la memoria los registros guardando su posicion de retorno
	ldr r0, .sprite_posx            @;Carga la dirección de sprite_posx en R0
	ldrb r0, [r0]			@;Carga el primer byte encontrado en la dirección sprite_posx en R0
	ldr r1, .var_8008		@;Carga la dirección de var_8008 en R1
	ldrb r1, [r1]			@;Carga el primer byte encontrado en la dirección var_8008 en R1
	cmp r0,r1			@;Compara los valores de R0 con R1
	beq check_posy			@;Si los valores de la comparacion son iguales salta al label check_posy
	bne bad_pos			@;Si los valores de la comparacion son diferentes salta al label bad_pos





@;#####################
@;# subfun CHECK_POSY #
@;#####################

check_posy:
	ldr r0, .sprite_posy	        @;Carga la dirección de sprite_posx en R0
	ldrb r0, [r0]     		@;Carga el primer byte encontrado en la dirección sprite_posy en R0   
	ldr r1, .var_8009		@;Carga la dirección de var_8009 en R1
	ldrb r1, [r1]			@;Carga el primer byte encontrado en la dirección var_8009 en R1
	cmp r0,r1			@;Compara los valores de R0 con R1
	beq good_pos			@;Si los valores de la comparacion son iguales salta al label good_pos
	bne bad_pos			@;Si los valores de la comparacion son diferentes salta al label bad_pos


@;###################
@;# subfun GOOD_POS #
@;###################
good_pos:
	ldr r0, .var_800D		@;Carga la dirección de var_800D en R4
	mov r1, #0xAD			@;Introduce el byte 0xAD como valor en R5 (posicion absoluta del sprite correcta)
	strb r1, [r0]			@;Guarda el primer byte de R5 en R4
	b the_end			@;Salta al label the_end


@;##################
@;# subfun BAD_POS #
@;##################
bad_pos:
	ldr r0, .var_800D		@;Carga la dirección de var_800D en R4
	mov r1, #0xBD			@;Introduce el byte 0xBD como valor en R5 (posicion absoluta del sprite incorrecta)
	strb r1, [r0]			@;Guarda el primer byte de R5 en R4
	b the_end			@;Salta al label the_end


@;##################
@;# subfun THE_END #
@;##################
the_end:
	pop {pc} @;Devuelve a la memoria los registros en su posicion antes de sacarlos de la memoria

	
	
	
@;###############
@;# GLOBAL VARS #
@;###############	
	
.align 2
.sprite_posx: .word 0x02020694
.sprite_posy: .word 0x02020696
.var_800D: .word 0x020375F0
.var_8008: .word 0x020375E8
.var_8009: .word 0x020375EA



----------- SCRIPT --------------

#dynamic 0x800000

#org @start
setvar 0x8008 0x48
setvar 0x8009 0xE8
callasm 0x1DBD38D
compare lastresult 0xAD
if 0x1 goto @good_pos
end

#org @good_pos
hidesprite 0x3
end



Guardamos los valores de la posicion absoluta correcta (donde queremos que este el sprite) en las variables temporales 8008(eje x) y 8009(eje y) y al llamar a esta rutina guarda en la variable 800D el valor 0xAD si la posicion es correcta o 0xBD si la posicion es incorrecta. Luego un script maneja este resultado para no hacer nada o ocultar la piedra. La idea es que cuando este encima de un agujero, desaparezca como si hubiera caido.

Se que no esta muy optimizada, sobre todo con el tema de los registros, pero bueno de momento es funcional y si le sirve a alguien libre es de utilizarla jeje (advierto que solo es para Esmeralda version Española).

CompuMax con respecto a lo del strb no se porque pero funciona así xD Tienes toda la razon en que deberia de guardarme otros valores, pero no me lo guardaba. Probe 30 formas y a base de prueba y error me di cuenta de que era el strb y que tenia que ponerlo de esa forma, yo tampoco lo entiendo pero funciona jajaja si alguien lo entiende me gustaria saber el porque

Tengo otra duda, y es como podria definir los valores 0x48 y 0xE8 (posiciones correctas de los ejes x e y) como variables, al igual que con var_800D y demas. He probado con:

good_x: .byte #0x48
good_x: .byte 0x48
good_x: .word #0x48

Y no me compila, si alguien sabe tambien como solucionar esto toda ayuda es bienvenida jejeje

Tambien tengo otras dudas como cual es la funcion de BX y BL, es como un call y return? y como haria para activar scripts con el uso de objeto del menu. Se que combinación es la de pulsar B para salir, pero he visto rutinas que lo hacen de otra forma al parecer (son para fire red).

De nuevo muchas gracias a CompuMax y Kakaroto, he tardado en responder pero porque queria hacer una rutina funcional y entendible en agradecimiento a vuestra ayuda.

Un saludo gente! ;)
 
Última edición:
Estado
Cerrado para nuevas respuestas.
Arriba