• Esta es la conversion de la version Spectrum 48K a la ZX81, el programa ocupa casi 5K, por lo que requiere 16K de RAM. Esta estructurado igual que la version de Spectrum, hay que asignar un texto a la variable Z$ y luego llamar a USR 16514 que es el sintetizador, cargado en la linea 0 REM. Creo que no es seguro borrar la linea 1, porque se empieza a listar infinitamente la linea 0 (me paso con otro programa).
    El programa tiene 3 rutinas, la demo del inicio esta dividida en 2 porque no pude hacer que muestre un texto y luego conserve la pantalla activada, por lo que llamando a USR 16517 imprime el texto del arranque, USR 16520 habla el texto correspondiente, y USR 16514 es el sintetizador que busca automaticamente si existe una variable Z$, y de ser asi reproduce el texto.
    El sintetizador es completamente funcional, y borrando todas las lineas menos la 0 se puede usar en programas BASIC propios. Lo que cambie con respecto a las otras versiones es el comando ' (apostrofe), ya que no existe en el conjunto de caracteres, o yo al menos no lo vi. Lo reemplace por : (dos puntos), lo que hace es agregar una pausa de 32 ms, es un espacio auxiliar, usado cuando dos sonidos de una misma palabra quedan muy pegados, para que se noten mas. Un ejemplo de eso es la palabra SPECTRUM, que tipeando SPE+KTRUM no se nota tan bien como con S:PE+KTRUM
    El ruido de la TV cuando no habla el sintetizador es bastante molesto, conviene en las frases que tipeen colocar un punto adelante y otro al final, lo cual genera un silencio de 1 segundo antes y despues, para que puedan escuchar el sonido con mas claridad.
    El programa tiene errores, la busqueda de variables esta copiada de Spectrum y solo le altere un byte cuando busca variables de control (las de bucles) que ocupan 1 byte menos que las de Spectrum. Pero en las pruebas que hice parece que se autodestruye, despues de unas pocas frases se borra de la memoria. Hay valores de los registros que no se deben modificar, o en todo caso restaurar al salir, cosa que no hice, asi que probablemente tenga que ver con eso, por ahora es beta 4, si se corrige lo de los cuelgues ya puede ser version final.
    El archivo adjunto esta en formato TZX.
    ]tav81_beta4.zip[/file]
     

  • Hola Jorge,

    Felicitaciones por el trabajo !!!

    Mañana Domingo lo voy a probar en emulador.
    Si necesitàs una mano para revisar el còdigo para ver porque se cuelga publicà o mandame el asm.

    El problema de listar infinitamente el còdigo se puede resolver agregando un byte de fin de linea en el binario. una tècnica comùn es poner un mensaje luego del REM con tu nombre por ejemplo y luego el caracter de fin de linea.
    Para generar lineas REM de muchos carateres exietn gran cantidad de programitas creo que algunos hemos publicado en los foros (en las revisatas PP o K-64)

    Abrazo,
    Gus

    P.D. Efectivamente el ZX81 no tiene apòstrofe smile
     

  • Estoy ensamblando todo desde el emulador Spin, que es exclusivamente para Spectrum, pero cuando estaba interiorizandome sobre el Z80 busque ensambladores para MSX, que era la maquina a la cual pensaba convertir el programa de C64, y no me convencieron los que habia para PC, en eso se me ocurrio probar el Spin para experimentar un poco en Spectrum, y descubri que tenia ensamblador integrado. Las primeras pruebas las hice ahi, pero el editor es muy primitivo, y termine usando un editor de textos para hacer los programas. El Spin no tiene ayuda sobre el ensamblador, tuve que investigar otros para Z80 e ir probando cual estandar era el que tomaron en Spin. Muchas herramientas que tiene el ACME (para 6502) no estan, asi que no me quedo otra que modificar el codigo, al punto que hago abuso del codigo automodificable para suplir faltas del ensamblador y porque no conozco lo suficiente al Z80.
    Para hacer la version MSX, ensamble a la Spectrum directo a RAM y de ahi grabe la zona de memoria a un archivo binario, despues le arme una cabecera para que lo tome como archivo .BIN, y en el caso de la ZX81 tuve que hacer unos pasos mas. La primera prueba que hice fue similar a la de MSX, es decir le borre llamadas a la ROM y le cambie el codigo para emitir por MIC a los adecuados para ZX81, despues reubique el codigo en Spin en distintas partes de la RAM de la ZX81, cargando el archivo binario directo a RAM, pero siempre sobreescribia algo y se reseteaba la maquina. Al final tuve que optar por cargarlo en una linea REM. Busque generadores de linea REM, que sabia que existian desde que lo leia en las K64, pero habia un monton de cosas que no sabia, como que limite tienen las lineas en tamaño, porque los generadores que vi eran para lineas muy chicas, no para 5000 bytes que es lo que yo uso. En las busquedas me retornaba mucha basura, me tuve que leer unos cuantos programas y paginas pero en ninguna salia un generador generico para usar. En eso encontre un kit de herramientas que traia varios programas en CM en varias lineas REM, que habia que ir borrando segun cual programa se usara, el primer programa estaba en la linea 0 REM y media justamente 5000 bytes! Ese tenia al final un generador de REM en CM, ahi es que cometi el error de borrar la linea 1, que no era importante pero seguia a la linea 0, y se empezo a listar infinitamente. Ya que no uso los 5000 bytes, voy a ver si le pongo un caracter al final del espacio para que no pase eso, de todas maneras solo importa si alguien borra la linea 1, se puede hacer LIST y se ve la primera parte de la linea 0 sin problemas. Con ponerle una linea 1 REM NO BORRE ESTA LINEA, creo que alcanza.
    Para ensamblar el programa, lo reubique en la direccion 16514 (para que caiga dentro de la linea 0 REM), lo ensamblo en Spin, por lo cual cae dentro del area de pantalla de la Spectrum, lo que hago es pausar la emulacion, ensamblar a RAM, y luego grabar esa zona de RAM en un archivo binario. En el EightyOne cargo el archivo binario en 16514, previamente haber cargado el programa con 0 REM de 5000 caracteres, y automaticamente el CM queda actualizado, luego SAVE y listo.
    Lo que fue un verdadero dolor de cabeza son los codigos de caracteres de la ZX81, que no son ASCII para el que no sabe, como el ensamblador es para Spectrum, no servia nada del texto que tenia escrito, tuve que convertir las directivas DEFM (para mensajes de texto) en DEFB (para una lista de bytes), y ponerme a mirar uno por uno los codigos de los caracteres que se imprimen en pantalla. No solo eso, tuve que cambiar todos los codigos en el programa, en las comparaciones y en el texto a hablar, lineas como CP "A" se convirtieron en CP 38, y lineas como DEFM '.RETROKOMPUTASIO+N PU+NTO KO+M.' pasaron a ser algo como DEFB 27,55,42,57,55,52,48,52,50,53,58,57,38,56,46,52,21,51,0,53,58,21,51,57,52,0,48,52,21,50,27
    Lo que trate de entender, por ahora en vano porque tengo que aprender mas de la ZX80 y las diferencias con la ZX81, es que hace exactamente FAST y el generador de NMI.
    Lo que hago para emitir sonido es leer el puerto $FE y escribir el puerto $FF, al principio leia y escribia el mismo y funcionaba igual, pero actua de forma diferente si activo FAST o no, segun que cambios haga se cuelga mas o menos. Lo ideal seria pasar a FAST en CM, desactivar la NMI, que ya vi como se hace pero no entiendo todavia que tanto afecta. Estuve peleando un poco con eso y me canse, el par de horas que tuve que andar tipeando codigos Sinclair me quitaron las ganas de entender hardware prehistorico.
    Ahora se me ocurrieron un par de cosas para probar en la C64 asi que me parece que el Z80 va a quedar en pausa por el momento, estas conversiones son cosas que toman demasiado tiempo y trato de no perderlo leyendo manuales durante dias, todo tiene que salir rapido para poder terminarlo, sino quedan como proyectos pendientes y al final no se terminan. Por eso es que cuando me encuentro con un obstaculo sigo con otra cosa. Si tenes alguna idea de como funciona lo del generador de NMI (que leia que no existia en la ZX80) y que hace la orden FAST exactamente, por ahi pueda acelerar un poco el desarrollo.
     

  • La sentencia BASIC FAST, lo que hace es llamar a una rutina de la ROM que simplemente setea un bit. Este bit le indica al nucleo de ejecuciòn de la ROM que no debe generar video. De esta forma la màquina alcanza los 3.25 MHz a costa de no generar imagen en la TV. La sentencia SLOW vuelve al modo normal.
    Se puede decir que el ZX80 siempre ejecuta en modo FAST.

    En todos mis desarrollos utilizo el ensamblador PASMO, que aparte te sirve para generar binarios de MSX y Spectrum entre otras plataformas.

    Saludos,
    Gus
     

  • Si, entiendo lo que hace FAST, pero no se cual es el equivalente exacto en assembler. La lectura del puerto $FE, que sirve para leer el teclado entre otras cosas, desactiva el video, pero no se si ademas hay que desactivar el generador de NMI, supongo que son dos cosas aparte porque la ZX80 no tenia eso y aun asi desactivaba el video.
     

  • La llamada para poner la màquina en modo FAST desde asm es CALL $02E7. Que te motiva a leer el teclado utilizando el puerto y no la rutina de la ROM ?

    La ZX80 no tiene modo SLOW, el kernel es distinto al de la ZX81.

    Saludos,
    Gus
     

  • No leo el teclado desde el programa, quise hacerlo pero me apaga la pantalla y no se lee el mensaje de PULSE UNA TECLA, no quise perder tiempo y dividi la rutina en dos partes, una para imprimir, vuelve al BASIC a esperar una tecla y luego llama a la segunda parte para emitir el sonido. Uso la orden IN porque eso es lo que hay que hacer para activar la salida MIC, y OUT para desactivarla. Asi funcionan los programas que emiten sonido en ZX81, pero el que vi lo hace con el puerto $FF en ambas ocasiones.
     

  • Respecto del uso de registros en los programas.
    A machine code program is called by using the USR function, for example:
      LET N=USR startaddress
      Note that only decimal addresses are supported. Cosa que evidentemente ya sabes wink

    The official ZX81 manual guidelines for returning to BASIC are:
      BC may contain returned value, if any (loaded into N in above example).
      IY must be 4000h upon return (pointer to the System Area)
      I must be 1Eh upon return (pointer to the Character set in ROM)
      return by RET opcode
    That is nonsense, IY=4000h is restored automatically when returning, but when
    video is enabled it might be not a good idea to change IY or I at all.
    The official ZX81 manual guidelines for machine code execution are:
      In SLOW mode, the AF' and IX' and R registers are used by
      the video interrupt handler and should not be modified.
    That's garbage in so far that I've never heard of a IX' register smile  

    Respecto del uso de puertos.
    Output to Port FFh (or ANY other port)
    Writing any data to any port terminates the Vertical Retrace period, and
    restarts the LINECNTR counter (ULA internal counter). Tambien es la salida de cassette.

    Input from Port FEh (or any other port with A0 zero)
    Reading from this port also initiates the Vertical Retrace period, and resets
    the LINECNTR register to zero, LINECNTR remains stopped/zero until user
    terminates retrace - In the ZX81, all of the above happens only if NMIs are
    disabled.
      Bit  Expl.
      0-4  Keyboard column bits (0=Pressed)
      5    Not used             (1)
      6    Display Refresh Rate (0=60Hz, 1=50Hz)
      7    Cassette input       (0=Normal, 1=Pulse)
    When reading from the keyboard, one of the upper bits (A8-A15) of the I/O
    address must be "0" to select the desired keyboard row (0-7).
    (When using IN A,(nn), the old value of the A register is output as upper
    address bits and as lower bits. Otherwise, ie. when using IN r,(C) or INI
    or IND, the BC register is output to the address bus.)
    The Keyboard Matrix
      __Line____Bit__0____1____2____3____4__
       0  (A8)     SHIFT  Z    X    C    V
       1  (A9)       A    S    D    F    G
       2  (A10)      Q    W    E    R    T
       3  (A11)      1    2    3    4    5
       4  (A12)      0    9    8    7    6
       5  (A13)      P    O    I    U    Y
       6  (A14)    ENTER  L    K    J    H
       7  (A15)     SPC   .    M    N    B

    Port FDh Write (ZX81 only)
    Writing any data to this port disables the NMI generator.

    Port FEh Write (ZX81 only)
    Writing any data to this port enables the NMI generator.
    NMIs (Non maskable interrupts) are used during SLOW mode vertical blanking
    periods to count the number of drawn blank scanlines.


    Podes setear el modo FAST solo haciendo OUT (#FD), A. para volver a SLOW haces OUT (#FE), A.
    El cuelgue puede deberse a que tenes alguno de los registros IX,IY o I con valores no adecuado para modo SLOW.
    Tene en cuenta tener deshabilitadas las NMI mientras haces la salida del PWM y no habilitarlas por error.
    Antes de retornar del codigo de maquina, ajusta los valores de IX, IY e I a lo que tenian cuando entraron a tu rutina. Volve al basic siempre con un RET.

    En este LINK podes ver la parte de la rutina de save de la ROM (en realidad empieza un poco mas arriba en #031E). En principio solo se ve el OUT(#FF), A, que inicia el pulso al cassete/video, pero en la rutina que chequea el break hace in IN A,(#FE) lo cual lo finaliza.

    En este LINK hay un muy buen articulo de como se genera el video asi como rutinas de HI-RES. Esta escrito por el guru del HI-RES Wilf Rigter y en este LINK pueden bajar juegos HI-RES y su codigo fuente.
    En este LINK hay una rutina de carga rapida donde se puede apreciar como deshabilita las NMI y con un buen truco vuelve a SLOW.
    En este LINK esta la data que puse al principio.

    Saludos.



     

  • Todo lo que sale ahi ya lo estaba haciendo, primera usaba RAND USR, como cada tanto daba un error erratico en el BASIC como que el contenido de la cadena no retornaba un valor adecuado para VAL, y cosas asi sin sentido, empece a usar LET A=USR, despues asigne 0 a BC antes de retornar. Tambien colocaba $4000 en IY y $1E en I, pero no cambiaba nada, incluso llegue a guardar los valores de esos registros y tambien IX, y restaurarlos al salir, pero siguieron los problemas.
    Ahora aparentemente tiene que ver con el retorno, porque parece saltar a cualquier parte cuando termina de ejecutar el sintetizador, ya son errores mas razonables, y debe tener que ver con las interrupciones, debe saltar por error a alguna antes de terminar de inicializar cosas.
    Cuando entro al programa deshabilito las interrupciones con DI y luego deshabilito la NMI, y vuelvo a habilitar todo al salir.
    Lo que acabo de mirar ahora es la pagina que pusiste sobre el video en HI-RES, creo que eso es justo lo que necesitaba porque explica paso a paso como se hace todo, lo voy a leer con mas tiempo despues.
     

  • gus, me olvidaba, anda muy bien el Pasmo, me ensamblo el fuente directamente sin cambios, para MSX el programa omitio poner la direccion de arranque, pero supongo que de alguna manera se le podra indicar, por ahora lo puse a mano porque es la misma direccion de carga. Lo malo es que no tiene soporte directo de ZX81, y por lo tanto no puedo usar "ASCII" de Sinclair, lo bueno es que todo el lio de numeros que habia hecho antes convirtiendo el texto no fue en vano.
     

Moderador (s): homecomputer, Selandari, pastbytes, Palamar, phd, Durandal