Karoshi MSX Community

MSX Actualidad => General => Mensaje iniciado por: Darth_Fistro en 25 de Enero de 2006, 04:11:01 pm



Título: Optimizando los listadillos basic
Publicado por: Darth_Fistro en 25 de Enero de 2006, 04:11:01 pm
He aquí una pequeña guía basada en pruebas que hice hace un par de años cuando empecé a programar en basic MSX, que puede que os resulte útil a los nuevos en el tema. El método fué hacer una serie de listados con operaciones matemáticas, bucles, sprites, etc. y al principio, inicializar TIME a cero, y mostrar su valor una vez terminado el bucle. Hice 5 pruebas en cada modalidad y saqué una media. No voy a publicar los números porque es una lata pero sí daré un resumen de los resultados, que es lo que interesa (conclusiones y moralejas varias, vamos)  ;)

Amos allá:

Empecemos por algo básico. Imaginemos:
Código:
20 for i=1 to 500
30 a=i-1
40 b=a*2
50 next i
-Si unimos las líneas 30 y 40 en una sola instrucción, separada por dos puntos (:), obtenemos una mejora ridícula (no llega al 1%) pero ya nos da una pista... hay que intentar dentro de lo posible unir en una sola línea tantas instrucciones como sea posible.

-Si insertamos una línea, por ejemplo, la 25, con un REM, la cosa se ralentiza. Así que a usar los menos rems posibles, ya que hay que procesar una instrucción que en definitiva no hace nada.

-Quitando los espacios entre instrucciones también se gana algo de velocidad. Poquísimo, pero algo es algo.

-Ganamos algo más apreciable si sustituimos el NEXT I por NEXT. No hace falta indicar la variable.Eso sí, contad cuántos bucles estáis usando para no haceros un lío y que se queden FORs sin NEXTs o viceversa.

Sigamos con más cositas... los veteranos estarán durmiéndose  ;) pero para nosotros, estas cositas nos pueden salvar el culo en un momento de apuro.

Código:
if x>0 then goto 500

-Una expresión es cierta (-1) cuando vale distinta de cero. Así, si quiero saber si la coordenada x de mi nave no sobrepasa la derecha de la pantalla, sólo hay que hacer i x then goto 500. No hace falta la comparación, ya que será verdadera la condición si x<>0 en cualquier caso. Con esto ganamos velocidad.

-Es más, respecto al THEN GOTO 500, podemos quitar el GOTO y poner directamente THEN 500, y ganamos algo. Curiosamente, ganamos algo más si quitamos el then y dejamos sólo el goto, o sea, IF X GOTO 500

-EL CAMPEON CONTRA LAS MANCHAS... DEFINT
Si nuestras variables no necesitan decimales y su valor no va a sobrepasar 32768 o -32768, a usar variables enteras. Definidlas con DEFINT al principio del programa y veréis la diferencia. Eso sí, usad DEFINT antes de dar cualquier valor a las variables u os las borrará. Lo mismo con las matrices. Primero usad DEFINT y luego DIM, si no se borran.

-Una vez usemos variables enteras,p.e. con DEFINT A-Z, ya no hace falta p.e. hacer A=INT(RND(1)*10), nos basta con A=RND(1)*10, ya que de todas formas A es una variable entera, y ejecutar la función INT sólo nos quitará un tiempo de ejecución precioso.

-Chorradita al canto. Aprended TODAS las instrucciones basic porque todas tienen un uso concreto y se les puede sacar partido. Por ejemplo, como ejemplo chorra, en vez de hacer un FOR I=1 to 20:PRINT CHR$(166);:NEXT, usar mejor PRINT STRING$(20,166), que es 10 veces más rápido.

-Sprites. Usar VPOKE donde sea posible (en los casos en que no se necesiten valores mayores de 255 o menores de cero), pues daría error. Incluso vpokeando las coordenadas, color y nº de patrón, es más rápido que usar PUT SPRITE.

-Evitad el uso de paréntesis innecesarios. Es más rápido X=X+2*(D=7 OR D=8) que X=X+2*((D=7) OR (D=8))

-Tanto si usáis variables enteras como si no, la división entera \ es más rápida que la normal /. Pero mucho más rápida. Así que en vez de usar A=INT(B/2), usad A=B\2 y veréis la diferencia. Eso sí, tened en cuenta que esta división tiene la menor prioridad, o sea que metedla entre paréntesis o el ordenador ejecutará antes una suma, resta, etc. que tenga al lado. A=2+B\2 os lo hará como 2+B dividido entre 2, en vez de darle la prioridad a la división, que es lo normal.

-No usar IF NOT(A) que consume mucho. Usar IF A=0 o IF A<>.

-Es más rápido hacer A=B+B o A=B+B+B que A=B*2 o A=B*3 respectivamente. A partir de 4, ya no compensa.

-Gran mito caído. El apóstrofe ' es más lento que el REM, y para colmo ocupa más (que es lo que siempre repetían en las revistas).


Seguro que hay cosas que corregir y aportar mil ideas más. Así que lo mejor es dejar esto abierto y que cada uno nos vaya contando sus experiencias  :)


Título: Re: Optimizando los listadillos basic
Publicado por: Darth_Fistro en 25 de Enero de 2006, 04:14:07 pm
-El basic almacena las variables en una lista, a la que accede secuencialmente desde la primera posición. A medidas que usas variables, se van metiendo en esa lista, por tanto la última variable que has usado es la última que encuentra, y por tanto la más lenta. Moraleja::define primero (da un valor, un cero por ejemplo) las variables que más uses y luego las menos importantes.

-Por esa regla de tres, cuantas menos variables tengamos, mejor. Menos memoria y más rapidez de acceso. Así que si I, T, X o lo que sea no los usas fuera de un bucle y da igual cambiarlos, úsalos en vez de definir otra variable. Vale, es más lioso, pero más eficaz.


Título: Re: Optimizando los listadillos basic
Publicado por: SapphiRe en 25 de Enero de 2006, 04:18:07 pm
Un truco más:

Las subrutinas que se ejecuten muchas veces y cuya velocidad sea crítica han de ir al principio del programa.

Y ahora la explicación:

Cuando se hace un salto de línea, el intérprete de BASIC recorre el listado DESDE EL COMIENZO para buscar la línea a la que tiene que saltar. Si la rutina está en una línea alta, se perderá muchísimo tiempo en este recorrido.

Moraleja: la primera línea del listado debería ser un GOTO xxx donde xxx representa la línea de inicio de la rutina de inicialización y presentación del juego. El menú (si lo tiene) también debería ir al final del listado. Las subrutinas que requieran velocidad, al principio.

Saludos
--
SapphiRe


Título: Re: Optimizando los listadillos basic
Publicado por: Darth_Fistro en 25 de Enero de 2006, 04:19:19 pm
-Una más. Es más rápido acceder a una variable matricial unidimensional que multidimensional. Así que es mejor definir p.e. un cuadro de juego de 8x8 como DIM A(64) que como DIM A(8,8). Tened en cuenta el acceso secuencial a las 64 casillas, que es más complicadillo (pero un pelín) y a cambio ganaréis en velocidad.


Título: Re: Optimizando los listadillos basic
Publicado por: SapphiRe en 25 de Enero de 2006, 04:27:01 pm
Ya puestos, una rutina para mover las coordenadas X,Y de un Sprite leyendo el joystick. Supongamos que en J está el valor del joystick y que queremos mover un pixel el Sprite en las 8 direcciones:

X=X-(J=2)-(J=3)-(J=4)+(J=6)+(J=7)+(J=8)
Y=Y-(J=4)-(J=5)-(J=6)+(J=8)+(J=1)+(J=2)

Y ahora (como siempre) la explicación:

Una expresión booleana puede ser verdadera o falsa, pero el BASIC del MSX codifica el Falso como 0 y el Verdadero como -1. Si asumís este hecho se pueden hacer muchos apaños de velocidad :)

Saludos
--
SapphiRe refrescando el Basic


Título: Re: Optimizando los listadillos basic
Publicado por: Imanok en 25 de Enero de 2006, 04:31:51 pm
Para todo el tema de espacios, comentarios y tal, vale MUCHO la pena probar el NestorPreter. Te puedes inflar a poner comentarios, nombres de variables largos, macros, etc, etc... que luego el programa en sí te queda en lo mínimo.


Título: Re: Optimizando los listadillos basic
Publicado por: jltursan en 25 de Enero de 2006, 09:16:07 pm
¡Muy buena la recopilación de trucos hasta ahora! :D

Ahí va otro:

Si estamos trabajando en SC0 o en SC1 es muy probable que en algún momento tengamos que hacer un montón de PRINTs con sus correspondientes LOCATEs. En lugar de emparejar cada PRINT con su LOCATE, podemos estudiar si hay alguna solución equivalente utilizando las secuencias de escape que son bastante más rápidas que los LOCATE a la hora de, por ejemplo, ubicar el cursor en pantalla (sobre todo porque el intérprete se ahorra procesar esa operación).

Las secuencias son (también consultables en el MTH, capítulo TH-AP.TXT) :

Movimiento del cursor

<ESC> A    mueve el cursor hacia arriba
<ESC> B    mueve el cursor hacia abajo
<ESC> C    mueve el cursor hacia la derecha
<ESC> D    mueve el cursor hacia la izquierda
<ESC> H    mueve el cursor a la posición de inicio (home)
<ESC> Y <coordenada-Y+20H> <coordenada-X+20H>
      mueve el cursor a (X, Y)


Editar, borrar

<ESC> j    Borra la pantalla
<ESC> E    Borra la pantalla
<ESC> K    Borra hasta el final de la linea
<ESC> J    Borra hasta el final de la pantalla
<ESC> L    Insertar una linea
<ESC> M    Borrar una linea


Miscelaneas

<ESC> x4   Selecciona el cursor de bloque
<ESC> x5   Esconde el cursor
<ESC> y4   Selecciona el cursor de linea
<ESC> y5   Muestra el cursor

Por ejemplo, si por casualidad tenemos un "sprite" construido a partir de 3x3 (abc,def,ghi) carácteres, no necesitamos hacer tres LOCATEs con sus correspondientes PRINTs; si definimos el "sprite" en una cadena, con un único LOCATE+PRINT podremos presentarlo en pantalla :

Código:
10 S1$="abc"+CHR$(27)+"B"+CHR$(27)+"D"+CHR$(27)+"D"+CHR$(27)+"D"+"def"+CHR$(27)+"B"+CHR$(27)+"D"+CHR$(27)+"D"+CHR$(27)+"D"+"ghi"
20 LOCATE X,Y:PRINT S1$

Código:
10 A$=CHR$(27)+"Y"+CHR$(42)+CHR$(44)+"MSX RULES!!":PRINT A$
Equivalente a LOCATE 12,10:PRINT "MSX RULES!!"

No sólo es más compacto, sino que a poco que tengamos unos cuantos muñecos sacad la cuenta de los LOCATE y PRINT que se ahorran.


Título: Re: Optimizando los listadillos basic
Publicado por: Imanok en 26 de Enero de 2006, 10:52:18 am
Hay alguna forma de mostrar por pantalla X patrones (consecutivos en la tabla de patrones) de manera más rápida que vpokeándolos uno por uno (ya sea con un FOR o con X vpokes)??


Título: Re: Optimizando los listadillos basic
Publicado por: pitpan en 26 de Enero de 2006, 11:11:24 am
Si son consecutivos en la tabla de nombres, lo que hago es inicializar la dirección inicial con un VPOKE y después mandar el resto con OUTs al VDP. Así no hace falta actualizar contadores, porque el registro apuntador de direcciones del VDP se autoincrementa sólo después de recibir cada byte. Pero cuidadín: ni se te ocurra hacer NADA que afecte a la VRAM mientras tanto, porque se volvería majareta.


Título: Re: Optimizando los listadillos basic
Publicado por: Imanok en 26 de Enero de 2006, 12:32:44 pm
Si son consecutivos en la tabla de nombres, lo que hago es inicializar la dirección inicial con un VPOKE y después mandar el resto con OUTs al VDP. Así no hace falta actualizar contadores, porque el registro apuntador de direcciones del VDP se autoincrementa sólo después de recibir cada byte

Un ejemplillo, please... imagina que quieres copiar los patrones del 0 al 9, en la posición 0 de la pantalla.

Pero cuidadín: ni se te ocurra hacer NADA que afecte a la VRAM mientras tanto, porque se volvería majareta.

Qué tipo de cosas podrían afectar??... porque cuando copio patrones, hago eso, no puedo hacer otra cosa a la vez...


Título: Re: Optimizando los listadillos basic
Publicado por: pitpan en 26 de Enero de 2006, 02:28:34 pm
VPOKE&h1800,0:FORI=1TO9:OUT&h98,I:NEXT

Ya veis que uso el máximo de ofuscación disponible. Explicación:

VPOKE&h1800,0: escribe 0 en la posición 6144 de VRAM, habitualmente inicio de la tabla de nombres. Deja el apuntador de memoria del VDP apuntando ya a la posición 6145 (se autoincremente después de cada lectura/escritura).

OUT&h98,I: escribe el valor I en la posición de memoria VRAM a la que apunta actualmente el apuntador del VDP e incrementa en uno nada más terminar.

Resulta más claro con un ejemplo, espero.


Título: Re: Optimizando los listadillos basic
Publicado por: Imanok en 26 de Enero de 2006, 04:31:00 pm
Comprendido... de esta forma copias los 10 patrones (uno a uno) en 10 posiciones consecutivas indicando sólo la primera posición... pero se puede hacer que se copien 10 patrones consecutivos indicando sólo el primer patrón de la tabla, en 10 posiciones consecutivas indicando sólo la primera posición?? (es un poco rebuscao...).


Título: Re: Optimizando los listadillos basic
Publicado por: pitpan en 26 de Enero de 2006, 05:18:36 pm
Pues no sé muy bien a lo que te refieres, pero podría ser algo así:

10 D=6144+32*8+15:P=45:GOSUB1000
...
...
1000 VPOKED,P:FORI=0TO9:P=P+1:OUT&h98,P:NEXT:RETURN

Si no te he entendido mal, claro.  ;)

Otra alternativa - no sé cual sería más rápida - es la siguiente:

1000 VPOKED,P:FORI=1TO9:OUT&h98,P+I:NEXT:RETURN

Ya me dirás.


Título: Re: Optimizando los listadillos basic
Publicado por: Jon_Cortazar en 26 de Enero de 2006, 06:13:22 pm
Sois unos freaks...  :spank:


Título: Re: Optimizando los listadillos basic
Publicado por: Imanok en 27 de Enero de 2006, 08:50:29 am
Pues no sé muy bien a lo que te refieres, pero podría ser algo así:

10 D=6144+32*8+15:P=45:GOSUB1000
...
...
1000 VPOKED,P:FORI=0TO9:P=P+1:OUT&h98,P:NEXT:RETURN

Si no te he entendido mal, claro.  ;)

No va por ahí la cosa, ya que tu recorres los 10 patrones de la tabla con un FOR. A ver si me explico mejor:

-Imaginemos que tengo un set de patrones completo, con las fuentes de los carácteres en sus lugares correspondientes y tal.
-Imaginemos que yo quiero mostrar por pantalla "ABCDEFGHIJ" (o sea, 10 patrones consecutivos de la tabla) en la posición 6144 de la VRAM (el la posición '0' de la pantalla que vemos, si no lo he puesto mal).
-Se puede hacer lo anterior sin utilizar un bucle, diciéndole de alguna forma "cópiame 10 patrones de la tabla (de la 'A' a la 'J') a partir de la posición 6144 de la VRAM (de la 6144 a la 6153)"??

No se si me explico...


Título: Re: Optimizando los listadillos basic
Publicado por: Imanok en 27 de Enero de 2006, 08:50:55 am
Pues no sé muy bien a lo que te refieres, pero podría ser algo así:

10 D=6144+32*8+15:P=45:GOSUB1000
...
...
1000 VPOKED,P:FORI=0TO9:P=P+1:OUT&h98,P:NEXT:RETURN

Si no te he entendido mal, claro.  ;)

No va por ahí la cosa, ya que tu recorres los 10 patrones de la tabla con un FOR. A ver si me explico mejor:

-Imaginemos que tengo un set de patrones completo, con las fuentes de los carácteres en sus lugares correspondientes y tal.
-Imaginemos que yo quiero mostrar por pantalla "ABCDEFGHIJ" (o sea, 10 patrones consecutivos de la tabla) en la posición 6144 de la VRAM (en la posición '0' de la pantalla que vemos, si no lo he puesto mal).
-Se puede hacer lo anterior sin utilizar un bucle, diciéndole de alguna forma "cópiame 10 patrones de la tabla (de la 'A' a la 'J') a partir de la posición 6144 de la VRAM (de la 6144 a la 6153)"??

No se si me explico...


Título: Re: Optimizando los listadillos basic
Publicado por: jltursan en 27 de Enero de 2006, 10:03:38 am
Si entiendo que hablas de SC2, entonces o mucho me equivoco o en BASIC no se puede. Si fuese SC1, entonces tu instrucción sería PRINT; pero claro, no van por ahí los tiros :(


Título: Re: Optimizando los listadillos basic
Publicado por: Imanok en 27 de Enero de 2006, 12:29:18 pm
Claro, claro... hablo de SR2.

Lo que quiero sería algo que funcionalmente fuese como ésto (haciendo un símil con el COPY en SR5 o SR8):

COPY (pattern_n)-(pattern_n+9),pattern_table TO (X,Y),main_screen


Título: Re: Optimizando los listadillos basic
Publicado por: jltursan en 27 de Enero de 2006, 01:59:05 pm
Pues lo dicho, pa mi que no... :(


Título: Re: Optimizando los listadillos basic
Publicado por: WYZ en 27 de Enero de 2006, 04:32:16 pm
Se pueden utilizar las rutinas de la BIOS para esto que pides Imanok, pero algunas no son directamente accesibles  sino que hay que introducir los parámetros previos en los registros del z80. En el ejemplo que te pongo, para pocos caracteres no se si se gana en velocidad, pero si cuando hay que mover grandes bloques. ( hace un scroll deun circulo simplemente copiando a ram y volcando a vram variando una posicion en la tabla de tiles. A ver si os sugiere algun otro uso de la BIOS)

Código:
5 COLOR 15,4,1
10 SCREEN 2
20 DEFINT A-L
21 CIRCLE (216,32),31
30 H=&H18:L=0:D=&HD1:E=0:B=&H1:C=0:FBIOS=&H59:GOSUB 50
32 H=&HD1:L=0:D=&H18:E=0:B=&H:C=&HFF:FBIOS=&H5C
34 L=L+1:C=C-1
35 GOSUB 50
36 IF C>0 THEN GOTO 34
40 GOTO 40
50 DIR=&HD000
60 POKE DIR,&H1
70 POKE DIR+1,C
80 POKE DIR+2,B
90 POKE DIR+3,&H11
100 POKE DIR+4,E
110 POKE DIR+5,D
120 POKE DIR+6,&H21
130 POKE DIR+7,L
140 POKE DIR+8,H
150 POKE DIR+9,&H3E
160 POKE DIR+10,A
170 POKE DIR+11,&HCD
180 POKE DIR+12,FBIOS
190 POKE DIR+13,&H
191 POKE DIR+14,&HC9
200 DEFUSR=DIR:A=USR(0)
210 RETURN

Solo se mueve la parte superior de la pantalla, pero podría hacerse sin problemas de la pantalla completa. Seguro que lo puedes mejorar :D


Título: Re: Optimizando los listadillos basic
Publicado por: pitpan en 27 de Enero de 2006, 06:08:09 pm
Efectivamente, así sí se puede hacer, usando la BIOS (LDIRVM, FILVRM, etc.). Lo que sucede es que, como bien dice WYZ, hay que pasar parámetros mediante registros, lo que supone programación adicional (desde BASIC, usando POKEs que guardan en RAM programas en código máquina). Para lo que tengas que hacer, perfecto. Pero no valdría, por ejemplo, para el concurso que nos traemos entre manos.


Título: Re: Optimizando los listadillos basic
Publicado por: WYZ en 27 de Enero de 2006, 06:36:46 pm


Se me ocurre otra pregunta:¿hay alguna manera de incluir en un listado basic datos binarios? No me refiro a los tipicos datas o cadenas alfanumericas que deben ser transformadas, sino bytes. Por ejemplo, si el listado basic termina en la direccion de memoria 9000h y quiero guardar en el mismo archivo .bas con save hasta la direccion &h9100 porque ahi he guardado ciertos datos graficos ¿Como seria posible adjuntarlos? ¿y si esto es posible como se podrían volver a cargar?


Título: Re: Optimizando los listadillos basic
Publicado por: SapphiRe en 27 de Enero de 2006, 06:45:37 pm
Prueba a meterlos con REM...


Título: Re: Optimizando los listadillos basic
Publicado por: jltursan en 27 de Enero de 2006, 06:49:52 pm
...o encriptándolos como tokens BASIC.

El problema es que supongo que el límite por linea en el intérprete será de 256 bytes, por lo que con cada cambio de linea te insertaría datos ajenos a los tuyos. No creo que se pueda integrar un bloque de más de 250 bytes de tamaño dentro de un listado BASIC, la verdad.


Título: Re: Optimizando los listadillos basic
Publicado por: pitpan en 27 de Enero de 2006, 09:19:15 pm
Por cierto, que hay una rutina de la BIOS muy útil para el desarrollo de juegos de calidad en BASIC. La técnica es un poco compleja, pero creo que sí será aceptable para el concurso. El procedimiento es el siguiente:

1.- Escribir todo el programa en el MSX.
2.- No hacer ninguna copia de seguridad.
3.- Cuando ya esté terminado, ejecutar el siguiente comando en BASIC:

DEFUSR=0:A=USR(0)

Esta rutina se llama CHKRAM, es decir, CHange to Klingon RAM mode, y habilita un modo de acceso a RAM del Z80 no documentado y que acelera todos los programas. De hecho, veréis que es como si a la CPU no le costara ejecutar el programa, gracias al acceso ultrarápido mediante indexación predictiva a la memoria principal. Hasta la fecha, es la técnica más efectiva que he visto para que un programa en BASIC, por pesado que sea, se ejecute muy rápido.

Espero que os ayude  ;D


Título: Re: Optimizando los listadillos basic
Publicado por: e_sedes en 28 de Enero de 2006, 03:16:45 am
Por cierto, que hay una rutina de la BIOS muy útil para el desarrollo de juegos de calidad en BASIC. La técnica es un poco compleja, pero creo que sí será
De hecho es con lo yo andaba experimentando. El problema es que aprovechando el incremento de velocidad y mis rutinas super-optimizadas, el programa BASIC mueve 32 sprites hardware  simultaneos cada 8 lineas  (sin contar con los sprites por software) y claro, el VDP se me calienta un poco. Voy a probar próximamente cuando me toque el aseo mensual a meter conmigo el MSX y la tele en la bañera, a ver si así se refresca un poco. Bueno, ya informaré de los resultados que consiga...  ;D ;D ;D

(que malo es esto de llegar a casa el viernes a las 3 de la mañana con un par de copas beer:) y tener que currar mañana...)


Título: Re: Optimizando los listadillos basic
Publicado por: jltursan en 28 de Enero de 2006, 12:36:53 pm
Ya te digo; pero malo, malo... ;D


Título: Re: Optimizando los listadillos basic
Publicado por: Imanok en 28 de Enero de 2006, 12:47:57 pm
Cita de: WYZ
Se pueden utilizar las rutinas de la BIOS para esto que pides Imanok, pero algunas no son directamente accesibles  sino que hay que introducir los parámetros previos en los registros del z80. En el ejemplo que te pongo, para pocos caracteres no se si se gana en velocidad, pero si cuando hay que mover grandes bloques.

Entonces no creo que me valga, porque estoy haciéndolo para mover bloques relativamente pequeños.

Cita de: robsy
Para lo que tengas que hacer, perfecto. Pero no valdría, por ejemplo, para el concurso que nos traemos entre manos.

No, no... no es para el concurso de basic.

Por cierto, Edu... he probado tu método ese del OUT y no me funciona... solo me muestra por pantalla el patron del vpoke inicial y el resto, nanai...



Título: Re: Optimizando los listadillos basic
Publicado por: Jon_Cortazar en 28 de Enero de 2006, 01:42:03 pm
También es muy socorrido el truco de: 10 MOTORON:MOTOROFF:GOTO10... creo que pone al z80 en modo turbo (o, por lo menos, le hace sonar como mi secadora)


Título: Re: Optimizando los listadillos basic
Publicado por: pitpan en 28 de Enero de 2006, 06:04:36 pm
Imanok: si lo que quieres es usar directamente un LOCATE X,Y:PRINT A$ en SCREEN 2 puedes hacerlo.

Simplemente, estando en SCREEN 2 y con todos los patrones de los 3 bancos ya definidos, usa el comando POKE &hFCAF,1. Con eso conseguirás que el BASIC crea que está en SCREEN 1, con lo que podrás usar LOCATE, PRINT, etc.

Para volver a convencer al MSX de que está en SCREEN 2, pokea la misma dirección con el valor 2. Así podrás volver a usar CIRCLE, LINE, PAINT, etc.

Pero cuidadín con lo que haces, ¿vale?  ;D


Título: Re: Optimizando los listadillos basic
Publicado por: Imanok en 28 de Enero de 2006, 08:09:39 pm
Imanok: si lo que quieres es usar directamente un LOCATE X,Y:PRINT A$ en SCREEN 2 puedes hacerlo.

Simplemente, estando en SCREEN 2 y con todos los patrones de los 3 bancos ya definidos, usa el comando POKE &hFCAF,1. Con eso conseguirás que el BASIC crea que está en SCREEN 1, con lo que podrás usar LOCATE, PRINT, etc.

Ah, sí?? sólo con eso??... y qué diferéncia hay entre ésto del poke y el modo mixto ese del que tanto se ha hablado??... porque parece que sea lo mismo...

Aparte de eso... has comprobado que lo del OUT que comentaste funciona??... en mi programa no me ha funcionado y luego he hecho pruebas utilizando el código que habías puesto tú y nada... puede ser que no hayas puesto la dirección correcta??

Aprovecho y otra duda...

Ya he visto que si quiero borrar la pantalla, al hacer un CLS me cargo todo... entonces, hay alguna forma de borrar toda la pantalla visible, que sea más rápida que vpokear el patron 0 en todas las posiciones una por una??... es que no veas qué peñazo...

Citar
Pero cuidadín con lo que haces, ¿vale?  ;D

Siiiiiiiiiiiiiiiiiiiiiiiiiiiiii!!!!!  :D


Título: Re: Optimizando los listadillos basic
Publicado por: e_sedes en 28 de Enero de 2006, 08:25:52 pm
Simplemente, estando en SCREEN 2 y con todos los patrones de los 3 bancos ya definidos, usa el comando POKE &hFCAF,1. Con eso conseguirás que el BASIC crea que está en SCREEN 1, con lo que podrás usar LOCATE, PRINT, etc.

no habría que hacer primero SCREEN 1: WIDTH 32 antes que el SCREEN2? Para que así el BASIC escriba en los lugares correspondientes a cada carácter, no?
Yo esto me lo acabo de aprender mirando el listado del Memory, que no lo sabía y mola. :)


Título: Re: Optimizando los listadillos basic
Publicado por: Imanok en 28 de Enero de 2006, 08:54:27 pm
Citar
Ya he visto que si quiero borrar la pantalla, al hacer un CLS me cargo todo... entonces, hay alguna forma de borrar toda la pantalla visible, que sea más rápida que vpokear el patron 0 en todas las posiciones una por una??... es que no veas qué peñazo...

Autorespuesta!
Investigando con eso de los pokes, he visto que lo mejor para borrar la pantalla es:

POKE &hFCAF,1:CLS:POKE &hFCAF,2

Y ale, pantalla borrada en un pis pas!! ;D



Título: Re: Optimizando los listadillos basic
Publicado por: jltursan en 28 de Enero de 2006, 08:59:19 pm
Vaya, mi gozo en un pozo, no parece que funcione ¿es posible que sólo vaya en algunos equipos?, ¿o será culpa del emulador?.
La idea parecía buena, la tabla de nombres en ambos modos (1 y 2) está en el mismo sitio; así a priori podría haber colado... ???

Autorespuesta!!

Acabo de descubrir que para que funcione la entrada a screen 2 debe de hacerse desde screen 1, no desde screen 0. O sea, algo así como:

Código:
screen 1:screen 2

...nada más empezar.


Título: Re: Optimizando los listadillos basic
Publicado por: jltursan en 28 de Enero de 2006, 09:01:51 pm
Citar
no habría que hacer primero SCREEN 1: WIDTH 32 antes que el SCREEN2? Para que así el BASIC escriba en los lugares correspondientes a cada carácter, no?

¡Ajum!, creo que me he repetido, sospecho que era esto a lo que te referías... ::)

En cualquier caso el truco está genial (pena de tener que cargar los tres bancos)


Título: Re: Optimizando los listadillos basic
Publicado por: e_sedes en 28 de Enero de 2006, 10:40:25 pm
¡Ajum!, creo que me he repetido, sospecho que era esto a lo que te referías... ::)

En cualquier caso el truco está genial (pena de tener que cargar los tres bancos)
Pozí, eso era. Y si, está genial.
Ya me lo apliqué al algo que estoy intentando hacer y el dibujado de la pantalla se ha disparado, jeje, mola.
Ten en cuenta que haciendo CLS te llena la pantalla con el tile 32 (el caracter del espacio), y para PRINTar los caracteres inferiores hay que poner chr$(0)+chr$(64+n), siendo n el nº de tile. Un poco lioso pero no demasiado.


Título: Re: Optimizando los listadillos basic
Publicado por: e_sedes en 28 de Enero de 2006, 11:09:24 pm
Ah, y también el WIDTH32 es importante para poder acceder bien a toda la pantalla. Y con KEYOFF apuras un pelín más el uso de PRINT. Para la última linea y el último carácter de la penúltima hay que vpokear.
Tal vez esto ya lo controlases, pero bueno, yo tuve que refrescarme la memoria. :)


Título: Re: Optimizando los listadillos basic
Publicado por: WYZ en 28 de Enero de 2006, 11:41:53 pm
defusr=&H77E:a=usr(0)

rellena la pantalla con &H300 tiles &H20 ( o 32) si hay un 1 en &HFCAF y con tres bancos de tiles incrementando de 1 en 1 si hay un 2 pero no te limpia la definicion de caracteres.

Ah, se me olvidaba. Hay que poner Keyoff


Título: Re: Optimizando los listadillos basic
Publicado por: Imanok en 30 de Enero de 2006, 10:21:56 am
Ten en cuenta que haciendo CLS te llena la pantalla con el tile 32 (el caracter del espacio), y para PRINTar los caracteres inferiores hay que poner chr$(0)+chr$(64+n), siendo n el nº de tile. Un poco lioso pero no demasiado.

Te refieres a que para printar los caracteres del 0 al 31 hay que hacer chr$(0)+chr$(64+n) ??... si es así, lo he probado y no funciona... alguna otra solución para printar esos caracteres?? (usando PRINT, no vpoke).


Título: Re: Optimizando los listadillos basic
Publicado por: e_sedes en 30 de Enero de 2006, 02:36:02 pm
Citar
Te refieres a que para printar los caracteres del 0 al 31 hay que hacer chr$(0)+chr$(64+n) ??... si es así, lo he probado y no funciona... alguna otra solución para printar esos caracteres?? (usando PRINT, no vpoke).
Opss, perdón, es chr$(1)+chr$(64+n). Prueba ahora.


Título: Re: Optimizando los listadillos basic
Publicado por: SapphiRe en 30 de Enero de 2006, 02:52:49 pm
Simplemente, estando en SCREEN 2 y con todos los patrones de los 3 bancos ya definidos, usa el comando POKE &hFCAF,1. Con eso conseguirás que el BASIC crea que está en SCREEN 1, con lo que podrás usar LOCATE, PRINT, etc.

Para volver a convencer al MSX de que está en SCREEN 2, pokea la misma dirección con el valor 2. Así podrás volver a usar CIRCLE, LINE, PAINT, etc.

Esto demuestra, una vez más, lo iguales que son SCREEN 1 y 2 en el MSX, lo cual nos da muchísimo juego a la hora de hacer efectos interesantes con los gráficos :D



Título: Re: Optimizando los listadillos basic
Publicado por: Imanok en 30 de Enero de 2006, 04:47:19 pm
Opss, perdón, es chr$(1)+chr$(64+n). Prueba ahora.

Ahora sí!  ;)


Título: Re: Optimizando los listadillos basic
Publicado por: Imanok en 31 de Enero de 2006, 08:46:01 am
Por cierto, he descubierto otra forma de poder escribir los patrones 0-31 con un PRINT, haciendo lo siguiente:

-Inicializamos como habéis comentado SCREEN 1:WIDTH32:SCREEN2:cargo_set:POKE &hFCAF,1
-A partir de aquí, mostramos por pantalla (con vpokes) los patrones que queramos de entre los 32 primeros.
-Hacemos un CTRL+STOP y nos situamos sobre la línea de patrones que acabamos de dibujar, insertándole delante un número de línea y un PRINT", para incluirlo en nuestro programa y ya está (luego ya coloco esa línea donde me convenga).

Lo que he hecho ha sido dibujar toda la pantalla con vpokes, hacer CTRL+STOP y crear 23 líneas de programa con los patrones de cada línea. Como ya habéis comentado, el último patrón de la penúltima línea y la última línea completa, hay que hacerlos con vpoke... pero vamos, la diferencia de velocidad es grandísima (entre dibujar toda la pantalla con vpoke's o con print's, quiero decir).


Título: Re: Optimizando los listadillos basic
Publicado por: jltursan en 31 de Enero de 2006, 11:32:53 am
Citar
Hacemos un CTRL+STOP y nos situamos sobre la línea de patrones que acabamos de dibujar, insertándole delante un número de línea y un PRINT", para incluirlo en nuestro programa y ya está

Esos carácteres creo que se podían obtener desde el teclado usando la tecla GRAPH, ¿no?. EL problema debe de ser, como habeis comentado, obtenerlos a partir de CHR$ ???


Título: Re: Optimizando los listadillos basic
Publicado por: Imanok en 01 de Febrero de 2006, 08:59:09 am
Esos carácteres creo que se podían obtener desde el teclado usando la tecla GRAPH, ¿no?. EL problema debe de ser, como habeis comentado, obtenerlos a partir de CHR$ ???

Yo pensaba que la primera fila de la tabla de patrones no se podía pintar con GRAPH... pero va a ser que sí. Torpedo que es uno... :P


Título: Re: Optimizando los listadillos basic
Publicado por: jltursan en 04 de Febrero de 2006, 12:27:26 pm
Citar
Aparte de eso... has comprobado que lo del OUT que comentaste funciona??... en mi programa no me ha funcionado y luego he hecho pruebas utilizando el código que habías puesto tú y nada... puede ser que no hayas puesto la dirección correcta??

¿Ya te ha funcionado?; como debería hacerlo, por si las moscas puedes probar esto :

Código:
10 SCREEN 1
20 VPOKE &H1800,65
30 OUT &H98,66
40 OUT &H98,67
50 OUT &H98,68
60 GOTO 60


Título: Re: Optimizando los listadillos basic
Publicado por: Imanok en 04 de Febrero de 2006, 12:36:36 pm
Citar
¿Ya te ha funcionado?; como debería hacerlo, por si las moscas puedes probar esto :

Código:
10 SCREEN 1
20 VPOKE &H1800,65
30 OUT &H98,66
40 OUT &H98,67
50 OUT &H98,68
60 GOTO 60

Qué se supone que debe hacer ese código??... a mí me ha pintado una 'A' y punto.

De todas formas, gracias al poke aquel que comentásteis, lo estoy haciendo con PRINT's, que es muchísimo más rápido.  ;D


Título: Re: Optimizando los listadillos basic
Publicado por: jltursan en 04 de Febrero de 2006, 12:50:13 pm
¡Ahí va, la leche!, si es que eso sólo funciona en los emuladores  :P :P :P
Lo he probado en el 2+ que me pillaba más a mano y, como tú dices, sólo muestra la A. En el MSX1 no he podido probarlo porque parece que se me ha jodido la tecla ","  :o :o. ¡Dos disgustos en uno!
Curioso el asunto este del puntero a la VRAM...


Título: Re: Optimizando los listadillos basic
Publicado por: Darth_Fistro en 04 de Febrero de 2006, 01:29:15 pm
¡Ahí va, la leche!, si es que eso sólo funciona en los emuladores  :P :P :P
Lo he probado en el 2+ que me pillaba más a mano y, como tú dices, sólo muestra la A. En el MSX1 no he podido probarlo porque parece que se me ha jodido la tecla ","  :o :o. ¡Dos disgustos en uno!
Curioso el asunto este del puntero a la VRAM...

¿Ya estáis creando incompatibilidades? ¡Usuarios de Spectrum teníais que ser!  ;D

Probé lo del poke para hacer creer al basic que se estaba en sc1 cuando en realidad es sc2, e hice un print"AAAA" pero sólo me salió una "A". Vpokee la A para redefinirla y colorearla y nada. Eso sí, lo probé en el rumsx  :P


Título: Re: Optimizando los listadillos basic
Publicado por: Imanok en 27 de Febrero de 2006, 12:28:35 pm
Otra dudilla... respecto al uso de DATA, READ y RESTORE.

Imaginemos que a partir de cierta línea tengo almacenadas las pantallas del juego... pues bien, para acceder a los datos hago lo normal, un RESTORE de la línea donde empiezan y voy leyendo con READ. De la forma que lo hago ahora, siempre tengo que hacer READ de los datos anteriores a la pantalla que quiero, hasta que llego a la misma (lo cual, ralentiza bastante el tema en pantallas avanzadas)... hay alguna forma de avanzar X posiciones al hacer un READ o algo del estilo??... si no, aún me veo que tendré que repartir las pantallas en bloques y hacer un RESTORE diferente según la pantalla que quiera cargar...


Título: Re: Optimizando los listadillos basic
Publicado por: SapphiRe en 27 de Febrero de 2006, 12:40:51 pm
si no, aún me veo que tendré que repartir las pantallas en bloques y hacer un RESTORE diferente según la pantalla que quiera cargar...

Será lo mejor... :D


Título: Re: Optimizando los listadillos basic
Publicado por: jltursan en 27 de Febrero de 2006, 03:20:35 pm
Así lo he hecho yo. Estuve dándole vueltas a alguna otra forma y mediante unos pokes puedes indicarle a partir de donde empiezan los DATAs a ser leidos, el problema es que esa posición no corresponde a un número de linea, sino a una dirección de memoria :P
La pregunta se convierte entonces en : ¿Se puede averiguar desde BASIC la posición de memoria en la que se encuentra una linea determinada?, supongo que no... :'(


Título: Re: Optimizando los listadillos basic
Publicado por: SapphiRe en 27 de Febrero de 2006, 03:23:32 pm
La pregunta se convierte entonces en : ¿Se puede averiguar desde BASIC la posición de memoria en la que se encuentra una linea determinada?, supongo que no... :'(

Mal supuesto. Claro que se puede averiguar, tendrías que hacer un recorrido de la memoria destinada al programa en BASIC parseando los números de línea y las direcciones. Aquí no tengo la información necesaria, pero prometo buscarla y si quieres charlamos en la MadriSX sobre cómo hacerlo.

Saludos
--
SapphiRe


Título: Re: Optimizando los listadillos basic
Publicado por: jltursan en 27 de Febrero de 2006, 03:29:44 pm
¡Quieto León!  :whip:

Es que me he expresado mal, claro que se puede averiguar la linea (de hecho así es como funciona el ROMCreator ;D); pero claro, lento y a costa de tirar código. Me refería a algo del tipo PEEK mágico o DEFUSR chulo. Algo que en un pispas te de el dato...voy a seguir suponiendo que no existe...(ojala que alguien demuestre lo contrario) ;)


Título: Re: Optimizando los listadillos basic
Publicado por: Imanok en 28 de Febrero de 2006, 08:35:04 am
Pues nada... resignación...  :(

En cuanto a la localización de las DATA's... comentásteis que las subrutinas que más se utilicen deberían ir al principio del programa, ya que de esta forma se ganaba velocidad... con las DATA's pasa lo mismo??


Título: Re: Optimizando los listadillos basic
Publicado por: jltursan en 28 de Febrero de 2006, 09:59:50 am
También, también. El RESTORE es el que curra cuando los DATAs están al final ya que para localizar la linea que le pones, se las recorre desde el principio. Como con los GOTOs y los GOSUBs pasa lo mismo; pues cuanto más arriba estén las subrutinas y los saltos; pues mejor. Hay otro detalle importante, los saltos de cualquier tipo hacia adelante, son mucho más rápidos que saltar hacia atrás, aunque sea una mísera linea de diferencia.


Título: Re: Optimizando los listadillos basic
Publicado por: Imanok en 28 de Febrero de 2006, 02:39:06 pm
Ok, Mackey!


Título: Re: Optimizando los listadillos basic
Publicado por: Imanok en 10 de Marzo de 2006, 09:57:31 am
Porculeando de nuevo...  ;)

A ver... si quiero hacer un binario que contenga el set gráfico comprimido y el código descompresor, dónde (de la página 3, supongo) sería mejor tener la zona de buffer para que no me cargue nada y que sea compatible??... solo se usaría al comienzo para cargar los gráficos y ya está.


Título: Re: Optimizando los listadillos basic
Publicado por: jltursan en 10 de Marzo de 2006, 10:06:03 am
Bueno, puede haber varias situaciones :

  • Si usas RLE : pues puedes descomprimir directamente a VRAM.
  • Si usas Bitbuster : tendrás que usar el buffer que comentas :P
  • El buffer siempre irá en la página 3 y dependerá de la organización de las variables del programa el que sea reaprovechable o no. Lo más sencillo creo yo que sería descomprimir en $C000 nada más empezar el programa y a continuación, una vez volcado a VRAM, crear tu area de variables a partir de $C000, borrándola con 0 e inicializándola como quieras.



Título: Re: Optimizando los listadillos basic
Publicado por: Imanok en 10 de Marzo de 2006, 02:01:40 pm
Pero la dirección $C000 está disponible en los MSX de 8K?


Título: Re: Optimizando los listadillos basic
Publicado por: jltursan en 10 de Marzo de 2006, 05:07:04 pm
¡Buf!, no te sabría decir si la RAM se localiza en $8000-$9FFF o en $C000-$DFFF; pero me decantaría por esta última. De todas formas los equipos de 8Kb (¿existía un Daewoo?) son tanto o más marginales como los equipos con los puertos del VDP diferentes al $98-$99; la verdad, yo no me preocuparía demasiado por eso... :P


Título: Re: Optimizando los listadillos basic
Publicado por: MsxKun en 10 de Marzo de 2006, 08:10:19 pm
Hola

Mas bien la direccion deberia ser $e000-$ffff no? Sino la ram del sistema estaria en direcciones raras y los programas q aun entraran en 8ks no rularian. Especialmente la direccion -1. Pa mi que era intocable, como el Eliot Nés ese... :D