diff --git a/lib_source/data/text.asm b/lib_source/data/text.asm
new file mode 100644
index 0000000..f2a71f6
--- /dev/null
+++ b/lib_source/data/text.asm
@@ -0,0 +1,35 @@
+;***********************************************************
+;
+; NGN TEMPLATE para ASMSX
+; ASM Z80 MSX
+;
+; Textos del programa
+;
+; (cc)2018 Cesar Rincon "NightFox"
+; http://www.nightfoxandco.com
+;
+;***********************************************************
+
+
+
+; ----------------------------------------------------------
+; Funcion principal
+; ----------------------------------------------------------
+
+; Texto de bienvenida
+TEXT_HELLO_WORLD:
+ db "Hello World!", $0D, $0A
+ db $00
+
+; Texto de reinicio
+TEXT_RESTART:
+
+ db "REBOOTING...", $0D, $0A
+ db $00
+
+
+
+;***********************************************************
+; Fin del archivo
+;***********************************************************
+TEXT_EOF:
\ No newline at end of file
diff --git a/lib_source/ngn/ngn.asm b/lib_source/ngn/ngn.asm
new file mode 100644
index 0000000..71afde6
--- /dev/null
+++ b/lib_source/ngn/ngn.asm
@@ -0,0 +1,50 @@
+;***********************************************************
+;
+; N'gine para MSX Asm Z80
+; Version 0.0.1-a
+;
+; (cc)2018 Cesar Rincon "NightFox"
+; http://www.nightfoxandco.com
+;
+; Archivo principal de includes
+;
+;***********************************************************
+
+
+
+; Descompresion de datos RLE
+.INCLUDE "ngn/ngn_rle.asm"
+
+; Funciones del sistema
+.INCLUDE "ngn/ngn_system.asm"
+
+; Funciones graficas
+.INCLUDE "ngn/ngn_screen.asm"
+
+; Funciones del PSG
+.INCLUDE "ngn/ngn_psg.asm"
+
+; Funciones del teclado
+.INCLUDE "ngn/ngn_keyboard.asm"
+
+; Creacion de fondos
+.INCLUDE "ngn/ngn_background.asm"
+
+; Creacion de sprites
+.INCLUDE "ngn/ngn_sprite.asm"
+
+; Funciones de texto
+.INCLUDE "ngn/ngn_text.asm"
+
+; Inicializacion de la libreria NGN
+.INCLUDE "ngn/ngn_start.asm"
+
+; Fin de los includes de la libreria
+ret
+
+
+
+;***********************************************************
+; Fin del archivo
+;***********************************************************
+NGN_EOF:
\ No newline at end of file
diff --git a/lib_source/ngn/ngn_background.asm b/lib_source/ngn/ngn_background.asm
new file mode 100644
index 0000000..5ad5910
--- /dev/null
+++ b/lib_source/ngn/ngn_background.asm
@@ -0,0 +1,245 @@
+;***********************************************************
+;
+; N'gine para MSX Asm Z80
+; Version 0.0.1-a
+;
+; (cc)2018 Cesar Rincon "NightFox"
+; http://www.nightfoxandco.com
+;
+; Rutinas de creacion de fondos (SCREEN 2)
+;
+;***********************************************************
+
+
+
+; ----------------------------------------------------------
+; NGN_BACKGROUND_CREATE
+; Carga una imagen y muestrala a la pantalla
+; HL = Direccion de la imagen (Origen de los datos)
+; Modifica A, BC, DE, HL
+; ----------------------------------------------------------
+
+NGN_BACKGROUND_CREATE:
+
+ ; Guarda el puntero de los datos de la imagen
+ push hl
+
+ ; Deshabilita la pantalla
+ call $0041 ; Ejecuta la rutina [DISSCR]
+
+ ; Borra la tabla de nombres (mapa) usando FILVRM
+ ; ----------------------------------------------------------
+ ; Address ... 0815H (from 0056H)
+ ; Name ...... FILVRM (Fill VRAM)
+ ; Input ..... A=Data byte, BC=Length, HL=VRAM address
+ ; Exit ...... None
+ ; Modifies .. AF, BC, EI
+ ; ----------------------------------------------------------
+
+ ld hl, NGN_NAMTBL ; Apunta a la tabla de nombres
+ ld bc, $300 ; Longitud de 768 celdas
+ xor a ; Pon A a 0
+ call $0056 ; Ejecuta la rutina [FILVRM]
+
+ ; Copia los datos a la VRAM
+ ; ----------------------------------------------------------
+ ; Address ... 0744H (from 005CH)
+ ; Name ...... LDIRVM (Load, Increment and Repeat to VRAM from Memory)
+ ; Input ..... BC=Length, DE=VRAM address, HL=RAM address
+ ; Exit ...... None
+ ; Modifies .. AF, BC, DE, HL, EI
+ ; ----------------------------------------------------------
+
+ ; Recupera el puntero a los datos de la imagen
+ pop hl
+
+ ; Copia el banco 1 de patterns
+ ld de, NGN_CHRTBL ; Destino de los datos
+ call @@DATA_TO_VRAM
+
+ ; Copia el banco 2 de patterns
+ ld de, NGN_CHRTBL + 2048 ; Destino de los datos
+ call @@DATA_TO_VRAM
+
+ ; Copia el banco 3 de patterns
+ ld de, NGN_CHRTBL + 4096 ; Destino de los datos
+ call @@DATA_TO_VRAM
+
+ ; Copia el banco 1 de colors
+ ld de, NGN_CLRTBL ; Destino de los datos
+ call @@DATA_TO_VRAM
+
+ ; Copia el banco 2 de colors
+ ld de, NGN_CLRTBL + 2048 ; Destino de los datos
+ call @@DATA_TO_VRAM
+
+ ; Copia el banco 3 de colors
+ ld de, NGN_CLRTBL + 4096 ; Destino de los datos
+ call @@DATA_TO_VRAM
+
+ ; Copia el banco 1 de names
+ ld de, NGN_NAMTBL ; Destino de los datos
+ call @@DATA_TO_VRAM
+
+ ; Copia el banco 2 de names
+ ld de, NGN_NAMTBL + 256 ; Destino de los datos
+ call @@DATA_TO_VRAM
+
+ ; Copia el banco 3 de names
+ ld de, NGN_NAMTBL + 512 ; Destino de los datos
+ call @@DATA_TO_VRAM
+
+
+ ; Habilita la pantalla
+ call $0044 ; Ejecuta la rutina [ENASCR]
+
+ ; Fin de la rutina de carga
+ ret
+
+
+
+ ; Rutina de carga de datos en VRAM desde la ROM/RAM
+ @@DATA_TO_VRAM:
+
+ ld b, [hl] ; Carga el tamaņo de los datos
+ inc hl
+ ld c, [hl]
+ inc hl
+ push hl ; Guarda el puntero a los datos de la imagen
+ push bc
+
+ call $005C ; Ejecuta la rutina [LDIRVM]
+
+ pop bc ; Recupera los parametros de la ultima imagen
+ pop hl
+ add hl, bc ; Y actualiza el puntero
+
+ ret ; Sal de la subrutina
+
+
+
+; ----------------------------------------------------------
+; NGN_BACKGROUND_CREATE_RLE
+; Carga una imagen y muestrala a la pantalla
+; HL = Direccion de la imagen (Origen de los datos)
+; Modifica A, BC, DE, HL
+; ----------------------------------------------------------
+
+NGN_BACKGROUND_CREATE_RLE:
+
+ ; Guarda el puntero de los datos de la imagen
+ push hl
+
+ ; Deshabilita la pantalla
+ call $0041 ; Ejecuta la rutina [DISSCR]
+
+ ; Borra la tabla de nombres (mapa) usando FILVRM
+ ; ----------------------------------------------------------
+ ; Address ... 0815H (from 0056H)
+ ; Name ...... FILVRM (Fill VRAM)
+ ; Input ..... A=Data byte, BC=Length, HL=VRAM address
+ ; Exit ...... None
+ ; Modifies .. AF, BC, EI
+ ; ----------------------------------------------------------
+
+ ld hl, NGN_NAMTBL ; Apunta a la tabla de nombres
+ ld bc, $300 ; Longitud de 768 celdas
+ xor a ; Pon A a 0
+ call $0056 ; Ejecuta la rutina [FILVRM]
+
+ ; Copia los datos a la VRAM
+ ; ----------------------------------------------------------
+ ; Address ... 0744H (from 005CH)
+ ; Name ...... LDIRVM (Load, Increment and Repeat to VRAM from Memory)
+ ; Input ..... BC=Length, DE=VRAM address, HL=RAM address
+ ; Exit ...... None
+ ; Modifies .. AF, BC, DE, HL, EI
+ ; ----------------------------------------------------------
+
+
+ ; Recupera el puntero a los datos de la imagen
+ pop hl
+
+ ; Copia el banco 1 de patterns
+ ld de, NGN_CHRTBL ; Destino de los datos
+ call @@DATA_TO_VRAM
+
+ ; Copia el banco 2 de patterns
+ ld de, NGN_CHRTBL + 2048 ; Destino de los datos
+ call @@DATA_TO_VRAM
+
+ ; Copia el banco 3 de patterns
+ ld de, NGN_CHRTBL + 4096 ; Destino de los datos
+ call @@DATA_TO_VRAM
+
+ ; Copia el banco 1 de colors
+ ld de, NGN_CLRTBL ; Destino de los datos
+ call @@DATA_TO_VRAM
+
+ ; Copia el banco 2 de colors
+ ld de, NGN_CLRTBL + 2048 ; Destino de los datos
+ call @@DATA_TO_VRAM
+
+ ; Copia el banco 3 de colors
+ ld de, NGN_CLRTBL + 4096 ; Destino de los datos
+ call @@DATA_TO_VRAM
+
+ ; Copia el banco 1 de names
+ ld de, NGN_NAMTBL ; Destino de los datos
+ call @@DATA_TO_VRAM
+
+ ; Copia el banco 2 de names
+ ld de, NGN_NAMTBL + 256 ; Destino de los datos
+ call @@DATA_TO_VRAM
+
+ ; Copia el banco 3 de names
+ ld de, NGN_NAMTBL + 512 ; Destino de los datos
+ call @@DATA_TO_VRAM
+
+ ; Habilita la pantalla
+ call $0044 ; Ejecuta la rutina [ENASCR]
+
+ ; Fin de la rutina de carga
+ ret
+
+
+
+ ; Rutina de carga de datos en VRAM desde el RAM_BUFFER del RLE
+ @@DATA_TO_VRAM:
+
+ push de ; Guarda la direccion de destino en VRAM
+
+ ld de, NGN_RAM_BUFFER ; Destino de los datos RLE
+ call NGN_RLE_DECOMPRESS ; Descomprime los datos
+
+ ld hl, NGN_RLE_NORMAL_SIZE ; Recupera el tamaņo de los datos descomprimidos
+ ld b, [hl]
+ inc hl
+ ld c, [hl]
+
+ ld hl, NGN_RAM_BUFFER ; Puntero a los datos
+ pop de ; Destino de los datos
+ call $005C ; Ejecuta la rutina [LDIRVM]
+
+ ld hl, NGN_RLE_COMPRESSED_SIZE ; Recupera el tamaņo de los datos comprimidos
+ ld b, [hl]
+ inc hl
+ ld c, [hl]
+
+ ld hl, NGN_RLE_POINTER ; Recupera el puntero
+ ld d, [hl]
+ inc hl
+ ld e, [hl]
+ ld h, d
+ ld l, e
+
+ add hl, bc ; Y sumale el tamaņo de los datos comprimidos
+
+ ret ; Sal de la subrutina
+
+
+
+;***********************************************************
+; Fin del archivo
+;***********************************************************
+NGN_BACKGROUND_EOF:
\ No newline at end of file
diff --git a/lib_source/ngn/ngn_consts.asm b/lib_source/ngn/ngn_consts.asm
new file mode 100644
index 0000000..e7f0d1a
--- /dev/null
+++ b/lib_source/ngn/ngn_consts.asm
@@ -0,0 +1,60 @@
+;***********************************************************
+;
+; N'gine para MSX Asm Z80
+; Version 0.0.1-a
+;
+; (cc)2018 Cesar Rincon "NightFox"
+; http://www.nightfoxandco.com
+;
+; Definicion de constantes
+;
+;***********************************************************
+
+
+
+; ----------------------------------------------------------
+; Constantes del Sistema
+; ----------------------------------------------------------
+
+; ----------------------------------------------------------
+; Definiciones para la VRAM
+; ----------------------------------------------------------
+; Registros
+NGN_VDPR0 .EQU $F3DF ; Valores del registro 0 del VDP
+NGN_VDPR1 .EQU $F3E0 ; Valores del registro 0 del VDP
+; Fondos
+NGN_CHRTBL .EQU $0000 ; Tabla de caracteres de los fondos (pattern)
+NGN_NAMTBL .EQU $1800 ; Tabla de nombres de los fondos (mapa)
+NGN_CLRTBL .EQU $2000 ; Tabla del color de los caracteres (paleta)
+; Sprites
+NGN_SPRATR .EQU $1B00 ; Tabla de los atributos de los sprites
+NGN_SPRTBL .EQU $3800 ; Tabla de caracteres de los Sprites (pattern)
+; Color
+NGN_COLOR_ADDR .EQU $F3E9 ; Direccion del Color
+
+
+
+; ----------------------------------------------------------
+; Definiciones de los dispositivos HID
+; ----------------------------------------------------------
+
+NGN_TOTAL_KEYS .EQU 89 ; Numero total de teclas
+NGN_TOTAL_JOYKEYS .EQU 12 ; Numero total de teclas del joystick
+
+NGN_KEY_STATE_HELD .EQU 1 ; Bit 0 a 1 [HELD]
+NGN_KEY_STATE_PRESS .EQU 2 ; Bit 1 a 1 [PRESS]
+NGN_KEY_STATE_UP .EQU 4 ; Bit 2 a 1 [UP]
+NGN_KEY_STATE_LAST .EQU 8 ; Bit 3 a 1 [LAST] (Estado en el frame anterior)
+
+
+
+; ----------------------------------------------------------
+; Definiciones para el sistema de Sprites
+; ----------------------------------------------------------
+
+
+
+;***********************************************************
+; Fin del archivo
+;***********************************************************
+NGN_CONSTS_EOF:
\ No newline at end of file
diff --git a/lib_source/ngn/ngn_keyboard.asm b/lib_source/ngn/ngn_keyboard.asm
new file mode 100644
index 0000000..2e118a3
--- /dev/null
+++ b/lib_source/ngn/ngn_keyboard.asm
@@ -0,0 +1,149 @@
+;***********************************************************
+;
+; N'gine para MSX Asm Z80
+; Version 0.0.1-a
+;
+; (cc)2018 Cesar Rincon "NightFox"
+; http://www.nightfoxandco.com
+;
+; Rutinas de acceso al teclado
+;
+;***********************************************************
+
+
+
+; ----------------------------------------------------------
+; NGN_KEYBOARD_READ
+; Lee las teclas definidas
+; Modifica A, BC, DE, HL
+; ----------------------------------------------------------
+
+NGN_KEYBOARD_READ:
+
+ ; Deshabilita las interrupciones
+ di
+
+ ; Resetea el registro de estado para NGN_KEY_ANY
+ ld d, $00
+
+ ; Lee los 8 bits de las 11 filas de la matriz del teclado
+ ld hl, NGN_KEY_0 ; Puntero donde esta la primera tecla
+ ld bc, $0000 ; Reset de fila y BIT
+ @@ROW_LOOP:
+ ld c, 1 ; Reset del BIT
+ @@BIT_LOOP:
+ call @@GET_KEY ; Actualiza el estado de la tecla
+ inc hl ; Siguiente tecla
+ ld a, c
+ cp $80 ; Si has leido el bit 7,
+ jr z, @@NEXT_ROW ; lee la siguiente fila
+ ;rlc c ; Siguiente BIT
+ sla c ; Siguiente BIT
+ jr @@BIT_LOOP
+ @@NEXT_ROW:
+ inc b ; Siguiente fila
+ ld a, b
+ cp 11 ; Si ya se han leido todas las filas
+ jr nz, @@ROW_LOOP ; Si no, siguiente fila
+
+ ; Habilita las interrupciones
+ ei
+
+ ; Actualiza el estado de NGN_KEY_ANY
+ call @@KEY_ANY
+
+ ; Limpia el buffer del teclado con la rutina de BIOS [KILBUF]
+ call $0156
+
+ ; Vuelve
+ ret
+
+
+
+
+ ; @@GET_KEY
+ ; Lee el estado de la tecla solicitada usando los puertos $A9 y $AA
+ ; Usa el registro BC para pasar la fila (B) y el BIT (C)
+ ; Usa el registro HL para la direccion de la variable asignada a cada tecla
+
+ @@GET_KEY:
+
+ in a, ($AA) ; Lee el contenido del selector de filas
+ and $F0 ; Manten los datos de los BITs 4 a 7 (resetea los bits 0 a 3)
+ or b ; Indica la fila
+ out ($AA), a ; y seleccionala
+ in a, ($A9) ; Lee el contenido de la fila
+ and c ; Lee el estado de la tecla segun el registro C
+ jr z, @@KEY_HELD ; En caso de que se haya pulsado, salta
+
+ ; Si no se ha pulsado
+ ld a, [hl]
+ and $08 ; Pero lo estabas
+ jr z, @@NO_KEY
+ ld [hl], $04 ; B0100
+ ret
+
+ ; La tecla no se ha pulsado ni estaba pulsada
+ @@NO_KEY:
+ ld [hl], $00 ; B0000
+ ret
+
+ ; Si se ha pulsado
+ @@KEY_HELD:
+ ; Actualiza el estado de NGN_KEY_ANY
+ ld d, $FF
+ ; Analiza si la pulsacion es nueva
+ ld a, [hl] ; Carga el estado anterior
+ and $08 ; Si no estava pulsada...
+ jr z, @@KEY_PRESS ; Salta a NEW PRESS
+ ld [hl], $09 ; Si ya estava pulsada, B1001
+ ret
+
+ ; Si era una nueva pulsacion
+ @@KEY_PRESS:
+ ld [hl], $0B ; B1011
+ ret
+
+
+
+ ; Actualiza el estado de NGN_KEY_ANY
+ @@KEY_ANY:
+
+ ld hl, NGN_KEY_ANY ; Apunta a la tecla
+
+ ; Analiza si hay pulsacion
+ ld a, d
+ cp $FF
+ jr z, @@KEY_ANY_HELD ; Hay pulsacion
+
+ ; Si no se ha pulsado
+ ld a, [hl]
+ and $08 ; Pero lo estabas
+ jr z, @@KEY_ANY_NONE
+ ld [hl], $04 ; B0100
+ ret
+
+ ; No se ha pulsado ni no estaba
+ @@KEY_ANY_NONE:
+ ld [hl], $00 ; B0000
+ ret
+
+ ; Si se ha pulsado
+ @@KEY_ANY_HELD:
+ ld a, [hl] ; Carga el estado anterior
+ and $08 ; Si no estava pulsada...
+ jr z, @@KEY_ANY_PRESS ; Salta a NEW PRESS
+ ld [hl], $09 ; B1001
+ ret
+
+ ; Si era una nueva pulsacion
+ @@KEY_ANY_PRESS:
+ ld [hl], $0B ; B1011
+ ret
+
+
+
+;***********************************************************
+; Fin del archivo
+;***********************************************************
+NGN_KEYBOARD_EOF:
\ No newline at end of file
diff --git a/lib_source/ngn/ngn_psg.asm b/lib_source/ngn/ngn_psg.asm
new file mode 100644
index 0000000..81ca0fd
--- /dev/null
+++ b/lib_source/ngn/ngn_psg.asm
@@ -0,0 +1,303 @@
+;***********************************************************
+;
+; N'gine para MSX Asm Z80
+; Version 0.0.1-a
+;
+; (cc)2018 Cesar Rincon "NightFox"
+; http://www.nightfoxandco.com
+;
+; Rutinas de acceso al PSG
+; (Programable Sound Generator)
+;
+;***********************************************************
+
+
+
+; --------------------------------------------------------------------------------------------------------------------------------------------------------------
+; $A0 = Reg Select $A1 = Write Data $A2 = Read Data
+; --------------------------------------------------------------------------------------------------------------------------------------------------------------
+; Register Bits
+; --------------------------------------------------------------------------------------------------------------------------------------------------------------
+; Reg. Function 7 6 5 4 3 2 1 0
+; --------------------------------------------------------------------------------------------------------------------------------------------------------------
+; R0 Channel A Period pa7 pa6 pa5 pa4 pa3 pa2 pa1 pa0
+; --------------------------------------------------------------------------------------------------------------------------------------------------------------
+; R1 Channel A Period - - - - paB paA pa9 pa8
+; --------------------------------------------------------------------------------------------------------------------------------------------------------------
+; R2 Channel B Period pb7 pb6 pb5 pb4 pb3 pb2 pb1 pb0
+; --------------------------------------------------------------------------------------------------------------------------------------------------------------
+; R3 Channel B Period - - - - pbB pbA pb9 pb8
+; --------------------------------------------------------------------------------------------------------------------------------------------------------------
+; R4 Channel C Period pc7 pc6 pc5 pc4 pc3 pc2 pc1 pc0
+; --------------------------------------------------------------------------------------------------------------------------------------------------------------
+; R5 Channel C Period - - - - pcB pcA pc9 pc8
+; --------------------------------------------------------------------------------------------------------------------------------------------------------------
+; R6 Noise Tone - - - n4 n3 n2 n1 n0
+; --------------------------------------------------------------------------------------------------------------------------------------------------------------
+; R7 /Enable Port B Dir. Port A Dir. C Noise B Noise A Noise C Tone B Tone A Tone
+; --------------------------------------------------------------------------------------------------------------------------------------------------------------
+; R8 Channel A Volume - - - A Mode va3 va2 va1 va0
+; --------------------------------------------------------------------------------------------------------------------------------------------------------------
+; R9 Channel B Volume - - - B Mode vb3 vb2 vb1 vb0
+; --------------------------------------------------------------------------------------------------------------------------------------------------------------
+; R10 Channel C Volume - - - C Mode vc3 vc2 vc1 vc0
+; --------------------------------------------------------------------------------------------------------------------------------------------------------------
+; R11 Envelope Period ep7 ep6 ep5 ep4 ep3 ep2 ep1 ep0
+; --------------------------------------------------------------------------------------------------------------------------------------------------------------
+; R12 Envelope Period epF epE epD epC epB epA ep9 ep8
+; --------------------------------------------------------------------------------------------------------------------------------------------------------------
+; R13 Envelope Wave Shape - - - - es3 es2 es1 es0
+; --------------------------------------------------------------------------------------------------------------------------------------------------------------
+; R14 I/O Port A Cas Input Kbd Mode Joy Trg.B Joy Trg.A Joy Right Joy Left Joy Back Joy Fwd
+; --------------------------------------------------------------------------------------------------------------------------------------------------------------
+; R15 I/O Port B Kana LED Joy Sel Pulse 2 Pulse 1 1 1 1 1
+; --------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+; --------------------------------------------------------------------------------------------------------------------------------------------------------------
+; Important note: the PSG registers R14 and R15 can be programmed for input or output. On MSX, R14 must be ever programmed for input and, R15, for output.
+; Thus, bit 6 of R7 must ever be set to "0" (input) and, bit 7, to "1" (output). Programming them otherwise may cause severe damage to the machine, putting
+; active coupling circuitry connected to R14 and R15 in short-circuit. More details on PSG register 7 section.
+; --------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+
+
+; ----------------------------------------------------------
+; NGN_PSG_COMMAND
+; Envia comandos al PSG
+; B = Registro
+; C = Dato
+; Modifica A
+; ----------------------------------------------------------
+
+NGN_PSG_COMMAND:
+
+ di ; Deshabilita las interrupciones
+
+ ld a, b
+ out ($A0), a ; Selecciona el registro
+ ld a, c
+ out ($A1), a ; Escribe el dato
+
+ ei ; Habilita las interrupciones
+
+ ; Vuelve
+ ret
+
+
+
+; ----------------------------------------------------------
+; NGN_PSG_INIT
+; Inicializa el PSG
+; Habilita los 3 canales de Melodia
+; No asignes ruido a ningun canal
+; Volumen al maximo en todos los canales
+; Modifica A
+; ----------------------------------------------------------
+
+NGN_PSG_INIT:
+
+ ; Deshabilita las interrupciones
+ di
+
+ ; Configura el I/O del PSG mediante el registro nē7
+ ld a, 7
+ out ($A0), a
+
+ ; Datos a enviar al registro 7
+ ld a, 56 ; Canales A, B y C como melodia
+ and 63 ; Proteccion al PSG, los BITs 6 y 7 a 0 [00xxxxxx]
+ or 128 ; Pon el BIT 7 a 1 y el BIT 6 a 0 [10xxxxxx]
+ out ($A1), a ; Escribe los datos en el registro
+
+ ld a, 8 ; Volumen del canal A
+ out ($A0), a
+ ld a, 15 ; Volumen a 15 (sin modulacion)
+ out ($A1), a
+
+ ld a, 9 ; Volumen del canal B
+ out ($A0), a
+ ld a, 15 ; Volumen a 15 (sin modulacion)
+ out ($A1), a
+
+ ld a, 10 ; Volumen del canal C
+ out ($A0), a
+ ld a, 15 ; Volumen a 15 (sin modulacion)
+ out ($A1), a
+
+ ; Habilita las interupciones
+ ei
+
+
+ ; Vuelve
+ ret
+
+
+
+
+
+; ----------------------------------------------------------
+; Lee los puertos de JoyStick usando el PSG
+; Modifica A, BC, HL
+; ----------------------------------------------------------
+
+; Lectura del puerto 1
+; NGN_PSG_READ_JOY1
+NGN_PSG_READ_JOY1:
+
+ ; Deshabilita las interrupciones
+ di
+
+ ; Seleccion del Puerto 1
+ ld a, 15 ; Seleccion del registro 15
+ out ($A0), a
+ out ($A1), a ; Puerto 1 seleccionado [00001111] = 15
+
+ ; Selecciona el registro de datos de puerto de JoyStick [14]
+ ld a, 14
+ out ($A0), a
+
+ ; Habilita las interrupciones
+ ei
+
+ ; Guarda la informacion de este Joystick en el registro C
+ in a, ($A2)
+ ld c, a
+
+ ; JOY1: ARRIBA [BIT 0]
+ ld hl, NGN_JOY1_UP
+ ld b, 1
+ call @@GET_KEY
+
+ ; JOY1: ABAJO [BIT 1]
+ ld hl, NGN_JOY1_DOWN
+ ld b, 2
+ call @@GET_KEY
+
+ ; JOY1: IZQUIERDA [BIT 2]
+ ld hl, NGN_JOY1_LEFT
+ ld b, 4
+ call @@GET_KEY
+
+ ; JOY1: DERECHA [BIT 3]
+ ld hl, NGN_JOY1_RIGHT
+ ld b, 8
+ call @@GET_KEY
+
+ ; JOY1: BOTON A [BIT 4]
+ ld hl, NGN_JOY1_TG1
+ ld b, 16
+ call @@GET_KEY
+
+ ; JOY1: BOTON B [BIT 5]
+ ld hl, NGN_JOY1_TG2
+ ld b, 32
+ call @@GET_KEY
+
+ ; Sal de la rutina
+ ret
+
+
+
+; Lectura del puerto 2
+; NGN_PSG_READ_JOY2
+NGN_PSG_READ_JOY2:
+
+ ; Deshabilita las interrupciones
+ di
+
+ ; Seleccion del Puerto 2
+ ld a, 15 ; Seleccion del registro 15
+ out ($A0), a
+ ld a, 79 ; Puerto 1 seleccionado [01001111] = 79
+ out ($A1), a
+
+ ; Selecciona el registro de datos de puerto de JoyStick [14]
+ ld a, 14
+ out ($A0), a
+
+ ; Habilita las interrupciones
+ ei
+
+ ; Guarda la informacion de este Joystick en el registro C
+ in a, ($A2)
+ ld c, a
+
+ ; JOY2: ARRIBA [BIT 0]
+ ld hl, NGN_JOY2_UP
+ ld b, 1
+ call @@GET_KEY
+
+ ; JOY2: ABAJO [BIT 1]
+ ld hl, NGN_JOY2_DOWN
+ ld b, 2
+ call @@GET_KEY
+
+ ; JOY2: IZQUIERDA [BIT 2]
+ ld hl, NGN_JOY2_LEFT
+ ld b, 4
+ call @@GET_KEY
+
+ ; JOY2: DERECHA [BIT 3]
+ ld hl, NGN_JOY2_RIGHT
+ ld b, 8
+ call @@GET_KEY
+
+ ; JOY2: BOTON A [BIT 4]
+ ld hl, NGN_JOY2_TG1
+ ld b, 16
+ call @@GET_KEY
+
+ ; JOY2: BOTON B [BIT 5]
+ ld hl, NGN_JOY2_TG2
+ ld b, 32
+ call @@GET_KEY
+
+ ; Sal de la rutina
+ ret
+
+
+
+; @@GET_KEY
+; Lee un valor en concreto
+; Lee el estado de la tecla solicitada usando el puerto $A2
+; BC = Datos de la tecla del Joystick B = BIT C = Datos
+; HL = Direccion de la variable asignada a la tecla
+
+@@GET_KEY:
+
+ ld a, c ; Carga los datos guardados del puerto
+ and b ; Comparalos con el bit correspondiente
+
+ jr z, @@KEY_HELD ; En caso de que se haya pulsado, salta
+
+ ; Si no se ha pulsado
+ ld a, [hl]
+ and $08 ; Pero lo estabas
+ jr z, @@NO_KEY
+ ld [hl], $04 ; B0100
+ ret
+
+ ; La tecla no se ha pulsado ni estaba pulsada
+ @@NO_KEY:
+ ld [hl], $00 ; B0000
+ ret
+
+ ; Si se ha pulsado
+ @@KEY_HELD:
+ ld a, [hl] ; Carga el estado anterior
+ and $08 ; Si no estava pulsada...
+ jr z, @@KEY_PRESS ; Salta a NEW PRESS
+ ld [hl], $09 ; Si ya estava pulsada, B1001
+ ret
+
+ ; Si era una nueva pulsacion
+ @@KEY_PRESS:
+ ld [hl], $0B ; B1011
+ ret
+
+
+
+;***********************************************************
+; Fin del archivo
+;***********************************************************
+NGN_PSG_EOF:
\ No newline at end of file
diff --git a/lib_source/ngn/ngn_rle.asm b/lib_source/ngn/ngn_rle.asm
new file mode 100644
index 0000000..9e5e09d
--- /dev/null
+++ b/lib_source/ngn/ngn_rle.asm
@@ -0,0 +1,129 @@
+;***********************************************************
+;
+; N'gine para MSX Asm Z80
+; Version 0.0.1-a
+;
+; (cc)2018 Cesar Rincon "NightFox"
+; http://www.nightfoxandco.com
+;
+; Descompresion de datos RLE
+;
+;***********************************************************
+
+
+
+; ----------------------------------------------------------
+; NGN_RLE_DECOMPRESS
+; Descomprime datos RLE y colocalos en el buffer de RAM
+; HL = Direccion de los datos comprimidos
+; DE = Direccion de destino
+; BC = Tamaņo de los datos a descomprimir [AUTO]
+; Modifica A, BC, DE, HL
+; ----------------------------------------------------------
+
+NGN_RLE_DECOMPRESS:
+
+ ; Lee la cabecera con la informacion sobre el
+ ; tamaņo de los datos comprimidos y descomprimidos
+
+ ld b, [hl] ; Lee el tamaņo descomprimido
+ inc hl
+ ld c, [hl]
+ inc hl
+ push hl
+
+ ld hl, NGN_RLE_NORMAL_SIZE ; Guarda el tamaņo descomprimido
+ ld [hl], b
+ inc hl
+ ld [hl], c
+ pop hl
+
+ ld b, [hl] ; Lee el tamaņo comprimido
+ inc hl
+ ld c, [hl]
+ inc hl
+ push hl
+
+ ld hl, NGN_RLE_COMPRESSED_SIZE ; Guarda el tamaņo comprimido
+ ld [hl], b
+ inc hl
+ ld [hl], c
+ pop hl
+
+ push hl ; Lee el puntero a los datos
+ push de
+ ld d, h
+ ld e, l
+
+ ld hl, NGN_RLE_POINTER ; Guarda el puntero a los datos
+ ld [hl], d
+ inc hl
+ ld [hl], e
+ pop de
+ pop hl
+
+
+
+
+ ; Loop principal de la descompresion de datos
+ @@MAIN_LOOP:
+
+ ld a, [hl] ; Carga el dato
+ and 192 ; Si los BITS 6 y 7 estan a 1, es un dato comprimido
+ cp 192
+ jr z, @@DECOMPRESS_DATA
+
+ ld a, [hl] ; Los datos no estan comprimidos, escribelos tal cual
+ ld [de], a
+ inc hl ; Suma una posicion a los punteros de origen y destino
+ inc de
+ dec bc ; Resta una unidad al contador de datos
+ ld a, b
+ or c ; Y verifica si aun hay datos
+ jr nz, @@MAIN_LOOP
+ jp @@END ; Sal de la rutina si no quedan datos
+
+
+
+ ; Descompresion de los datos
+ @@DECOMPRESS_DATA:
+
+ push bc ; Guarda el numero de datos restantes
+ ld a, [hl] ; Ahora mira el numero de repeticiones
+ and 63 ; En base a los BITS 0 a 5
+ ld b, a ; Guarda las repeticiones en B
+ inc hl ; Muevete al siguiente byte
+ ld a, [hl] ; lee el dato a repetir
+ ld c, a ; y guardalo en C
+ inc hl ; Y mueve el puntero de lectura
+
+ ; Escribe los datos RLE
+ @@WRITE_LOOP:
+
+ ld a, c ; Carga el dato a escribir
+ ld [de], a ; Escribelo en el destino
+ inc de ; Mueve el puntero
+ dec b ; Resta una repeticion
+ jr nz, @@WRITE_LOOP ; Si aun quedan repeticiones, repite
+
+ ; Si se ha terminado de escribir datos RLE
+ pop bc ; Recupera los datos restantes
+ dec bc ; Resta 2 bytes
+ dec bc
+ ld a, b
+ or c ; Y verifica si aun hay datos
+ jp nz, @@MAIN_LOOP
+
+
+
+ ; Fin de la descompresion RLE
+ @@END:
+
+ ret ; Fin de la rutina
+
+
+
+;***********************************************************
+; Fin del archivo
+;***********************************************************
+NGN_RLE_EOF:
\ No newline at end of file
diff --git a/lib_source/ngn/ngn_screen.asm b/lib_source/ngn/ngn_screen.asm
new file mode 100644
index 0000000..6209b68
--- /dev/null
+++ b/lib_source/ngn/ngn_screen.asm
@@ -0,0 +1,172 @@
+;***********************************************************
+;
+; N'gine para MSX Asm Z80
+; Version 0.0.1-a
+;
+; (cc)2018 Cesar Rincon "NightFox"
+; http://www.nightfoxandco.com
+;
+; Rutinas de acceso al la pantalla
+;
+;***********************************************************
+
+
+; ----------------------------------------------------------
+; NGN_SCREEN_SET_MODE_0
+; Inicializa la pantalla en modo SCREEN 0
+; (SPRITES habilitados, 8x8 sin magnificar)
+; B = Color de frente
+; C = Color de fondo
+; D = Color de borde (sin uso)
+; E = Ancho de la pantalla en columnas
+; Modifica A, BC, DE, HL
+; ----------------------------------------------------------
+
+NGN_SCREEN_SET_MODE_0:
+
+ ; Guarda los parametros de la funcion
+ push bc
+ push de
+
+ ; Borra la pantalla (CLS)
+ xor a
+ call $00C3 ; Borra la pantalla con la rutina [CLS] de la BIOS
+
+ ; Recupera los parametros de la funcion
+ pop de
+ pop bc
+
+ ; Ancho de la pantalla
+ ld a, e
+ ld [$F3AE], a ; Cambia el ancho en columnas de la pantalla [LINL40]
+
+ ; Color por defecto
+ ld hl, NGN_COLOR_ADDR
+ ld [hl], b ; Color de frente
+ inc l
+ ld [hl], c ; Color de fondo
+ inc l
+ ld [hl], 1 ; Color del borde (Negro)
+ call $0062 ; Aplica el color con la rutina [CHGCLR] de la BIOS
+
+ ; Ajusta el VDP
+ call @@SETUP_VDP
+
+ ; Inicializa el VDP con la rutina [INITXT] de la BIOS
+ call $006C
+
+ ; Sal de la rutina
+ ret
+
+
+
+; ----------------------------------------------------------
+; NGN_SCREEN_SET_MODE_2
+; Inicializa la pantalla en modo SCREEN 2
+; (SPRITES habilitados, 8x8 sin magnificar)
+; B = Color de frente
+; C = Color de fondo
+; D = Color de borde
+; E = Sin uso
+; Modifica A, BC, DE, HL
+; ----------------------------------------------------------
+
+NGN_SCREEN_SET_MODE_2:
+
+ ; Guarda los parametros de la funcion
+ push bc
+ push de
+
+ ; Borra la pantalla (CLS)
+ xor a
+ call $00C3 ; Borra la pantalla con la rutina [CLS] de la BIOS
+
+ ; Recupera los parametros de la funcion
+ pop de
+ pop bc
+
+ ; Color por defecto
+ ld hl, NGN_COLOR_ADDR
+ ld [hl], b ; Color de frente (Blanco)
+ inc l
+ ld [hl], c ; Color de fondo (Negro)
+ inc l
+ ld [hl], d ; Color del borde (Negro)
+ call $0062 ; Aplica el color con la rutina [CHGCLR] de la BIOS
+
+ ; Ajusta el VDP
+ call @@SETUP_VDP
+
+ ; Inicializa el VDP con la rutina [INIGRP] de la BIOS
+ call $0072
+
+ ; Sal de la rutina
+ ret
+
+
+
+; ----------------------------------------------------------
+; Ajusta los parametros por defecto del VDP
+; Modifica A, BC
+; ----------------------------------------------------------
+
+@@SETUP_VDP:
+
+ di ; Deshabilita las interrupciones
+
+ ; Address ... 057FH (from 0047H)
+ ; Name ...... WRTVDP (Write to VDP Register)
+ ; Input ..... B=Data byte, C=VDP Mode Register number
+ ; Exit ...... None
+ ; Modifies .. AF, B, EI
+
+ ; M1 M2 M3 M4 M5 Mode MSX Version BASIC Screen
+ ; --------------------------------------------------------------------------------------
+ ; 0 0 0 0 0 32x24 Text 1 2 2+ tR 1
+ ; 1 0 0 0 0 40x24 Text 1 2 2+ tR 0
+ ; 1 0 0 1 0 80x24 Text 2 2+ tR 0
+ ; 0 1 0 0 0 Multicolour 1 2 2+ tR 3
+ ; 0 0 1 0 0 Graphics 1 1 2 2+ tR 2
+ ; 0 0 0 1 0 Graphics 2 2 2+ tR 4
+ ; 0 0 1 1 0 Graphics 4 2 2+ tR 5
+ ; 0 0 0 0 1 Graphics 5 2 2+ tR 6
+ ; 0 0 1 0 1 Graphics 6 2 2+ tR 7
+ ; 0 0 1 1 1 Graphics 7 2 2+ tR 8
+
+ ; Modifica el registro 0 del VDP
+ ; BIT 0 The External VDP (EV) bit determines whether external VDP input is to be enabled or disabled: 0=Disabled, 1=Enabled.
+ ; BIT 1 The M3, one of the five VDP mode Selection bits that define the VDP display mode.
+ ; BIT 2 The M4, one of the five VDP mode Selection bits that define the VDP display mode.
+ ; BIT 3 The M5, one of the five VDP mode Selection bits that define the VDP display mode.
+ ; BIT 4 The Interruption Enable 1 (IE1) bit, when set to "1", enables the line interruption.
+ ; BIT 5 The Interruption Enable 2 (IE2) bit, when set to "1", enables light-pen interruption.
+ ; BIT 6 The Digitizer (DG) bit, when set to "1", enables the colour bus input mode, capturing data into the VRAM.
+ ; BIT 7 Always 0
+
+ ld bc, $0200 ; B = 00000010 C = VDP REG 0
+ call $0047 ; [WRTVDP]
+
+ ; Modifica el registro 1 del VDP
+ ; BIT 0 The Magnification (Mag) bit determines whether sprites will be normal or doubled in size: 0=Normal, 1=Doubled.
+ ; BIT 1 The Size bit determines whether each sprite pattern will be 8x8 bits or 16x16 bits: 0=8x8, 1=16x16.
+ ; BIT 2 Always 0
+ ; BIT 3 The M2, one of the five VDP mode Selection bits that define the VDP display mode.
+ ; BIT 4 The M1, one of the five VDP mode Selection bits that define the VDP display mode.
+ ; BIT 5 The Interrupt Enable bit enables or disables the interrupt output signal from the VDP: 0=Disable, 1=Enable.
+ ; BIT 6 The Blank bit is used to enable or disable the entire video display: 0=Disable, 1=Enable.
+ ; BIT 7 The 4/16K bit alters the VDP VRAM addressing characteristics to suit either 4 KB or 16 KB chips: 0=4 KB, 1=16 KB.
+
+ ld bc, $E001 ; B = 11100000 C = VDP REG 1
+ call $0047 ; [WRTVDP]
+
+ ei ; Habilita las interrupciones
+
+ ; Sal de la subrutina
+ ret
+
+
+
+;***********************************************************
+; Fin del archivo
+;***********************************************************
+NGN_SCREEN_EOF:
\ No newline at end of file
diff --git a/lib_source/ngn/ngn_sprite.asm b/lib_source/ngn/ngn_sprite.asm
new file mode 100644
index 0000000..6d6d861
--- /dev/null
+++ b/lib_source/ngn/ngn_sprite.asm
@@ -0,0 +1,251 @@
+;***********************************************************
+;
+; N'gine para MSX Asm Z80
+; Version 0.0.1-a
+;
+; (cc)2018 Cesar Rincon "NightFox"
+; http://www.nightfoxandco.com
+;
+; Rutinas de sprites
+;
+;***********************************************************
+
+
+
+; ----------------------------------------------------------
+; NGN_SPRITE_MODE
+; Cambia el modo de los Sprites
+; NGN_SPR_8x8 NGN_SPR_8x8_D NGN_SPR_16x16 NGN_SPR_16x16_D
+; Modifica A, BC
+; ----------------------------------------------------------
+
+; 8x8
+NGN_SPRITE_MODE_8x8:
+ ld a, [NGN_VDPR1] ; Consulta el valor del registro 1
+ and $FC ; xxxxxx00
+ jp @@SETUP_VDP
+
+; 8x8_D
+NGN_SPRITE_MODE_8x8_D:
+ ld a, [NGN_VDPR1] ; Consulta el valor del registro 1
+ and $FC ; xxxxxx00
+ or $01 ; xxxxxx01
+ jp @@SETUP_VDP
+
+; 16x16
+NGN_SPRITE_MODE_16x16:
+ ld a, [NGN_VDPR1] ; Consulta el valor del registro 1
+ and $FC ; xxxxxx00
+ or $02 ; xxxxxx10
+ jp @@SETUP_VDP
+
+; 16x16_D
+NGN_SPRITE_MODE_16x16_D:
+ ld a, [NGN_VDPR1] ; Consulta el valor del registro 1
+ or $03 ; xxxxxx11
+
+; Actualiza el VDP
+@@SETUP_VDP:
+ di ; Deshabilita las interrupciones
+ ld b, a ; B = Valor a escribir en el registro del VDP
+ ld c, $01 ; C = Seleccion del registro
+ call $0047 ; [WRTVDP] Escribe los datos
+ ei ; Habilita las interrupciones
+ ret
+
+
+
+; ----------------------------------------------------------
+; NGN_SPRITE_RESET
+; Reinicia el sistema de sprites
+; Modifica A, BC, DE, HL
+; ----------------------------------------------------------
+
+NGN_SPRITE_RESET:
+
+ call $0069 ; Borra los sprites con la rutina [CLRSPR] de la BIOS
+ ld hl, NGN_SPRATR ; Puntero a la tabla de sprites en VRAM
+ ld de, NGN_SPRITE_00 ; Puntero al primer sprite en RAM
+ ld bc, $0080 ; 128 bytes de datos (32*4)
+ call $0059 ; Ejecuta la rutina [LDIRMV] (Mueve datos de VRAM a RAM)
+ ret ; Sal de la funcion
+
+
+
+; ----------------------------------------------------------
+; NGN_SPRITE_UPDATE
+; Actualiza los atributos de todos los sprites
+; Modifica A, BC, DE, HL
+; ----------------------------------------------------------
+
+NGN_SPRITE_UPDATE:
+
+ ld hl, NGN_SPRITE_00 ; Puntero al primer sprite en RAM
+ ld bc, $0080 ; 128 bytes de datos (32*4)
+ ld de, NGN_SPRATR ; Puntero a la tabla de sprites en VRAM
+
+ ; Transfiere los datos a la VRAM (usando la BIOS)
+ call $005C ; Ejecuta la rutina [LDIRVM]
+ ; HL Origen de los datos (RAM)
+ ; BC Cantidad de datos a transferir
+ ; DE Destino de los datos (VRAM)
+
+ ret ; Sal de la funcion
+
+
+
+; ----------------------------------------------------------
+; NGN_SPRITE_LOAD_DATA
+; Carga los graficos de un Sprite en la VRAM
+; HL = Direccion de los CHR del Sprite (Origen de los datos)
+; B = Nē de Slot (0-255) o (0-63)
+; Modifica A, BC, DE, HL
+; ----------------------------------------------------------
+
+NGN_SPRITE_LOAD_DATA:
+
+ ; Guarda el origen de los datos
+ push hl
+
+ ; Posicion inicial
+ ld hl, NGN_SPRTBL
+ ld c, 0
+
+ ; Calcula el tamaņo del slot
+ ld a, [NGN_VDPR1] ; Consulta el modo actual de los sprites
+ and $02
+ jr nz, @@MODE_16
+ ld de, $0008 ; +8
+ @@MODE_16:
+ ld de, $0020 ; +32
+
+ ; Busca el slot de destino
+ @@SEARCH_SLOT:
+ ; Si ya estas en el slot correcto
+ ld a, c
+ cp b
+ jr z, @@DATA_TO_VRAM
+ ; Aņade el desplazamiento del tamaņo del slot
+ add hl, de
+ ; Conteo de slot
+ inc c
+ ; Loop
+ jr @@SEARCH_SLOT
+
+ ; Transfiere los datos a la VRAM
+ @@DATA_TO_VRAM:
+ ld d, h ; Direccion de destino (DE)
+ ld e, l
+ pop hl ; Recupera la posicion de los datos (HL)
+ ld b, [hl] ; Tamaņo de los datos a transferir (BC)
+ inc hl
+ ld c, [hl]
+ inc hl ; Datos a transferir
+
+ ; Transfiere los datos a la VRAM (usando la BIOS)
+ call $005C ; Ejecuta la rutina [LDIRVM]
+ ; HL Origen de los datos (RAM)
+ ; BC Cantidad de datos a transferir
+ ; DE Destino de los datos (VRAM)
+
+ ; Sal de la rutina
+ ret
+
+
+
+; ----------------------------------------------------------
+; NGN_SPRITE_CREATE
+; Crea un Sprite los graficos cargados en la VRAM
+; A = Nē de slot del Sprite (0-31)
+; B = Nē de slot del grafico (0-255) o (0-63)
+; C = Nē de color de la paleta
+; D = Coordenada X
+; E = Coordenada Y
+; Modifica A, BC, DE, HL
+; ----------------------------------------------------------
+
+NGN_SPRITE_CREATE:
+
+ ; Guarda el numero de slot de Sprite
+ push af
+
+ ld a, [NGN_VDPR1] ; Consulta el modo actual de los sprites
+ and $02
+ jr z, @@SET_ATTRIB ; Si es modo 8x8, continua
+ ld a, b ; Slot de graficos
+ sla a ; Multiplicalo x4
+ sla a
+ ld b, a ; Actualiza el contenido
+
+
+ ; Guarda los atributos dados en el buffer
+ @@SET_ATTRIB:
+ pop af ; Recupera el numero de slot del sprite
+ push bc ; Guarda BC (Slot grafico / Color)
+
+ sla a ; Desplazamiento de 4 bytes * nē de slot de sprite
+ sla a
+
+ ld b, 0 ; Prepara el offset
+ ld c, a
+
+ ld hl, NGN_SPRITE_00 ; Puntero al primer sprite
+ add hl, bc ; Posicionalo en el slot correcto (Inicial + offset)
+
+ pop bc ; Recupera BC (Slot grafico / Color)
+
+ ld [hl], e ; Posicion Y
+ inc hl
+ ld [hl], d ; Posicion X
+ inc hl
+ ld [hl], b ; nē Slot del grafico
+ inc hl
+ ld [hl], c ; nē de color de la paleta
+
+ ret ; Sal de la funcion
+
+
+
+; ----------------------------------------------------------
+; NGN_SPRITE_POSITION
+; Posiciona un Sprite en las coordenadas dadas
+; HL = Direccion del sprite NGN_SPRITE_XX
+; B = Coordenada X
+; C = Coordenada Y
+; Modifica BC, HL
+; ----------------------------------------------------------
+
+NGN_SPRITE_POSITION:
+
+ ; Actualiza los parametros
+ ld [hl], c ; Y
+ inc hl
+ ld [hl], b ; X
+
+ ret ; Sal de la funcion
+
+
+
+; ----------------------------------------------------------
+; NGN_SPRITE_COLOR
+; Cambia el color de un Sprite
+; HL = Direccion del sprite NGN_SPRITE_XX
+; B = Color de la paleta (0-15)
+; Modifica BC, DE, HL
+; ----------------------------------------------------------
+
+NGN_SPRITE_COLOR:
+
+ ; Actualiza los parametros
+ ld de, $0003
+ add hl, de
+ ld [hl], b
+
+ ret ; Sal de la funcion
+
+
+
+;***********************************************************
+; Fin del archivo
+;***********************************************************
+NGN_SPRITE_EOF:
\ No newline at end of file
diff --git a/lib_source/ngn/ngn_start.asm b/lib_source/ngn/ngn_start.asm
new file mode 100644
index 0000000..9b85ccd
--- /dev/null
+++ b/lib_source/ngn/ngn_start.asm
@@ -0,0 +1,84 @@
+;***********************************************************
+;
+; N'gine para MSX Asm Z80
+; Version 0.0.1-a
+;
+; (cc)2018 Cesar Rincon "NightFox"
+; http://www.nightfoxandco.com
+;
+; Inicializacion de la libreria
+;
+;***********************************************************
+
+
+
+; ----------------------------------------------------------
+; NGN_START
+; Inicializa la libreria
+; Modifica A, BC, DE, HL
+; ----------------------------------------------------------
+
+NGN_START:
+
+ ; Habilita las interrupciones
+ ei
+
+ ; Inicializa las variables
+ call @@INIT_VARIABLES
+
+ ; Inicializa el PSG
+ call NGN_PSG_INIT
+
+ ; Deshabilita el sonido del teclado
+ xor a ; Fuerza a que A sea 0
+ ld [$F3DB], a ; [CLIKSW]
+
+ ; Sal de la rutina
+ ret
+
+
+
+; ----------------------------------------------------------
+; Inicializa las variables
+; Modifica A, BC, DE, HL
+; ----------------------------------------------------------
+
+@@INIT_VARIABLES:
+
+ ; Teclas
+ ld hl, NGN_KEY_0 ; Puntero donde esta la primera tecla
+ ld b, NGN_TOTAL_KEYS ; Numero de teclas a reiniciar
+ @@RESET_KEYS:
+ xor a ; Registro A a 0
+ ld [hl], a ; Borra el contenido de la tecla
+ inc hl ; Siguiente tecla
+ dec b ; Cuenta las teclas iniciadas
+ jr nz, @@RESET_KEYS ; Repite el proceso
+
+ ; Joysticks
+ ld hl, NGN_JOY1_UP ; Puntero donde esta la primera tecla de joystick
+ ld b, NGN_TOTAL_JOYKEYS ; Numero de teclas a reiniciar
+ @@RESET_JOYKEYS:
+ xor a ; Registro A a 0
+ ld [hl], a ; Borra el contenido de la tecla
+ inc hl ; Siguiente tecla
+ dec b ; Cuenta las teclas iniciadas
+ jr nz, @@RESET_JOYKEYS ; Repite el proceso
+
+ ; Atributos de sprites (0-31)
+ call $0069 ; Borra los sprites con la rutina [CLRSPR] de la BIOS
+ ld hl, NGN_SPRATR ; Puntero a la tabla de sprites en VRAM
+ ld de, NGN_SPRITE_00 ; Puntero al primer sprite en RAM
+ ld bc, $0080 ; 128 bytes de datos (32*4)
+ call $0059 ; Ejecuta la rutina [LDIRMV] (Mueve datos de VRAM a RAM)
+
+
+ ; Vuelve
+ ret
+
+
+
+;***********************************************************
+; Fin del archivo
+;***********************************************************
+NGN_START_EOF:
\ No newline at end of file
diff --git a/lib_source/ngn/ngn_system.asm b/lib_source/ngn/ngn_system.asm
new file mode 100644
index 0000000..b2ac8a1
--- /dev/null
+++ b/lib_source/ngn/ngn_system.asm
@@ -0,0 +1,38 @@
+;***********************************************************
+;
+; N'gine para MSX Asm Z80
+; Version 0.0.1-a
+;
+; (cc)2018 Cesar Rincon "NightFox"
+; http://www.nightfoxandco.com
+;
+; Funciones del sistema
+;
+;***********************************************************
+
+
+
+; ----------------------------------------------------------
+; NGN_SYSTEM_RANDOM_NUMBER
+; Genera un numero aleatorio entre 0-255
+; A = Devuelve el numero generado
+; Modifica A, B
+; ----------------------------------------------------------
+
+NGN_SYSTEM_RANDOM_NUMBER:
+
+ ld a, [NGN_RANDOM_SEED]
+ ld b, a
+ add a, a
+ add a, a
+ add a, b
+ add a, 7
+ ld [NGN_RANDOM_SEED], a
+ ret
+
+
+
+;***********************************************************
+; Fin del archivo
+;***********************************************************
+NGN_SYSTEM_EOF:
\ No newline at end of file
diff --git a/lib_source/ngn/ngn_text.asm b/lib_source/ngn/ngn_text.asm
new file mode 100644
index 0000000..76194c0
--- /dev/null
+++ b/lib_source/ngn/ngn_text.asm
@@ -0,0 +1,103 @@
+;***********************************************************
+;
+; N'gine para MSX Asm Z80
+; Version 0.0.1-a
+;
+; (cc)2018 Cesar Rincon "NightFox"
+; http://www.nightfoxandco.com
+;
+; Rutinas para la impresion de texto
+;
+;***********************************************************
+
+
+
+; ----------------------------------------------------------
+; NGN_TEXT_PRINT
+; Carga una imagen y muestrala a la pantalla
+; HL = Direccion del texto a imprimir (Origen de los datos)
+; Modifica A, BC, DE, HL
+; ----------------------------------------------------------
+
+NGN_TEXT_PRINT:
+
+ @@WRITE_TEXT:
+
+ ld a, [hl] ; Lee el caracter
+
+ cp $00 ; Si es el final del texto, sal
+ ret z
+
+ call $00A2 ; Imprime el caracter. Rutina [CHPUT] de la BIOS
+
+ inc hl ; Siguiente caracter
+
+ jr @@WRITE_TEXT ; Repite el bucle
+
+
+
+; ----------------------------------------------------------
+; NGN_TEXT_POSITION
+; Carga una imagen y muestrala a la pantalla
+; H = Coordenada X del cursor
+; L = Coordenada Y del cursor
+; Modifica A, BC, DE, HL
+; ----------------------------------------------------------
+
+NGN_TEXT_POSITION:
+
+ call $00C6; ; Rutina de BIOS [POSIT]
+ ret
+
+
+
+; ----------------------------------------------------------
+; NGN_TEXT_CLS
+; Borra la pantalla
+; Modifica A, BC, DE, HL
+; ----------------------------------------------------------
+
+NGN_TEXT_CLS:
+
+ xor a
+ call $00C3 ; Borra la pantalla con la rutina [CLS] de la BIOS
+ ret
+
+
+
+; ----------------------------------------------------------
+; NGN_TEXT_COLOR
+; B = Color del texto
+; C = Color del fondo
+; Modifica A, BC, DE, HL
+; ----------------------------------------------------------
+
+NGN_TEXT_COLOR:
+
+ ld hl, NGN_COLOR_ADDR
+ ld [hl], b ; Color de frente
+ inc l
+ ld [hl], c ; Color de fondo
+ inc l
+ ld [hl], 1 ; Color del borde (Negro)
+ call $0062 ; Aplica el color con la rutina [CHGCLR] de la BIOS
+ ret
+
+
+
+; ----------------------------------------------------------
+; NGN_TEXT_WIDTH
+; A = Ancho del texto
+; ----------------------------------------------------------
+
+NGN_TEXT_WIDTH:
+
+ ld [$F3AE], a ; Cambia el ancho en columnas de la pantalla [LINL40]
+ ret
+
+
+
+;***********************************************************
+; Fin del archivo
+;***********************************************************
+NGN_TEXT_EOF:
\ No newline at end of file
diff --git a/lib_source/ngn/ngn_vars.asm b/lib_source/ngn/ngn_vars.asm
new file mode 100644
index 0000000..fb3d1f9
--- /dev/null
+++ b/lib_source/ngn/ngn_vars.asm
@@ -0,0 +1,214 @@
+;***********************************************************
+;
+; N'gine para MSX Asm Z80
+; Version 0.0.1-a
+;
+; (cc)2018 Cesar Rincon "NightFox"
+; http://www.nightfoxandco.com
+;
+; Definicion de variables
+;
+;***********************************************************
+
+
+
+; --------------------------------------------------------------
+; Declara las variables del sistema [VARIABLE] [BYTES]
+; --------------------------------------------------------------
+
+; -----------------------------------------------------------------------
+; Teclas
+; STATE [LAST] [UP] [PRESS] [HELD] Key num: 89
+; BIT 3 2 1 0 NGN_TOTAL_KEYS
+; -----------------------------------------------------------------------
+; ROW 0
+NGN_KEY_0: ds 1 ; Tecla 0
+NGN_KEY_1: ds 1 ; Tecla 1
+NGN_KEY_2: ds 1 ; Tecla 2
+NGN_KEY_3: ds 1 ; Tecla 3
+NGN_KEY_4: ds 1 ; Tecla 4
+NGN_KEY_5: ds 1 ; Tecla 5
+NGN_KEY_6: ds 1 ; Tecla 6
+NGN_KEY_7: ds 1 ; Tecla 7
+; ROW 1
+NGN_KEY_8: ds 1 ; Tecla 8
+NGN_KEY_9: ds 1 ; Tecla 9
+NGN_KEY_MINUS: ds 1 ; Tecla -
+NGN_KEY_EQUAL: ds 1 ; Tecla =
+NGN_KEY_BACKSLASH: ds 1 ; Tecla \
+NGN_KEY_LEFT_BRACKET: ds 1 ; Tecla [
+NGN_KEY_RIGHT_BRACKET: ds 1 ; Tecla ]
+NGN_KEY_SEMICLON: ds 1 ; Tecla ;
+; ROW 2
+NGN_KEY_APOSTROPHE: ds 1 ; Tecla '
+NGN_KEY_GRAVE: ds 1 ; Tecla `
+NGN_KEY_COMMA: ds 1 ; Tecla ,
+NGN_KEY_PERIOD: ds 1 ; Tecla .
+NGN_KEY_SLASH: ds 1 ; Tecla /
+NGN_KEY_DEAD: ds 1 ; Tecla DEAD KEY
+NGN_KEY_A: ds 1 ; Tecla A
+NGN_KEY_B: ds 1 ; Tecla B
+; ROW 3
+NGN_KEY_C: ds 1 ; Tecla C
+NGN_KEY_D: ds 1 ; Tecla D
+NGN_KEY_E: ds 1 ; Tecla E
+NGN_KEY_F: ds 1 ; Tecla F
+NGN_KEY_G: ds 1 ; Tecla G
+NGN_KEY_H: ds 1 ; Tecla H
+NGN_KEY_I: ds 1 ; Tecla I
+NGN_KEY_J: ds 1 ; Tecla J
+; ROW 4
+NGN_KEY_K: ds 1 ; Tecla K
+NGN_KEY_L: ds 1 ; Tecla L
+NGN_KEY_M: ds 1 ; Tecla M
+NGN_KEY_N: ds 1 ; Tecla N
+NGN_KEY_O: ds 1 ; Tecla O
+NGN_KEY_P: ds 1 ; Tecla P
+NGN_KEY_Q: ds 1 ; Tecla Q
+NGN_KEY_R: ds 1 ; Tecla R
+; ROW 5
+NGN_KEY_S: ds 1 ; Tecla S
+NGN_KEY_T: ds 1 ; Tecla T
+NGN_KEY_U: ds 1 ; Tecla U
+NGN_KEY_V: ds 1 ; Tecla V
+NGN_KEY_W: ds 1 ; Tecla W
+NGN_KEY_X: ds 1 ; Tecla X
+NGN_KEY_Y: ds 1 ; Tecla Y
+NGN_KEY_Z: ds 1 ; Tecla Z
+; ROW 6
+NGN_KEY_SHIFT: ds 1 ; Tecla SHIFT
+NGN_KEY_CTRL: ds 1 ; Tecla CTRL
+NGN_KEY_GRAPH: ds 1 ; Tecla GRAPH
+NGN_KEY_CAPS: ds 1 ; Tecla CAPS
+NGN_KEY_CODE: ds 1 ; Tecla CODE
+NGN_KEY_F1: ds 1 ; Tecla F1
+NGN_KEY_F2: ds 1 ; Tecla F2
+NGN_KEY_F3: ds 1 ; Tecla F3
+; ROW 7
+NGN_KEY_F4: ds 1 ; Tecla F4
+NGN_KEY_F5: ds 1 ; Tecla F5
+NGN_KEY_ESC: ds 1 ; Tecla ESC
+NGN_KEY_TAB: ds 1 ; Tecla TAB
+NGN_KEY_STOP: ds 1 ; Tecla STOP
+NGN_KEY_BS: ds 1 ; Tecla BS
+NGN_KEY_SELECT: ds 1 ; Tecla SELECT
+NGN_KEY_RETURN: ds 1 ; Tecla RETURN
+; ROW 8
+NGN_KEY_SPACE: ds 1 ; Tecla SPACE
+NGN_KEY_HOME: ds 1 ; Tecla HOME
+NGN_KEY_INS: ds 1 ; Tecla INS
+NGN_KEY_DEL: ds 1 ; Tecla DEL
+NGN_KEY_LEFT: ds 1 ; Tecla CURSOR LEFT
+NGN_KEY_UP: ds 1 ; Tecla CURSOR UP
+NGN_KEY_DOWN: ds 1 ; Tecla CURSOR DOWN
+NGN_KEY_RIGHT: ds 1 ; Tecla CURSOR RIGHT
+; ROW 9
+NGN_KEY_NUM_ASTERISK: ds 1 ; Tecla NUM *
+NGN_KEY_NUM_PLUS: ds 1 ; Tecla NUM +
+NGN_KEY_NUM_SLASH: ds 1 ; Tecla NUM /
+NGN_KEY_NUM_0: ds 1 ; Tecla NUM 0
+NGN_KEY_NUM_1: ds 1 ; Tecla NUM 1
+NGN_KEY_NUM_2: ds 1 ; Tecla NUM 2
+NGN_KEY_NUM_3: ds 1 ; Tecla NUM 3
+NGN_KEY_NUM_4: ds 1 ; Tecla NUM 4
+; ROW 10
+NGN_KEY_NUM_5: ds 1 ; Tecla NUM 5
+NGN_KEY_NUM_6: ds 1 ; Tecla NUM 6
+NGN_KEY_NUM_7: ds 1 ; Tecla NUM 7
+NGN_KEY_NUM_8: ds 1 ; Tecla NUM 8
+NGN_KEY_NUM_9: ds 1 ; Tecla NUM 9
+NGN_KEY_NUM_MINUS: ds 1 ; Tecla NUM -
+NGN_KEY_NUM_COMMA: ds 1 ; Tecla NUM ,
+NGN_KEY_NUM_PERIOD: ds 1 ; Tecla NUM .
+; EXTRAS
+NGN_KEY_ANY: ds 1 ; Cualquier tecla
+
+
+; -----------------------------------------------------------------------
+; Joysticks
+; STATE [TEMP] [PRESS] [HELD] Key num: 12
+; BIT 2 1 0 NGN_TOTAL_JOYKEYS
+; -----------------------------------------------------------------------
+
+NGN_JOY1_UP: ds 1 ; Joystick 1 Arriba
+NGN_JOY1_DOWN: ds 1 ; Joystick 1 Abajo
+NGN_JOY1_LEFT: ds 1 ; Joystick 1 Izquierda
+NGN_JOY1_RIGHT: ds 1 ; Joystick 1 Derecha
+NGN_JOY1_TG1: ds 1 ; Joystick 1 Tigger 1
+NGN_JOY1_TG2: ds 1 ; Joystick 1 Tigger 2
+
+NGN_JOY2_UP: ds 1 ; Joystick 2 Arriba
+NGN_JOY2_DOWN: ds 1 ; Joystick 2 Abajo
+NGN_JOY2_LEFT: ds 1 ; Joystick 2 Izquierda
+NGN_JOY2_RIGHT: ds 1 ; Joystick 2 Derecha
+NGN_JOY2_TG1: ds 1 ; Joystick 2 Tigger 1
+NGN_JOY2_TG2: ds 1 ; Joystick 2 Tigger 2
+
+
+
+; -----------------------------------------------------------------------
+; Gestion del sistema de sprites
+; [Y] [X] [GRAIFCO] [COLOR]
+; 0-255 0-255 0-63 0-15
+; -----------------------------------------------------------------------
+
+NGN_SPRITE_00: ds 4 ; Attributos del Sprite nē 00
+NGN_SPRITE_01: ds 4
+NGN_SPRITE_02: ds 4
+NGN_SPRITE_03: ds 4
+NGN_SPRITE_04: ds 4
+NGN_SPRITE_05: ds 4
+NGN_SPRITE_06: ds 4
+NGN_SPRITE_07: ds 4
+NGN_SPRITE_08: ds 4
+NGN_SPRITE_09: ds 4
+NGN_SPRITE_10: ds 4
+NGN_SPRITE_11: ds 4
+NGN_SPRITE_12: ds 4
+NGN_SPRITE_13: ds 4
+NGN_SPRITE_14: ds 4
+NGN_SPRITE_15: ds 4
+NGN_SPRITE_16: ds 4
+NGN_SPRITE_17: ds 4
+NGN_SPRITE_18: ds 4
+NGN_SPRITE_19: ds 4
+NGN_SPRITE_20: ds 4
+NGN_SPRITE_21: ds 4
+NGN_SPRITE_22: ds 4
+NGN_SPRITE_23: ds 4
+NGN_SPRITE_24: ds 4
+NGN_SPRITE_25: ds 4
+NGN_SPRITE_26: ds 4
+NGN_SPRITE_27: ds 4
+NGN_SPRITE_28: ds 4
+NGN_SPRITE_29: ds 4
+NGN_SPRITE_30: ds 4
+NGN_SPRITE_31: ds 4
+
+
+
+; -----------------------------------------------------------------------
+; Descompresion RLE
+; -----------------------------------------------------------------------
+
+NGN_RANDOM_SEED: ds 1
+
+
+
+; -----------------------------------------------------------------------
+; Descompresion RLE
+; -----------------------------------------------------------------------
+
+; Gestion de la descompresion RLE
+NGN_RLE_NORMAL_SIZE: ds 2
+NGN_RLE_COMPRESSED_SIZE: ds 2
+NGN_RLE_POINTER: ds 2
+; Buffer de RAM
+NGN_RAM_BUFFER: ds 2048
+
+
+
+;***********************************************************
+; Fin del archivo
+;***********************************************************
+NGN_VARS_EOF:
\ No newline at end of file
diff --git a/lib_source/ngn_template.asm b/lib_source/ngn_template.asm
new file mode 100644
index 0000000..675e3b5
--- /dev/null
+++ b/lib_source/ngn_template.asm
@@ -0,0 +1,101 @@
+;***********************************************************
+;
+; NGN TEMPLATE para ASMSX
+; ASM Z80 MSX
+;
+; (cc)2018 Cesar Rincon "NightFox"
+; http://www.nightfoxandco.com
+;
+;***********************************************************
+
+
+
+
+
+;***********************************************************
+; Directivas para el compilador
+;***********************************************************
+
+; ----------------------------------------------------------
+; Definicion de variables [PAGE 3] $C000
+; ----------------------------------------------------------
+; Almacena las variables en la pagina 3 (Comentar si no es una ROM)
+.PAGE 3
+.INCLUDE "ngn/ngn_vars.asm"
+
+
+
+; ----------------------------------------------------------
+; Otras directivas
+; ----------------------------------------------------------
+
+.PAGE 1 ; Selecciona la pagina 1 [$4000] (Codigo del programa)
+.BIOS ; Nombres de las llamadas a BIOS
+.ROM ; Se creara el binario en formato ROM de hasta 32kb
+.START PROGRAM_START_ADDRESS ; Indicale al compilador donde empieza el programa
+.db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; 12 ceros para completar la cabecera de la ROM
+
+
+
+;***********************************************************
+; Programa
+;***********************************************************
+
+PROGRAM_START_ADDRESS:
+
+ ; ----------------------------------------------------------
+ ; Punto de incicio
+ ; ----------------------------------------------------------
+
+ .SEARCH ; Busca un punto de inicio valido
+
+
+ ; ----------------------------------------------------------
+ ; Ejecuta el programa
+ ; ----------------------------------------------------------
+
+ ; Ejecuta el programa
+ jp FUNCTION_MAIN
+
+ ; Punto final del programa
+ ret
+
+
+ ; ----------------------------------------------------------
+ ; Definicion de constantes
+ ; ----------------------------------------------------------
+
+ .INCLUDE "ngn/ngn_consts.asm" ; Constantes de N'gine
+
+
+
+ ; ----------------------------------------------------------
+ ; Codigo principal
+ ; ----------------------------------------------------------
+
+ ; Archivo principal
+ .INCLUDE "prog/main.asm"
+
+
+
+ ; ----------------------------------------------------------
+ ; Libreria N'gine
+ ; ----------------------------------------------------------
+
+ .INCLUDE "ngn/ngn.asm"
+
+
+
+ ; ----------------------------------------------------------
+ ; Datos del programa
+ ; ----------------------------------------------------------
+
+ ; Textos del programa
+ .INCLUDE "data/text.asm"
+
+
+
+;***********************************************************
+; Fin del archivo
+;***********************************************************
+NGN_TEMPLATE_EOF:
\ No newline at end of file
diff --git a/lib_source/prog/main.asm b/lib_source/prog/main.asm
new file mode 100644
index 0000000..b1a57bc
--- /dev/null
+++ b/lib_source/prog/main.asm
@@ -0,0 +1,77 @@
+;***********************************************************
+;
+; NGN TEMPLATE para ASMSX
+; ASM Z80 MSX
+;
+; Archivo principal
+;
+; (cc)2018 Cesar Rincon "NightFox"
+; http://www.nightfoxandco.com
+;
+;***********************************************************
+
+
+
+; ----------------------------------------------------------
+; Funcion principal
+; ----------------------------------------------------------
+
+FUNCTION_MAIN:
+
+ ; Inicializaciones
+ call NGN_START ; Inicia la libreria NGN
+
+ ; Pon la VDP en MODO SCR0 / 40 columnas
+ ld bc, $0F04 ; Color de frente/fondo
+ ld de, $0128 ; Color de bore/ancho en columnas (40)
+ call NGN_SCREEN_SET_MODE_0
+
+ ; Ejecuta la rutina [DISSCR] para deshabilitar la pantalla
+ call $0041
+ ; Borra la pantalla
+ call NGN_TEXT_CLS
+ ; Hello world!
+ ld hl, TEXT_HELLO_WORLD ; Apunta al texto a mostrar
+ call NGN_TEXT_PRINT ; E imprimelo en pantalla
+ ; Ejecuta la rutina [ENASCR] para habilitar la pantalla
+ call $0044
+
+ ; Espera a que se pulse una tecla para salir
+ @@LOOP:
+
+ call NGN_KEYBOARD_READ ; Lee el teclado
+
+ ld a, [NGN_KEY_ANY] ; Lee el estado de "Cualquier tecla"
+ and $02 ; Estado "PRESS"
+ jr nz, FUNCTION_EXIT ; Si se ha pulsado, sal del bucle
+
+ halt ; Espera a la interrupcion del VDP
+
+ jr @@LOOP ; Repite el bucle
+
+
+
+; Fin del programa
+FUNCTION_EXIT:
+
+ ; Ejecuta la rutina [DISSCR] para deshabilitar la pantalla
+ call $0041
+ ; Borra la pantalla
+ call NGN_TEXT_CLS
+ ; Texto de reinicio
+ ld hl, $0F0B ; Posicion del cursor de texto [XXYY]
+ call NGN_TEXT_POSITION ; Posiciona el cursor
+ ld hl, TEXT_RESTART ; Apunta al texto a mostrar
+ call NGN_TEXT_PRINT ; E imprimelo en pantalla
+ ; Ejecuta la rutina [ENASCR] para habilitar la pantalla
+ call $0044
+
+ ; Reinicia el MSX en caso de que pase algo fuera de lo comun y se salga del programa (o se haya pulsado la tecla de salir)
+ call $0000 ; (CHKRAM)
+
+
+
+;***********************************************************
+; Fin del archivo
+;***********************************************************
+MAIN_EOF:
\ No newline at end of file
diff --git a/tools_source/ngn_msx_sprites/NGN_MSX_Sprites.cbp b/tools_source/ngn_msx_sprites/NGN_MSX_Sprites.cbp
new file mode 100644
index 0000000..d40e696
--- /dev/null
+++ b/tools_source/ngn_msx_sprites/NGN_MSX_Sprites.cbp
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tools_source/ngn_msx_sprites/source/bmp.c b/tools_source/ngn_msx_sprites/source/bmp.c
new file mode 100644
index 0000000..fe3a746
--- /dev/null
+++ b/tools_source/ngn_msx_sprites/source/bmp.c
@@ -0,0 +1,236 @@
+/*
+-------------------------------------------------------------------------------
+ MSX Sprite to VRAM converter
+ Genera desde una imagen las tablas de SPRITE.
+ (cc)2015-2018 by Cesar Rincon "NightFox"
+ http://www.nightfoxandco.com
+ Version 0.1.0-a
+-------------------------------------------------------------------------------
+*/
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Includes
+-------------------------------------------------------------------------------
+*/
+
+#include
+#include
+#include
+
+#include "defines.h"
+#include "bmp.h"
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Carga el archivo BIPMAP y conviertelo a RAW
+-------------------------------------------------------------------------------
+*/
+
+// Funcion NF_LoadBMP();
+s32 LoadBitmap(const char* file) {
+
+ // Buffers locales
+ u8* buffer; // Buffer temporal
+ buffer = NULL;
+ u8* palette; // Paleta (requerida por algun modo)
+ palette = NULL;
+
+ // Magic ID
+ char magic_id[4];
+ memset(magic_id, 0, 4);
+
+ // Define la estructura para almacenar la cabecera del BMP
+ typedef struct {
+ u32 bmp_size; // Tamaņo en bytes del BMP
+ u16 res_a; // Reservado
+ u16 res_b; // Reservado
+ u32 offset; // Offset donde empiezan los datos
+ u32 header_size; // Tamaņo de la cabecera (40 bytes)
+ u32 bmp_width; // Ancho de la imagen en pixeles
+ u32 bmp_height; // Altura de la imagen en pixeles
+ u16 color_planes; // Numero de planos de color
+ u16 bpp; // Numero de bits por pixel
+ u32 compression; // Compresion usada
+ u32 raw_size; // Tamaņo de los datos en RAW despues de la cabecera
+ u32 dpi_hor; // Puntos por pulgada (horizontal)
+ u32 dpi_ver; // Puntos por pulgada (vertical)
+ u32 pal_colors; // Numero de colores en la paleta
+ u32 imp_colors; // Colores importantes
+ } bmp_header_info;
+ bmp_header_info bmp_header;
+
+ // Pon todos los bytes de la estructura a 0
+ memset(&bmp_header, 0, sizeof(bmp_header));
+
+ // Declara los punteros a los ficheros
+ FILE* file_id;
+
+ // Carga el archivo .BMP
+ file_id = fopen(file, "rb");
+
+ if (file_id) { // Si el archivo existe...
+ // Posicionate en el byte 0
+ fseek(file_id, 0, SEEK_SET);
+ // Lee el Magic String del archivo BMP (2 primeros Bytes, "BM") / (0x00 - 0x01)
+ fread(magic_id, 1, 2, file_id);
+ // Si es un archivo BMP... (Magic string == "BM")
+ if (strcmp(magic_id, "BM") == 0) {
+ // Posicionate en el byte 2
+ fseek(file_id, 2, SEEK_SET);
+ // Lee la cabecera del archivo BMP (0x02 - 0x36)
+ fread((void*)&bmp_header, 1, sizeof(bmp_header), file_id);
+ /////////////////////////////////////////////////////////////
+ // Es un archivo BMP valido, cargalo en un buffer temporal //
+ /////////////////////////////////////////////////////////////
+ // Crea un buffer temporal
+ buffer = (u8*) calloc (bmp_header.raw_size, sizeof(u8));
+ if (buffer == NULL) {
+ printf("No se ha podido crear el buffer temporal para la imagen.\nError critico.\n");
+ free(buffer);
+ buffer = NULL;
+ free(palette);
+ palette = NULL;
+ return -1;
+ }
+ // Si se ha creado con exito, carga el archivo al buffer
+ fseek(file_id, bmp_header.offset, SEEK_SET);
+ fread(buffer, 1, bmp_header.raw_size, file_id);
+ } else {
+ // No es un archivo BMP valido
+ printf("El archivo %s no es un BMP valido.\nError critico.\n", file);
+ free(buffer);
+ buffer = NULL;
+ free(palette);
+ palette = NULL;
+ return -1;
+ }
+ } else {
+ // El archivo no existe
+ printf("El archivo %s no existe.\nError critico.\n", file);
+ free(buffer);
+ buffer = NULL;
+ free(palette);
+ palette = NULL;
+ return -1;
+ }
+ // Cierra el archivo
+ fclose(file_id);
+
+ // Variables que se usaran a partir de aqui
+ u32 x = 0; // Coordemada X
+ u32 y = 0; // Coordenada Y
+ u32 idx = 0; // Indice en el buffer temporal
+ u32 offset = 0; // Indice en el buffer de destino
+ u16 colors = 0; // En 8 bits, numero de colores
+ u32 size = 0; // Tamaņo del buffer (en bytes)
+
+ // Analiza la imagen y guarda los parametros de la misma
+ img.width = bmp_header.bmp_width;
+ img.height = bmp_header.bmp_height;
+
+ // Segun el ancho, decide si es 8x8 o 16x16
+ if ((img.width != 8) && (img.width != 16)) {
+ printf("Tamaņo ilegal de imagen.\nSe requiere una imagen de 8x8 o 16x16 pixeles.\n");
+ free(buffer);
+ buffer = NULL;
+ free(palette);
+ palette = NULL;
+ return -1;
+ } else {
+ img.format = img.width;
+ // Ahora, calcula el numero de frames de este sprite
+ if ((img.height % img.format) != 0) {
+ printf("Tamaņo ilegal de imagen.\nSe requiere una imagen de 8x8 o 16x16 pixeles.\n");
+ free(buffer);
+ buffer = NULL;
+ free(palette);
+ palette = NULL;
+ return -1;
+ } else {
+ img.frames = (int)(img.height / img.format);
+ }
+ }
+ // Habilita el buffer de destino (u8 de alto x ancho del tamaņo de imagen)
+ size = (bmp_header.bmp_width * bmp_header.bmp_height);
+ img.data = (u8*) calloc (size, sizeof(u8));
+ if (img.data == NULL) {
+ printf("No se ha podido crear el buffer de datos para la imagen.\nError critico.\n");
+ free(buffer);
+ buffer = NULL;
+ free(palette);
+ palette = NULL;
+ return -1;
+ }
+
+ // Segun los BITS por Pixel (8, 16, 24)
+ switch (bmp_header.bpp) {
+
+ case 8: // 8 bits por pixel
+ // Calcula el tamaņo de la paleta
+ colors = ((bmp_header.offset - 0x36) >> 2);
+ palette = (u8*) calloc ((colors << 2), sizeof(u8));
+ if (palette == NULL) {
+ printf("No se ha podido crear el buffer para la paleta.\nError critico.\n");
+ free(buffer);
+ buffer = NULL;
+ free(palette);
+ palette = NULL;
+ return -1;
+ }
+ // Abre de nuevo el archivo y carga la paleta
+ file_id = fopen(file, "rb");
+ if (!file_id) {
+ printf("El archivo %s no existe.\nError critico.\n", file);
+ free(buffer);
+ buffer = NULL;
+ free(palette);
+ palette = NULL;;
+ return -1;
+ }
+ fseek(file_id, 0x36, SEEK_SET);
+ fread(palette, 1, (colors << 2), file_id);
+ fclose(file_id);
+ // Convierte el archivo a RAW de 8 bits
+ for (y = 0; y < bmp_header.bmp_height; y ++) {
+ for (x = 0; x < bmp_header.bmp_width; x ++) {
+ // Calcula los offsets
+ offset = ((((bmp_header.bmp_height - 1) - y) * bmp_header.bmp_width) + x);
+ // Guarda el pixel del buffer en img_data
+ img.data[offset] = buffer[idx];
+ // Siguiente pixel
+ idx ++;
+ }
+ // Ajusta la alineacion a 4 bytes al final de linea
+ while ((idx % 4) != 0) idx ++;
+ }
+ // Elimina la paleta de la RAM
+ free(palette);
+ palette = NULL;
+ break;
+
+ default:
+ printf("La imagen no esta indexada.\nError critico.\n");
+ free(buffer);
+ buffer = NULL;
+ free(palette);
+ palette = NULL;
+ return -1;
+ break;
+
+ }
+
+
+ // Libera el buffer temporal
+ free(buffer);
+ buffer = NULL;
+
+
+ // Devuelve el puntero al buffer de datos
+ return 0;
+
+}
diff --git a/tools_source/ngn_msx_sprites/source/bmp.h b/tools_source/ngn_msx_sprites/source/bmp.h
new file mode 100644
index 0000000..9f94fa3
--- /dev/null
+++ b/tools_source/ngn_msx_sprites/source/bmp.h
@@ -0,0 +1,37 @@
+/*
+-------------------------------------------------------------------------------
+ MSX Sprite to VRAM converter
+ Genera desde una imagen las tablas de SPRITE.
+ (cc)2015-2018 by Cesar Rincon "NightFox"
+ http://www.nightfoxandco.com
+ Version 0.1.0-a
+-------------------------------------------------------------------------------
+*/
+
+
+
+#ifndef BMP_H_INCLUDED
+#define BMP_H_INCLUDED
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Includes
+-------------------------------------------------------------------------------
+*/
+
+#include "defines.h"
+
+
+/*
+-------------------------------------------------------------------------------
+ Carga el archivo BIPMAP y conviertelo a RAW
+-------------------------------------------------------------------------------
+*/
+
+extern s32 LoadBitmap(const char* file);
+
+
+
+#endif // BMP_H_INCLUDED
diff --git a/tools_source/ngn_msx_sprites/source/defines.c b/tools_source/ngn_msx_sprites/source/defines.c
new file mode 100644
index 0000000..45c5a07
--- /dev/null
+++ b/tools_source/ngn_msx_sprites/source/defines.c
@@ -0,0 +1,58 @@
+/*
+-------------------------------------------------------------------------------
+ MSX Sprite to VRAM converter
+ Genera desde una imagen las tablas de SPRITE.
+ (cc)2015-2018 by Cesar Rincon "NightFox"
+ http://www.nightfoxandco.com
+ Version 0.1.0-a
+-------------------------------------------------------------------------------
+*/
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Includes
+-------------------------------------------------------------------------------
+*/
+
+
+#include
+#include
+#include
+
+#include "defines.h"
+
+
+
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Variables globales
+-------------------------------------------------------------------------------
+*/
+
+img_info img;
+
+
+
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Limpia los buffers
+-------------------------------------------------------------------------------
+*/
+
+void CleanBuffers(void) {
+
+ free(img.data);
+ img.data = NULL;
+
+ free(img.tiles);
+ img.tiles = NULL;
+
+}
diff --git a/tools_source/ngn_msx_sprites/source/defines.h b/tools_source/ngn_msx_sprites/source/defines.h
new file mode 100644
index 0000000..e6288f4
--- /dev/null
+++ b/tools_source/ngn_msx_sprites/source/defines.h
@@ -0,0 +1,77 @@
+/*
+-------------------------------------------------------------------------------
+ MSX Sprite to VRAM converter
+ Genera desde una imagen las tablas de SPRITE.
+ (cc)2015-2018 by Cesar Rincon "NightFox"
+ http://www.nightfoxandco.com
+ Version 0.1.0-a
+-------------------------------------------------------------------------------
+*/
+
+
+
+#ifndef DEFINES_H_INCLUDED
+#define DEFINES_H_INCLUDED
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Definicion de tipos
+-------------------------------------------------------------------------------
+*/
+
+typedef signed char s8;
+typedef unsigned char u8;
+typedef signed short s16;
+typedef unsigned short u16;
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef unsigned char bool;
+#define true 1
+#define false 0
+
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Variables globales
+-------------------------------------------------------------------------------
+*/
+
+typedef struct {
+
+ u32 width; // Ancho de la imagen
+ u32 height; // Alto de la imagen
+
+ u32 format; // Formato del Sprite (8x8 o 16x16)
+ u32 frames; // nē de frames (si los hay)
+
+ u8* data; // Datos de la imagen
+ u8* tiles; // Tiles en bruto
+
+ u32 tiles_size_normal;
+
+ bool sz; // Flag de generacion de info del tamaņo
+ bool inc; // Flag de generacion de archivo de .INCLUDE
+
+} img_info;
+
+extern img_info img; // Guarda la imagen cargada y su informacion
+
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Limpia los buffers
+-------------------------------------------------------------------------------
+*/
+
+extern void CleanBuffers(void);
+
+
+
+#endif // DEFINES_H_INCLUDED
diff --git a/tools_source/ngn_msx_sprites/source/filesystem.c b/tools_source/ngn_msx_sprites/source/filesystem.c
new file mode 100644
index 0000000..9a9e999
--- /dev/null
+++ b/tools_source/ngn_msx_sprites/source/filesystem.c
@@ -0,0 +1,160 @@
+/*
+-------------------------------------------------------------------------------
+ MSX Sprite to VRAM converter
+ Genera desde una imagen las tablas de SPRITE.
+ (cc)2015-2018 by Cesar Rincon "NightFox"
+ http://www.nightfoxandco.com
+ Version 0.1.0-a
+-------------------------------------------------------------------------------
+*/
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Includes
+-------------------------------------------------------------------------------
+*/
+
+#include
+#include
+#include
+
+#include "defines.h"
+#include "filesystem.h"
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Graba los datos a los archivos (Normal)
+-------------------------------------------------------------------------------
+*/
+
+s32 SaveFile (const char* filename) {
+
+ // Variables
+ u32 l = 0;
+ u8 hi = 0, lo = 0;
+ char fnam[256];
+ char output[256];
+ char txt[32];
+ char name[256];
+ u32 n = 0;
+ char lt;
+ u32 filesize = 0;
+ u32 tiles_num = 0;
+ u32 tiles_temp = 4;
+
+ // Genera un nombre base para el archivo
+ for (n = 0; n < (strlen(filename) - 4); n ++) {
+ lt = filename[n];
+ if (lt >= 65 && lt <= 90) lt += 32;
+ name[n] = lt;
+ }
+ name[n] = '\0';
+
+ // Fase 3, genera el archivo codificado
+ if (img.inc) {
+ sprintf(fnam, "%s.inc", name);
+ } else {
+ sprintf(fnam, "%s.asm", name);
+ }
+ FILE* file = fopen(fnam, "wb");
+
+ // Genera un nombre base para las etiquetas
+ for (n = 0; n < (strlen(filename) - 4); n ++) {
+ lt = filename[n];
+ if (lt >= 97 && lt <= 122) lt -= 32;
+ name[n] = lt;
+ }
+ name[n] = '\0';
+
+ // Si se puede crear el archivo...
+ if (file != NULL) {
+
+ // Cabecera del archivo
+ if (img.sz) filesize = 2;
+ filesize += img.tiles_size_normal;
+ sprintf(output, ";************************************************************\n");
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, ";* Imagen convertida para MSX - SCREEN 2\n");
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, ";* Archivo de origen: %s\n", filename);
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, ";* Tamaņo: %02dx%02d pixeles\n", img.format, img.format);
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, ";* Nē de frames: %02d\n", img.frames);
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, ";* Total de datos: %d bytes\n", filesize);
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, ";************************************************************\n\n\n");
+ fwrite(output, strlen(output), 1, file);
+
+ // Etiqueta general
+ sprintf(output, "%s_SPRITE:\n\n", name);
+ fwrite(output, strlen(output), 1, file);
+
+ // Genera los CHR del sprite
+ printf("Grabando datos del SPRITE ");
+
+
+ if (img.sz) {
+ // Genera los bytes de tamaņo
+ sprintf(output, "; Tamaņo:\n");
+ fwrite(output, strlen(output), 1, file);
+ hi = (img.tiles_size_normal >> 8) & 0xff;
+ lo = (img.tiles_size_normal & 0xff);
+ sprintf(output, "db $%02x, $%02x\n", hi, lo);
+ fwrite(output, strlen(output), 1, file);
+ }
+
+ for (n = 0; n < img.tiles_size_normal; n += 8) {
+ // Contador de frames
+ if (img.format == 8) {
+ sprintf(output, "; CHR: %02d\n", tiles_num);
+ fwrite(output, strlen(output), 1, file);
+ tiles_num ++;
+ } else {
+ tiles_temp ++;
+ if (tiles_temp >= 4) {
+ sprintf(output, "; CHR: %02d\n", (tiles_num * 4));
+ fwrite(output, strlen(output), 1, file);
+ tiles_num ++;
+ tiles_temp = 0;
+ }
+ }
+ // Tiles
+ sprintf(output, "db ");
+ // Lineas
+ for (l = 0; l < 8; l ++) { // Linea
+ if (l != 7) {
+ sprintf(txt, "$%02x, ", img.tiles[(n + l)]);
+ } else {
+ sprintf(txt, "$%02x\n", img.tiles[(n + l)]);
+ }
+ strcat(output, txt);
+ }
+ // Guarda la info
+ printf(".");
+ fwrite(output, strlen(output), 1, file);
+ }
+
+ // Fin del archivo
+ sprintf(output, "\n");
+ fwrite(output, strlen(output), 1, file);
+ printf(" ok\n\n");
+
+ } else {
+
+ printf("No se puede generar el archivo.\n");
+ return -1;
+
+ }
+
+ // Cierra el archivo
+ fclose(file);
+
+ return 0;
+
+}
diff --git a/tools_source/ngn_msx_sprites/source/filesystem.h b/tools_source/ngn_msx_sprites/source/filesystem.h
new file mode 100644
index 0000000..f77bb00
--- /dev/null
+++ b/tools_source/ngn_msx_sprites/source/filesystem.h
@@ -0,0 +1,39 @@
+/*
+-------------------------------------------------------------------------------
+ MSX Sprite to VRAM converter
+ Genera desde una imagen las tablas de SPRITE.
+ (cc)2015-2018 by Cesar Rincon "NightFox"
+ http://www.nightfoxandco.com
+ Version 0.1.0-a
+-------------------------------------------------------------------------------
+*/
+
+
+
+#ifndef FILESYSTEM_H_INCLUDED
+#define FILESYSTEM_H_INCLUDED
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Includes
+-------------------------------------------------------------------------------
+*/
+
+#include "defines.h"
+
+
+/*
+-------------------------------------------------------------------------------
+ Graba los datos a los archivos
+-------------------------------------------------------------------------------
+*/
+
+s32 SaveFile (const char* filename);
+
+
+
+
+
+#endif // FILESYSTEM_H_INCLUDED
diff --git a/tools_source/ngn_msx_sprites/source/main.c b/tools_source/ngn_msx_sprites/source/main.c
new file mode 100644
index 0000000..070e49b
--- /dev/null
+++ b/tools_source/ngn_msx_sprites/source/main.c
@@ -0,0 +1,103 @@
+/*
+-------------------------------------------------------------------------------
+ MSX Sprite to VRAM converter
+ Genera desde una imagen las tablas de SPRITE.
+ (cc)2015-2018 by Cesar Rincon "NightFox"
+ http://www.nightfoxandco.com
+ Version 0.1.0-a
+-------------------------------------------------------------------------------
+*/
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Includes
+-------------------------------------------------------------------------------
+*/
+
+#include
+#include
+#include
+
+#include "defines.h"
+#include "bmp.h"
+#include "tiles.h"
+#include "filesystem.h"
+
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Archivo MAIN
+-------------------------------------------------------------------------------
+*/
+
+int main(int argc, char *argv[]) {
+
+ // Variables
+ u8 param = argc;
+ s32 n = 0;
+
+ // Mensage de Bienvenida
+ printf("\n\nConversor de imagenes BMP a formato SPRITE para MSX.\nVersion 0.1.0-a.\n(cc)2015-2018 por Cesar Rincon.\nhttp://www.nightfoxandco.com\n\n\n");
+
+ // Inicializa las estructuras
+ memset(&img, 0, sizeof(img));
+
+ if (argc > 2) {
+ for (n = 2; n < argc; n ++) {
+ // Busca coincidencias en los parametros
+ if (strcmp(argv[n], "-size") == 0) {
+ img.sz = true;
+ param --;
+ } else if (strcmp(argv[n], "-inc") == 0) {
+ img.inc = true;
+ param --;
+ }
+ }
+ }
+
+ // Error en la linea de comandos
+ if (param != 2) {
+ printf("Uso: %s archivo.bmp [-rle][-size][-inc]\n\n", argv[0]);
+ printf(" -size Aņade al archivo la informacion del tamaņo de los datos\n");
+ printf(" -inc Genera el archivo con la extension .INC\n\n");
+ CleanBuffers();
+ return -1;
+ }
+
+
+ // Carga el archivo BITMAP
+ if (LoadBitmap(argv[1]) == -1) {
+ printf("Error al procesar el archivo BITMAP.\n");
+ CleanBuffers();
+ return -1;
+ }
+ printf("Imagen de %dx%d pixeles cargada con exito.\n\n", img.width, img.height);
+
+ // Procesa el archivo
+ if (GenerateTiles() == -1) {
+ printf("Error al procesar los datos.\n");
+ CleanBuffers();
+ return -1;
+ }
+
+ // Genera y guarda el fichero
+ if (SaveFile(argv[1]) == -1) {
+ printf("Error al grabar el archivo.\n");
+ CleanBuffers();
+ return -1;
+ }
+ if (img.inc) {
+ printf("Archivo .INC generado con exito.\n\n");
+ } else {
+ printf("Archivo .ASM generado con exito.\n\n");
+ }
+
+
+ // Sal del programa
+ return 0;
+
+}
diff --git a/tools_source/ngn_msx_sprites/source/tiles.c b/tools_source/ngn_msx_sprites/source/tiles.c
new file mode 100644
index 0000000..5ff87e1
--- /dev/null
+++ b/tools_source/ngn_msx_sprites/source/tiles.c
@@ -0,0 +1,178 @@
+/*
+-------------------------------------------------------------------------------
+ MSX Sprite to VRAM converter
+ Genera desde una imagen las tablas de SPRITE.
+ (cc)2015-2018 by Cesar Rincon "NightFox"
+ http://www.nightfoxandco.com
+ Version 0.1.0-a
+-------------------------------------------------------------------------------
+*/
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Includes
+-------------------------------------------------------------------------------
+*/
+
+#include
+#include
+#include
+
+#include "defines.h"
+#include "tiles.h"
+
+
+/*
+-------------------------------------------------------------------------------
+ Analiza los datos y genera el archivo tileset
+-------------------------------------------------------------------------------
+*/
+
+s32 GenerateTiles(void) {
+
+ // Variables
+ s32 n = 0;
+ s32 i = 0;
+ s32 img_size = (img.width * img.height);
+ s32 buffer_size = (img_size / 8);
+
+ // Crea los buffers para las tablas de pattern del Sprite
+ // (Asume que todos los tiles son unicos)
+ img.tiles = (u8*) calloc(buffer_size, sizeof(u8));
+ if (img.tiles == NULL) {
+ printf("No se ha podido crear el buffer para los tiles.\nError critico.\n");
+ CleanBuffers();
+ }
+
+
+ // Analisis del RAW
+ u32 src_offset = 0;
+ u32 dst_offset = 0;
+ u8 pixel = 0;
+ u8 encode = 0;
+ u32 tile_num = 0;
+ u32 last_tile = 0;
+ u32 temp_tile = 0;
+ u8 idx = 0;
+
+ // Copia la informacion de la imagen en el formato correcto de tiles
+ if (img.format == 8) {
+ printf("Codificando Sprite de 8x8...\n\n");
+ // Formato 8x8
+ for (n = 0; n < img_size; n += 8) {
+ encode = 0;
+ idx = 0;
+ tile_num = ((int)(n / 64));
+ if (tile_num != last_tile) {
+ last_tile = tile_num;
+ printf("\n");
+ }
+ printf("T: %03d ", tile_num);
+ for (i = n; i < (n + 8); i ++) {
+ pixel = img.data[i] & 0x0f; // Adquiere el color del pixel
+ // Si el pixel no es transparente
+ if (pixel != 0x0f) {
+ // Codifica esta BIT
+ encode |= (1 << (7 - idx));
+ printf("Û");
+ } else {
+ printf(" ");
+ }
+ idx ++;
+ }
+ printf("\n");
+ // Guarda el valor de la fila del tile
+ img.tiles[dst_offset] = encode;
+ dst_offset ++;
+ }
+ printf("\n");
+
+ } else {
+
+ printf("Codificando Sprite de 16x16...\n\n");
+
+ // Formato 16x16
+ for (src_offset = 0 ; src_offset < img_size; src_offset += 256) {
+
+ // Filas bloques 0 y 1
+ for (n = src_offset; n < (src_offset + 256); n += 16) {
+ // Columnas bloques 0 y 1
+ encode = 0;
+ idx = 0;
+ if (tile_num != last_tile) {
+ last_tile = tile_num;
+ printf("\n");
+ }
+ printf("T: %03d ", tile_num);
+ for (i = n; i < (n + 8); i ++) {
+ pixel = img.data[i] & 0x0f; // Adquiere el color del pixel
+ // Si el pixel no es transparente
+ if (pixel != 0x0f) {
+ // Codifica esta BIT
+ encode |= (1 << (7 - idx));
+ printf("Û");
+ } else {
+ printf(" ");
+ }
+ idx ++;
+ }
+ printf("\n");
+ // Guarda el valor de la fila del tile
+ img.tiles[dst_offset] = encode;
+ dst_offset ++;
+ temp_tile ++;
+ if (temp_tile >= 8) {
+ temp_tile = 0;
+ tile_num ++;
+ }
+ }
+
+ // Filas bloques 2 y 3
+ temp_tile = 0;
+ for (n = src_offset; n < (src_offset + 256); n += 16) {
+ // Columnas bloques 2 y 3
+ encode = 0;
+ idx = 0;
+ if (tile_num != last_tile) {
+ last_tile = tile_num;
+ printf("\n");
+ }
+ printf("T: %03d ", tile_num);
+ for (i = (n + 8); i < (n + 16); i ++) {
+ pixel = img.data[i] & 0x0f; // Adquiere el color del pixel
+ // Si el pixel no es transparente
+ if (pixel != 0x0f) {
+ // Codifica esta BIT
+ encode |= (1 << (7 - idx));
+ printf("Û");
+ } else {
+ printf(" ");
+ }
+ idx ++;
+ }
+ printf("\n");
+ // Guarda el valor de la fila del tile
+ img.tiles[dst_offset] = encode;
+ dst_offset ++;
+ temp_tile ++;
+ if (temp_tile >= 8) {
+ temp_tile = 0;
+ tile_num ++;
+ }
+ }
+
+ }
+ printf("\n");
+
+ }
+
+
+ printf("\nCodificacion finalizada.\n\n");
+
+ img.tiles_size_normal = dst_offset;
+
+ return 0;
+
+}
diff --git a/tools_source/ngn_msx_sprites/source/tiles.h b/tools_source/ngn_msx_sprites/source/tiles.h
new file mode 100644
index 0000000..e38297d
--- /dev/null
+++ b/tools_source/ngn_msx_sprites/source/tiles.h
@@ -0,0 +1,38 @@
+/*
+-------------------------------------------------------------------------------
+ MSX Sprite to VRAM converter
+ Genera desde una imagen las tablas de SPRITE.
+ (cc)2015-2018 by Cesar Rincon "NightFox"
+ http://www.nightfoxandco.com
+ Version 0.1.0-a
+-------------------------------------------------------------------------------
+*/
+
+
+
+#ifndef TILES_H_INCLUDED
+#define TILES_H_INCLUDED
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Includes
+-------------------------------------------------------------------------------
+*/
+
+#include "defines.h"
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Analiza los datos y genera los tiles
+-------------------------------------------------------------------------------
+*/
+
+s32 GenerateTiles(void);
+
+
+
+#endif // TILES_H_INCLUDED
diff --git a/tools_source/ngn_msx_tiles/NGN_MSX_Tiles.cbp b/tools_source/ngn_msx_tiles/NGN_MSX_Tiles.cbp
new file mode 100644
index 0000000..f937711
--- /dev/null
+++ b/tools_source/ngn_msx_tiles/NGN_MSX_Tiles.cbp
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tools_source/ngn_msx_tiles/source/bmp.c b/tools_source/ngn_msx_tiles/source/bmp.c
new file mode 100644
index 0000000..0829416
--- /dev/null
+++ b/tools_source/ngn_msx_tiles/source/bmp.c
@@ -0,0 +1,222 @@
+/*
+-------------------------------------------------------------------------------
+ MSX Image to VRAM converter
+ Genera desde una imagen las tablas de PATTERN, COLOR & NAME
+ para usarlas en el modo SCREEN 2.
+ (cc)2015-2018 by Cesar Rincon "NightFox"
+ http://www.nightfoxandco.com
+ Version 0.1.0-a
+-------------------------------------------------------------------------------
+*/
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Includes
+-------------------------------------------------------------------------------
+*/
+
+#include
+#include
+#include
+
+#include "defines.h"
+#include "bmp.h"
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Carga el archivo BIPMAP y conviertelo a RAW
+-------------------------------------------------------------------------------
+*/
+
+// Funcion NF_LoadBMP();
+s32 LoadBitmap(const char* file) {
+
+ // Buffers locales
+ u8* buffer; // Buffer temporal
+ buffer = NULL;
+ u8* palette; // Paleta (requerida por algun modo)
+ palette = NULL;
+
+ // Magic ID
+ char magic_id[4];
+ memset(magic_id, 0, 4);
+
+ // Define la estructura para almacenar la cabecera del BMP
+ typedef struct {
+ u32 bmp_size; // Tamaņo en bytes del BMP
+ u16 res_a; // Reservado
+ u16 res_b; // Reservado
+ u32 offset; // Offset donde empiezan los datos
+ u32 header_size; // Tamaņo de la cabecera (40 bytes)
+ u32 bmp_width; // Ancho de la imagen en pixeles
+ u32 bmp_height; // Altura de la imagen en pixeles
+ u16 color_planes; // Numero de planos de color
+ u16 bpp; // Numero de bits por pixel
+ u32 compression; // Compresion usada
+ u32 raw_size; // Tamaņo de los datos en RAW despues de la cabecera
+ u32 dpi_hor; // Puntos por pulgada (horizontal)
+ u32 dpi_ver; // Puntos por pulgada (vertical)
+ u32 pal_colors; // Numero de colores en la paleta
+ u32 imp_colors; // Colores importantes
+ } bmp_header_info;
+ bmp_header_info bmp_header;
+
+ // Pon todos los bytes de la estructura a 0
+ memset(&bmp_header, 0, sizeof(bmp_header));
+
+ // Declara los punteros a los ficheros
+ FILE* file_id;
+
+ // Carga el archivo .BMP
+ file_id = fopen(file, "rb");
+
+ if (file_id) { // Si el archivo existe...
+ // Posicionate en el byte 0
+ fseek(file_id, 0, SEEK_SET);
+ // Lee el Magic String del archivo BMP (2 primeros Bytes, "BM") / (0x00 - 0x01)
+ fread(magic_id, 1, 2, file_id);
+ // Si es un archivo BMP... (Magic string == "BM")
+ if (strcmp(magic_id, "BM") == 0) {
+ // Posicionate en el byte 2
+ fseek(file_id, 2, SEEK_SET);
+ // Lee la cabecera del archivo BMP (0x02 - 0x36)
+ fread((void*)&bmp_header, 1, sizeof(bmp_header), file_id);
+ /////////////////////////////////////////////////////////////
+ // Es un archivo BMP valido, cargalo en un buffer temporal //
+ /////////////////////////////////////////////////////////////
+ // Crea un buffer temporal
+ buffer = (u8*) calloc (bmp_header.raw_size, sizeof(u8));
+ if (buffer == NULL) {
+ printf("No se ha podido crear el buffer temporal para la imagen.\nError critico.\n");
+ free(buffer);
+ buffer = NULL;
+ free(palette);
+ palette = NULL;
+ return -1;
+ }
+ // Si se ha creado con exito, carga el archivo al buffer
+ fseek(file_id, bmp_header.offset, SEEK_SET);
+ fread(buffer, 1, bmp_header.raw_size, file_id);
+ } else {
+ // No es un archivo BMP valido
+ printf("El archivo %s no es un BMP valido.\nError critico.\n", file);
+ free(buffer);
+ buffer = NULL;
+ free(palette);
+ palette = NULL;
+ return -1;
+ }
+ } else {
+ // El archivo no existe
+ printf("El archivo %s no existe.\nError critico.\n", file);
+ free(buffer);
+ buffer = NULL;
+ free(palette);
+ palette = NULL;
+ return -1;
+ }
+ // Cierra el archivo
+ fclose(file_id);
+
+ // Variables que se usaran a partir de aqui
+ u32 x = 0; // Coordemada X
+ u32 y = 0; // Coordenada Y
+ u32 idx = 0; // Indice en el buffer temporal
+ u32 offset = 0; // Indice en el buffer de destino
+ u16 colors = 0; // En 8 bits, numero de colores
+ u32 size = 0; // Tamaņo del buffer (en bytes)
+
+ // Guarda el tamaņo de la imagen
+ img.width = bmp_header.bmp_width;
+ img.height = bmp_header.bmp_height;
+ if ((img.width != 256) || (img.height != 192)) {
+ printf("Tamaņo ilegal de archivo.\nSe requiere una imagen de 256x192 pixeles.\n");
+ free(buffer);
+ buffer = NULL;
+ free(palette);
+ palette = NULL;
+ return -1;
+ }
+ // Habilita el buffer de destino (u8 de alto x ancho del tamaņo de imagen)
+ size = (bmp_header.bmp_width * bmp_header.bmp_height);
+ img.data = (u8*) calloc (size, sizeof(u8));
+ if (img.data == NULL) {
+ printf("No se ha podido crear el buffer de datos para la imagen.\nError critico.\n");
+ free(buffer);
+ buffer = NULL;
+ free(palette);
+ palette = NULL;
+ return -1;
+ }
+
+ // Segun los BITS por Pixel (8, 16, 24)
+ switch (bmp_header.bpp) {
+
+ case 8: // 8 bits por pixel
+ // Calcula el tamaņo de la paleta
+ colors = ((bmp_header.offset - 0x36) >> 2);
+ palette = (u8*) calloc ((colors << 2), sizeof(u8));
+ if (palette == NULL) {
+ printf("No se ha podido crear el buffer para la paleta.\nError critico.\n");
+ free(buffer);
+ buffer = NULL;
+ free(palette);
+ palette = NULL;
+ return -1;
+ }
+ // Abre de nuevo el archivo y carga la paleta
+ file_id = fopen(file, "rb");
+ if (!file_id) {
+ printf("El archivo %s no existe.\nError critico.\n", file);
+ free(buffer);
+ buffer = NULL;
+ free(palette);
+ palette = NULL;;
+ return -1;
+ }
+ fseek(file_id, 0x36, SEEK_SET);
+ fread(palette, 1, (colors << 2), file_id);
+ fclose(file_id);
+ // Convierte el archivo a RAW de 8 bits
+ for (y = 0; y < bmp_header.bmp_height; y ++) {
+ for (x = 0; x < bmp_header.bmp_width; x ++) {
+ // Calcula los offsets
+ offset = ((((bmp_header.bmp_height - 1) - y) * bmp_header.bmp_width) + x);
+ // Guarda el pixel del buffer en img_data
+ img.data[offset] = buffer[idx];
+ // Siguiente pixel
+ idx ++;
+ }
+ // Ajusta la alineacion a 4 bytes al final de linea
+ while ((idx % 4) != 0) idx ++;
+ }
+ // Elimina la paleta de la RAM
+ free(palette);
+ palette = NULL;
+ break;
+
+ default:
+ printf("La imagen no esta indexada.\nError critico.\n");
+ free(buffer);
+ buffer = NULL;
+ free(palette);
+ palette = NULL;
+ return -1;
+ break;
+
+ }
+
+
+ // Libera el buffer temporal
+ free(buffer);
+ buffer = NULL;
+
+
+ // Devuelve el puntero al buffer de datos
+ return 0;
+
+}
diff --git a/tools_source/ngn_msx_tiles/source/bmp.h b/tools_source/ngn_msx_tiles/source/bmp.h
new file mode 100644
index 0000000..77c2867
--- /dev/null
+++ b/tools_source/ngn_msx_tiles/source/bmp.h
@@ -0,0 +1,38 @@
+/*
+-------------------------------------------------------------------------------
+ MSX Image to VRAM converter
+ Genera desde una imagen las tablas de PATTERN, COLOR & NAME
+ para usarlas en el modo SCREEN 2.
+ (cc)2015-2018 by Cesar Rincon "NightFox"
+ http://www.nightfoxandco.com
+ Version 0.1.0-a
+-------------------------------------------------------------------------------
+*/
+
+
+
+#ifndef BMP_H_INCLUDED
+#define BMP_H_INCLUDED
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Includes
+-------------------------------------------------------------------------------
+*/
+
+#include "defines.h"
+
+
+/*
+-------------------------------------------------------------------------------
+ Carga el archivo BIPMAP y conviertelo a RAW
+-------------------------------------------------------------------------------
+*/
+
+extern s32 LoadBitmap(const char* file);
+
+
+
+#endif // BMP_H_INCLUDED
diff --git a/tools_source/ngn_msx_tiles/source/defines.c b/tools_source/ngn_msx_tiles/source/defines.c
new file mode 100644
index 0000000..6d324ac
--- /dev/null
+++ b/tools_source/ngn_msx_tiles/source/defines.c
@@ -0,0 +1,67 @@
+/*
+-------------------------------------------------------------------------------
+ MSX Image to VRAM converter
+ Genera desde una imagen las tablas de PATTERN, COLOR & NAME
+ para usarlas en el modo SCREEN 2.
+ (cc)2015-2018 by Cesar Rincon "NightFox"
+ http://www.nightfoxandco.com
+ Version 0.1.0-a
+-------------------------------------------------------------------------------
+*/
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Includes
+-------------------------------------------------------------------------------
+*/
+
+
+#include
+#include
+#include
+
+#include "defines.h"
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Variables globales
+-------------------------------------------------------------------------------
+*/
+
+img_info img;
+
+
+
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Limpia los buffers
+-------------------------------------------------------------------------------
+*/
+
+void CleanBuffers(void) {
+
+ free(img.data);
+ img.data = NULL;
+
+ int n = 0;
+ for (n = 0; n < 3; n ++) {
+ free(img.raw[n]);
+ img.raw[n] = NULL;
+ free(img.patterns[n]);
+ img.patterns[n] = NULL;
+ free(img.colors[n]);
+ img.colors[n] = NULL;
+ free(img.names[n]);
+ img.names[n] = NULL;
+ free(img.rle);
+ img.rle = NULL;
+ }
+
+}
diff --git a/tools_source/ngn_msx_tiles/source/defines.h b/tools_source/ngn_msx_tiles/source/defines.h
new file mode 100644
index 0000000..60bab1c
--- /dev/null
+++ b/tools_source/ngn_msx_tiles/source/defines.h
@@ -0,0 +1,89 @@
+/*
+-------------------------------------------------------------------------------
+ MSX Image to VRAM converter
+ Genera desde una imagen las tablas de PATTERN, COLOR & NAME
+ para usarlas en el modo SCREEN 2.
+ (cc)2015-2018 by Cesar Rincon "NightFox"
+ http://www.nightfoxandco.com
+ Version 0.1.0-a
+-------------------------------------------------------------------------------
+*/
+
+
+
+#ifndef DEFINES_H_INCLUDED
+#define DEFINES_H_INCLUDED
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Definicion de tipos
+-------------------------------------------------------------------------------
+*/
+
+typedef signed char s8;
+typedef unsigned char u8;
+typedef signed short s16;
+typedef unsigned short u16;
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef unsigned char bool;
+#define true 1
+#define false 0
+
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Variables globales
+-------------------------------------------------------------------------------
+*/
+
+typedef struct {
+
+ u32 width; // Ancho de la imagen
+ u32 height; // Alto de la imagen
+
+ u8* data; // Datos de la imagen
+ u8* raw[3]; // Tiles en bruto
+ u32 tiles[3]; // Tiles en cada "banco" (3)
+ u32 map_pos[3]; // Posicion en el mapa
+
+ u8* patterns[3]; // Buffer para los patterns
+ u32 patterns_size_normal[3];
+ u32 patterns_size_rle[3];
+
+ u8* colors[3]; // Buffer para los colores
+ u32 colors_size_normal[3];
+ u32 colors_size_rle[3];
+
+ u8* names[3]; // Buffer para los nombres (mapa)
+ u32 names_size_normal[3];
+ u32 names_size_rle[3];
+
+ u8* rle; // Buffer temporal para la compresion RLE
+
+ bool sz; // Flag de generacion de info del tamaņo
+ bool inc; // Flag de generacion de archivo de .INCLUDE
+
+} img_info;
+
+extern img_info img; // Guarda la imagen cargada y su informacion
+
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Limpia los buffers
+-------------------------------------------------------------------------------
+*/
+
+extern void CleanBuffers(void);
+
+
+
+#endif // DEFINES_H_INCLUDED
diff --git a/tools_source/ngn_msx_tiles/source/filesystem.c b/tools_source/ngn_msx_tiles/source/filesystem.c
new file mode 100644
index 0000000..6c00556
--- /dev/null
+++ b/tools_source/ngn_msx_tiles/source/filesystem.c
@@ -0,0 +1,592 @@
+/*
+-------------------------------------------------------------------------------
+ MSX Image to VRAM converter
+ Genera desde una imagen las tablas de PATTERN, COLOR & NAME
+ para usarlas en el modo SCREEN 2.
+ (cc)2015-2018 by Cesar Rincon "NightFox"
+ http://www.nightfoxandco.com
+ Version 0.1.0-a
+-------------------------------------------------------------------------------
+*/
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Includes
+-------------------------------------------------------------------------------
+*/
+
+#include
+#include
+#include
+
+#include "defines.h"
+#include "filesystem.h"
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Graba los datos a los archivos (Normal)
+-------------------------------------------------------------------------------
+*/
+
+s32 SaveFileNormal (const char* filename) {
+
+ // Variables
+ u32 b = 0;
+ u32 tbl = 0;
+ u32 l = 0;
+ u32 i = 0;
+ u8 hi = 0, lo = 0;
+ char fnam[256];
+ char output[256];
+ char txt[32];
+ char name[256];
+ u32 n = 0;
+ char lt;
+ u32 original = 0;
+
+ // Genera un nombre base para el archivo
+ for (n = 0; n < (strlen(filename) - 4); n ++) {
+ lt = filename[n];
+ if (lt >= 65 && lt <= 90) lt += 32;
+ name[n] = lt;
+ }
+ name[n] = '\0';
+
+ // Fase 3, genera el archivo codificado
+ if (img.inc) {
+ sprintf(fnam, "%s.inc", name);
+ } else {
+ sprintf(fnam, "%s.asm", name);
+ }
+ FILE* file = fopen(fnam, "wb");
+
+ // Genera un nombre base para las etiquetas
+ for (n = 0; n < (strlen(filename) - 4); n ++) {
+ lt = filename[n];
+ if (lt >= 97 && lt <= 122) lt -= 32;
+ name[n] = lt;
+ }
+ name[n] = '\0';
+
+ // Si se puede crear el archivo...
+ if (file != NULL) {
+
+ // Cabecera del archivo
+ if (img.sz) original = 2;
+ for (n = 0; n < 3; n ++) {
+ original += (img.patterns_size_normal[n] + img.colors_size_normal[n] + img.names_size_normal[n]);
+ }
+ sprintf(output, ";************************************************************\n");
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, ";* Imagen convertida para MSX - SCREEN 2\n");
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, ";* Archivo de origen: %s\n", filename);
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, ";* Tamaņo: %03dx%03d pixeles\n", img.width, img.height);
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, ";* Total de datos: %d bytes\n", original);
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, ";************************************************************\n\n\n");
+ fwrite(output, strlen(output), 1, file);
+
+ // Etiqueta general
+ sprintf(output, "%s_IMAGE:\n\n", name);
+ fwrite(output, strlen(output), 1, file);
+
+ // Informacion de los CHR
+ sprintf(output, "; Datos CHR\n");
+ fwrite(output, strlen(output), 1, file);
+ for (b = 0; b < 3; b ++) {
+ sprintf(output, "; Banco %01d: %03d bloques de CHR (%d bytes) [$%04x bytes]\n", b, img.tiles[b], img.patterns_size_normal[b], img.patterns_size_normal[b]);
+ fwrite(output, strlen(output), 1, file);
+ }
+ sprintf(output, "\n");
+ fwrite(output, strlen(output), 1, file);
+
+ // Genera los patterns
+ printf("Grabando datos CHR ");
+ for (b = 0; b < 3; b ++) {
+ tbl = 0;
+ // Genera la etiqueta
+ sprintf(output, "%s_CHR_%01d:\n", name, b);
+ fwrite(output, strlen(output), 1, file);
+ if (img.sz) {
+ // Genera los bytes de tamaņo
+ sprintf(output, "; Tamaņo:\n");
+ fwrite(output, strlen(output), 1, file);
+ hi = (img.patterns_size_normal[b] >> 8) & 0xff;
+ lo = (img.patterns_size_normal[b] & 0xff);
+ sprintf(output, "db $%02x, $%02x\n", hi, lo);
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, "; Datos:\n");
+ fwrite(output, strlen(output), 1, file);
+ }
+ for (n = 0; n < img.tiles[b]; n ++) {
+ // Tiles
+ sprintf(output, "db ");
+ // Lineas
+ for (l = 0; l < 8; l ++) { // Linea
+ if (l != 7) {
+ sprintf(txt, "$%02x, ", img.patterns[b][tbl]);
+ } else {
+ sprintf(txt, "$%02x\n", img.patterns[b][tbl]);
+ }
+ strcat(output, txt);
+ tbl ++;
+ }
+ // Guarda la info
+ printf(".");
+ fwrite(output, strlen(output), 1, file);
+ }
+ // Genera un espacio entre bancos
+ sprintf(output, "\n");
+ fwrite(output, strlen(output), 1, file);
+ }
+ // Genera un espacio entre bancos
+ sprintf(output, "\n");
+ fwrite(output, strlen(output), 1, file);
+ printf(" ok\n\n");
+
+
+ // Informacion de los CLR
+ sprintf(output, "; Datos CLR\n");
+ fwrite(output, strlen(output), 1, file);
+ for (b = 0; b < 3; b ++) {
+ sprintf(output, "; Banco %01d: %03d bloques de CLR (%d bytes) [$%04x bytes]\n", b, img.tiles[b], img.colors_size_normal[b], img.colors_size_normal[b]);
+ fwrite(output, strlen(output), 1, file);
+ }
+ sprintf(output, "\n");
+ fwrite(output, strlen(output), 1, file);
+
+
+ // Genera los colores
+ printf("Grabando datos CLR ");
+ for (b = 0; b < 3; b ++) {
+ tbl = 0;
+ // Genera la etiqueta
+ sprintf(output, "%s_CLR_%01d:\n", name, b);
+ fwrite(output, strlen(output), 1, file);
+ if (img.sz) {
+ // Genera los bytes de tamaņo
+ sprintf(output, "; Tamaņo:\n");
+ fwrite(output, strlen(output), 1, file);
+ hi = (img.colors_size_normal[b] >> 8) & 0xff;
+ lo = (img.colors_size_normal[b] & 0xff);
+ sprintf(output, "db $%02x, $%02x\n", hi, lo);
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, "; Datos:\n");
+ fwrite(output, strlen(output), 1, file);
+ }
+ for (n = 0; n < img.tiles[b]; n ++) {
+ // Tiles
+ sprintf(output, "db ");
+ // Lineas
+ for (l = 0; l < 8; l ++) { // Linea
+ if (l != 7) {
+ sprintf(txt, "$%02x, ", img.colors[b][tbl]);
+ } else {
+ sprintf(txt, "$%02x\n", img.colors[b][tbl]);
+ }
+ strcat(output, txt);
+ tbl ++;
+ }
+ // Guarda la info
+ printf(".");
+ fwrite(output, strlen(output), 1, file);
+ }
+ // Genera un espacio entre bancos
+ sprintf(output, "\n");
+ fwrite(output, strlen(output), 1, file);
+ }
+ // Genera un espacio entre bancos
+ sprintf(output, "\n");
+ fwrite(output, strlen(output), 1, file);
+ printf(" ok\n\n");
+
+
+ // Informacion de los NAMES
+ sprintf(output, "; Datos NAME\n");
+ fwrite(output, strlen(output), 1, file);
+ for (b = 0; b < 3; b ++) {
+ sprintf(output, "; Banco %01d: (%d bytes) [$%04x bytes]\n", b, img.names_size_normal[b], img.names_size_normal[b]);
+ fwrite(output, strlen(output), 1, file);
+ }
+ sprintf(output, "\n");
+ fwrite(output, strlen(output), 1, file);
+
+ // Genera la tabla de nombres
+ printf("Grabando datos NAME ");
+ for (b = 0; b < 3; b ++) {
+ // Genera la etiqueta
+ sprintf(output, "%s_NAM_%01d:\n", name, b);
+ fwrite(output, strlen(output), 1, file);
+ if (img.sz) {
+ // Genera los bytes de tamaņo
+ sprintf(output, "; Tamaņo:\n");
+ fwrite(output, strlen(output), 1, file);
+ hi = (img.names_size_normal[b] >> 8) & 0xff;
+ lo = (img.names_size_normal[b] & 0xff);
+ sprintf(output, "db $%02x, $%02x\n", hi, lo);
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, "; Datos:\n");
+ fwrite(output, strlen(output), 1, file);
+ }
+ l = 0; i = 0;
+ sprintf(output, "db ");
+ for (n = 0; n < img.map_pos[b]; n ++) {
+ // Lineas
+ if (i != 31) {
+ sprintf(txt, "$%02x, ", img.names[b][n]);
+ } else {
+ sprintf(txt, "$%02x\n", img.names[b][n]);
+ }
+ strcat(output, txt);
+ // Ajuste de indice
+ i ++;
+ if (i > 31) {
+ i = 0;
+ // Guarda la info de la linea
+ printf(".");
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, "db ");
+ }
+ }
+ // Genera un espacio entre bancos
+ if (b < 2) {
+ sprintf(output, "\n");
+ fwrite(output, strlen(output), 1, file);
+ }
+ }
+ // Msg
+ printf(" ok\n\n");
+
+ } else {
+
+ printf("No se puede generar el archivo.\n");
+
+ return -1;
+
+ }
+
+ // Cierra el archivo
+ fclose(file);
+
+ printf("\n");
+
+ return 0;
+
+}
+
+
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Graba los datos a los archivos (RLE)
+-------------------------------------------------------------------------------
+*/
+
+s32 SaveFileRLE (const char* filename) {
+
+ // Variables
+ u32 b = 0;
+ u32 idx = 0;
+ u32 l = 0;
+ u8 hi = 0, lo = 0;
+ char fnam[256];
+ char output[256];
+ char txt[32];
+ char name[256];
+ u32 n = 0;
+ char lt;
+ u32 compressed = 0;
+
+ // Genera un nombre base para el archivo
+ for (n = 0; n < (strlen(filename) - 4); n ++) {
+ lt = filename[n];
+ if (lt >= 65 && lt <= 90) lt += 32;
+ name[n] = lt;
+ }
+ name[n] = '\0';
+
+ // Fase 3, genera el archivo codificado
+ if (img.inc) {
+ sprintf(fnam, "%s.inc", name);
+ } else {
+ sprintf(fnam, "%s.asm", name);
+ }
+ FILE* file = fopen(fnam, "wb");
+
+ // Genera un nombre base para las etiquetas
+ for (n = 0; n < (strlen(filename) - 4); n ++) {
+ lt = filename[n];
+ if (lt >= 97 && lt <= 122) lt -= 32;
+ name[n] = lt;
+ }
+ name[n] = '\0';
+
+ // Si se puede crear el archivo...
+ if (file != NULL) {
+
+ // Cabecera del archivo
+ if (img.sz) compressed = 4;
+ for (n = 0; n < 3; n ++) {
+ compressed += (img.patterns_size_rle[n] + img.colors_size_rle[n] + img.names_size_rle[n]);
+ }
+ sprintf(output, ";************************************************************\n");
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, ";* Imagen convertida para MSX - SCREEN 2\n");
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, ";* Archivo de origen: %s\n", filename);
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, ";* Tamaņo: %03dx%03d pixeles\n", img.width, img.height);
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, ";* Compresion RLE habilitada\n");
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, ";* Total de datos: %d bytes\n", compressed);
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, ";************************************************************\n\n\n");
+ fwrite(output, strlen(output), 1, file);
+
+ // Etiqueta general
+ sprintf(output, "%s_IMAGE:\n\n", name);
+ fwrite(output, strlen(output), 1, file);
+
+ // Informacion de los CHR
+ sprintf(output, "; Datos CHR\n");
+ fwrite(output, strlen(output), 1, file);
+ for (b = 0; b < 3; b ++) {
+ sprintf(output, "; Banco %01d: %03d bloques de CHR\n", b, img.tiles[b]);
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, "; Tamaņo descomprimido: %d bytes [$%04x bytes]\n", img.patterns_size_normal[b], img.patterns_size_normal[b]);
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, "; Tamaņo RLE: %d bytes [$%04x bytes]\n", img.patterns_size_rle[b], img.patterns_size_rle[b]);
+ fwrite(output, strlen(output), 1, file);
+ }
+ sprintf(output, "\n");
+ fwrite(output, strlen(output), 1, file);
+
+ // Genera los patterns
+ printf("Grabando datos CHR ");
+ for (b = 0; b < 3; b ++) {
+ // Incializa el indice
+ idx = 0;
+ l = 0;
+ // Genera la etiqueta
+ sprintf(output, "%s_CHR_%01d:\n",name, b);
+ fwrite(output, strlen(output), 1, file);
+ if (img.sz) {
+ // Genera los bytes de tamaņo
+ sprintf(output, "; Tamaņo descomprimido:\n");
+ fwrite(output, strlen(output), 1, file);
+ hi = (img.patterns_size_normal[b] >> 8) & 0xff;
+ lo = (img.patterns_size_normal[b] & 0xff);
+ sprintf(output, "db $%02x, $%02x\n", hi, lo);
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, "; Tamaņo comprimido (RLE):\n");
+ fwrite(output, strlen(output), 1, file);
+ hi = (img.patterns_size_rle[b] >> 8) & 0xff;
+ lo = (img.patterns_size_rle[b] & 0xff);
+ sprintf(output, "db $%02x, $%02x\n", hi, lo);
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, "; Datos:\n");
+ fwrite(output, strlen(output), 1, file);
+ }
+ while (idx < img.patterns_size_rle[b]) {
+ // Cabecera de la linea
+ if (l == 0) {
+ sprintf(output, "db ");
+ }
+ l ++;
+ // Mientras no llegues al final de linea...
+ if ((l < 8) && (idx < (img.patterns_size_rle[b] - 1))) {
+ sprintf(txt, "$%02x, ", img.patterns[b][idx]);
+ strcat(output, txt);
+ } else {
+ // Reinicia el contador
+ l = 0;
+ // Genera la linea
+ sprintf(txt, "$%02x\n", img.patterns[b][idx]);
+ strcat(output, txt);
+ // Guarda la info
+ printf(".");
+ fwrite(output, strlen(output), 1, file);
+ }
+ idx ++;
+ }
+ // Genera un espacio entre bancos
+ sprintf(output, "\n");
+ fwrite(output, strlen(output), 1, file);
+ }
+ // Genera un espacio entre bancos
+ sprintf(output, "\n");
+ fwrite(output, strlen(output), 1, file);
+ printf(" ok\n\n");
+
+
+
+ // Informacion de los CLR
+ sprintf(output, "; Datos CLR\n");
+ fwrite(output, strlen(output), 1, file);
+ for (b = 0; b < 3; b ++) {
+ sprintf(output, "; Banco %01d: %03d bloques de CLR\n", b, img.tiles[b]);
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, "; Tamaņo descomprimido: %d bytes [$%04x bytes]\n", img.colors_size_normal[b], img.colors_size_normal[b]);
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, "; Tamaņo RLE: %d bytes [$%04x bytes]\n", img.colors_size_rle[b], img.colors_size_rle[b]);
+ fwrite(output, strlen(output), 1, file);
+ }
+ sprintf(output, "\n");
+ fwrite(output, strlen(output), 1, file);
+
+ // Genera los colors
+ printf("Grabando datos CLR ");
+ for (b = 0; b < 3; b ++) {
+ // Incializa el indice
+ idx = 0;
+ l = 0;
+ // Genera la etiqueta
+ sprintf(output, "%s_CLR_%01d:\n",name, b);
+ fwrite(output, strlen(output), 1, file);
+ if (img.sz) {
+ // Genera los bytes de tamaņo
+ sprintf(output, "; Tamaņo descomprimido:\n");
+ fwrite(output, strlen(output), 1, file);
+ hi = (img.colors_size_normal[b] >> 8) & 0xff;
+ lo = (img.colors_size_normal[b] & 0xff);
+ sprintf(output, "db $%02x, $%02x\n", hi, lo);
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, "; Tamaņo comprimido (RLE):\n");
+ fwrite(output, strlen(output), 1, file);
+ hi = (img.colors_size_rle[b] >> 8) & 0xff;
+ lo = (img.colors_size_rle[b] & 0xff);
+ sprintf(output, "db $%02x, $%02x\n", hi, lo);
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, "; Datos:\n");
+ fwrite(output, strlen(output), 1, file);
+ }
+ while (idx < img.colors_size_rle[b]) {
+ // Cabecera de la linea
+ if (l == 0) {
+ sprintf(output, "db ");
+ }
+ l ++;
+ // Mientras no llegues al final de linea...
+ if ((l < 8) && (idx < (img.colors_size_rle[b] - 1))) {
+ sprintf(txt, "$%02x, ", img.colors[b][idx]);
+ strcat(output, txt);
+ } else {
+ // Reinicia el contador
+ l = 0;
+ // Genera la linea
+ sprintf(txt, "$%02x\n", img.colors[b][idx]);
+ strcat(output, txt);
+ // Guarda la info
+ printf(".");
+ fwrite(output, strlen(output), 1, file);
+ }
+ idx ++;
+ }
+ // Genera un espacio entre bancos
+ sprintf(output, "\n");
+ fwrite(output, strlen(output), 1, file);
+ }
+ // Genera un espacio entre bancos
+ sprintf(output, "\n");
+ fwrite(output, strlen(output), 1, file);
+ printf(" ok\n\n");
+
+
+
+ // Informacion de los NAME
+ sprintf(output, "; Datos NAME\n");
+ fwrite(output, strlen(output), 1, file);
+ for (b = 0; b < 3; b ++) {
+ sprintf(output, "; Banco %01d: 256 bloques de NAME\n", b);
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, "; Tamaņo descomprimido: %d bytes [$%04x bytes]\n", img.names_size_normal[b], img.names_size_normal[b]);
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, "; Tamaņo RLE: %d bytes [$%04x bytes]\n", img.names_size_rle[b], img.names_size_rle[b]);
+ fwrite(output, strlen(output), 1, file);
+ }
+ sprintf(output, "\n");
+ fwrite(output, strlen(output), 1, file);
+
+ // Genera los NAMES
+ printf("Grabando datos NAME ");
+ for (b = 0; b < 3; b ++) {
+ // Incializa el indice
+ idx = 0;
+ l = 0;
+ // Genera la etiqueta
+ sprintf(output, "%s_NAM_%01d:\n",name, b);
+ fwrite(output, strlen(output), 1, file);
+ if (img.sz) {
+ // Genera los bytes de tamaņo
+ sprintf(output, "; Tamaņo descomprimido:\n");
+ fwrite(output, strlen(output), 1, file);
+ hi = (img.names_size_normal[b] >> 8) & 0xff;
+ lo = (img.names_size_normal[b] & 0xff);
+ sprintf(output, "db $%02x, $%02x\n", hi, lo);
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, "; Tamaņo comprimido (RLE):\n");
+ fwrite(output, strlen(output), 1, file);
+ hi = (img.names_size_rle[b] >> 8) & 0xff;
+ lo = (img.names_size_rle[b] & 0xff);
+ sprintf(output, "db $%02x, $%02x\n", hi, lo);
+ fwrite(output, strlen(output), 1, file);
+ sprintf(output, "; Datos:\n");
+ fwrite(output, strlen(output), 1, file);
+ }
+ while (idx < img.names_size_rle[b]) {
+ // Cabecera de la linea
+ if (l == 0) {
+ sprintf(output, "db ");
+ }
+ l ++;
+ // Mientras no llegues al final de linea...
+ if ((l < 8) && (idx < (img.names_size_rle[b] - 1))) {
+ sprintf(txt, "$%02x, ", img.names[b][idx]);
+ strcat(output, txt);
+ } else {
+ // Reinicia el contador
+ l = 0;
+ // Genera la linea
+ sprintf(txt, "$%02x\n", img.names[b][idx]);
+ strcat(output, txt);
+ // Guarda la info
+ printf(".");
+ fwrite(output, strlen(output), 1, file);
+ }
+ idx ++;
+ }
+ // Genera un espacio entre bancos
+ if (b < 2) {
+ sprintf(output, "\n");
+ fwrite(output, strlen(output), 1, file);
+ }
+ }
+ // Msg
+ printf(" ok\n\n");
+
+ } else {
+
+ printf("No se puede generar el archivo.\n");
+
+ return -1;
+
+ }
+
+ // Cierra el archivo
+ fclose(file);
+
+ printf("\n");
+
+ return 0;
+
+}
diff --git a/tools_source/ngn_msx_tiles/source/filesystem.h b/tools_source/ngn_msx_tiles/source/filesystem.h
new file mode 100644
index 0000000..dcbc395
--- /dev/null
+++ b/tools_source/ngn_msx_tiles/source/filesystem.h
@@ -0,0 +1,40 @@
+/*
+-------------------------------------------------------------------------------
+ MSX Image to VRAM converter
+ Genera desde una imagen las tablas de PATTERN, COLOR & NAME
+ para usarlas en el modo SCREEN 2.
+ (cc)2015-2018 by Cesar Rincon "NightFox"
+ http://www.nightfoxandco.com
+ Version 0.1.0-a
+-------------------------------------------------------------------------------
+*/
+
+
+
+#ifndef FILESYSTEM_H_INCLUDED
+#define FILESYSTEM_H_INCLUDED
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Includes
+-------------------------------------------------------------------------------
+*/
+
+#include "defines.h"
+
+
+/*
+-------------------------------------------------------------------------------
+ Graba los datos a los archivos
+-------------------------------------------------------------------------------
+*/
+
+s32 SaveFileNormal (const char* filename);
+s32 SaveFileRLE (const char* filename);
+
+
+
+
+#endif // FILESYSTEM_H_INCLUDED
diff --git a/tools_source/ngn_msx_tiles/source/main.c b/tools_source/ngn_msx_tiles/source/main.c
new file mode 100644
index 0000000..c3cdc4a
--- /dev/null
+++ b/tools_source/ngn_msx_tiles/source/main.c
@@ -0,0 +1,138 @@
+/*
+-------------------------------------------------------------------------------
+ MSX Image to VRAM converter
+ Genera desde una imagen las tablas de PATTERN, COLOR & NAME
+ para usarlas en el modo SCREEN 2.
+ (cc)2015-2018 by Cesar Rincon "NightFox"
+ http://www.nightfoxandco.com
+ Version 0.1.0-a
+-------------------------------------------------------------------------------
+*/
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Includes
+-------------------------------------------------------------------------------
+*/
+
+#include
+#include
+#include
+
+#include "defines.h"
+#include "bmp.h"
+#include "tilemap.h"
+#include "filesystem.h"
+#include "rle.h"
+
+
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Archivo MAIN
+-------------------------------------------------------------------------------
+*/
+
+int main(int argc, char *argv[]) {
+
+ // Variables
+ u8 param = argc;
+ bool rle = false;
+ s32 n = 0;
+ s32 original = 0;
+ s32 compressed = 0;
+
+ printf("\n\nConversor de imagenes BMP a formato SCREEN2 para MSX.\nVersion 0.1.0-a.\n(cc)2015-2018 por Cesar Rincon.\nhttp://www.nightfoxandco.com\n\n\n");
+
+ // Inicializa las estructuras
+ memset(&img, 0, sizeof(img));
+
+ if (argc > 2) {
+ for (n = 2; n < argc; n ++) {
+ // Busca coincidencias en los parametros
+ if (strcmp(argv[n], "-rle") == 0) {
+ rle = true;
+ param --;
+ } else if (strcmp(argv[n], "-size") == 0) {
+ img.sz = true;
+ param --;
+ } else if (strcmp(argv[n], "-inc") == 0) {
+ img.inc = true;
+ param --;
+ }
+ }
+ }
+
+ // Error en la linea de comandos
+ if (param != 2) {
+ printf("Uso: %s archivo.bmp [-rle][-size][-inc]\n\n", argv[0]);
+ printf(" -rle Comprime los datos en formato RLE\n");
+ printf(" -size Aņade al archivo la informacion del tamaņo de los datos\n");
+ printf(" -inc Genera el archivo con la extension .INC\n\n");
+ CleanBuffers();
+ return -1;
+ }
+
+ // Carga el archivo BITMAP
+ if (LoadBitmap(argv[1]) == -1) {
+ printf("Error al procesar el archivo BITMAP.\n");
+ CleanBuffers();
+ return -1;
+ }
+
+ printf("\nProcesando archivo BITMAP...\n\nNombre: %s\nTamaņo: %dx%d pixeles.\n\n", argv[1], img.width, img.height);
+
+ if (GenerateTileset() == -1) {
+ printf("Error al procesar los datos.\n");
+ CleanBuffers();
+ return -1;
+ }
+
+
+ if (rle) {
+ for (n = 0; n < 3; n ++) img.patterns_size_rle[n] = RleCompress(img.patterns[n], img.patterns_size_normal[n]);
+ for (n = 0; n < 3; n ++) img.colors_size_rle[n] = RleCompress(img.colors[n], img.colors_size_normal[n]);
+ for (n = 0; n < 3; n ++) img.names_size_rle[n] = RleCompress(img.names[n], img.names_size_normal[n]);
+ if (SaveFileRLE(argv[1]) == -1) {
+ printf("Error al grabar los archivos.\n");
+ CleanBuffers();
+ return -1;
+ }
+ } else {
+ if (SaveFileNormal(argv[1]) == -1) {
+ printf("Error al grabar los archivos.\n");
+ CleanBuffers();
+ return -1;
+ }
+ }
+
+
+ // Sal del programa
+ if (img.inc) {
+ printf("Archivo .INC generado con exito.\n\n");
+ } else {
+ printf("Archivo .ASM generado con exito.\n\n");
+ }
+
+
+ for (n = 0; n < 3; n ++) {
+ original += (img.patterns_size_normal[n] + img.colors_size_normal[n] + img.names_size_normal[n]);
+ compressed += (img.patterns_size_rle[n] + img.colors_size_rle[n] + img.names_size_rle[n]);
+ }
+ if (rle) {
+ printf("Compresion RLE realizada\n");
+ printf("Tamaņo original: %d bytes.\n", original);
+ printf("Tamaņo comprimido: %d bytes.\n", compressed);
+ printf("Relacion de compresion: %d %%.\n\n\n", ((compressed * 100) / original));
+ } else {
+ printf("Tamaņo de los datos: %d bytes.\n", original);
+ }
+
+ CleanBuffers();
+ return 0;
+
+}
diff --git a/tools_source/ngn_msx_tiles/source/rle.c b/tools_source/ngn_msx_tiles/source/rle.c
new file mode 100644
index 0000000..c7f1836
--- /dev/null
+++ b/tools_source/ngn_msx_tiles/source/rle.c
@@ -0,0 +1,194 @@
+/*
+-------------------------------------------------------------------------------
+ MSX Image to VRAM converter
+ Genera desde una imagen las tablas de PATTERN, COLOR & NAME
+ para usarlas en el modo SCREEN 2.
+ (cc)2015-2018 by Cesar Rincon "NightFox"
+ http://www.nightfoxandco.com
+ Version 0.1.0-a
+-------------------------------------------------------------------------------
+*/
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Includes
+-------------------------------------------------------------------------------
+*/
+
+#include
+#include
+#include
+
+#include "defines.h"
+#include "rle.h"
+
+
+/*
+-------------------------------------------------------------------------------
+ Comprime los datos en RLE
+-------------------------------------------------------------------------------
+*/
+
+s32 RleCompress(u8* data, u32 length) {
+
+ // Variables
+ u32 pos = 0;
+ u32 dest_pos = 0;
+ u32 new_length = 0;
+ u8 rle_data = 0;
+ u8 rle_repeat = 0;
+ u32 start_point = 0;
+ u32 end_point = 0 ;
+ u8 command = 1;
+ u8 next_command = 1;
+ s32 n = 0;
+ bool repeat = false;
+
+ u8* buffer = (u8*) calloc(4096, sizeof(u8));
+ if (buffer == NULL) {
+ printf("Memoria insuficiente.\n");
+ return -1;
+ }
+
+ printf("\nCompresion RLE en proceso:\n\n");
+
+
+ // Si aun quedan datos por evaluar
+ do {
+
+ // Primero verifica si no es el ultimo dato del buffer
+ switch (command) {
+
+ // Empieza a comparar datos
+ case 1:
+ // Si el siguiente dato, aun esta dentro del rango...
+ if ((pos + 1) < length) {
+ if (data[pos] == data[(pos + 1)]) {
+ // Guarda la informacion de inicio
+ rle_data = data[pos];
+ rle_repeat = 1;
+ start_point = pos;
+ // Salta a la seccion de busqueda
+ next_command = 2;
+ } else {
+ // El dato no se repite, escribelo tal cual
+ next_command = 3;
+ }
+ break;
+ } else { // El dato es el ultimo del buffer
+ next_command = 3;
+ }
+ break;
+
+
+ // Busca cuantos datos iguales consecutivos hay
+ case 2:
+
+ n = start_point; // Punto de incio de la busqueda
+ do {
+ // Si no estamos al final de buffer
+ if ((n + 1) < length) {
+ // Si los datos concuerdan
+ if (data[n] == data[(n + 1)]) {
+ n ++;
+ rle_repeat ++;
+ // Verifica si no has sobrepasado el numero maximo de repeticiones
+ if (rle_repeat >= 63) {
+ end_point = n;
+ repeat = false;
+ } else {
+ repeat = true;
+ }
+ } else {
+ // Si no concuerdan, sal
+ end_point = n;
+ repeat = false;
+ }
+ } else {
+ // Fin del buffer, sal si o si
+ end_point = n;
+ repeat = false;
+ }
+ } while (repeat);
+ next_command = 4;
+
+ break;
+
+
+ // Escribe el dato tal cual
+ case 3:
+ // Si el dato es >= 192...
+ if (data[pos] >= 192) {
+ printf("*");
+ buffer[dest_pos] = 192 | 1; // Indica que es un dato comprimido
+ dest_pos ++; // con una sola repeticion
+ buffer[dest_pos] = data[pos]; // Escribe el dato en el buffer de destino
+ } else {
+ printf("O");
+ buffer[dest_pos] = data[pos]; // Escribe los datos tal cual
+ }
+ dest_pos ++; // E incrementa los contadores
+ pos ++;
+ next_command = 1; // Indica que busque de nuevo
+ break;
+
+ // Escribe el dato comprimido
+ case 4:
+ //printf("[%d.%d]", rle_data, rle_repeat);
+ if (rle_repeat >= 16) {
+ printf("˛");
+ } else if (rle_repeat >= 8) {
+ printf("ą");
+ } else {
+ printf("°");
+ }
+ buffer[dest_pos] = 192 | rle_repeat; // Escribe la ID de compresion
+ dest_pos ++; // [192 + repeticiones]
+ buffer[dest_pos] = rle_data; // Escribe el dato
+ dest_pos ++;
+ pos = (end_point + 1); // Offset de busqueda al inicio del siguiente bloque
+ next_command = 1;
+ break;
+
+ }
+
+ // Actualiza el comando
+ command = next_command;
+
+
+ } while (pos < length);
+
+ new_length = dest_pos;
+
+ // Actualiza el buffer
+ memcpy(data, buffer, new_length);
+
+ // Si la compresion es exitosa
+ if (new_length < length) {
+
+ // Mensage
+ printf("\n\nCompresion finalizada.\n");
+ printf("Tamaņo original: %d bytes.\n", length);
+ printf("Tamaņo comprimido: %d bytes.\n", dest_pos);
+ printf("Tamaņo reducido en un: %d%%.\n\n", (100 - ((new_length * 100) / length)));
+
+ } else {
+
+ // Mensage
+ printf("\n\nCompresion fallida.\n");
+ printf("Tamaņo original: %d bytes.\n", length);
+ printf("Tamaņo comprimido: %d bytes.\n", dest_pos);
+ printf("Tamaņo incrementado al: %d%%.\n\n", ((new_length * 100) / length));
+
+ }
+
+ // Limpia los buffers
+ free (buffer);
+ buffer = NULL;
+
+ // Devuelve la nueva longitud
+ return new_length;
+
+}
diff --git a/tools_source/ngn_msx_tiles/source/rle.h b/tools_source/ngn_msx_tiles/source/rle.h
new file mode 100644
index 0000000..19f650f
--- /dev/null
+++ b/tools_source/ngn_msx_tiles/source/rle.h
@@ -0,0 +1,38 @@
+/*
+-------------------------------------------------------------------------------
+ MSX Image to VRAM converter
+ Genera desde una imagen las tablas de PATTERN, COLOR & NAME
+ para usarlas en el modo SCREEN 2.
+ (cc)2015-2018 by Cesar Rincon "NightFox"
+ http://www.nightfoxandco.com
+ Version 0.1.0-a
+-------------------------------------------------------------------------------
+*/
+
+
+
+#ifndef RLE_H_INCLUDED
+#define RLE_H_INCLUDED
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Includes
+-------------------------------------------------------------------------------
+*/
+
+#include "defines.h"
+
+
+/*
+-------------------------------------------------------------------------------
+ Compresion RLE
+-------------------------------------------------------------------------------
+*/
+
+s32 RleCompress(u8* data, u32 length);
+
+
+
+#endif // RLE_H_INCLUDED
diff --git a/tools_source/ngn_msx_tiles/source/tilemap.c b/tools_source/ngn_msx_tiles/source/tilemap.c
new file mode 100644
index 0000000..9ba692b
--- /dev/null
+++ b/tools_source/ngn_msx_tiles/source/tilemap.c
@@ -0,0 +1,241 @@
+/*
+-------------------------------------------------------------------------------
+ MSX Image to VRAM converter
+ Genera desde una imagen las tablas de PATTERN, COLOR & NAME
+ para usarlas en el modo SCREEN 2.
+ (cc)2015-2018 by Cesar Rincon "NightFox"
+ http://www.nightfoxandco.com
+ Version 0.1.0-a
+-------------------------------------------------------------------------------
+*/
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Includes
+-------------------------------------------------------------------------------
+*/
+
+#include
+#include
+#include
+
+#include "defines.h"
+#include "tilemap.h"
+
+
+/*
+-------------------------------------------------------------------------------
+ Analiza los datos y genera el archivo tileset
+-------------------------------------------------------------------------------
+*/
+
+s32 GenerateTileset(void) {
+
+ // Variables
+ s32 n = 0;
+
+ // Buffers temporales para los tiles
+ u8* tile_pattern = (u8*) calloc(64, sizeof(u8));
+ u8* test_pattern = (u8*) calloc(64, sizeof(u8));
+ // Verifica si se han creado todos los buffers
+ if (
+ (tile_pattern == NULL)
+ ||
+ (test_pattern == NULL)
+ ) {
+ printf("Error creando los buffers internos.\nError critico.\n");
+ free(tile_pattern);
+ tile_pattern = NULL;
+ free(test_pattern);
+ test_pattern = NULL;
+ return -1;
+ }
+
+ // Crea los buffers para las tablas de pattern y color
+ // (Asume que todos los tiles son unicos y haz el buffer el doble de grande para la compresion RLE)
+ for (n = 0; n < 3; n ++) {
+ img.raw[n] = (u8*) calloc(32768, sizeof(u8)); // Tiles diferentes de 8x8 x 256
+ img.patterns[n] = (u8*) calloc(4096, sizeof(u8)); // 8 bytes por tile (8 filas de 8 pixeles)
+ img.colors[n] = (u8*) calloc(4096, sizeof(u8)); // Cada fila de pixeles tiene dos colores de 4 bits
+ img.names[n] = (u8*) calloc(512, sizeof(u8)); // Tabla de nombres de cada banco (mapa)
+ if ((img.raw[n] == NULL) || (img.patterns[n] == NULL) || (img.colors[n] == NULL) || (img.names[n] == NULL)) {
+ printf("Error creando los buffers internos.\nError critico.\n");
+ free(tile_pattern);
+ tile_pattern = NULL;
+ free(test_pattern);
+ test_pattern = NULL;
+ return -1;
+ }
+ }
+
+ // Analisis del RAW
+ u32 main_offset = 0;
+ u32 local_offset = 0;
+ u32 b = 0;
+ s32 match = 0;
+ s32 exist = -1;
+
+ // Analiza el archivo en pasos de 8x8 pixeles
+ printf("Generando banco de tiles:\n\n");
+ u32 pos_y = 0, pos_x = 0, temp_y = 0, temp_x = 0, t = 0;
+
+ for (pos_y = 0; pos_y < img.height; pos_y += 8) {
+
+ // Calcula el banco
+ b = (int)(pos_y / 64);
+
+ for (pos_x = 0; pos_x < img.width; pos_x += 8) {
+
+ // Copia los datos al tile
+ for (temp_y = 0; temp_y < 8; temp_y ++) {
+ for (temp_x = 0; temp_x < 8; temp_x ++) {
+ local_offset = (temp_y << 3) + temp_x;
+ main_offset = ((pos_y + temp_y) * img.width) + (pos_x + temp_x);
+ tile_pattern[local_offset] = img.data[main_offset];
+ }
+ }
+
+
+
+ // Borra la asignacion de tile existente
+ exist = -1;
+
+ // Ahora verifica si ya hay algun tile registrado
+ if (img.tiles[b] > 0) {
+ // Verifica si el tile es nuevo o ya existe
+ for (n = 0; n < img.tiles[b]; n ++) {
+ // Flag de repeticion
+ match = 0;
+ // Compara la info con la almacenada en el buffer de tiles
+ for (t = 0; t < 64; t ++) {
+ local_offset = (n * 64) + t;
+ // Si los pixeles son iguales...
+ if (tile_pattern[t] == img.raw[b][local_offset]) {
+ match ++;
+ }
+ // Si todos los pixeles eran iguales, indicalo
+ if (match == 64) {
+ exist = n;
+ n = img.tiles[b]; // Sal
+ }
+ }
+ }
+
+ // Si el tile ya existe...
+ if (exist != -1) {
+ // Indicador
+ img.names[b][img.map_pos[b]] = exist;
+ // Indicador
+ printf(".");
+ img.map_pos[b] ++;
+ } else { // SI no existe, agregalo a los buffers
+ // Indicador
+ //printf("B:%01d.P%03d.M%03d", b, img.tiles[b], img.map_pos[b]);
+ // Actualiza los buffers
+ memcpy(img.raw[b] + (img.tiles[b] * 64), tile_pattern, 64); // Copia la informacion del tile
+ img.names[b][img.map_pos[b]] = img.tiles[b]; // Indica al mapa que tile es
+ // Indicador
+ printf("%01d", b);
+ // Actualiza los contadores
+ img.map_pos[b] ++;
+ img.tiles[b] ++;
+ }
+
+ } else {
+
+ // Si el el primero, registralo
+ memcpy(img.raw[b], tile_pattern, 64); // Copia la informacion del tile
+ img.names[b][img.map_pos[b]] = img.tiles[b]; // Indica al mapa que tile es
+ // Indicador
+ printf("%01d", b);
+ // Actualiza los contadores
+ img.map_pos[b] ++;
+ img.tiles[b] ++;
+
+ }
+
+ }
+ }
+
+ // Resumen
+ printf("\n\nBanco de tiles creado con exito.\n\n");
+ printf("Banco 1: %03d tiles.\n", img.tiles[0]);
+ printf("Banco 2: %03d tiles.\n", img.tiles[1]);
+ printf("Banco 3: %03d tiles.\n\n", img.tiles[2]);
+
+
+ // Guarda los tamaņos en bytes
+ for (n = 0; n < 3; n ++) {
+ img.patterns_size_normal[n] = (img.tiles[n] << 3);
+ img.colors_size_normal[n] = (img.tiles[n] << 3);
+ img.names_size_normal[n] = 256;
+ }
+
+
+ // Fase 2, genera las tablas de pattern y color para cada banco
+ u32 l = 0;
+ u32 i = 0;
+ u8 bg_color = 0;
+ u8 pixel_color = 0;
+ u32 encode = 0;
+ u32 tbl = 0;
+ u8 color_table[16];
+ u8 max_val = 0;
+ printf("Codificando los tiles a filas de patterns...\n\n");
+ for (b = 0; b < 3; b ++) {
+ tbl = 0;
+ // Analiza los tiles de ese banco
+ for (n = 0; n < img.tiles[b]; n ++) {
+ // Paso 1, analiza cada linea y calcula su valor en binario
+ printf("B: %01d T: %03d LINES: ", b, n);
+ for (l = 0; l < 8; l ++) { // Linea del tile
+ // Guarda el primer color de la fila
+ local_offset = (n * 64) + (l * 8);
+ bg_color = (img.raw[b][local_offset] & 0x0f);
+ pixel_color = bg_color;
+ encode = 0;
+ // Borra la tabla de analisis de color
+ memset(color_table, 0, 16);
+ max_val = 0;
+ // Analiza la fila de 8 pixeles
+ for (i = 0; i < 8; i ++) { // Pixel
+ local_offset = (n * 64) + (l * 8) + i; // Calcula el offset del pixel en el buffer
+ if (bg_color != img.raw[b][local_offset]) {
+ // Si el color no es el de fondo, codifica el bit
+ encode |= (1 << (7 - i));
+ pixel_color = (img.raw[b][local_offset] & 0x0f);
+ // Y registralo en la tabla de colores
+ color_table[pixel_color] ++;
+ }
+ }
+ // Calcula el color predominante de pixel
+ for (i = 0; i < 16; i ++) {
+ if (color_table[i] > max_val) {
+ max_val = color_table[i];
+ pixel_color = i;
+ }
+ }
+ // Guarda la fila
+ img.patterns[b][tbl] = encode;
+ img.colors[b][tbl] = ((((pixel_color + 1) << 4) & 0xf0)| ((bg_color + 1) & 0x0f));
+ printf("$%02x ", img.patterns[b][tbl]);
+ tbl ++;
+ }
+ printf("\n");
+ }
+
+ }
+
+ // Limpia los buffers
+ free(tile_pattern);
+ tile_pattern = NULL;
+ free(test_pattern);
+ test_pattern = NULL;
+
+ printf("\n\n");
+
+ return 0;
+
+}
diff --git a/tools_source/ngn_msx_tiles/source/tilemap.h b/tools_source/ngn_msx_tiles/source/tilemap.h
new file mode 100644
index 0000000..d350ab4
--- /dev/null
+++ b/tools_source/ngn_msx_tiles/source/tilemap.h
@@ -0,0 +1,39 @@
+/*
+-------------------------------------------------------------------------------
+ MSX Image to VRAM converter
+ Genera desde una imagen las tablas de PATTERN, COLOR & NAME
+ para usarlas en el modo SCREEN 2.
+ (cc)2015-2018 by Cesar Rincon "NightFox"
+ http://www.nightfoxandco.com
+ Version 0.1.0-a
+-------------------------------------------------------------------------------
+*/
+
+
+
+#ifndef TILEMAP_H_INCLUDED
+#define TILEMAP_H_INCLUDED
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Includes
+-------------------------------------------------------------------------------
+*/
+
+#include "defines.h"
+
+
+
+/*
+-------------------------------------------------------------------------------
+ Analiza los datos y genera el archivo tileset
+-------------------------------------------------------------------------------
+*/
+
+s32 GenerateTileset(void);
+
+
+
+#endif // TILEMAP_H_INCLUDED