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