Foro de elhacker.net

Programación => .NET (C#, VB.NET, ASP) => Mensaje iniciado por: Meta en 10 Junio 2015, 04:59 am



Título: Leer una clase en un formulario Windows de Visual C#
Publicado por: Meta en 10 Junio 2015, 04:59 am
Buenas:

Voy a empezar desde el principio. El código lo he sacado de esta Web.

https://github.com/Zeokat/SNES-ROM-Header-Dumper-CSharp/blob/master/snes_dumper.cs

El archivo se llama snes_dumper.cs.

Creo un proyecto nuevo. Se que lo expliqué pero haré lo mismo por si acaso no me haya expresado bien o no he entendido bien. Uso Visual C# Express 2013. Hay gente que me recomienda el VS Comunity, ni sabía su existencia, no se de que va ni ventajas que tiene y no se si es gratuito como el Express, esto es otra historia.

Archivo-->Nuevo Proyecto...
(http://www.subeimagenes.com/img/re2-1345995.png)

A crear una clase nueva en, PROYECTO-->Agregar clase...
(http://www.subeimagenes.com/img/re2-1345997.png)

Le pongo el nombre de la clase llamado snes_dumper.cs, como indica abajo, luego pulso el botón Agregar.
(http://www.subeimagenes.com/img/re2-1346000.png)

Seañade la calse snes_dumper.cs como muestra abajo. El código generado a borrarlo.
(http://www.subeimagenes.com/img/re2-1346001.png)

He copiado el código que descargué en la Web de origen dentro del archivo snes_dumper.cs en el formulario como puedes ver abajo.
(http://www.subeimagenes.com/img/re2-1346005.png)

¿Qué es lo que quiero?

1) Con un botón leer el archivo *.smc, es una ROM, un archivo binario.
2) Lo que lea la clase snes_dumper.cs lo tiene que mostrar en sus textBox correspondiente en el Form1.

La mayoría de los datos que quiero visualizar en el TextBox son estas variables.
Código
  1.       // Los diferentes datos que obtenemos de la ROM
  2.        public string Name;
  3.        public byte Layout;
  4.        public byte CartridgeType;
  5.        public byte RomSize;
  6.        public byte RamSize;
  7.        public byte CountryCode;
  8.        public byte LicenseCode;
  9.        public byte VersionNumber;
  10.        ushort Checksum;
  11.        ushort ChecksumCompliment;
  12.        public BankTypeEnum BankType;

Hay 11 variables en el primer Cuadro en verde. Esas 11 variables es lo que tengo que leer en el textBox. La lectura lo hace a la hora de pulsar un botón, seleccionar el archivo binario a leer y lo leído, lo muestra en el formulario. Les dejo el formulario hecho estilo colores y nombrado por Cuadros 1 al 4. El que me interesa mucho es el Cuadro 1 y el Cuadro 4 para cargar el archivo binario.
(http://www.subeimagenes.com/img/re2-1346029.png)

Los nombres de cada textBox están identificado por el nombre de sus variables así no te perderás. Digamos que esto es una plantilla con la clase snes_dumper.cs sin hacer nada, solo a la espera de ser programado.

Les dejo aquí para descargar esta plantilla por llamarlo de alguna manera, bueno, lo llamaremos proyecto vacío.

Descarga (https://www.dropbox.com/s/m2dzec96b69a4hq/ROM_SNES_alfa_v0.2.zip?dl=0)

Espero ayuda para leer esta clase. En resumen, quiero leer las variables que indiqué arriba y lo muestre en el Formulario que he hecho arriba de colorines.

Saludos.


Título: Re: Leer una clase en un formulario Widnows de Visual C#
Publicado por: Eleкtro en 10 Junio 2015, 07:39 am
¿Y cual es el problema?, si ya tienes una Class que lo hace todo.

¿Y si en lugar de perdir que te lo hagan, mejor preguntas por lo que no entiendas de esa Class, para poder hacerlo por tus propios medios?.

Solo debes leer el archivo.smc de principio a fin para generar un array de Bytes, y pasarle esos bytes cómo argumento al constructor de la Class RomDump, el cual automaticamente llama al método ReadHeader y se asignan los valores a las propiedades de esa Class.

Es muy sencillo de realizar (en apenas 2 lineas de código), pero si no has entendido algo, especifica el que.

Te sugiero leer la documentación de los métodos de lectura de la Class System.IO.File, y la documentación de la Class System.IO.FileStream.

PD: Deja los copy/paste, ¡intenta aprender!.

Saludos!


Título: Re: Leer una clase en un formulario Widnows de Visual C#
Publicado por: Meta en 10 Junio 2015, 08:22 am
Buenas campeón:

Buscando el IO.Stream (https://msdn.microsoft.com/es-es/library/system.io.filestream%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396) encontré códigos de ejemplo como este.

Me interesa leer, no modificar, al menos por ahora. Supuestamente es este por lo que veo.
Código
  1.        //Open the stream and read it back.
  2.        using (FileStream fs = File.OpenRead(path))
  3.        {
  4.            byte[] b = new byte[1024];
  5.            UTF8Encoding temp = new UTF8Encoding(true);
  6.            while (fs.Read(b,0,b.Length) > 0)
  7.            {
  8.                Console.WriteLine(temp.GetString(b));
  9.            }
  10.        }

Viendo File.ReadAllBytes (https://msdn.microsoft.com/es-es/library/system.io.file.readallbytes%28v=vs.110%29.aspx). En el Form1 hice este código.
Código
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10.  
  11. using System.IO; // No olvidar.
  12.  
  13. namespace ROM_SNES
  14. {
  15.    public partial class Form1 : Form
  16.    {
  17.        public Form1()
  18.        {
  19.            InitializeComponent();
  20.        }
  21.  
  22.        private void button1_Click(object sender, EventArgs e)
  23.        {
  24.  
  25.            if (openFileDialog1.ShowDialog() == DialogResult.OK)
  26.            {
  27.                SnesKit.RomDump VARIABLE = new SnesKit.RomDump(File.ReadAllBytes(textBox_Nombre_de_archivo.Text.ToString()));
  28.                textBox_Nombre_ruta_archivo.Text = openFileDialog1.FileName.ToString(); // Muestra la ruta del archivo.
  29.            }
  30.        }
  31.    }
  32. }

Lo ejecuta efectivamente, si pulso el botón abrir, muestra este error.
Citar
Excepción no controlada del tipo 'System.ArgumentException' en mscorlib.dll

Información adicional: No se puede dejar vacío el nombre de la ruta de acceso.

Encontré lo que dice del System.ArgumentException (https://msdn.microsoft.com/es-es/library/system.argumentexception%28v=vs.110%29.aspx). Ahí no entiendo nada.

Estoy haciendo pruebas por si acaso. :)

Dejo lo que hice en este enlace.

Descarga (https://www.dropbox.com/s/nnqy544jtoh2ykb/ROM_SNES_Alfa_v0.3.zip?dl=0) Proyecto alfa v0.3. (incluye una rom de 4 MB).

Saludos.


Título: Re: Leer una clase en un formulario Widnows de Visual C#
Publicado por: Eleкtro en 10 Junio 2015, 09:27 am
Con el mensaje de error puedes deducir que la propiedad 'Text' del control 'textBox_Nombre_de_archivo' está vacía, ya que le estás pasando un argumento vacío a la función 'Readallbytes', y esto significa que estás intentando utilizar dicha propiedad antes de haberle asignado ninguna ruta de archivo.

Utiliza la propiedad 'FileName' de la instancia de ese diálogo 'OpenFileDialog'.

Saludos!


Título: Re: Leer una clase en un formulario Widnows de Visual C#
Publicado por: Meta en 10 Junio 2015, 11:04 am
Hola Señor:

Lo he hecho así, me ejecuta, no da problemas, no se si realmente así funciona. Ahora te toca hacer algo como esto a ver que tal.
Código
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10.  
  11. using System.IO; // No olvidar.
  12.  
  13. namespace ROM_SNES
  14. {
  15.    public partial class Form1 : Form
  16.    {
  17.        public Form1()
  18.        {
  19.            InitializeComponent();
  20.        }
  21.  
  22.        private void button1_Click(object sender, EventArgs e)
  23.        {
  24.  
  25.            if (openFileDialog1.ShowDialog() == DialogResult.OK)
  26.            {
  27.                SnesKit.RomDump VARIABLE = new SnesKit.RomDump(File.ReadAllBytes(openFileDialog1.FileName.ToString()));
  28.                textBox_Nombre_ruta_archivo.Text = openFileDialog1.FileName.ToString(); // Muestra la ruta del archivo.
  29.            }
  30.        }
  31.    }
  32. }
  33.  

Ahora estoy bien perdido para leer la variable Name del archivo Snes_dumper.cs.
Usando este otro código, no logro de ninguna manera leer algo de la ROM, al menos el nombre.
Código
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10.  
  11. using System.IO; // No olvidar.
  12.  
  13. namespace ROM_SNES
  14. {
  15.    public partial class Form1 : Form
  16.    {
  17.        public Form1()
  18.        {
  19.            InitializeComponent();
  20.            Mostar_Datos();
  21.        }
  22.  
  23.            public void Mostar_Datos()
  24.    {
  25.         this.textBox_Name.Text  = RomDump.Name;
  26.    }
  27.  
  28.        private void button1_Click(object sender, EventArgs e)
  29.        {
  30.  
  31.            if (openFileDialog1.ShowDialog() == DialogResult.OK)
  32.            {
  33.                SnesKit.RomDump VARIABLE = new SnesKit.RomDump(File.ReadAllBytes(openFileDialog1.FileName.ToString()));
  34.                textBox_Nombre_ruta_archivo.Text = openFileDialog1.FileName.ToString(); // Muestra la ruta del archivo.
  35.            }
  36.        }
  37.    }
  38. }

Error   1   El nombre 'RomDump' no existe en el contexto actual   C:\Users\Usuario\Documents\Visual Studio 2013\Projects\ROM_SNES\ROM_SNES\Form1.cs   25   36   ROM_SNES

Da igual lo que haga, aquí si estoy perdido. Intento leer la classe pero no lo capto.

Saludos.


Título: Re: Leer una clase en un formulario Widnows de Visual C#
Publicado por: Eleкtro en 10 Junio 2015, 11:26 am
Meta, fíjate bien en lo que estás haciendo ...leches xD.

La Class "RomDump" la estás declarando e instanciando en el bloque del event-handler "button1_Click", ahí es donde empieza y donde también termina la vida de ese objeto;
luego, tú estás haciendo un (mal) intento de leer esa instancia en otro método distinto, en el bloque del método "Mostar_Datos", no puedes leer una referencia que no existe.

1. Declara una variable 'snesRom' hacia una referencia vacía de la Class 'RomDump', fuera de cualquier método.
Código
  1. SnesKit.RomDump snesRom

2. Crea una instancia la Class 'RomDump' a la variable 'snesRom', dentro del handler "button1_Click" o dentro del método que prefieras.
Código
  1. this.snesRom = new SnesKit.RomDump(bytes);

3. Ya puedes leer la referencia de la propiedad 'snesRom.Name' donde quieras:
Código
  1. MessageBox.Show(snesRom.Name);

Saludos


Título: Re: Leer una clase en un formulario Widnows de Visual C#
Publicado por: Meta en 10 Junio 2015, 12:56 pm
Buenas honorable Elektro:

Para arriba y para abajo me salió esto.
Código
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10.  
  11. using System.IO; // No olvidar.
  12.  
  13. namespace ROM_SNES
  14. {
  15.    public partial class Form1 : Form
  16.    {
  17.        public Form1()
  18.        {
  19.            InitializeComponent();
  20.        }
  21.  
  22.        private void button1_Click(object sender, EventArgs e)
  23.        {
  24.  
  25.            if (openFileDialog1.ShowDialog() == DialogResult.OK)
  26.            {
  27.                SnesKit.RomDump VARIABLE = new SnesKit.RomDump(File.ReadAllBytes(openFileDialog1.FileName.ToString()));
  28.                textBox_Nombre_ruta_archivo.Text = openFileDialog1.FileName.ToString(); // Muestra la ruta del archivo.
  29.  
  30.                textBox_RomSize.Text = VARIABLE.RomSize.ToString();
  31.            }
  32.        }
  33.    }
  34. }

(http://www.subeimagenes.com/img/autosave-1346254.gif)

Auí hay una Web perfecta para convertir códigos.
https://www.easycalculation.com/hex-converter.php

O verlo directamenta la tabla ASCII.
http://www.elcodigoascii.com.ar/codigo-americano-estandar-intercambio-informacion/codigo-ascii.gif

El 12 que presenta es decimal, quiero se se vea hexadecimal, que es 0C. (En C# se presenta así 0x0C).

Busqué aquí.
https://msdn.microsoft.com/es-es/library/bb311038.aspx?f=255&MSPPError=-2147217396

Este es el código que hice.
Código
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10.  
  11. using System.IO; // No olvidar.
  12.  
  13. namespace ROM_SNES
  14. {
  15.    public partial class Form1 : Form
  16.    {
  17.        public Form1()
  18.        {
  19.            InitializeComponent();
  20.        }
  21.  
  22.        private void button1_Click(object sender, EventArgs e)
  23.        {
  24.  
  25.            if (openFileDialog1.ShowDialog() == DialogResult.OK)
  26.            {
  27.                SnesKit.RomDump VARIABLE = new SnesKit.RomDump(File.ReadAllBytes(openFileDialog1.FileName.ToString()));
  28.                textBox_Nombre_ruta_archivo.Text = openFileDialog1.FileName.ToString(); // Muestra la ruta del archivo.
  29.  
  30.                textBox_RomSize.Text = string.Format("{0:X}", VARIABLE.RomSize);
  31.            }
  32.        }
  33.    }
  34. }
  35.  

Me sale la C. Quiero que salga 0C.


Título: Re: Leer una clase en un formulario Widnows de Visual C#
Publicado por: Eleкtro en 10 Junio 2015, 13:37 pm
Auí hay una Web perfecta para convertir códigos.
https://www.easycalculation.com/hex-converter.php

O verlo directamenta la tabla ASCII.
http://www.elcodigoascii.com.ar/codigo-americano-estandar-intercambio-informacion/codigo-ascii.gif

El 12 que presenta es decimal, quiero se se vea hexadecimal, que es 0C. (En C# se presenta así 0x0C).

No necesitas recurrir a ningún servicio online ni tabla de caracteres, la librería de clases de .Net Framework tiene varias funciones built-in para llevar a cabo ese tipo de conversiones.

Convert.ToInt32 Method - MSDN (https://msdn.microsoft.com/en-us/library/sf1aw27b%28v=vs.110%29.aspx)
Convert.ToString Method - MSDN (https://msdn.microsoft.com/en-us/library/system.convert.tostring%28v=vs.110%29.aspx)
Convert.ToChar Method - MSDN (https://msdn.microsoft.com/en-us/library/system.convert.tochar%28v=vs.110%29.aspx)
y:
String.Format Method - MSDN (https://msdn.microsoft.com/en-us/library/system.string.format%28v=vs.110%29.aspx)

PD: Fíjate en el parámetro 'fromBase' de los overloads de la función Convert.ToInt32, y el parámetro 'toBase' de los overloads de la función Convert.ToString.

Ejemplo:
Código
  1. String.Format("0x{0}", Convert.ToString(255, toBase:=16))

Saludos!


Título: Re: Leer una clase en un formulario Widnows de Visual C#
Publicado por: Meta en 10 Junio 2015, 13:44 pm
Entendido buen hombre:

Hice este código.
Código
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10.  
  11. using System.IO; // No olvidar.
  12.  
  13. namespace ROM_SNES
  14. {
  15.    public partial class Form1 : Form
  16.    {
  17.        public Form1()
  18.        {
  19.            InitializeComponent();
  20.        }
  21.  
  22.        private void button1_Click(object sender, EventArgs e)
  23.        {
  24.  
  25.            if (openFileDialog1.ShowDialog() == DialogResult.OK)
  26.            {
  27.                SnesKit.RomDump VARIABLE = new SnesKit.RomDump(File.ReadAllBytes(openFileDialog1.FileName.ToString()));
  28.                textBox_Nombre_ruta_archivo.Text = openFileDialog1.FileName.ToString(); // Muestra la ruta del archivo.
  29.  
  30.                textBox_Name.Text = VARIABLE.Name;
  31.                textBox_Layout.Text = string.Format("{0:X}", VARIABLE.Layout);
  32.                textBox_CartridgeType.Text = string.Format("{0:X}", VARIABLE.CartridgeType);
  33.                textBox_RomSize.Text = string.Format("{0:X}", VARIABLE.RomSize);
  34.                textBox_RamSize.Text = string.Format("{0:X}", VARIABLE.RamSize);
  35.                textBox_CountryCode.Text = string.Format("{0:X}", VARIABLE.CountryCode);
  36.                textBox_LicenseCode.Text = string.Format("{0:X}", VARIABLE.LicenseCode);
  37.                textBox_VersionNumber.Text = string.Format("{0:X}", VARIABLE.VersionNumber);
  38.                textBox_BankType.Text = VARIABLE.BankType.ToString();
  39.            }
  40.        }
  41.    }
  42. }
  43.  

Me salió este resultado. En los demás txtBox vacíos, no tengo la menor idea de como lograrlo, me machaqué las neuronas un poco por esta tontería.
(http://www.subeimagenes.com/img/autosave-1346289.gif)

El Cuadro 3 Azul si me sale, estaba haciendo pruebas, los demás no.

Saludo.


Título: Re: Leer una clase en un formulario Widnows de Visual C#
Publicado por: Eleкtro en 10 Junio 2015, 13:51 pm
El formato que le das al string es incorrecto, lee el ejemplo que he añadido en mi última respuesta.

Saludos!


Título: Re: Leer una clase en un formulario Widnows de Visual C#
Publicado por: Meta en 10 Junio 2015, 14:13 pm
Lo dejaré así mismo, me gusta.

Código
  1. textBox_Layout.Text = string.Format("0x{0}", VARIABLE.Layout);

Solo falta añadir los demás cuadros vacíos.


Título: Re: Leer una clase en un formulario Widnows de Visual C#
Publicado por: Eleкtro en 10 Junio 2015, 15:07 pm
Lo dejaré así mismo, me gusta.

Código
  1. textBox_Layout.Text = string.Format("0x{0}", VARIABLE.Layout);

Pero eso que haces no tiene ningún sentido aunque te guste; "0x" es el prefijo estándar para un valor hexadecimal, pero la propiedad "Layout" devuelve un valor decimal entre 0 y 255, es decir, un Byte.

Si haces eso solo conseguirás mostrar resultados confusos en la UI.

Saludos!


Título: Re: Leer una clase en un formulario Windows de Visual C#
Publicado por: Meta en 10 Junio 2015, 19:32 pm
Haciendo pruebas o no me sale bien, algo se me escapa o C# no le gusta.

Código
  1. private void button1_Click(object sender, EventArgs e)
  2.        {
  3.  
  4.            if (openFileDialog1.ShowDialog() == DialogResult.OK)
  5.            {
  6.                SnesKit.RomDump VARIABLE = new SnesKit.RomDump(File.ReadAllBytes(openFileDialog1.FileName.ToString()));
  7.                textBox_Nombre_ruta_archivo.Text = openFileDialog1.FileName.ToString(); // Muestra la ruta del archivo.
  8.  
  9.                textBox_Name.Text = VARIABLE.Name;
  10.                //textBox_Layout.Text = string.Format("0x{0}", VARIABLE.Layout);
  11.                textBox_CartridgeType.Text = string.Format("0x{0}", VARIABLE.CartridgeType);
  12.                textBox_RomSize.Text = string.Format("0x{0}", VARIABLE.RomSize);
  13.                textBox_RamSize.Text = string.Format("0x{0}", VARIABLE.RamSize);
  14.                textBox_CountryCode.Text = string.Format("0x{0}", VARIABLE.CountryCode);
  15.                textBox_LicenseCode.Text = string.Format("0x{0}", VARIABLE.LicenseCode);
  16.                textBox_VersionNumber.Text = string.Format("0x{0}", VARIABLE.VersionNumber);
  17.                textBox_BankType.Text = VARIABLE.BankType.ToString();
  18.  
  19.  
  20.                  textBox_Layout.Text = string.Format("0x{0}", Convert.ToString(255, toBase:=16));
  21.  
  22.            }
  23.        }

Hay mucho errores.
Error   3   El término de la expresión ')' no es válido   C:\Users\Usuario\Documents\Visual Studio 2013\Projects\ROM_SNES\ROM_SNES\Form1.cs   41   96   ROM_SNES

Error   1   El término de la expresión '=' no es válido   C:\Users\Usuario\Documents\Visual Studio 2013\Projects\ROM_SNES\ROM_SNES\Form1.cs   41   93   ROM_SNES

Error   4   Se esperaba ;   C:\Users\Usuario\Documents\Visual Studio 2013\Projects\ROM_SNES\ROM_SNES\Form1.cs   41   96   ROM_SNES

Saludos.


Título: Re: Leer una clase en un formulario Windows de Visual C#
Publicado por: Eleкtro en 10 Junio 2015, 19:45 pm
Te voy a hacer un regalito :P ...es cosa tuya traducirlo a C#, o compilar el código en una dll para no tener que traducir.

La SNES siempre me ha fascinado, bueno, tengo cierta melancolía y bastantes roms por ahí perdidas xD, en fin, me ha interesado el tema, he cogido la Class que publicaste al principio del tema, y la he extendido para mejorarla en varios aspectos, añadiendo mayor y mejor documentación, así cómo nuevas funcionalidades.



Cosas a tener en cuenta:

1. Me ha sido imposible descifrar los 13 códigos de paises que se pueden usar en una ROM de SNES, no encuentro información sobre esto en ningún lugar, solo encontré información parcial en la que se dice que '0' equivale a Japón, '1' a U.S., y bajo mis propias conclusiones '8' debe ser España.
Si alguien conoce esta información al completo, que me lo haga saber, gracias.

2. No he testeado mi Class con cientos de ROMs para comprobar que todo funciona cómo debería funcionar a las mil maravillas en todas las circunstancias posibles, pero supongo que si, ya que me he basado en las especificaciones de la cabecera de SNES, las cuales ya estaban implementados en la Class original de donde saqué la idea.
Si alguien encuentra algún error, que me lo comunique, gracias.



A continuación publico el código fuente, y abajo del todo unos ejemplos de lectura y escritura:

Código
  1. ' ***********************************************************************
  2. ' Author   : Elektro.
  3. '            Based on this 3rd party project:
  4. '            https://github.com/Zeokat/SNES-ROM-Header-Dumper-CSharp/blob/master/snes_dumper.cs
  5. ' Modified : 10-June-2015
  6. ' ***********************************************************************
  7. ' <copyright file="SnesRom.vb" company="Elektro Studios">
  8. '     Copyright (c) Elektro Studios. All rights reserved.
  9. ' </copyright>
  10. ' ***********************************************************************
  11.  
  12. #Region " Usage Examples "
  13.  
  14. ' CONTENIDO OMITIDO...
  15.  
  16. #End Region
  17.  
  18. #Region " Option Statements "
  19.  
  20. Option Strict On
  21. Option Explicit On
  22. Option Infer Off
  23.  
  24. #End Region
  25.  
  26. #Region " Imports "
  27.  
  28. Imports System.IO
  29. Imports System.Text
  30.  
  31. #End Region
  32.  
  33. Public NotInheritable Class SnesRom
  34.  
  35. #Region " Properties "
  36.  
  37.    ''' <summary>
  38.    ''' Gets the raw byte-data of the ROM file.
  39.    ''' </summary>
  40.    ''' <value>The raw byte-data of the ROM file.</value>
  41.    Public ReadOnly Property RawData As Byte()
  42.        Get
  43.            Return Me.rawDataB
  44.        End Get
  45.    End Property
  46.    ''' <summary>
  47.    ''' (backing field) The raw byte-data of the ROM file.
  48.    ''' </summary>
  49.    Private ReadOnly rawDataB As Byte()
  50.  
  51.    ''' <summary>
  52.    ''' Gets The ROM header type.
  53.    ''' </summary>
  54.    ''' <remarks>http://romhack.wikia.com/wiki/SMC_header</remarks>
  55.    ''' <value>The ROM header type.</value>
  56.    Public ReadOnly Property HeaderType As HeaderTypeEnum
  57.        Get
  58.            Return Me.headerTypeB
  59.        End Get
  60.    End Property
  61.    ''' <summary>
  62.    ''' (backing field) The ROM header type.
  63.    ''' </summary>
  64.    Private headerTypeB As HeaderTypeEnum
  65.  
  66.    ''' <summary>
  67.    ''' Gets the SNES header address location.
  68.    ''' </summary>
  69.    ''' <remarks>http://romhack.wikia.com/wiki/SNES_header</remarks>
  70.    ''' <value>The SNES header address location.</value>
  71.    Private ReadOnly Property HeaderLocation As Integer
  72.        Get
  73.            Return Me.headerLocationB
  74.        End Get
  75.    End Property
  76.    ''' <summary>
  77.    ''' (backing field) The SNES header address location.
  78.    ''' </summary>
  79.    Private headerLocationB As Integer = 33216
  80.  
  81.    ''' <summary>
  82.    ''' Gets or sets the name of the ROM, typically in ASCII.
  83.    ''' The name buffer consists in 21 characters.
  84.    ''' </summary>
  85.    ''' <remarks>http://romhack.wikia.com/wiki/SNES_header</remarks>
  86.    ''' <value>The name of the ROM.</value>
  87.    Public Property Name As String
  88.        Get
  89.            Return Me.nameB
  90.        End Get
  91.        Set(ByVal value As String)
  92.            Me.SetName(value)
  93.            Me.nameB = value
  94.        End Set
  95.    End Property
  96.    ''' <summary>
  97.    ''' (backing field) The name of the ROM.
  98.    ''' </summary>
  99.    Private nameB As String
  100.  
  101.    ''' <summary>
  102.    ''' Gets the ROM layout.
  103.    ''' The SNES ROM layout describes how the ROM banks appear in a ROM image and in the SNES address space.
  104.    ''' </summary>
  105.    ''' <remarks>http://romhack.wikia.com/wiki/SNES_ROM_layout</remarks>
  106.    ''' <value>The ROM layout.</value>
  107.    Public ReadOnly Property Layout As Byte
  108.        Get
  109.            Return Me.layoutB
  110.        End Get
  111.    End Property
  112.    ''' <summary>
  113.    ''' (backing field) The ROM layout.
  114.    ''' </summary>
  115.    Private layoutB As Byte
  116.  
  117.    ''' <summary>
  118.    ''' Gets the bank type.
  119.    ''' An image contains only LoROM banks or only HiROM banks, not both.
  120.    ''' </summary>
  121.    ''' <remarks>http://romhack.wikia.com/wiki/SNES_ROM_layout</remarks>
  122.    ''' <value>The bank type.</value>
  123.    Public ReadOnly Property BankType As BankTypeEnum
  124.        Get
  125.            Return Me.bankTypeB
  126.        End Get
  127.    End Property
  128.    ''' <summary>
  129.    ''' (backing field) The bank type.
  130.    ''' </summary>
  131.    Private bankTypeB As BankTypeEnum
  132.  
  133.    ''' <summary>
  134.    ''' Gets the cartrifge type, it can be a ROM only, or a ROM with save-RAM.
  135.    ''' </summary>
  136.    ''' <remarks>http://romhack.wikia.com/wiki/SNES_header</remarks>
  137.    ''' <value>The cartridge type.</value>
  138.    Public ReadOnly Property CartridgeType As CartridgeTypeEnum
  139.        Get
  140.            Return Me.cartridgeTypeB
  141.        End Get
  142.    End Property
  143.    ''' <summary>
  144.    ''' (backing field) The cartrifge type.
  145.    ''' </summary>
  146.    Private cartridgeTypeB As CartridgeTypeEnum
  147.  
  148.    ''' <summary>
  149.    ''' Gets the ROM size byte.
  150.    ''' </summary>
  151.    ''' <remarks>http://romhack.wikia.com/wiki/SNES_header</remarks>
  152.    ''' <value>The ROM size byte.</value>
  153.    Public ReadOnly Property RomSize As Byte
  154.        Get
  155.            Return Me.romSizeB
  156.        End Get
  157.    End Property
  158.    ''' <summary>
  159.    ''' (backing field) The ROM size byte.
  160.    ''' </summary>
  161.    Private romSizeB As Byte
  162.  
  163.    ''' <summary>
  164.    ''' Gets the RAM size byte.
  165.    ''' </summary>
  166.    ''' <remarks>http://romhack.wikia.com/wiki/SNES_header</remarks>
  167.    ''' <value>The RAM size byte.</value>
  168.    Public ReadOnly Property RamSize As Byte
  169.        Get
  170.            Return Me.ramSizeB
  171.        End Get
  172.    End Property
  173.    ''' <summary>
  174.    ''' (backing field) The ROM size byte.
  175.    ''' </summary>
  176.    Private ramSizeB As Byte
  177.  
  178.    ''' <summary>
  179.    ''' Gets or sets the country data.
  180.    ''' </summary>
  181.    ''' <remarks>http://romhack.wikia.com/wiki/SNES_header</remarks>
  182.    ''' <value>The country data.</value>
  183.    Public Property Country As CountryData
  184.        Get
  185.            Return New CountryData(Me.CountryCode)
  186.        End Get
  187.        Set(ByVal value As CountryData)
  188.            Me.SetByte(Me.startAddressCountryCode, value.Code)
  189.            Me.CountryCode = value.Code
  190.        End Set
  191.    End Property
  192.  
  193.    ''' <summary>
  194.    ''' The country code.
  195.    ''' </summary>
  196.    Private Property CountryCode As Byte
  197.  
  198.    ''' <summary>
  199.    ''' Gets or sets the license code.
  200.    ''' </summary>
  201.    ''' <remarks>http://romhack.wikia.com/wiki/SNES_header</remarks>
  202.    ''' <value>The license code.</value>
  203.    Public Property LicenseCode As Byte
  204.        Get
  205.            Return Me.licenseCodeB
  206.        End Get
  207.        Set(ByVal value As Byte)
  208.            Me.SetByte(Me.startAddressLicenseCode, value)
  209.            Me.licenseCodeB = value
  210.        End Set
  211.    End Property
  212.    ''' <summary>
  213.    ''' (backing field) The license code.
  214.    ''' </summary>
  215.    Private licenseCodeB As Byte
  216.  
  217.    ''' <summary>
  218.    ''' Gets or sets the version number.
  219.    ''' </summary>
  220.    ''' <remarks>http://romhack.wikia.com/wiki/SNES_header</remarks>
  221.    ''' <value>The version number.</value>
  222.    Public Property VersionNumber As Byte
  223.        Get
  224.            Return Me.versionNumberB
  225.        End Get
  226.        Set(ByVal value As Byte)
  227.            Me.SetByte(Me.startAddressVersionNumber, value)
  228.            Me.versionNumberB = value
  229.        End Set
  230.    End Property
  231.    ''' <summary>
  232.    ''' (backing field) The version number.
  233.    ''' </summary>
  234.    Private versionNumberB As Byte
  235.  
  236.    ''' <summary>
  237.    ''' Gets the checksum compliment.
  238.    ''' </summary>
  239.    ''' <remarks>http://romhack.wikia.com/wiki/SNES_header</remarks>
  240.    ''' <value>The checksum compliment.</value>
  241.    Public ReadOnly Property ChecksumCompliment As UShort
  242.        Get
  243.            Return Me.checksumComplimentB
  244.        End Get
  245.    End Property
  246.    ''' <summary>
  247.    ''' (backing field) The checksum compliment.
  248.    ''' </summary>
  249.    Private checksumComplimentB As UShort
  250.  
  251.    ''' <summary>
  252.    ''' Gets the checksum.
  253.    ''' </summary>
  254.    ''' <remarks>http://romhack.wikia.com/wiki/SNES_header</remarks>
  255.    ''' <value>The checksum.</value>
  256.    Public ReadOnly Property Checksum As UShort
  257.        Get
  258.            Return Me.checksumB
  259.        End Get
  260.    End Property
  261.    ''' <summary>
  262.    ''' (backing field) The checksum.
  263.    ''' </summary>
  264.    Private checksumB As UShort
  265.  
  266. #End Region
  267.  
  268. #Region " Header Addresses "
  269.  
  270.    ' ********************************************************************************************************************
  271.    ' NOTE:
  272.    ' The reason for the variables that are commented-out is just because are unused, but could be helpful in the future.
  273.    ' ********************************************************************************************************************
  274.  
  275.    ' ''' <summary>
  276.    ' ''' The start address of a Lo-ROM header.
  277.    ' ''' </summary>
  278.    'Private ReadOnly loRomHeaderAddress As UShort = 32704
  279.  
  280.    ' ''' <summary>
  281.    ' ''' The start address of a Hi-ROM header.
  282.    ' ''' </summary>
  283.    'Private ReadOnly hiRomHeaderAddress As UShort = 65472
  284.  
  285.    ''' <summary>
  286.    ''' The start address of the ROM name.
  287.    ''' </summary>
  288.    Private ReadOnly startAddressName As Integer = 0
  289.  
  290.    ''' <summary>
  291.    ''' The end address of the ROM name.
  292.    ''' </summary>
  293.    Private ReadOnly endAddressName As Integer = 20
  294.  
  295.    ''' <summary>
  296.    ''' The start address of the ROM layout.
  297.    ''' </summary>
  298.    Private ReadOnly startAddressLayout As Integer = 21
  299.  
  300.    ' ''' <summary>
  301.    ' ''' The end address of the ROM layout.
  302.    ' ''' </summary>
  303.    'Private ReadOnly endAddressLayout As Integer = 21
  304.  
  305.    ''' <summary>
  306.    ''' The start address of the ROM cartridge type.
  307.    ''' </summary>
  308.    Private ReadOnly startAddressCartridgeType As Integer = 22
  309.  
  310.    ' ''' <summary>
  311.    ' ''' The end address of the ROM cartridge type.
  312.    ' ''' </summary>
  313.    'Private ReadOnly endAddressCartridgeType As Integer = 22
  314.  
  315.    ''' <summary>
  316.    ''' The start address of the ROM size (rom).
  317.    ''' </summary>
  318.    Private ReadOnly startAddressRomSize As Integer = 23
  319.  
  320.    ' ''' <summary>
  321.    ' ''' The end address of the ROM size (rom).
  322.    ' ''' </summary>
  323.    'Private ReadOnly endAddressRomSize As Integer = 23
  324.  
  325.    ''' <summary>
  326.    ''' The start address of the ROM size (ram).
  327.    ''' </summary>
  328.    Private ReadOnly startAddressRamSize As Integer = 24
  329.  
  330.    ' ''' <summary>
  331.    ' ''' The end address of the ROM size (ram).
  332.    ' ''' </summary>
  333.    'Private ReadOnly endAddressRamSize As Integer = 24
  334.  
  335.    ''' <summary>
  336.    ''' The start address of the ROM country code.
  337.    ''' </summary>
  338.    Private ReadOnly startAddressCountryCode As Integer = 25
  339.  
  340.    ' ''' <summary>
  341.    ' ''' The end address of the ROM country code.
  342.    ' ''' </summary>
  343.    'Private ReadOnly endAddressCountryCode As Integer = 25
  344.  
  345.    ''' <summary>
  346.    ''' The start address of the ROM license code.
  347.    ''' </summary>
  348.    Private ReadOnly startAddressLicenseCode As Integer = 26
  349.  
  350.    ' ''' <summary>
  351.    ' ''' The end address of the ROM license code.
  352.    ' ''' </summary>
  353.    'Private ReadOnly endAddressLicenseCode As Integer = 26
  354.  
  355.    ''' <summary>
  356.    ''' The start address of the ROM Version Number.
  357.    ''' </summary>
  358.    Private ReadOnly startAddressVersionNumber As Integer = 27
  359.  
  360.    ' ''' <summary>
  361.    ' ''' The end address of the ROM Version Number.
  362.    ' ''' </summary>
  363.    'Private ReadOnly endAddresVersionNumber As Integer = 27
  364.  
  365.    ''' <summary>
  366.    ''' The start address of the ROM checksum compliment.
  367.    ''' </summary>
  368.    Private ReadOnly startAddressChecksumCompliment As Integer = 28
  369.  
  370.    ''' <summary>
  371.    ''' The end address of the ROM checksum compliment.
  372.    ''' </summary>
  373.    Private ReadOnly endAddressChecksumCompliment As Integer = 29
  374.  
  375.    ''' <summary>
  376.    ''' The start address of the ROM checksum.
  377.    ''' </summary>
  378.    Private ReadOnly startAddressChecksum As Integer = 30
  379.  
  380.    ''' <summary>
  381.    ''' The end address of the ROM checksum.
  382.    ''' </summary>
  383.    Private ReadOnly endAddressChecksum As Integer = 31
  384.  
  385. #End Region
  386.  
  387. #Region " Enumerations "
  388.  
  389.    ''' <summary>
  390.    ''' Specifies a SNES ROM header type.
  391.    ''' A headered ROM has SMC header and SNES header.
  392.    ''' A headerless ROM has no SMC header, but still contains a SNES header.
  393.    ''' Note that both a LoRom and HiRom images can be headered, or headerless.
  394.    ''' <remarks>http://romhack.wikia.com/wiki/SNES_header</remarks>
  395.    ''' </summary>
  396.    Public Enum HeaderTypeEnum As Integer
  397.  
  398.        ''' <summary>
  399.        ''' A headered SNES ROM.
  400.        ''' The ROM contains an SMC header, and also contains an SNES header.
  401.        ''' </summary>
  402.        Headered = 0
  403.  
  404.        ''' <summary>
  405.        ''' A headerless SNES ROM.
  406.        ''' The ROM does not contains an SMC header, but contains an SNES header.
  407.        ''' </summary>
  408.        Headerless = 1
  409.  
  410.    End Enum
  411.  
  412.    ''' <summary>
  413.    ''' Specifies a SNES ROM bank type.
  414.    ''' <remarks>http://romhack.wikia.com/wiki/SNES_ROM_layout</remarks>
  415.    ''' </summary>
  416.    Public Enum BankTypeEnum As UShort
  417.  
  418.        ''' <summary>
  419.        ''' A LoROM maps each ROM bank into the upper half (being addresses $8000 to $ffff) of each SNES bank,
  420.        ''' starting with SNES bank $00, and starting again with SNES bank $80.
  421.        ''' </summary>
  422.        LoRom = 32704US
  423.  
  424.        ''' <summary>
  425.        ''' A HiROM maps each ROM bank into the whole (being addresses $0000 to $ffff) of each SNES bank,
  426.        ''' starting with SNES bank $40, and starting again with SNES bank $80.
  427.        ''' </summary>
  428.        HiRom = 65472US
  429.  
  430.    End Enum
  431.  
  432.    ''' <summary>
  433.    ''' Specifies a SNES ROM cartridge type.
  434.    ''' <remarks>http://romhack.wikia.com/wiki/SNES_ROM_layout</remarks>
  435.    ''' </summary>
  436.    Public Enum CartridgeTypeEnum As Byte
  437.  
  438.        ''' <summary>
  439.        ''' A ROM without save-RAM.
  440.        ''' </summary>
  441.        NoSram0 = 0
  442.  
  443.        ''' <summary>
  444.        ''' A ROM without save-RAM.
  445.        ''' <remarks>I didn't fully verified this value...</remarks>
  446.        ''' </summary>
  447.        NoSram1 = 1
  448.  
  449.        ''' <summary>
  450.        ''' A ROM with save-RAM.
  451.        ''' </summary>
  452.        Sram = 2
  453.  
  454.    End Enum
  455.  
  456. #End Region
  457.  
  458. #Region " Exceptions "
  459.  
  460.    ''' <summary>
  461.    ''' Exception that is thrown when a SNES ROM has an invalid format.
  462.    ''' </summary>
  463.    <Serializable>
  464.    Public NotInheritable Class InvalidRomFormatException : Inherits Exception
  465.  
  466.        ''' <summary>
  467.        ''' Initializes a new instance of the <see cref="InvalidROMFormatException"/> class.
  468.        ''' </summary>
  469.        Public Sub New()
  470.            MyBase.New("The SNES ROM image has an invalid format.")
  471.        End Sub
  472.  
  473.        ''' <summary>
  474.        ''' Initializes a new instance of the <see cref="InvalidROMFormatException"/> class.
  475.        ''' </summary>
  476.        ''' <param name="message">The message that describes the error.</param>
  477.        Public Sub New(ByVal message As String)
  478.            MyBase.New(message)
  479.        End Sub
  480.  
  481.        ''' <summary>
  482.        ''' Initializes a new instance of the <see cref="InvalidROMFormatException"/> class.
  483.        ''' </summary>
  484.        ''' <param name="message">The message that describes the error.</param>
  485.        ''' <param name="inner">The inner exception.</param>
  486.        Public Sub New(ByVal message As String, ByVal inner As Exception)
  487.            MyBase.New(message, inner)
  488.        End Sub
  489.  
  490.    End Class
  491.  
  492. #End Region
  493.  
  494. #Region " Types "
  495.  
  496.    ''' <summary>
  497.    ''' Defines a SNES ROM country.
  498.    ''' </summary>
  499.    <Serializable>
  500.    Public NotInheritable Class CountryData
  501.  
  502. #Region " Properties "
  503.  
  504.        ''' <summary>
  505.        ''' Gets the region, which can de PAL or NTSC.
  506.        ''' </summary>
  507.        ''' <remarks>http://romhack.wikia.com/wiki/SNES_header</remarks>
  508.        ''' <value>The country code.</value>
  509.        Public ReadOnly Property Region As RegionTypeEnum
  510.            Get
  511.                Return Me.regionB
  512.            End Get
  513.        End Property
  514.        ''' <summary>
  515.        ''' (backing field) The region, which can de PAL or NTSC.
  516.        ''' </summary>
  517.        Private ReadOnly regionB As RegionTypeEnum
  518.  
  519.        ''' <summary>
  520.        ''' Gets the country code.
  521.        ''' </summary>
  522.        ''' <value>The country code.</value>
  523.        Public ReadOnly Property Code As Byte
  524.            Get
  525.                Return Me.codeB
  526.            End Get
  527.        End Property
  528.        ''' <summary>
  529.        ''' (backing field) The country code.
  530.        ''' </summary>
  531.        Private ReadOnly codeB As Byte
  532.  
  533.        ''' <summary>
  534.        ''' Gets the country name.
  535.        ''' </summary>
  536.        ''' <value>The country name.</value>
  537.        Public ReadOnly Property Name As String
  538.            Get
  539.                Return Me.nameB
  540.            End Get
  541.        End Property
  542.        ''' <summary>
  543.        ''' (backing field) The country name.
  544.        ''' </summary>
  545.        Private ReadOnly nameB As String
  546.  
  547. #End Region
  548.  
  549. #Region " Enumerations "
  550.  
  551.        ''' <summary>
  552.        ''' Specifies a SNES ROM region type.
  553.        ''' <remarks>http://romhack.wikia.com/wiki/SNES_header</remarks>
  554.        ''' </summary>
  555.        Public Enum RegionTypeEnum As Integer
  556.  
  557.            ''' <summary>
  558.            ''' A PAL SNES ROM.
  559.            ''' </summary>
  560.            Pal = 0
  561.  
  562.            ''' <summary>
  563.            ''' An NTSC SNES ROM.
  564.            ''' </summary>
  565.            Ntsc = 1
  566.  
  567.        End Enum
  568.  
  569. #End Region
  570.  
  571. #Region " Countries "
  572.  
  573.        ''' <summary>
  574.        ''' The known ROM countries, based on country code from 0 to 13, so countrycode 0 = Japan, countrycode 1 = United States, and so on...
  575.        ''' Unknown country codes are just unknown.
  576.        ''' </summary>
  577.        Private ReadOnly countryDict As New Dictionary(Of Integer, String) From
  578.            {
  579.                {0, "Japan"},
  580.                {1, "United States"},
  581.                {2, "Unknown"},
  582.                {3, "Unknown"},
  583.                {4, "Unknown"},
  584.                {5, "Unknown"},
  585.                {6, "Unknown"},
  586.                {7, "Unknown"},
  587.                {8, "Spain"},
  588.                {9, "Unknown"},
  589.                {10, "Unknown"},
  590.                {11, "Unknown"},
  591.                {12, "Unknown"},
  592.                {13, "Unknown"}
  593.            }
  594.  
  595. #End Region
  596.  
  597. #Region " Regions "
  598.  
  599.        ''' <summary>
  600.        ''' The country codes for NTSC region.
  601.        ''' <remarks>http://romhack.wikia.com/wiki/SMC_header</remarks>
  602.        ''' </summary>
  603.        Private ReadOnly ntscRegionCodes As Integer() =
  604.            {0, 1, 13}
  605.  
  606.        ''' <summary>
  607.        ''' The country codes for PAL region.
  608.        ''' <remarks>http://romhack.wikia.com/wiki/SMC_header</remarks>
  609.        ''' </summary>
  610.        Private ReadOnly palRegionCodes As Integer() =
  611.            {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}
  612.  
  613. #End Region
  614.  
  615. #Region " Constructors "
  616.  
  617.        ''' <summary>
  618.        ''' Initializes a new instance of the <see cref="CountryData"/> class.
  619.        ''' </summary>
  620.        ''' <param name="countryCode">The SNES ROM country code.</param>
  621.        ''' <exception cref="ArgumentException">Invalid country code.;countryCode</exception>
  622.        Public Sub New(ByVal countryCode As Byte)
  623.  
  624.            If Not (Me.ntscRegionCodes.Concat(Me.palRegionCodes)).Contains(countryCode) Then
  625.                Throw New ArgumentException(message:="Invalid country code.", paramName:="countryCode")
  626.  
  627.            Else
  628.                Me.codeB = countryCode
  629.                Me.nameB = Me.countryDict(countryCode)
  630.  
  631.                ' Determine region.
  632.                If Me.ntscRegionCodes.Contains(countryCode) Then
  633.                    Me.regionB = RegionTypeEnum.Ntsc
  634.  
  635.                ElseIf Me.palRegionCodes.Contains(countryCode) Then
  636.                    Me.regionB = RegionTypeEnum.Pal
  637.  
  638.                End If
  639.  
  640.            End If
  641.  
  642.        End Sub
  643.  
  644.        ''' <summary>
  645.        ''' Prevents a default instance of the <see cref="CountryData"/> class from being created.
  646.        ''' </summary>
  647.        Private Sub New()
  648.        End Sub
  649.  
  650. #End Region
  651.  
  652.    End Class
  653.  
  654. #End Region
  655.  
  656. #Region " Constructors "
  657.  
  658.    ''' <summary>
  659.    ''' Prevents a default instance of the <see cref="SnesRom"/> class from being created.
  660.    ''' </summary>
  661.    Private Sub New()
  662.    End Sub
  663.  
  664.    ''' <summary>
  665.    ''' Initializes a new instance of the <see cref="SnesRom"/> class.
  666.    ''' </summary>
  667.    ''' <param name="romFilePath">The SNES ROM file path.</param>
  668.    Public Sub New(ByVal romFilePath As String)
  669.  
  670.        Me.New(File.ReadAllBytes(romFilePath))
  671.  
  672.    End Sub
  673.  
  674.    ''' <summary>
  675.    ''' Initializes a new instance of the <see cref="SnesRom"/> class.
  676.    ''' </summary>
  677.    ''' <param name="romData">The raw byte-data of the ROM file.</param>
  678.    Public Sub New(ByVal romData As Byte())
  679.  
  680.        Me.rawDataB = romData
  681.  
  682.        Me.VerifyRomFormat()
  683.        Me.VerifyBankType()
  684.        Me.ReadHeader()
  685.  
  686.    End Sub
  687.  
  688. #End Region
  689.  
  690. #Region " Private Methods "
  691.  
  692.    ''' <summary>
  693.    ''' Reads the ROM header to retrieve the header data.
  694.    ''' </summary>
  695.    Private Sub ReadHeader()
  696.  
  697.        ' Read range of bytes.
  698.        Me.nameB = Encoding.ASCII.GetString(Me.GetBytes(Me.startAddressName, Me.endAddressName)).Trim
  699.  
  700.        ' Read single bytes.
  701.        Me.layoutB = Me.GetByte(Me.startAddressLayout)
  702.        Me.cartridgeTypeB = DirectCast(Me.GetByte(Me.startAddressCartridgeType), CartridgeTypeEnum)
  703.        Me.romSizeB = Me.GetByte(Me.startAddressRomSize)
  704.        Me.ramSizeB = Me.GetByte(Me.startAddressRamSize)
  705.        Me.CountryCode = Me.GetByte(Me.startAddressCountryCode)
  706.        Me.LicenseCode = Me.GetByte(Me.startAddressLicenseCode)
  707.        Me.VersionNumber = Me.GetByte(Me.startAddressVersionNumber)
  708.  
  709.    End Sub
  710.  
  711.    ''' <summary>
  712.    ''' Verifies the SNES ROM format.
  713.    ''' </summary>
  714.    ''' <exception cref="SnesRom.InvalidRomFormatException">The SNES ROM image has an invalid format.</exception>
  715.    Private Sub VerifyRomFormat()
  716.  
  717.        If (Me.rawDataB.Length Mod 1024 = 512) Then
  718.            Me.headerTypeB = HeaderTypeEnum.Headered
  719.  
  720.        ElseIf (Me.rawDataB.Length Mod 1024 = 0) Then
  721.            Me.headerTypeB = HeaderTypeEnum.Headerless
  722.  
  723.        Else
  724.            Throw New InvalidRomFormatException(message:="The SNES ROM image has an invalid format.")
  725.  
  726.        End If
  727.  
  728.    End Sub
  729.  
  730.    ''' <summary>
  731.    ''' Verifies the SNES ROM bank type.
  732.    ''' </summary>
  733.    ''' <exception cref="Exception">Cannot recognize the bank type.</exception>
  734.    Private Sub VerifyBankType()
  735.  
  736.        If Me.HeaderIsAt(BankTypeEnum.LoRom) Then
  737.            Me.bankTypeB = BankTypeEnum.LoRom
  738.  
  739.        ElseIf Me.HeaderIsAt(BankTypeEnum.HiRom) Then
  740.            Me.bankTypeB = BankTypeEnum.HiRom
  741.  
  742.        Else
  743.            Throw New Exception(message:="Cannot recognize the bank type.")
  744.  
  745.        End If
  746.  
  747.    End Sub
  748.  
  749.    ''' <summary>
  750.    ''' Verifies the checksum.
  751.    ''' </summary>
  752.    ''' <remarks>
  753.    ''' Offset 0x07FC0 in a headerless LoROM image (LoROM rom sin smc header)
  754.    ''' Offset 0x0FFC0 in a headerless HiROM image (HiROM rom sin smc header)
  755.    ''' </remarks>
  756.    ''' <returns><c>true</c> if checksum is ok, <c>false</c> otherwise.</returns>
  757.    Private Function VerifyChecksum() As Boolean
  758.  
  759.        If Me.HeaderType = HeaderTypeEnum.Headered Then
  760.            Me.headerLocationB += 512
  761.        End If
  762.  
  763.        Me.checksumComplimentB = BitConverter.ToUInt16(Me.GetBytes(Me.startAddressChecksumCompliment, Me.endAddressChecksumCompliment), startIndex:=0)
  764.  
  765.        Me.checksumB = BitConverter.ToUInt16(Me.GetBytes(Me.startAddressChecksum, Me.endAddressChecksum), startIndex:=0)
  766.  
  767.        Return CUShort(Me.Checksum Xor Me.ChecksumCompliment).Equals(UShort.MaxValue)
  768.  
  769.    End Function
  770.  
  771.    ''' <summary>
  772.    ''' Determines whether the ROM header is in the specified address.
  773.    ''' </summary>
  774.    ''' <param name="address">The address.</param>
  775.    ''' <returns><c>true</c> if the ROM header is in the specified address, <c>false</c> otherwise.</returns>
  776.    Private Function HeaderIsAt(ByVal address As UShort) As Boolean
  777.  
  778.        Me.headerLocationB = address
  779.        Return Me.VerifyChecksum()
  780.  
  781.    End Function
  782.  
  783.    ''' <summary>
  784.    ''' Gets the specified byte from the raw byte-data.
  785.    ''' </summary>
  786.    ''' <param name="address">The address.</param>
  787.    ''' <returns>The specified byte from the raw byte-data.</returns>
  788.    Private Function GetByte(ByVal address As Integer) As Byte
  789.  
  790.        Return Buffer.GetByte(array:=Me.RawData,
  791.                              index:=Me.HeaderLocation + address)
  792.  
  793.    End Function
  794.  
  795.    ''' <summary>
  796.    ''' Gets the specified range of bytes from the raw byte-data.
  797.    ''' </summary>
  798.    ''' <param name="from">From address.</param>
  799.    ''' <param name="to">To address.</param>
  800.    ''' <returns>The specified bytes from the raw byte-data.</returns>
  801.    Private Function GetBytes(ByVal from As Integer,
  802.                              ByVal [to] As Integer) As Byte()
  803.  
  804.        Return Me.RawData.Skip(Me.HeaderLocation + from).Take(([to] - from) + 1).ToArray()
  805.  
  806.    End Function
  807.  
  808.    ''' <summary>
  809.    ''' Replaces a single byte in the raw byte-data, with the specified data.
  810.    ''' </summary>
  811.    ''' <param name="address">the address.</param>
  812.    ''' <param name="data">The byte-data.</param>
  813.    Private Sub SetByte(ByVal address As Integer,
  814.                       ByVal data As Byte)
  815.  
  816.        Buffer.SetByte(array:=Me.rawDataB,
  817.                       index:=Me.HeaderLocation + address,
  818.                       value:=data)
  819.  
  820.    End Sub
  821.  
  822.    ''' <summary>
  823.    ''' Replaces the specified range of bytes in the raw byte-data, with the specified data.
  824.    ''' </summary>
  825.    ''' <param name="from">From address.</param>
  826.    ''' <param name="to">To address.</param>
  827.    ''' <param name="data">The byte-data.</param>
  828.    ''' <exception cref="ArgumentException">The byte-length of the specified data differs from the byte-length to be replaced;data</exception>
  829.    Private Sub SetBytes(ByVal from As Integer,
  830.                        ByVal [to] As Integer,
  831.                        ByVal data As Byte())
  832.  
  833.        If data.Length <> (([to] - from) + 1) Then
  834.            Throw New ArgumentException("The byte-length of the specified data differs from the byte-length to be replaced.", "data")
  835.  
  836.        Else
  837.            Buffer.BlockCopy(src:=data, srcOffset:=0,
  838.                             dst:=Me.rawDataB, dstOffset:=Me.HeaderLocation + from,
  839.                             count:=([to] - from) + 1)
  840.  
  841.        End If
  842.  
  843.    End Sub
  844.  
  845.    ''' <summary>
  846.    ''' Sets the ROM name.
  847.    ''' </summary>
  848.    ''' <param name="name">The ROM name.</param>
  849.    ''' <exception cref="ArgumentNullException">name</exception>
  850.    ''' <exception cref="ArgumentException">The name should contain 21 or less characters;name.</exception>
  851.    Private Sub SetName(ByVal name As String)
  852.  
  853.        Dim fixedNameLength As Integer = (Me.endAddressName - Me.startAddressName) + 1
  854.  
  855.        If String.IsNullOrEmpty(name) Then
  856.            Throw New ArgumentNullException(paramName:="name")
  857.  
  858.        ElseIf (name.Length > fixedNameLength) Then
  859.            Throw New ArgumentException(message:="The name should contain 21 or less characters.", paramName:="name")
  860.  
  861.        Else
  862.            ' fill with spaces up to 21 character length.
  863.            name = name.PadRight(totalWidth:=fixedNameLength, paddingChar:=" "c)
  864.  
  865.            Me.SetBytes(Me.startAddressName, Me.endAddressName, Encoding.ASCII.GetBytes(name))
  866.  
  867.        End If
  868.  
  869.    End Sub
  870.  
  871. #End Region
  872.  
  873. #Region " Public Methods "
  874.  
  875.    ''' <summary>
  876.    ''' Save the ROM changes to the specified file path.
  877.    ''' </summary>
  878.    ''' <param name="filePath">The ROM file path.</param>
  879.    ''' <param name="replace">
  880.    ''' If set to <c>true</c>, then replaces any existing file,
  881.    ''' otherwise, throws an <see cref="IOException"/> exception if file already exists.
  882.    ''' </param>
  883.    ''' <exception cref="IOException">The destination file already exists.</exception>
  884.    Public Sub Save(ByVal filePath As String, ByVal replace As Boolean)
  885.  
  886.        If Not replace AndAlso File.Exists(filePath) Then
  887.            Throw New IOException(message:="The destination file already exists.")
  888.  
  889.        Else
  890.            Try
  891.                File.WriteAllBytes(filePath, Me.rawDataB)
  892.  
  893.            Catch ex As Exception
  894.                Throw
  895.  
  896.            End Try
  897.  
  898.        End If
  899.  
  900.    End Sub
  901.  
  902. #End Region
  903.  
  904. End Class



Ejemplo para leer los datos de una ROM:
Código
  1. Dim romDump As New SnesRom("C:\ROM.smc")
  2. ' Or...
  3. ' Dim romDump As New SnesRom(File.ReadAllBytes("C:\ROM.smc"))
  4.  
  5. Dim sb As New StringBuilder
  6. With sb
  7.    .AppendLine(String.Format("Name...............: {0}", romDump.Name))
  8.    .AppendLine(String.Format("Bank Type..........: {0}", romDump.BankType.ToString))
  9.    .AppendLine(String.Format("Cartridge Type.....: {0}", romDump.CartridgeType.ToString.ToUpper))
  10.    .AppendLine(String.Format("Checksum...........: {0}", romDump.Checksum.ToString))
  11.    .AppendLine(String.Format("Checksum Compliment: {0}", romDump.ChecksumCompliment.ToString))
  12.    .AppendLine(String.Format("Country Region.....: {0}", romDump.Country.Region.ToString.ToUpper))
  13.    .AppendLine(String.Format("Country Code.......: {0}", romDump.Country.Code.ToString))
  14.    .AppendLine(String.Format("Country Name.......: {0}", romDump.Country.Name))
  15.    .AppendLine(String.Format("Header Type........: {0}", romDump.HeaderType.ToString))
  16.    .AppendLine(String.Format("Layout.............: {0}", romDump.Layout.ToString))
  17.    .AppendLine(String.Format("License Code.......: {0}", romDump.LicenseCode.ToString))
  18.    .AppendLine(String.Format("RAM Size...........: {0}", romDump.RamSize.ToString))
  19.    .AppendLine(String.Format("ROM Size...........: {0}", romDump.RomSize.ToString))
  20.    .AppendLine(String.Format("Version Number.....: {0}", romDump.VersionNumber.ToString))
  21. End With
  22.  
  23. Clipboard.SetText(sb.ToString) : MessageBox.Show(sb.ToString)

Resultado de ejecución de la lectura de una ROM:
Código:
Name...............: THE LEGEND OF ZELDA
Bank Type..........: LoRom
Cartridge Type.....: SRAM
Checksum...........: 44813
Checksum Compliment: 20722
Country Region.....: NTSC
Country Code.......: 1
Country Name.......: United States
Header Type........: Headered
Layout.............: 32
License Code.......: 1
RAM Size...........: 3
ROM Size...........: 10
Version Number.....: 0

Ejemplo para modificar una ROM:
Código
  1. Dim romDump As New SnesRom("C:\ROM.smc")
  2. ' Or...
  3. ' Dim romDump As New SnesRom(File.ReadAllBytes("C:\Rom.smc"))
  4.  
  5. With romDump
  6.    .Name = "Elektrozoider"
  7.    .Country = New SnesRom.CountryData(countryCode:=8) ' Spain.
  8.    .VersionNumber = CByte(3)
  9.    .Save("C:\Hacked.smc", replace:=True)
  10. End With


Título: Re: Leer una clase en un formulario Windows de Visual C#
Publicado por: Meta en 10 Junio 2015, 20:08 pm
Hola:

Fuerte código. ;)

Con estas dos Web he intentado traducirloa C# y me dice:
http://www.developerfusion.com/tools/convert/vb-to-csharp/?batchId=37f5bff7-8541-40f9-aa53-a9e112a0aac2
Citar
An error occured converting your code, probably due to a syntax error: -- line 577 col 84: "{" expected

En esta otra Web me dice.
http://converter.telerik.com/
Citar
CONVERSION ERROR: Code could not be converted. Details:

-- line 577 col 84: "{" expected

Please check for any errors in the original code and try again.


Muy pero que muy, muy, muy y muy buen trabajo.

Lo del código del país, lo poco he encontra está aquí.
http://romhack.wikia.com/wiki/SNES_header
http://romhack.wikia.com/wiki/SMC_header

No se si el código del país con teléfonos tiene algo que ver.
http://personas.entel.cl/PortalPersonas/appmanager/entelpcs/personas?_nfpb=true&_pageLabel=P4400216791251672510516

Esto no tiene nada que ver, pero puede dar ideas para algo.
http://www.elotrolado.net/hilo_acerca-de-los-codigos-de-los-juegos-de-super-nintendo_999526

Más datos referente a código de país de la ROM.
http://es.wikipedia.org/wiki/Imagen_ROM

Seguiré buscando...

Por cierto, para leer SmcHeader, no lo tenía en public, ajjajajajaa. Ahora si lo lee.
Código
  1. textBox_SmcHeader.Text = VARIABLE.SmcHeader ? "True" : "False";

Voy acabar los demás. Y la parte que quiero guardar, es la del título del juego, para poner información.

Saludos.


Título: Re: Leer una clase en un formulario Windows de Visual C#
Publicado por: Eleкtro en 10 Junio 2015, 20:25 pm
he intentado traducirloa C# y me dice:

El motor/librería NRefactory que utilizan practicamente todos los traductores, es bastante estricto con los saltos de linea en ciertas partes, los cuales si que están permitidos en la IDE.

Debes escribir el bracket despues del keyword From.

Es decir, de esto:
Citar
Código
  1.        Private ReadOnly countryDict As New Dictionary(Of Integer, String) From
  2.            {
  3.                {0, "Japan"},
  4.                {1, "United States"},
  5.                {2, "Unknown"},
  6.                {3, "Unknown"},
  7.                {4, "Unknown"},
  8.                {5, "Unknown"},
  9.                {6, "Unknown"},
  10.                {7, "Unknown"},
  11.                {8, "Spain"},
  12.                {9, "Unknown"},
  13.                {10, "Unknown"},
  14.                {11, "Unknown"},
  15.                {12, "Unknown"},
  16.                {13, "Unknown"}
  17.            }

A esto otro:
Código
  1.        Private ReadOnly countryDict As New Dictionary(Of Integer, String) From {
  2.                {0, "Japan"},
  3.                {1, "United States"},
  4.                {2, "Unknown"},
  5.                {3, "Unknown"},
  6.                {4, "Unknown"},
  7.                {5, "Unknown"},
  8.                {6, "Unknown"},
  9.                {7, "Unknown"},
  10.                {8, "Spain"},
  11.                {9, "Unknown"},
  12.                {10, "Unknown"},
  13.                {11, "Unknown"},
  14.                {12, "Unknown"},
  15.                {13, "Unknown"}
  16.            }



Muy pero que muy, muy, muy y muy buen trabajo.

Gracias. Alguien debería donarme unos eurillos a mi paypal :silbar:.

Saludos!


Título: Re: Leer una clase en un formulario Windows de Visual C#
Publicado por: Meta en 10 Junio 2015, 21:38 pm
Hola:

Hice esto rápido, ya lo puliré.
Código
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10.  
  11. using System.IO; // No olvidar.
  12.  
  13. namespace ROM_SNES
  14. {
  15.    public partial class Form1 : Form
  16.    {
  17.        public Form1()
  18.        {
  19.            InitializeComponent();
  20.        }
  21.  
  22.        private void button1_Click(object sender, EventArgs e)
  23.        {
  24.  
  25.            if (openFileDialog1.ShowDialog() == DialogResult.OK)
  26.            {
  27.                FileInfo Archivo = new FileInfo(openFileDialog1.FileName);
  28.                SnesKit.RomDump VARIABLE = new SnesKit.RomDump(File.ReadAllBytes(openFileDialog1.FileName.ToString()));
  29.                textBox_Nombre_ruta_archivo.Text = openFileDialog1.FileName.ToString(); // Muestra la ruta del archivo.
  30.                textBox_Name.Text = VARIABLE.Name;
  31.                textBox_Layout.Text = string.Format("{0:X}", VARIABLE.Layout);
  32.                textBox_CartridgeType.Text = string.Format("{0:X}", VARIABLE.CartridgeType);
  33.                textBox_RomSize.Text = string.Format("{0:X}", VARIABLE.RomSize);
  34.                textBox_RamSize.Text = string.Format("{0:X}", VARIABLE.RamSize);
  35.                textBox_CountryCode.Text = string.Format("{0:X}", VARIABLE.CountryCode);
  36.                textBox_LicenseCode.Text = string.Format("{0:X}", VARIABLE.LicenseCode);
  37.                textBox_VersionNumber.Text = string.Format("{0:X}", VARIABLE.VersionNumber);
  38.                textBox_BankType.Text = VARIABLE.BankType.ToString();
  39.                textBox_Checksum.Text = string.Format("{0:X}", VARIABLE.Checksum);
  40.                textBox_ChecksumCompliment.Text = string.Format("{0:X}", VARIABLE.ChecksumCompliment);
  41.                textBox_SmcHeader.Text = VARIABLE.SmcHeader ? "True" : "False";
  42.                textBox_HeaderLocation.Text = string.Format("{0:X}", VARIABLE.HeaderLocation);
  43.                textBox_MB.Text = string.Format("{0:N0}", (Archivo.Length / 1024f) / 1024f); // Resultado 4 MB.
  44.                textBox_KB.Text = string.Format("{0:N0}", (Archivo.Length / 1024f)); // 4.907 KB.
  45.                textBox_Bytes.Text = string.Format("{0:N0}", Archivo.Length); // 4.194.816 B o Bytes.
  46.                textBox_Mbit.Text = string.Format("{0:N0}", ((Archivo.Length / 1024f) / 1024f) * 8); // Mega bits.
  47.            }
  48.        }
  49.    }
  50. }
  51.  

Había que poner variables en public para que me hiciera caso, el que no logro es el textbox addr, no se como poner esa variable en public.

Muestro la imagen de abajo.

(https://social.msdn.microsoft.com/Forums/getfile/667989)

1) Como puedes ver arriba, en el Cuadro 3 azul, en el textBox en MB pone 4. ¿Cómo hago que se vea el subfijo de esta manera?

En vez de 4 MB que muestre 4.00 MB.

2) En el Cuadro 4 amarillo, en el textBox "Nombre del archivo". Cuando abro un archivo en el botón "Arbrir archivo" en eltextBox "Ruta del archivo" se ve la ruta y el nombre del archivo. En el textBox "Nombre del archivo". ¿Cómo hago para que vea su nombre?

He estado mirando los formatos y no me sale.

Saludos.


Título: Re: Leer una clase en un formulario Windows de Visual C#
Publicado por: Eleкtro en 10 Junio 2015, 22:23 pm

1)¿Cómo hago que se vea el subfijo de esta manera?
En vez de 4 MB que muestre 4.00 MB.

Debes usar la extensión ToString para convertir el valor numérico (repito, numérico, no String) a String, dándole el formato númerico al string, donde debes usar un formato que añada una precisión de 2 decimales.

Código
  1. 4.ToString("formato específico")

Es muy sencillo lo que quieres hacer, lee aquí para conocer la sintaxis del formato numérico, no te costará nada encontrar los caracteres que debes para el formato que necesitas darle:
Custom Numeric Format Strings - MSDN (https://msdn.microsoft.com/en-us/library/0c899ak8%28v=vs.110%29.aspx)



2) En el Cuadro 4 amarillo, en el textBox "Nombre del archivo". Cuando abro un archivo en el botón "Arbrir archivo" en eltextBox "Ruta del archivo" se ve la ruta y el nombre del archivo. En el textBox "Nombre del archivo". ¿Cómo hago para que vea su nombre?

Lee los métodos de la Class System.IO.Path, tiene un método para devolver el nombre de archivo de una ruta de archivo. Esto tampoco tiene pérdida.
Path Methods (System.IO) - MSDN (https://msdn.microsoft.com/en-us/library/system.io.path_methods%28v=vs.110%29.aspx)

PD: De todas formas no creo que te costase nada buscar en Google "C# get filename" antes de preguntarlo... seguro que saldran miles de resultados por que es muy básico.

Saludos!


Título: Re: Leer una clase en un formulario Windows de Visual C#
Publicado por: Meta en 11 Junio 2015, 09:55 am
Hola:

Hay algo de aquí que no me cuadra.
http://romhack.wikia.com/wiki/SNES_header

Donde pone:
Código
  1. ROM and RAM size bytes ($ffd7 and $ffd8) Edit
  2.  
  3. Byte $ffd7 indicates the amount of ROM in the cartridge; byte $ffd8 indicates the amount of RAM in the cartridge (excluding the RAM in the SNES system). Both bytes use the same scale.
  4.  
  5.    $00 => no RAM
  6.    $01 => $800 bytes == 2 kilobytes, amount of RAM in Super Mario World
  7.    $02 => $1000 bytes == 4 kilobytes
  8.    $03 => $2000 bytes == 8 kilobytes
  9.    $04 => $4000 bytes == 16 kilobytes
  10.    $05 => $8000 bytes == 32 kilobytes, amount of RAM in Mario Paint
  11.    $06 => $10000 bytes == 64 kilobytes
  12.    $07 => $20000 bytes == 128 kilobytes, amount of RAM in Dezaemon - Kaite Tsukutte Asoberu
  13.    $08 => $40000 bytes == 256 kilobytes, minimum for ROM
  14.    $09 => $80000 bytes == 512 kilobytes, amount of ROM in Super Mario World
  15.    $0a => $100000 bytes == 1 megabyte, amount of ROM in Mario Paint
  16.    $0b => $200000 bytes == 2 megabytes
  17.    $0c => $400000 bytes == 4 megabytes

Según tengo entendido, los valores de la ROM y la RAM son los mismos. Me pasa con cualquier juego. A mi me dan valores diferentes. Fijarse en la imagen de abajo.
(http://www.subeimagenes.com/img/re2-1347002.png)

¿Qué opinas?

Saludos.



Título: Re: Leer una clase en un formulario Windows de Visual C#
Publicado por: Eleкtro en 11 Junio 2015, 15:27 pm
¿Qué opinas?

No quiero parecer arrogante, pero opino que no deberías manejar algo que no entiendes ...y encima haciendo copy/pastes.

Solo has tenido una comprensión incorrecta de las palabras que pone en esa documentación. El tamaño de la memoria de solo lectura (ROM) difiere de la memoria RAM, busca las definiciones de ambas para comprender. La wikipedia está para algo.

Primero deberías aprender lo que te falta por aprender del lenguaje, y de los conceptos que necesites aprender para llevar a cabo esa tarea (aunque yo tampoco soy ningún erudito en el entendimiento de las especificaciones del formato de los cartuchos ROM de SNES ni de la lectura y escritura de offsets), y luego ya, cuando te veas más capaz, te pones a hacer un lector de cabeceras para "X" formato.



Dicho esto, no todo iba a ser malo, he actualizado y mejorado el código fuente que publiqué en la página anterior para añadirle toda la información que faltaba (y más), gracias a las especificaciones que encontré en esta página:
http://softpixel.com/~cwright/sianse/docs/Snesrom.txt
y a esta aplicación para comprobar los resultados de mis modificaciones:
http://www.zophar.net/utilities/snesaud/snes-explorer.html

Ahora el código está mucho mejor, y con algunas funcionalidades de escritura más, aunque sigue faltando algún que otro detalle del que me cuesta encontrar documentación.

Aunque no lo vayas a usar, de todas maneras lo comparto en este hilo por si a otra persona le viene bien esta ayuda en VB.Net:

Código fuente:
http://pastebin.com/JMUEdWrK

Ejemplo de uso para la lectura:
Código
  1. Dim romDump As New SnesRom("C:\ROM.smc")
  2. ' Or...
  3. ' Dim romDump As New SnesRom(File.ReadAllBytes("C:\ROM.smc"))
  4.  
  5. Dim sb As New StringBuilder
  6. With sb
  7.    .AppendLine(String.Format("Name..................: {0}", romDump.Name))
  8.    .AppendLine(String.Format("Bank Type.............: {0}", romDump.BankType.ToString))
  9.    .AppendLine(String.Format("Cartridge Type........: {0}", romDump.CartridgeType.ToString.ToUpper.Replace("_", "/")))
  10.    .AppendLine(String.Format("Checksum..............: {0}", String.Format("0x{0}", Convert.ToString(CInt(romDump.Checksum), toBase:=16).ToUpper)))
  11.    .AppendLine(String.Format("Checksum Complement...: {0}", String.Format("0x{0}", Convert.ToString(CInt(romDump.ChecksumComplement), toBase:=16).ToUpper)))
  12.    .AppendLine(String.Format("Country Code..........: {0}", romDump.Country.Code.ToString))
  13.    .AppendLine(String.Format("Country Name..........: {0}", romDump.Country.Name))
  14.    .AppendLine(String.Format("Country Region........: {0}", romDump.Country.Region.ToString.ToUpper))
  15.    .AppendLine(String.Format("Header Type (SMC).....: {0}", romDump.HeaderType.ToString))
  16.    .AppendLine(String.Format("Layout................: {0}", romDump.Layout.ToString))
  17.    .AppendLine(String.Format("License Code/Name.....: {0}", romDump.LicenseCode.ToString))
  18.    .AppendLine(String.Format("ROM Size..............: {0} MBits", romDump.RomSize.ToString.Substring(1, romDump.RomSize.ToString.LastIndexOf("M") - 2)).Replace("_or_", "/"))
  19.    .AppendLine(String.Format("RAM Size..............: {0} KBits", romDump.RamSize.ToString.Substring(1, romDump.RamSize.ToString.LastIndexOf("K") - 2)))
  20.    .AppendLine(String.Format("Version Number........: 1.{0}", romDump.Version.ToString))
  21. End With
  22.  
  23. Clipboard.SetText(sb.ToString) : MessageBox.Show(sb.ToString)

Resultado de ejecución de la lectura:
Código:
Name..................: SUPER MARIOWORLD
Bank Type.............: LoRom
Cartridge Type........: ROM/SRAM
Checksum..............: 0xA0DA
Checksum Complement...: 0x5F25
Country Code..........: 1
Country Name..........: United States
Country Region........: NTSC
Header Type (SMC).....: Headered
Layout................: 32
License Code/Name.....: Nintendo
ROM Size..............: 8 MBits
RAM Size..............: 16 KBits
Version Number........: 1.0

Ejemplo de uso para la escritura:
Código
  1. Dim romDump As New SnesRom("C:\ROM.smc")
  2. ' Or...
  3. ' Dim romDump As New SnesRom(File.ReadAllBytes("C:\ROM.smc"))
  4.  
  5. With romDump
  6.    .Name = "Elektrocitos"
  7.    .Version = 1
  8.    .Country = New SnesRom.CountryData(countryCode:=0) ' Japan.
  9.    .LicenseCode = SnesRom.LicenseCodeEnum.Taito
  10.    .RomSize = SnesRom.ROMSizeEnum._4_Mbits
  11.    .RamSize = SnesRom.SRAMSizeEnum._256_Kbits
  12.    .Save("C:\Elektron.smc", replace:=True)
  13. End With

Saludos!


Título: Re: Leer una clase en un formulario Windows de Visual C#
Publicado por: Meta en 11 Junio 2015, 23:25 pm
Hola:

Impresionante, pedazo trabajo. JAjaja.

Te iba poner el mismo documento pero en otra Web.
http://www.emulatronia.com/doctec/consolas/snes/sneskart.html

Sacada de aqui.
http://www.emulatronia.com/consolas/doctec/dt-snes.htm

En este se explica mejor las cabeceras.
http://en.m.wikibooks.org/wiki/Super_NES_Programming/SNES_memory_map

Aquí información de SNES de unas 800 páginas, descarga de 24 MB.
http://www.romhacking.net/documents/226/

Una curiosidad. Por ejemplo, cuando vayas a modificar un dato, que es el único ASCII que hay legible en toda la ROM, es decir, el título del juego, si lo modificas, también en otra área de la ROM, se cambia el Checksum.

¿Cómo lo solucionas?

Saludos.


Edito:
Hice por ahora hasta aquí y esto hasta las ******************************** de colocar compañías.
Código
  1.                if (Codigo_Licencia == "0")
  2.                {
  3.                    textBox_Codigo_Licencia_2.Text = "Código de Licencia inválida";
  4.                }
  5.                else if (Codigo_Licencia == "1")
  6.                {
  7.                    textBox_Codigo_Licencia_2.Text = "Nintendo";
  8.                }
  9.                else if (Codigo_Licencia == "5")
  10.                {
  11.                    textBox_Codigo_Licencia_2.Text = "Zamuse";
  12.                }
  13.                else if (Codigo_Licencia == "8")
  14.                {
  15.                    textBox_Codigo_Licencia_2.Text = "Capcom";
  16.                }
  17.                else if (Codigo_Licencia == "9")
  18.                {
  19.                    textBox_Codigo_Licencia_2.Text = "HOT B";
  20.                }
  21.                else if (Codigo_Licencia == "A")
  22.                {
  23.                    textBox_Codigo_Licencia_2.Text = "Jaleco";
  24.                }
  25.                else if (Codigo_Licencia == "B")
  26.                {
  27.                    textBox_Codigo_Licencia_2.Text = "STORM (Sales Curve) (1)";
  28.                }
  29.                else if (Codigo_Licencia == "F")
  30.                {
  31.                    textBox_Codigo_Licencia_2.Text = "Mebio Software";
  32.                }
  33.                else if (Codigo_Licencia == "12")
  34.                {
  35.                    textBox_Codigo_Licencia_2.Text = "Gremlin Graphics";
  36.                }
  37.                else if (Codigo_Licencia == "15")
  38.                {
  39.                    textBox_Codigo_Licencia_2.Text = "COBRA Team";
  40.                }
  41.                else if (Codigo_Licencia == "16")
  42.                {
  43.                    textBox_Codigo_Licencia_2.Text = "Human/Field";
  44.                }
  45.                else if (Codigo_Licencia == "18")
  46.                {
  47.                    textBox_Codigo_Licencia_2.Text = "Hudson Soft";
  48.                }
  49.                else if (Codigo_Licencia == "1A")
  50.                {
  51.                    textBox_Codigo_Licencia_2.Text = "Yanoman";
  52.                }
  53.                else if (Codigo_Licencia == "1C")
  54.                {
  55.                    textBox_Codigo_Licencia_2.Text = "Tecmo (1)";
  56.                }
  57.                else if (Codigo_Licencia == "1E")
  58.                {
  59.                    textBox_Codigo_Licencia_2.Text = "Forum";
  60.                }
  61.                else if (Codigo_Licencia == "1F")
  62.                {
  63.                    textBox_Codigo_Licencia_2.Text = "Park Place Productions / VIRGIN";
  64.                }
  65.                else if (Codigo_Licencia == "21")
  66.                {
  67.                    textBox_Codigo_Licencia_2.Text = "Tokai Engeneering (SUNSOFT?)";
  68.                }
  69.                else if (Codigo_Licencia == "22")
  70.                {
  71.                    textBox_Codigo_Licencia_2.Text = "POW";
  72.                }
  73.                else if (Codigo_Licencia == "23")
  74.                {
  75.                    textBox_Codigo_Licencia_2.Text = "Loriciel / Micro World";
  76.                }
  77.                else if (Codigo_Licencia == "28")
  78.                {
  79.                    textBox_Codigo_Licencia_2.Text = "Kemco (1)";
  80.                }
  81.                else if (Codigo_Licencia == "29")
  82.                {
  83.                    textBox_Codigo_Licencia_2.Text = "Seta Co.,Ltd.";
  84.                }
  85.                else if (Codigo_Licencia == "2D")
  86.                {
  87.                    textBox_Codigo_Licencia_2.Text = "Visit Co.,Ltd.";
  88.                }
  89.                else if (Codigo_Licencia == "53")
  90.                {
  91.                    textBox_Codigo_Licencia_2.Text = "HECT";
  92.                }
  93.                else if (Codigo_Licencia == "3D")
  94.                {
  95.                    textBox_Codigo_Licencia_2.Text = "Loriciel";
  96.                }
  97.                else if (Codigo_Licencia == "3F")
  98.                {
  99.                    textBox_Codigo_Licencia_2.Text = "Seika Corp.";
  100.                }
  101.                else if (Codigo_Licencia == "40")
  102.                {
  103.                    textBox_Codigo_Licencia_2.Text = "UBI Soft";
  104.                }
  105.                else if (Codigo_Licencia == "47")
  106.                {
  107.                    textBox_Codigo_Licencia_2.Text = "Spectrum Holobyte";
  108.                }
  109.                else if (Codigo_Licencia == "49")
  110.                {
  111.                    textBox_Codigo_Licencia_2.Text = "Irem";
  112.                }
  113.                else if (Codigo_Licencia == "4B")
  114.                {
  115.                    textBox_Codigo_Licencia_2.Text = "Raya Systems/Sculptured Software";
  116.                }
  117.                else if (Codigo_Licencia == "4C")
  118.                {
  119.                    textBox_Codigo_Licencia_2.Text = "Renovation Pruducts";
  120.                }
  121.                else if (Codigo_Licencia == "4D")
  122.                {
  123.                    textBox_Codigo_Licencia_2.Text = "Malibu Games (T*HQ Inc.) / Black Pearl";
  124.                }
  125.                else if (Codigo_Licencia == "4F")
  126.                {
  127.                    textBox_Codigo_Licencia_2.Text = "U.S. Gold";
  128.                }
  129.                else if (Codigo_Licencia == "50")
  130.                {
  131.                    textBox_Codigo_Licencia_2.Text = "Absolute Entertainment";
  132.                }
  133.                else if (Codigo_Licencia == "51")
  134.                {
  135.                    textBox_Codigo_Licencia_2.Text = "Acclaim";
  136.                }
  137.                else if (Codigo_Licencia == "52")
  138.                {
  139.                    textBox_Codigo_Licencia_2.Text = "Activision";
  140.                }
  141.                else if (Codigo_Licencia == "53")
  142.                {
  143.                    textBox_Codigo_Licencia_2.Text = "American Sammy";
  144.                }
  145.                else if (Codigo_Licencia == "54")
  146.                {
  147.                    textBox_Codigo_Licencia_2.Text = "GameTek";
  148.                }
  149.                else if (Codigo_Licencia == "55")
  150.                {
  151.                    textBox_Codigo_Licencia_2.Text = "Hi Tech";
  152.                }
  153.                else if (Codigo_Licencia == "56")
  154.                {
  155.                    textBox_Codigo_Licencia_2.Text = "LJN Toys";
  156.                }
  157.                else if (Codigo_Licencia == "5A")
  158.                {
  159.                    textBox_Codigo_Licencia_2.Text = "Mindscape";
  160.                }
  161.                else if (Codigo_Licencia == "5D")
  162.                {
  163.                    textBox_Codigo_Licencia_2.Text = "Technos Japan Corp. (Tradewest)";
  164.                }
  165.                else if (Codigo_Licencia == "5F")
  166.                {
  167.                    textBox_Codigo_Licencia_2.Text = "American Softworks Corp.";
  168.                }
  169.                else if (Codigo_Licencia == "60")
  170.                {
  171.                    textBox_Codigo_Licencia_2.Text = "Titus";
  172.                }
  173.                else if (Codigo_Licencia == "61")
  174.                {
  175.                    textBox_Codigo_Licencia_2.Text = "Virgin Games";
  176.                }
  177.                else if (Codigo_Licencia == "62")
  178.                {
  179.                    textBox_Codigo_Licencia_2.Text = "Maxis";
  180.                }
  181.                else if (Codigo_Licencia == "67")
  182.                {
  183.                    textBox_Codigo_Licencia_2.Text = "Ocean";
  184.                }

Aún me queda mucho y cansa psicológicamente.  ;D

Me salen juego con el valor 33 Hex. En la lista de abajo de tu enlace, no está precismamente esa compañía.

Código
  1. LICENSE       : 1 BYTE
  2.     0 <Invalid License Code>
  3.     1 Nintendo
  4.     5 Zamuse
  5.     8 Capcom
  6.     9 HOT B
  7.    10 Jaleco
  8.    11 STORM (Sales Curve) (1)
  9.    15 Mebio Software
  10.    18 Gremlin Graphics
  11.    21 COBRA Team
  12.    22 Human/Field
  13.    24 Hudson Soft
  14.    26 Yanoman
  15.    28 Tecmo (1)
  16.    30 Forum
  17.    31 Park Place Productions / VIRGIN
  18.    33 Tokai Engeneering (SUNSOFT?)
  19.    34 POW
  20.    35 Loriciel / Micro World
  21.    38 Enix
  22.    40 Kemco (1)
  23.    41 Seta Co.,Ltd.
  24.    45 Visit Co.,Ltd.
  25.    53 HECT
  26.    61 Loriciel
  27.    64 Seika Corp.
  28.    65 UBI Soft
  29.    71 Spectrum Holobyte
  30.    73 Irem
  31.    75 Raya Systems/Sculptured Software
  32.    76 Renovation Pruducts
  33.    77 Malibu Games (T*HQ Inc.) / Black Pearl
  34.    79 U.S. Gold
  35.    80 Absolute Entertainment
  36.    81 Acclaim
  37.    82 Activision
  38.    83 American Sammy
  39.    84 GameTek
  40.    85 Hi Tech
  41.    86 LJN Toys
  42.    90 Mindscape
  43.    93 Technos Japan Corp. (Tradewest)
  44.    95 American Softworks Corp.
  45.    96 Titus
  46.    97 Virgin Games
  47.    98 Maxis
  48.   103 Ocean
  49.   105 Electronic Arts
  50.   107 Laser Beam
  51.   110 Elite
  52.   111 Electro Brain
  53.   112 Infogrames
  54.   113 Interplay
  55.   114 LucasArts
  56.   115 Sculptured Soft
  57.   117 STORM (Sales Curve) (2)
  58.   120 THQ Software
  59.   121 Accolade Inc.
  60.   122 Triffix Entertainment
  61.   124 Microprose
  62.   127 Kemco (2)
  63.   130 Namcot/Namco Ltd. (1)
  64.   132 Koei/Koei! (second license?)
  65.   134 Tokuma Shoten Intermedia
  66.   136 DATAM-Polystar
  67.   139 Bullet-Proof Software
  68.   140 Vic Tokai
  69.   143 I'Max
  70.   145 CHUN Soft
  71.   146 Video System Co., Ltd.
  72.   147 BEC
  73.   151 Kaneco
  74.   153 Pack in Video
  75.   154 Nichibutsu
  76.   155 TECMO (2)
  77.   156 Imagineer Co.
  78.   160 Wolf Team
  79.   164 Konami
  80.   165 K.Amusement
  81.   167 Takara
  82.   169 Technos Jap. ????
  83.   170 JVC
  84.   172 Toei Animation
  85.   173 Toho
  86.   175 Namcot/Namco Ltd. (2)
  87.   177 ASCII Co. Activison
  88.   178 BanDai America
  89.   180 Enix
  90.   182 Halken
  91.   186 Culture Brain
  92.   187 Sunsoft
  93.   188 Toshiba EMI/System Vision
  94.   189 Sony (Japan) / Imagesoft
  95.   191 Sammy
  96.   192 Taito
  97.   194 Kemco (3) ????
  98.   195 Square
  99.   196 NHK
  100.   197 Data East
  101.   198 Tonkin House
  102.   200 KOEI
  103.   202 Konami USA
  104.   205 Meldac/KAZe
  105.   206 PONY CANYON
  106.   207 Sotsu Agency
  107.   209 Sofel
  108.   210 Quest Corp.
  109.   211 Sigma
  110.   214 Naxat
  111.   216 Capcom Co., Ltd. (2)
  112.   217 Banpresto
  113.   219 Hiro
  114.   221 NCS
  115.   222 Human Entertainment
  116.   223 Ringler Studios
  117.   224 K.K. DCE / Jaleco
  118.   226 Sotsu Agency
  119.   228 T&ESoft
  120.   229 EPOCH Co.,Ltd.
  121.   231 Athena
  122.   232 Asmik
  123.   233 Natsume
  124.   234 King/A Wave
  125.   235 Atlus
  126.   236 Sony Music
  127.   238 Psygnosis / igs
  128.   243 Beam Software
  129.   244 Tec Magik
  130.   255 Hudson Soft

Por si alguien lo sabe, lo indica.

Gracias por todo.


Título: Re: Leer una clase en un formulario Windows de Visual C#
Publicado por: Eleкtro en 12 Junio 2015, 12:51 pm
¿Cómo lo solucionas?

No llego a comprender cómo se computa el Checksum.

De todas formas tampoco le doy ningún interés, ya que el checksum es solo un indicador, un bad checksum no afecta al comportamiento del juego.


Edito:
Hice por ahora hasta aquí y esto hasta las ******************************** de colocar compañías.

Lo que estás haciendo, aparte de no ser nada práctico, son malas prácticas de programación,
¿en que momento se te ocurre que la mejor solución es ponerte a escribir una a una las +120 condicionales?  :-\,
¿para que tienes a tu disposición las Classes/Types de .Net Framework si no las usas?, ¿para que estás programando en C#?.

Existe una cosa que se llama Diccionarios (Dictionary) entre otros muchos tipos de objetos que puedes utilizar, como listas, tuplas, arrays dimensionales, arrays escalonados (jagged array), etc, o tu propia Class.

Piensa mejor en las alternativas que realmente existen para ahorrarte tiempo, antes de volver a hacer algo cómo lo que has hecho :P.

yo por ejemplo no me puse a escribir una a una la enumeración con las +120 entradas, no, esa enumeración la conseguí desarrollando un código de 2 o 3 lineas para reemplazar el orden de las palabras (los números a la derecha) de la lista original, y luego cojí un editor de texto que soportase expresiones regulares (Sublime Text) y usé el reemplazo mediante dichas expresiones para los caracteres ilegales; En caso de no haber tenido un editor que lo hiciese, habría desarrollado un pequeño código de pocas lineas para utilizar RegEx con los mismos fines.

Ejemplo:
Código
  1. Public Class Form1
  2.  
  3.    Dim licenses As String =
  4.        <a>
  5. 0 Invalid License Code
  6. 1 Nintendo
  7. 5 Zamuse
  8. 8 Capcom
  9. 9 HOT B
  10. 10 Jaleco
  11. 11 STORM (Sales Curve) (1)
  12. 15 Mebio Software
  13. 18 Gremlin Graphics
  14. 21 COBRA Team
  15. 22 Human/Field
  16. 24 Hudson Soft
  17. 26 Yanoman
  18. 28 Tecmo (1)
  19. 30 Forum
  20. 31 Park Place Productions / VIRGIN
  21. 33 Tokai Engeneering (SUNSOFT?)
  22. 34 POW
  23. 35 Loriciel / Micro World
  24. 38 Enix
  25. 40 Kemco (1)
  26. 41 Seta Co.,Ltd.
  27. 45 Visit Co.,Ltd.
  28. 53 HECT
  29. 61 Loriciel
  30. 64 Seika Corp.
  31. 65 UBI Soft
  32. 71 Spectrum Holobyte
  33. 73 Irem
  34. 75 Raya Systems/Sculptured Software
  35. 76 Renovation Pruducts
  36. 77 Malibu Games (T*HQ Inc.) / Black Pearl
  37. 79 U.S. Gold
  38. 80 Absolute Entertainment
  39. 81 Acclaim
  40. 82 Activision
  41. 83 American Sammy
  42. 84 GameTek
  43. 85 Hi Tech
  44. 86 LJN Toys
  45. 90 Mindscape
  46. 93 Technos Japan Corp. (Tradewest)
  47. 95 American Softworks Corp.
  48. 96 Titus
  49. 97 Virgin Games
  50. 98 Maxis
  51. 103 Ocean
  52. 105 Electronic Arts
  53. 107 Laser Beam
  54. 110 Elite
  55. 111 Electro Brain
  56. 112 Infogrames
  57. 113 Interplay
  58. 114 LucasArts
  59. 115 Sculptured Soft
  60. 117 STORM (Sales Curve) (2)
  61. 120 THQ Software
  62. 121 Accolade Inc.
  63. 122 Triffix Entertainment
  64. 124 Microprose
  65. 127 Kemco (2)
  66. 130 Namcot/Namco Ltd. (1)
  67. 132 Koei/Koei! (second license?)
  68. 134 Tokuma Shoten Intermedia
  69. 136 DATAM-Polystar
  70. 139 Bullet-Proof Software
  71. 140 Vic Tokai
  72. 143 I'Max
  73. 145 CHUN Soft
  74. 146 Video System Co., Ltd.
  75. 147 BEC
  76. 151 Kaneco
  77. 153 Pack in Video
  78. 154 Nichibutsu
  79. 155 TECMO (2)
  80. 156 Imagineer Co.
  81. 160 Wolf Team
  82. 164 Konami
  83. 165 K.Amusement
  84. 167 Takara
  85. 169 Technos Jap. ????
  86. 170 JVC
  87. 172 Toei Animation
  88. 173 Toho
  89. 175 Namcot/Namco Ltd. (2)
  90. 177 ASCII Co. Activison
  91. 178 BanDai America
  92. 180 Enix
  93. 182 Halken
  94. 186 Culture Brain
  95. 187 Sunsoft
  96. 188 Toshiba EMI/System Vision
  97. 189 Sony (Japan) / Imagesoft
  98. 191 Sammy
  99. 192 Taito
  100. 194 Kemco (3) ????
  101. 195 Square
  102. 196 NHK
  103. 197 Data East
  104. 198 Tonkin House
  105. 200 KOEI
  106. 202 Konami USA
  107. 205 Meldac/KAZe
  108. 206 PONY CANYON
  109. 207 Sotsu Agency
  110. 209 Sofel
  111. 210 Quest Corp.
  112. 211 Sigma
  113. 214 Naxat
  114. 216 Capcom Co., Ltd. (2)
  115. 217 Banpresto
  116. 219 Hiro
  117. 221 NCS
  118. 222 Human Entertainment
  119. 223 Ringler Studios
  120. 224 K.K. DCE / Jaleco
  121. 226 Sotsu Agency
  122. 228 TandESoft;
  123. 229 EPOCH Co.,Ltd.
  124. 231 Athena
  125. 232 Asmik
  126. 233 Natsume
  127. 234 King/A Wave
  128. 235 Atlus
  129. 236 Sony Music
  130. 238 Psygnosis / igs
  131. 243 Beam Software
  132. 244 Tec Magik
  133. 255 Hudson Soft
  134. </a>.Value
  135.  
  136.    Private licDict As New Dictionary(Of String, String)
  137.  
  138.    Private Sub CreateLicenseDictionary()
  139.  
  140.        For Each line As String In licenses.Trim.Split({ControlChars.Lf}, StringSplitOptions.RemoveEmptyEntries)
  141.  
  142.            Dim code As Byte = Convert.ToByte(line.Substring(0, line.IndexOf(" "c)))
  143.            Dim codeHex As String = Convert.ToString(code, toBase:=16)
  144.            Dim name As String = line.Substring(line.IndexOf(" "c), line.Length - code.ToString.Length)
  145.  
  146.            licDict.Add(codeHex, name)
  147.  
  148.        Next line
  149.  
  150.    End Sub
  151.  
  152.    Private Sub Test()
  153.  
  154.        textBox_Codigo_Licencia_2.Text = Me.licDict(Codigo_Licencia)
  155.  
  156.    End Sub
  157.  
  158. End Class

Puedes hacer algo parecido en C#, con los datos de la variable "code" y "name" también puedes crear la enumeración de C# en un archivo de texto, construyendo el string con ese formato específico, que solo tendrías que copiar y pegar en tu código fuente.

En fin... será por porisiblidades.

Saludos!