Categoría : Programación

Tutorial de instalación de entorno de desarrollo en lenguaje C para Commodore 64, usando CC65 y WinVICE sobre Windows XP/7


El motivo de este tutorial es instalar un entorno básico de desarrollo en lenguaje C para crear aplicaciones de Commodore 64 bajo Windows, con las siguientes características:

  • WinVICE: emulador de Commodore
  • CC65: compilador C para 6502
  • Plataforma Windows XP/7

Mi intención es tener todo el entorno en formato "portable" (recomiendo la web Portable Apps para obtener programas portables), o sea que no dependa de instalar aplicaciones y que sea fácilmente portable de un ordenador a otro, por ejemplo en una memoria USB o como en mi caso, usando la aplicación de almacenamiento online y sincronización automática Dropbox.

La estructura de carpetas que utilizaré será esta:
Carpetas de entorno de desarrollo usando CC65 en Windows
Básicamente en /programas irá el emulador WinVICE y el compilador CC65 y luego en /proyectos/c64 estarán los archivos del "Hola mundo"

Teniendo en cuenta este árbol, cada uno puede usarla tal cual o adaptarla a su forma de trabajo, reemplazando por ejemplo la unidad D:\ por la C:\, etc.

Comencemos con el tutorial:

  1. Descargar el emulador de Commodore WinVICE

    Logo WinVICEWinVICE es un emulador Open Source que permite emular los sistemas de Commodore C16, C64, C128, C64DTV, VIC20, PLUS4, CBM-II y Pet.

    Hay versiones disponibles para todo tipo de sistemas: Windows, DOS, GNU/Linux, etc.

    La versión que voy a usar es la MS-Windows 32bit (Pentium-optimized) que se puede descargar desde aquí: WinVICE-2.2-x86.zip.

    Pantalla de descarga de WinVICE

  2. Instalar el emulador de Commodore WinVICE en Windows XP/7

    En mi caso tengo una carpeta donde voy "instalando" todos los programas portables y como este tema de Commodore 64 me interesa que esté accesible desde varios ordenadores, instalaré todo en la carpeta \programas de Dropbox, en mi caso la carpeta donde descomprimo el WinVICE es D:\documentos\My Dropbox\programas\WinVICE\

    Luego lo que hay que hacer es asociar los archivos .PRG, .D64, .T64, etc. al emulador. Por ejemplo pinchando con el botón derecho sobre un archivo .PRG y eligiendo Abrir con... > Examinar, navegar por el disco ir hasta la carpeta del emulador y seleccionar x64.exe

    Consejo útil: cuando se hace lío con estas asociaciones lo mejor es pasar el CCleaner con la opción de "Limpiar el Registro de Windows", repetir el proceso varias veces hasta que no muestre más errores.

    Una guía sobre este tema: Asociar un tipo de archivo a un Programa determinado

  3. Descargar CC65, el compilador de C para 6502

    Logo CC65 CC65 es un completo compilador cruzado de C para Windows y GNU/Linux que permite compilar código para varias plataformas basadas en el procesador 65(C)02, como los Commodore 16, 64, 128, CBM510, CBM610, PET, PLUS4, VIC20, GEOS, Atari 400/800/65XE/130XE/800XL/1200XL/5200 y Apple ][.
    Incluye un potente macro ensamblador, un compilador de C, un enlazador (linker), librerías y varias otras herramientas. La licencia de este software es Open Source.

    La opción más fácil (pero no la que usaré) es descargar el instalador (cc65-2.13.2-1.exe) e instalarlo directamente, una de las ventajas de hacerlo así es que se auto-configuran todas las variables de entorno de forma automática y quizás para empezar sea mejor, pero yo me voy a centrar en la opción portable, que tiene más pasos pero todo queda donde uno quiere, como uno quiere, sin ensuciar el sistema (el registro) y además nos permite la libertad de compartir nuestro entorno entre varios ordenadores.

    Enlaces para descargar los archivos de la versión portable:
    - Compilador CC65: cc65-win32-2.13.2-1.zip
    - Librerías CC65 para la plataforma Commodore 64: cc65-c64-2.13.2-1.zip

    Sección de descargas de CC65:
    Pantalla de descarga de CC65

  4. Instalación de CC65, compilador de C para 6502

    En caso de instalar la versión autoinstalable se puede saltar directamente al punto 6.

    Descomprimir el compilador (archivo cc65-win32-2.13.2-1.zip) en la carpeta D:\documentos\My Dropbox\programas\cc65.

    Luego descomprimir cc65-c64-2.13.2-1.zip en la misma carpeta.

    El resultado final debería ser así:
    Arbol de carpetas de CC65

  5. Crear un "makefile"

    Me he creado un simple archivo .BAT para compilar, enlazar las librerías, archivos externos, crear un ejecutable y mostrarlo llamando al emulador de Commodore 64, todo en un solo paso.

    Logo de Notepad++

    Editor de código fuente:

    Mención especial merecen los editores de código fuente, la herramienta de programación base, personalmente uso el Notepadd++ (en su versión portable), es un editor liviano que me resulta muy cómodo, permite agregar plugins, reconoce el lenguaje Ensamblador y C (además de muchos otros que uso a diario, como PHP, HTML, CSS, Javascript, SQL, Flash ActionScript, etc.) Seguramente el tipo de editor sea algo personal y cada uno prefiera uno distinto, por ejemplo el Crimson Editor también parece ser una buena opción.

    Bibliografía sobre el tema: cc65:project setup.

    Archivo /proyectos/c64/holamundo.bat

    @ECHO OFF

    REM ### INICIO ZONA DE CONFIGURACION ###

    REM moverse a la carpeta donde se encuentran nuestros archivos fuente
    D:
    CD \
    CD documentos\My Dropbox\proyectos\c64\

    REM nombre del archivo C a compilar (sin la extension)
    SET NOMBRE=holamundo

    REM la libreria a incluir
    SET LIBRERIAS=text.s

    REM ruta a la carpeta de CC65
    SET CC65_HOME=D:\documentos\My Dropbox\programas\cc65\

    REM ruta al emulador
    SET EMULADOR="D:\documentos\My Dropbox\programas\WinVICE\x64.exe"

    REM ### FIN ZONA DE CONFIGURACION ###


    PATH %CC65_HOME%bin


    REM cl65 -t c64 -l Walker.asm -o walker_nocomp.prg Walker.c
    cl65 -t c64 -l -L %CC65%lib -o %NOMBRE%.prg %NOMBRE%.c %LIBRERIAS%


    REM borrar el archivo objeto generado al compilar
    DEL *.o


    REM borrar el archivo assembler generado al compilar
    DEL *.lst


    REM comprimir el resultado (opcional)
    REM exomizer -o walker.prg -s sys walker_nocomp.prg


    REM ejecutar el juego compilado
    %EMULADOR% %NOMBRE%.prg


    COLOR 30
    ECHO *** TERMINADO ***

    REM PAUSE
  6. Crear un "Hola mundo!" en C para Commodore 64

    Bibliografía, dos enlaces a la documentación en CC65 que pueden ser muy interesantes:
    - cc65:hello_world
    - cc65:overview

    Crear archivo de texto /proyectos/c64/holamundo.c

    #include
    #include

    /* declarar texto como variable externa en text.s */
    extern const char texto[];

    int main (void)
    {
          printf ("%s\n", texto);
          return EXIT_SUCCESS;
    }

    Crear archivo de texto /proyectos/c64/text.s

    .export _texto
    _texto: .asciiz "Hola mundo!!"

    Y si todo ha ido bien al ejecutar holamundo.bat se cargará de forma automática el emulador mostrándonos la característica pantalla azul de C64 (no la de Windows jeje) con nuestro "Hola mundo!", así que ¡¡bienvenido al mundo de Commodore 64 y los 8 bits!! :)

    Hola mundo en Commodore 64

    También veremos en la carpeta de nuestro proyecto que se ha creado un archivo de nombre holamundo.prg, que es el programa listo para funcionar desde Commodore 64.

    La estructura de carpetas y archivos quedaría así:
    Carpetas de instalacion CC65 en Windows

  7. Y mucho más

    • Mi "makefile" es muy básico, seguro que se puede mejorar muchísimo y ademas me imagino que habrá otras maneras de hacerlos.
    • CC65 ofrece muchas posibilidades, entre ellas las de compilar código para otras plataformas basadas en el procesador 6502.
    • También se puede obtener el código assembler generado a partir del fuente C, que resulta muy interesante para ver y curiosear.
    • Recomiendo explorar la web de CC65 donde hay bastante información aunque a veces resulta un poco "mareante" :P
    • Sobre el lenguaje C, al comenzar con este tema nunca había programado en C, así que he usado algunas paginas de consulta que me fueron muy útiles para dar mis primeros pasos, por ejemplo C con Clase.

He creado este tutorial pensando en la guía que me hubiera gustado encontrar cuando dí mis primeros pasos en este tema, espero que resulte útil para otras personas que quieran meterse en la programación retro y no sepan cómo hacerlo.

Finalmente, he preparado un archivo comprimido con todos los archivos del tutorial para descargar y descomprimir en un sólo paso, se puede descargar desde aquí: CC65 + WinVICE + holamundo.c + makefile.bat.

Agradecería que me aviséis de cualquier fallo o problema que noteis.

Tutorial creado por José Zanni.

Código Assembler del algoritmo de Bresenham

Revisando (muy) antiguos proyectos encontré este trocito de código en ensamblador (o assembler) que hice (o copié, ya no recuerdo) alrededor de 1992, para el juego Defender, que en realidad es un remake de Command Comander, sólo que no sabíamos que se llamaba así... :P

El código en ensamblador es para procesadores 80286, las famosas PC AT 286. Y pinta el pixel en el modo gráfico #13 de las VGA (320x200 pixeles y 256 colores).

Está preparado para funcionar dentro del código fuente del Turbo Pascal, por eso está declarado como una función, con parámetros de coordenada X/Y de inicio y  fin, el color a pintar y otro parámetro que no sé que es :D

No tengo idea si esto le será de utilidad a alguien, espero que sí.

Procedure LineaASM( x1_,y1_,x2_,y2_:Integer; Color_,Poner_:Byte); assembler;
var
x1,
y1,
x2,
y2,
delp,
delr,
delrx,
delry,
deldx,
deldy,
delre,
delde   :Word;

asm

{ tomar parametros }

          mov   ax,x1_
          mov   x1,ax         { X1 }

          mov   ax,y1_
          mov   y1,ax         { Y1 }

          mov   ax,x2_
          mov   x2,ax         { X2 }

          mov   ax,y2_
          mov   y2,ax         { Y2 }

{ inc de perder todo }
          mov   si,1
          mov   di,1

{ calcular /x2-/y1/ }
         mov    dx,y2_
         sub    dx,y1_
         jge    @almay
         neg    di
         neg    dx
@almay:
         mov    deldy,di

{ calcular /x2-x1/ }
         mov    cx,x2
         sub    cx,x1
         jge    @almax
         neg    si
         neg    cx
@almax:
         mov    deldx,si

{ clasificar /y2-y1/ y /x2-x1/  }
         cmp    cx,dx
         jge    @mover
         mov    si,0
         xchg   cx,dx
         jmp    @alma

@mover:
         mov    di,0

{ almacenar delr,delp,delrx y delry }
@alma:
         mov    delr,cx
         mov    delp,dx
         mov    delrx,si
         mov    delry,di

{ obtener valores iniciales para x e y }
         mov    si,x1
         mov    di,y1

{ calcular valor inicial e incrementos para la funcion de error }
         mov    ax,delp
         sal    ax,1
         mov    delre,ax

         sub    ax,cx
         mov    bx,ax

         sub    ax,cx
         mov    delde,ax

{ ajustar contador }
         inc    cx
{ ------------------------------ }
{ estructura del bucle principal }
{ ------------------------------ }

@bucle:
{ dibujar punto en (x,y) }

         push bx
         push ax
         push cx
         push es


         mov  BX,SI           { si=x }
         mov  AX,DI           { di=y }

{ PQLL:         AX = coordenada y (0-199)
;               BX = coordenada x (399)
;
; Devuelve:     BX = desplazamiento de byte en el buffer
;               ES = segmento del buffer de v¡deo}

               xchg    ah,al           { AX := 256 * y     }
               add     bx,ax           { BX := 256 * y + x }
               shr     ax,1
               shr     ax,1            { AX := 64 * y      }
               add     bx,ax           { BX := 320 * y + x }

               mov     ax, $A000
               mov     es,ax           { ES:BX := direcci¢n de byte del pixel }


         { pone el punto }
               mov     al,Color_      { Color }
               mov     es:[bx],al

         pop   es
         pop   cx
         pop   ax
         pop   bx

         cmp   bx,0
         jge   @diagonal

{ caso linea recta }
@recta:
         add   si,delrx
         add   di,delry
         add   bx,delre
         loop  @bucle
         jmp   @fin

{ caso linea diagonal }
@diagonal:
         add   si,deldx
         add   di,deldy
         add   bx,delde
         loop  @bucle

{ restaurar registros afectados }
@fin:
end;

Relacionado: El algoritmo de Bresenham

Un interesante aporte: Proyectos robóticos

En la web Proyectos robóticos se pueden encontrar programas con ejemplos del Algoritmo de Bresenham para 2D, 3D... hasta 6D. Este algoritmo no sólo sirve para hacer líneas.

En mi caso lo uso para coordinar los movimientos de un simulador de Brazo Robot de 5 grados de libertad (la mano no se cuenta como grado de libertad). Todo el brazo se mueve a la vez para la realización de cualquier trayectorias. En mis simuladores el brazo robot llega a dibujar. Para esta tarea uso los ficheros de extensión ".PLT" (HPGL).

Los ejemplos están escrito en FreeBasic y en este caso compatibles con QBasic. Las variables están declaras en tipo, así que es bien fácil traducirlo a cualquier lenguaje de programación.

 
#