COOKIES

This site may be using cookies to melk you with your own data. I, ben0bi, am not the owner of this web service and I also do not maintain their servers. But the EU and the owner of this service think, that the user (me) has the responsibility to inform the consumer (you), that this website uses cookies. Again: I, ben0bi, NEVER use cookies. I am not responsible for the setup of this web service. I just present some information here and do not intend to spy on you for whatever reason ever. But (also again), I do not host this website nor do I maintain any servers related to this website nor do I benefit from using the cookies maintained from this service. I hereby give the responsibility for using cookies on blogspot back to the owners of blogspot.

Mittwoch, 4. November 2015

GAMEBOY Devkit ben0bi Edition

I downloaded the Gameboy devkit and played around with it like here.
In the developing process, there were some stuff downloaded which I included in the original devkit.

Here are the downloads:
gbdk_ben0biEdition.zip from Mirror 1 (Onedrive)
gbdk_ben0biEdition.zip from Mirror 2 (Homeserver)

And here is what you get for it (copied from README.txt):

First of all, you need to call do.path in every new terminal window, else the paths are not defined. Call it like that: . do.path in your gbdk-root directory. (NOT ./do.path)

Please look also at this post, my friend SneezyCerritus got all out of an old Gameboy Color.


Additions:
+ gbdk-doc downloaded from sourceforge.net (If you can redeem 8.8Mb for the Nintendo Manual,  you can do that with this 50kb for sure.)

+ A shell script to set the path for GBDKDIR. Please change this to your own path.
    + do.path ->    Call it with: ". do.path" because "./do.path" will not
            set the variable globally.

+ RGBDS (compiled and source) for fixing the code to run on real GameBoy hardware.

+ Some PDF-resource.
    + GBCPUman.pdf             -> GameBoy CPU Manual by some people from the internet.
                        This one contains some tips and tricks.
    + gb_programming_manual.pdf    -> Original document by Nintendo.
                        I have no idea where I found this.
                        Biggest file of the whole compilation. ;)

+ A tile editor for LibreOffice: assets/ben0bis_GB_TileEditor.
    + And a font created with it, spread over several files in the assets/new folder.
    + Also as zip-file if you do something wrong.

+ New code from myself in the ben0bi-folder with some shell-scripts to automate.
    + ben0bi/credits    -> Credits of this whole project.     (Not finished yet)
    + ben0bi/IRremote    -> An IR remote for your TV.         (Not finished yet)

+ Some shell scripts from myself and updated Makefiles to use with libraries. (multiple .o-files)
    Look in the subfolders of the ben0bi-folder:
    + Makefile    -> the original one from the examples does not work properly.
    + do.all    -> calls all the other do-files and starts the game after compiling.
                It uses VisualBoy Advance (vba) as emulator, please install it.
    + do.compile     -> calls "make clean" and then "make"
    + do.fix    -> fixes the file to use on real GameBoy-Hardware.

        You need to set the proper filename/s in all of this files.


+ New Examples, stolen from the internet:
    + examples/burlyGBC_src    ->    a little game where you are a bear.
                I learned how to use graphics with that one.
                Contains the original tile editor tiles17.xlsx
    + examples/IR        ->    contains some source to use the IR sensor.
                (code not used yet.)

Samstag, 29. August 2015

GameBoy Color: Hardware Modding

Like mentioned in this post here, my friend SneezyCerritus gets the best out of an old GameBoy Color on the hardware side. I wanted to load my homebrew GBC-modules so he ordered a cardridge with a microSD-slot. Then he had the idea to put that cardridge inside the GBC so we could either use games from the microSD slot (all there are ;) ) or use an original Gameboy-cardridge on the other side, without taking the microSD-cardridge out.

Also, he decided to put an accumulator pack and a microUSB-accumulator-load-slot into it.

WARNING: This project is freaking expensive and only for enthusiasts. It is a nice thing but it's very costly. I bet you can never sell it for the price below, which is:
--> more than 300 CHF and counting...

This is the device we are talking about, in exactly that color (but this images are stolen from the internet because we started making pictures after the start of modding.)


And here is an image of the back, for your consideration:


Here is what we got to build into the case:
http://opcoa.st/JGdT7

It's an "Everdrive GB V1.2"

Also he got a Li-Ion-Accumulator-pack, a loading-chipset hardware breakout and a miniUSB-plug.

Accumulator, USB-and-loader-breakout and Everdrive.

First a view from the workplace: In front you see a not-yet-functional 3D-printer (software issues). The GameBoy workplace is just beneath it, you cannot see it.
Workplace
Here you see all the parts, on the backside is a cutout because there were not enough space.
All the needed parts.

Ok, first he opened that the GBC and the Everdrive. For the GameBoy you need a special screwdriver with three 3 "corners". (NOT a triangle! It's like a normal screwdriver but...triple.)

He soldered a cable to each pin of the GameBoy-hardware and put in the Accumulator and loading-stuff.
First try with cables.

Soldering the cables together.

After that he soldered it to the Everdrive and tried to close the case.
All done, does it fit?

It's not possible, so he unsoldered the Everdrive and made a special PCB only to connect the two pieces together.
PCB for the second try.
That glassy thing is a selfmade PCB-creator. It's just some ultraviolett LEDs and a glass plate and some covering, I don't know how it works exactly.

He then cut the wires short and soldered the PCB on the GBC and the Everdrive on the PCB.
 
PCB, GBC and Everdrive soldered together.

PCB sideview.

Problem is, it will not fit to the case either. The case needs to be extended, with some parts changed.

SneezyCerritus used some 2-component superglue to create the outer shell of the expansion on the original case. Then another friend removed the inner parts, until only the superglue-case was left.
Some glue on the right place...

..makes the shell bigger.

Getting rid of the stuff inside.
When you fail in this (there was a hole where no hole should be), you can use some more glue to fix it, easy. The battery case cannot be opened anymore so the accumulator is necessary from now on.

He put it all together but it won't fit either. The PCB was to big.

The last solution for that issue (which finally worked) was to take a ribbon cable like on that image here:
 

Here you see an image from the de-soldering process, with the ribbon cable in the background.
De-soldering the PCB.

After that, soldering the stuff to the ribbon cable:
Nice view with ribbon cable.

Third and last soldering process. :)

Two LEDs were included into the case to indicate if the battery is charging or fully loaded:
Loading LEDs.

After reassembling, the working test...it works:


Do you like the color? I do.

It is now possible to use the internal microSD-card OR an original cardridge. You can even take out the microSD-card without opening the whole case. It's not very beautiful but it makes its job.

microSD-card slot.
Switch for cardridge-or-microSD-operation.
microUSB-slot for charging battery.
And finally, homebrew software running on the "original" device:
Homebrew Software. YAY!

That's it, all is working like it should. This project lasted over several months.

Sorry for the long post, I hope you enjoyed it.

Sonntag, 9. August 2015

GameBoy Color: Getting Started

I found a Gameboy Color somewhere, and while my friend is modding it to the max on hardware side, I am unable to find any programming sources explicitly for GBC.

All I can find is for GameBoy (original) or for GameBoy Advance.

I want to program the infrared sensor which is GBC only, so I need some reference for GBC.

First of all, when using GBC mode, you need to modify some stuff to "get the graphics back" (which you already have in your GameBoy-NonColor-Game).

It lasted some time to just get the printf()-output back to screen, and here is what you have to do.

Development Setup

[EDIT] You just need to set up palettes and use the GBCSetup-method below. The rest is just for consideration, you can also use gb/drawing.h to draw stuff and print text.

Linux:
Search for a good GameBoy emulator. I am using VisualBoy Advance, which is available over the Marketplace from Ubuntu.

Download the GameBoy Development Kit GBDK from sourceforge.net:
http://sourceforge.net/projects/gbdk/ 
gbdk ben0bi Edition ;)

1. Unpack the archive somewhere. Mine is in the users root directory.
2. Set the path to your installation. Type in your console:
export GBDKDIR=/home/ben0bi/gbdk

Now you should be able to compile the examples. Go into the examples directory and type make.

If all went good, you should have several .gb files now which you can start with the emulator.

In the directory examples/colorbars you will find a Makefile which sets the flag to GBC instead of GB in the last two lines.

Copy it to your project folder, alter the file names in it and set the right path to lcc on the top. You can use it yourself now.

Here is a Makefile which compiles two source files into a GBC-rom.
I needed some time to find out how the second file (core.c) has to be added to the compile-workflow as a "library".

It patches byte 0x143 in the header of the ROM to the value 0x80 (GB + GBC Mode) or 0xC0 (GBC only mode)
-> -Wa means "pass the next arg directly to the asm-compiler."
-> -Wl means "pass the next arg directly to the linker".
-> -ypX=Y means "patch byte X to value Y"

The Makefile

I don't get exactly how it works, but it..works..like that.

WARNING: The first two commands were suited otherwise. I got the parameters wrong by some functions, so I changed it.
They were made for a project with just one source file.
(Or I don't get it at all)

Instead of:
    $(CC) $(CFLAGS) -c -o $@ $<
I wrote:
    $(CC) $(CFLAGS) -c $<

-c means "compile only" and -o means "create output file" or something like that.
Some stuff only needs to be compiled and then linked together.

# Set the path to the compiler with some parameters.
CC    = ../bin/lcc -Wa-l -Wl-m

# Some other params... (why here?)
CFLAGS    = -DGBDK_2_COMPAT

# To get your other .c files compiled, add them here as .o-file
BINS    = mylib.o \
                someCfile.o \
                IRremote.gbc

# Refer to BINS for "make all" / "make"
all:    $(BINS)

# What files are created from which files...(I think. (?))
%.o:    %.c
    $(CC) $(CFLAGS) -c $<

%.o:    %.s
    $(CC) $(CFLAGS) -c $<

%.s:    %.c
    $(CC) $(CFLAGS) -S -o $@ $<

%.gbc:    %.o
    $(CC) $(CFLAGS) -o $@ $<

# The clean command: Just remove all the stuff which is not needed.
clean:
    rm -f *.o *.lst *.map *.gb *.gbc *~

# Link file, and write 0x80 at position 0x143 in header
# 0x80 is GBC compatible, 0xC0 is GBC-only.
# link together all the files which are created -> add your .o files.
IRremote.gbc:    IRremote.o
    $(CC) $(CFLAGS) -Wl-yp0x143=0xC0 -o IRremote.gbc IRremote.o mylib.o someCfile.o

Ok, we can now generate GBC-only-ROMs, but they show nothing with normal GB-code.

The Code

First, a hello world program which runs on normal GameBoys, no problem at all:

#include <stdio.h>
#include <gb/gb.h>

int main()
{
    printf("Hello World!");
    return 0;
}
You don't even need to give some compiler options, just type lcc -o myfile.gb myfile.c (You need to give the right path for lcc, though) and test it with vba myfile.gb.

Now, if you patch it, it won't work properly anymore.

Patching goes like this (without Makefile):
lcc -c -o myfile.o myfile.c
lcc -o -Wl-yp0x143=0x80 myfile.gb myfile.o
Remember: GBC ONLY needs the flag 0xC0 instead of 0x80.

Well then, let's do some stuff to get that "Hello World!" back on screen.

The following shows how to set up tiles (for background, I think foreground is almost the same.) and colour palettes to use with GBC. Finally some stuff will be drawn on the screen. Problem here is that printf and tiles don't work well together. (It works for printf if you only do the palette stuff.)
We need one or more palettes with some colours in it. We can have up to 8 palettes, but one is enough for now. Also, we need to check the hardware if it is really a GameBoy Color (only this one has IR-stuff.) These are the Values to check, they are defined in gb/gb.h ;)
DMG_TYPE 0x01 /* Original GB or Super GB */
MGB_TYPE 0xFF /* Pocket GB or Super GB 2 */
CGB_TYPE 0x11 /* Color GB */

Here is the source code for the absolute minimum. You can extend it at your belief, there are some comments about "the other stuff".

#include <gb/gb.h>
#include <stdio.h>

//+++++++++++++++ Stuff to check for Hardware-Version.
extern UBYTE _cpu;          /* Check this var for... */
// the other defines are in gb/gb.h //+++++++++++++++ EndOf Stuff for Hardware-Check

//+++++++++++++++ Palette Stuff
// Some palette indexes. Possible: 0 - 7
#define PAL_BACK_DEFAULT  0  // Background default palette on index 0
#define PAL_DEFAULT 0 // That would be the palette index for sprites. (Foreground)

//********* Palette Definitions -> Here are the colors.
// 4 Shades: First is Background Color (black), last one (blue) is Font Color
// Positions in the Tile-Editor (later): 0,2,1,3

const UWORD pal_def_default[] = { RGB_BLACK, RGB_WHITE, RGB_GREEN, RGB_BLUE };
// ... define some more ...

//********* EndOf Palette Definitions
//+++++++++++++++ EndOf Palette Stuff

//+++++++++++++++ Some Tile Data
// I will only show how 8x8 tiles work,  I don't know if 8x16 is just 2px
// instead of one or if it can be defined separately.
// One tile has 16bytes assigned, that are 2bit for each pixel = 4 colours.

// the hardware start adress -> must be a define to make an enum later.
#define adress_characters 0x00     
const UBYTE count_characters=2;  // how many characters are there
const UBYTE data_characters[] =   // the characters (tiles) itself.
{
      0x00, 0x00, 0x00 0x18, 0x00, 0x24, 0x00, 0x42, 0x00, 0x42, 0x00, 0x7E, 0x00, 0x42, 0x00, 0x42, // A - starts at adress Adress+0
      0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F  //  some junk ;) - starts at adress Adress+1
// ...don't forget the comma ^
}

// if you have many tiles in one array, you can refer to the tiles with an enum:
enum
{
     tile_A=adress_characters, // adress_characters CAN NOT be a variable. :(
     tile_B, tile_C,   // ... every name here is adress_characters + x ;)
} eTiles_characters;

// now every tile is at (tileadress)+position where position a counter for each whole tile of 16bytes. (a=0, b=1, c=2 etc.)

//+++++++++++++++ EndOf Tile Data

//+++++++++++++++ Function Bodies
void GBCSetup();       // this method sets up the graphics for GBC.
void load_palettes();  // load and assign palettes into hardware.
void load_tiles();        // load the tiles into the hardware.
//+++++++++++++++ EndOf Function Bodies

int main()
{
   GBCSetup();

   printf("Hello World!");
   return 0;
}


Now load the palettes and tiles into the hardware and then the almigthy GBCSetup function:
// load the palettes
void load_palettes()
{
// Params: Palette-Index, Unknown, Start-Position

    set_sprite_palette(PAL_DEFAULT, 1, &pal_def_default[0] );
    // ...define some more (foreground)...

    set_bkg_palette(PAL_BACK_DEFAULT, 1, &pal_def_default[0] );    // ...define some more (background)...
}

// load the tiles into the hardware.
void load_tiles()
{
    // load the background tiles.
    set_bkg_data(adress_characters,count_characters, data_characters); // start adress, tile count, tile-array   
}

// Set Up GameBoy Color
void GBCSetup()
{
    if(_cpu!=CGB_TYPE)
    {
        // It's not a GBC, nothing to do here.
        return;
    }

    // turn off display and disable interrupts.
    disable_interrupts();
    DISPLAY_OFF;

    // set tile size in LCDC-register. 0x67 = 8x16 tiles.
    LCDC_REG = 0x63; // 8x8 tiles

    // load palette data
    load_palettes();

    // Put the tiles into the tile-buffer.
    load_tiles();

    // reset display and re-enable interrupts.
    DISPLAY_ON;
    enable_interrupts();
}

Now we have a tile (exactly two but the last one is junk.)
We can put the tile on the screen with some functions...

A function to draw a background tile:
// the define is just a shorcut. #define render_back_tile(x,y,tile,palette) render_background_tile(x,y,tile,palette) void render_background_tile(UBYTE x,UBYTE y,UBYTE w, UBYTE h,UBYTE tileIndex,UBYTE paletteIndex)
{
    UBYTE c, d;
    UBYTE til[]={tileIndex}; // somehow it is needed as array. Idk why.
    UWORD pal[]={paletteIndex}; // somehow it is needed as array. Idk why.

    VBK_REG=0; // set background tileregister or something)
    set_bkg_tiles(x,y,w,h,til);  // put the tile into hardware (only with VBK_REG==0)

    // now set it to set the palettes.
    VBK_REG=1;

    // set the palette at that position, maybe for multiple tiles.
    if(w*h==1){
         set_bkg_tiles(x,y,w,h,pal);
    }else{
         // if we are rendering multiple tiles, we need to set the attributes for all tiles.
        for(c=0;c<w;c++)
            for(d=0;d<h;d++)
                 set_bkg_tiles(x+c,y+d,1,1,pal);
    }
}

For drawing something, you just have to wait until the vblank-interrupt is called with wait_vbl_done(); after or before drawing. (I don't see any difference on the emulator.)
 

Sonntag, 17. Mai 2015

jMonkeyEngine: Circle Class

With this class you can draw simple circles in 3D-Space.

This post is somewhat a direct copy of this post here:
http://hub.jmonkeyengine.org/t/drawing-a-simple-circle-in-jme3/15461/13
because there it is a little bit messed up.

Here's the class:

/*
 * Original code by Martin Simons.
 * Created by Oki Wan Ben0bi @ 2015
 */

import com.jme3.math.FastMath;
import com.jme3.math.Vector3f;
import com.jme3.scene.Mesh;
import com.jme3.scene.VertexBuffer.Type;
import com.jme3.util.BufferUtils;
import java.nio.FloatBuffer;

public class Circle extends Mesh
{
    private Vector3f center;
    private float radius;
    private int sampleCount;
   
    public Circle(float radius)
    {
        this(Vector3f.ZERO,radius, 16);
    }
   
    public Circle(float radius, int samples)
    {
        this(Vector3f.ZERO, radius, samples);
    }
   
    public Circle(Vector3f center, float radius, int samples)
    {
        super();
           
        this.center=center;
        this.radius=radius;
        this.sampleCount=samples;
       
        setMode(Mode.Lines);
        updateGeometry();
    }
   
    protected void updateGeometry()
    {
        FloatBuffer positions=BufferUtils.createFloatBuffer(sampleCount*3);
        FloatBuffer normals=BufferUtils.createFloatBuffer(sampleCount*3);
        short[] indices = new short[sampleCount*2];
       
        float rate=FastMath.TWO_PI / (float)sampleCount;
        float angle=0;
       
        int idc=0;
        for(int i=0;i<sampleCount;i++)
        {
            float x=FastMath.cos(angle)*radius+center.x;
            float z=FastMath.sin(angle)*radius+center.z;
           
            positions.put(x).put(center.y).put(z);
            normals.put(new float[] {0,1,0});
           
            indices[idc++]=(short)i;
            if(i< sampleCount-1)
                indices[idc++]=(short)(i+1);
            else
                indices[idc++]=0;
           
            angle+=rate;
        }
       
        setBuffer(Type.Position,3, positions);
        setBuffer(Type.Normal,3,normals);
        setBuffer(Type.Index, 2, indices);
       
        setBuffer(Type.TexCoord,2,new float[] {0,0,1,1});
        updateBound();
    }
}

And here is an example for implementing it:

Circle circle=new Circle(10);
Geometry g=new Geometry("Circle", circle);
Material mat= new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", ColorRGBA.Red);
g.setMaterial(mat);
rootNode.attachChild(g);

I hope you can use it.

Dienstag, 10. März 2015

Part 2A: The Graphics Engine

This is Part 2A of my tutorial series about how to write an emulator.

In this part we will set up some graphics where the emulator can "draw to".

After reading Part 2 you should have created a basic WinPhone & MonoGame project, which we will extend now.

Note: If you downloaded the source from Part 2, you need to move some static methods to the new created GFXEngine.cs file (which is also there, but empty).

The Graphics-Engine needs to draw a texture on the screen, which is scaled to the screen size or an appropriate format (4:3 etc). There needs to be a method which can put all the graphics data from the emulator (intended to be a 1-dimensional Int32 array in the size consoleScreenWidth*consoleScreenHeight) onto this texture.

The texture itself will be the size of the console screen, but scaled to the size of the device (phone) screen. If the emulator changes, it should create a new texture in the appropriate size and reset the scaling factor.

There's more to that: A console can have more pixels than there will be seen. These must be covered or be outside of the device screen.

After this tutorial, you have a texture to draw on, which is scaled to the right size and in portrait mode, rotated about 90 degrees.

It will be filled with test pixels - you don't need to do that, it's only that you see something.

A little note: I am talking about UNSIGNED integers here. When I write Int32, you can assume it's meant UInt32. Unsigned means that there can be only positive numbers, not negative ones. This leaves one bit more for the value itself. Otherwise that bit would be used to determine if it's a positive or negative number.

Implementing

Ok then, first remove all the SpriteBatch-related code in Game1.cs.
We will implement that into our graphics-engine.

Now, lets create a new class called GFXEngine.cs.

public class GFXEngine
{
     // the graphics device from the engine.
     private GraphicsDevice graphicsDevice;

     // a SpriteBatch to draw sprites/textures.
     SpriteBatch spriteBatch;

     // the texture to draw on.
     Texture2D texture;

     // the device screen resolution is stored here.
     public int DeviceScreenWidth { get; private set; }
     public int DeviceScreenHeight { get; private set; }

     // Get device screen resolution
     // You need to call that before the game starts/outside of the game thread.
     public void ActualizeScreenResolution() {}

     // use this as constructor, it's called in a "safe region".
     public void LoadContent(GraphicsDevice gfxDevice) {}

     // the update call from the game engine.
     public void Update(GameTime gameTime) {}

    //the draw call from the game engine.
    public void Draw(GameTime gameTime) {}
}


That class will be extended later. First, we implement it into the engine.

Create an instance of the class in the Static.cs - class.

public class Static
{
      public static GFXEngine GFX = new GFXEngine();
      ...
}

And now call the methods in Game1.cs.
Call Static.GFX.ActualizeScreenResolution(); in the Constructor of Game1.cs.
Call Static.GFX.LoadContent(GraphicsDevice); in the LoadContent-method of Game1.cs.
Call Static.GFX.Update(gameTime); in the Update-method of Game1.cs.
Call Static.GFX.Draw(gameTime); in the Draw-method of Game1.cs.

We have  implemented our GFXEngine into the game and will now extend the class to our needs.

Extending

The MonoGame-screen is in portrait-mode. That means, we need to rotate our texture 90 degrees.
If you managed to run it in "real" landscape mode, you can skip the rotation part and just use 0 at the right position.

Add an enum, the PI-Constant and the RGBAToInt32-methods to your Static.cs-file:

public static class Static
{
    ...
    public enum EColorShift
    {
        RED = 0,
        GREEN = 8,
        BLUE = 16,
        ALPHA = 24
    }

    public const double PI = 3.14159265359;
    ....
    public static UInt32 RGBAToInt32i(int R, int G, int B, int A = 255)
    {
        return RGBAToInt32b((byte)R, (byte)G, (byte)B, (byte)A);
    }

    public static UInt32 RGBAToInt32b(byte R, byte G, byte B, byte A = 255)
    {
        UInt32 c= (UInt32)(R << (int)EColorShift.RED);
        c += (UInt32)(G << (int)EColorShift.GREEN);
        c += (UInt32)(B << (int)EColorShift.BLUE);
        c += (UInt32)(A << (int)EColorShift.ALPHA);
        return c;
    }

    // additional method to get color values back.
    public static byte ColorFromInt32(UInt32 value, EColorShift color)
    {
        // value (bit-)shift right by color, then get last 8 bits (0xFF = 255 = 8 bits all up)
        // e.g: 0xAABBCC & 0xFF = 0xAABBCC & 0x0000FF = 0xCC

        return (byte)((value >> (int)color) & 0xFF);
    }
}

The enum defines the right values for bitshifting later.
If you have another format than RGBA (e.g. AGBR) then you have to change only these values.

We need PI to get the correct radian angle. (I tried with 0.5 and 1.0 but it did'nt work.)

The RGBAToInt32-methods are the main functions to create the color-values for the console screen array. (And the ColorFromInt32-method does the exact opposite - getting color values back from Int32)

It simply pushes all values (ranging from 0-255 / 0x00-0xFF) into an Int32 variable by bitshifting.

Bitshifting works like that: You have x which is 4 bits "wide", the last one is up (1): 0001 => x=1
Shift Left 2 (x = x << 2) means shift all bits two to the left: 0001=>0100 (<--) => x=4
Shift Right 1 (x = x >> 1) means shift all bits one to the right: 0100=>0010 (-->) => x=2

E.g: R=0x11, G=0x22, B=0x33 and A=0xFF will give this hex value into the Int32-variable: 0xFF332211 because A is shifted 24 bits to the left, then B shifted 16 bits to the left and G shifted 8 bits to the left. R remained "where it was".

This methods are used by the emulators and have nothing to do with the graphics engine internals.
(But they are set up to correspond to the texture data format used by the graphics engine.)
The graphics engine must react to this functions, not otherwise.

That's why this methods are in the Static-class and not in the GFXEngine class.

Now, lets extend the GFXEngine-class. First we need some variables and properties:

public class GFXEngine
{
...
      private Vector2 textureOrigin;
      private Vector2 deviceHalfScreenSize;
      private Rectangle consoleRectangle;
      private float scaleFactor = 1.0f;
      // and the rotation for the portrait-to-landscape-hack:
      private const float consoleScreenRotation = (float)(90 * Static.PI / 180);

      public DeviceScreenWidthForConsole { get { return DeviceScreenHeight; }}
      public DeviceScreenHeightForConsole { get { return DeviceScreenWidth; }}
...
}

We could compute the most of them in each frame, but that's not necessary and like that, it saves some performance.

textureOrigin is the position on the texture from where it is accessed from outside (rotated / positioned). It's half the texture size.
deviceHalfScreenSize is the half of the device screen size. No need to compute that in each frame.
consoleRectangle is the rectangle on the texture which will actually be drawn. That is for the cutoff lines.
scaleFactor is used to scale the texture to device screen size. There is no independent scale factor for x and y. It's the same for both.
consoleScreenRotation is the rotation of the texture. It needs to be rotated 90 degrees because it's in portrait mode. If you managed to use real landscape mode, just use 0 here.
DeviceScreenWidthForConsole and DeviceScreenHeightForConsole return the "real" width and height for the console screen. Because it's in portrait mode, this values return the "other" value instead of the "right" one. (Height = DeviceWidth and vice versa.)

ActualizeScreenResolution

Extend the ActualizeScreenResolution()-method:
public void ActualizeScreenResolution()
{
      DeviceScreenWidth = (int)Application.Current.Host.Content.ActualWidth;
      DeviceScreenHeight = (int)Application.Current.Host.Content.ActualHeight;
      deviceHalfScreenSize = new Vector2(DeviceScreenWidth * 0.5, DeviceScreenHeight * 0.5);
}

(It's better to multiplicate instead of dividing (* 0.5 instead of / 2))

This method gets the device screen width and height. If you call that Application.xxx stuff inside the game, there will be an asyncrounous error. The method is called once at startup.

LoadContent

This is somewhat our constructor. Stuff will be created and initialized here for the first time.
public void LoadContent(GraphicsDevice gfxDev)
{
     graphicsDevice = gfxDev;
     spriteBatch = new SpriteBatch(graphicsDevice);

     // create a first texture so there is one. (...and it's used for testing.)
     ResizeTexture(140,100); // for the exact same test image like mine, use size 34x24

     // build the test image.
     BuildTestImage();
}

The methods ResizeTexture and BuildTestImage will follow later. You don't need BuildTestImage, it's only here to see something because otherwise, the texture would be transparent.

Draw

Lets extend the Draw-method.
public void Draw(GameTime gameTime)
{
     // we only need the samplerstate here.
     // needed for pixel-perfect scaling without blur and stuff.
      spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend,
                                    SamplerState.PointClamp,
                                    DephtStencilState.Default,
                                    RasterizerState.CullCounterClockwise);

     // now draw the texture with all given values.
     spriteBatch.Draw(texture,
                           deviceHalfScreenSize,
                           consoleRectangle,
                           Color.White,
                           consoleScreenRotation,
                           textureOrigin,
                           scaleFactor,       // bad that there is no scaling for x / y individually.
                           SpriteEffects.None,
                           0.0f);

     spriteBatch.End();
}

We need to modify the SamplerState in SpriteBatch.Begin so there is no blurry image. All other values are left default. Then we give all the values which are computed in ResizeTexture to SpriteBatch.Draw. SpriteBatch.End must be called to end the draw call.

ResizeTexture

Create the method ResizeTexture(int,int,int,int):
public void ResizeTexture(int width, int height, int cutOffTopLines = 0, int cutOffBottomLines = 0)
{
        // first, create the new texture with given width and height.
        texture = new Texture2D(graphicsDevice, width, height);

        // hcalc is the height minus the cutoff.
        // it's stored in consoleRectangle and used for scaling and origin.
        float hcalc = height - cutOffTopLines - cutOffBottomLines;
        // origin needs to be calculated using hcalc instead of height.
        textureOrigin = new Vector2(width * 0.5f, hcalc * 0.5f);
        // define the shown rectangle on the texture.
        consoleRectangle = new Rectangle(0, cutOffTopLines, width, (int)hcalc);
        // now calculate the scale factor.
        scaleFactor = (float)DeviceScreenHeightForConsole / hcalc;
        // maybe it's a widescreen. (not possible, but why not calculate it?)
        if(width * scaleFactor > DeviceScreenWidthForConsole)
               scaleFactor = (float)DeviceScreenWidthForConsole / width;
}

Everything is explained in the comments above.

This is the basic "graphics engine". All we need to do now, are some methods to put the given array from the console to the texture. For that, we set up some helper functions to modify textures.

"Interface" Methods

I call those "Interface Methods" because this are the methods which the emulators need to interface with the graphics engine.

Create these four methods in GFXEngine.cs:
public class GFXEngine
{
    // set the data for the main (onscreen) texture.
    public void SetMainTexData<T>(T[] data) where T:struct
    {
        ArrayToTexture(data, texture);
    }

    // get the data from the main (onscreen) texture.
    public T[] GetMainTexData<T>() where T:struct
    {
        return TextureToArray<T>(texture);
    }

    // retrieves all colors from a texture in an 1-dimensional {T} array.
    public static T TextureToArray<T>(Texture2D tex) where T:struct
    {
        T[] colors1D = new T[tex.Width * tex.Height];
        tex.GetData(colors1D);
        return colors1D;
    }

    // set an 1-dimensional {T} array to a texture.
    public static void ArrayToTexture<T>(T [] cols, Texture2D tex) where T:struct
    {
         tex.SetData(cols);
    }
}

The T stuff means simply that you can get/put any data type you wish, as long as it's accepted by the texture code itself. You can either use an Xna.Color-Array or an Int32-Array or something else there. ...where T:struct defines the T-variables as not-nullable.

To create an array with the right size, just use the TextureToArray-method.

Int32[] ar = TextureToArray<Int32>(myTex);



Testimage

Last but not least, the test image:

public void BuildTestImage()
{
   Microsoft.Xna.Framework.Color[] c = GetMainTexData<Microsoft.Xna.Framework.Color>();

  // go through all the pixels and color them.
  for(int i=0; i<c.Length; i++)
  {
       // color every second pixel different.
       if(i % 2 == 1)
             c[i] = Microsoft.Xna.Framework.Color.Red;
       else
             c[i] = Microsoft.Xna.Framework.Color.Green;

      // color the first four lines.
      if(i < texture.Width * 4)
         c[i] = Microsoft.Xna.Framework.Color.Yellow;
      // color the first 2 lines.
      if(i < texture.Width * 2)
         c[i] = Microsoft.Xna.Framework.Color.Magenta;

      // color the last two lines
      if(i > (texture.Height - 2) * texture.Width)
         c[i] = Microsoft.Xna.Framework.Color.Magenta;
  }

    // set the new data to the texture.
    SetMainTexData(c);
}

You will see an image like this:


On the left and right there is the background which is actually in the color "Cornflowerblue".
If you have a widescreen image (e.g. 200x100px), the background will be visible on the top and bottom.

The first two lines (magenta, top and bottom) are used to test the cutoff. You can use ResizeTexture(w, h, 2,2) to test that. The yellow line indicates the first two lines of the "real visible" screen. Then, every pixel is either red or green. In the bottom of the image, you should see a green or red pixel in the magenta lines. That one indicates if the image is drawn from left to right.


Download

Download the Source for this Part:
Emu_02_GraphicsEngine.zip from Mirror 1 (OneDrive)
Emu_02_GraphicsEngine.zip from Mirror 2 (homeserver)


That's it with this part. You should now have a "graphics engine" which your emulators can use.

In Part 2B [TBA] we will create the "Sound Engine"/Sound Interface for the emulators to use.

Part 2B: The Sound Engine [TBA]

You can skip the whole Part 2x stuff and just go to Part 3 if you do that on another Engine/Platform.

Montag, 9. März 2015

Part 2: Basic Winphone Setup

This is part 2 in my tutorial series about writing an emulator.
I am doing this with WinPhone 8.1 and MonoGame.

If you don't know what I'm talking about, here is Part 1.

In this section, we will install the right development environment and create a basic game-app.

I take this part first because you and I want to see at least something, not? You can skip that part if you use another engine/platform.

OK, I will use MonoGame, the (open source) successor of XNA.
If you want to use DirectX, you have to use C++ and that's none of my business anymore.

At least now, you should have downloaded and installed MS Visual Studio 2013 Express Update 4 or something similar.

After that, you should install MonoGame.

You can download MonoGame from here:
http://www.monogame.net/downloads/
Use at least V. 3.2 which has templates for MS VS 2013.

With the install also comes OpenAL, which I decided to install because, as mentioned, I don't know nothing about sound programming and if there is an "Open Source Audio Library", why not use that?

Start up Visual Studio and create a new Application using the C#->"MonoGame Windows Phone 8 Project"-Template.

There you have three "main" files:
GamePage.xaml, which is your WinPhone-Layout-file for that page.
GamePage.xaml.cs, which is the source-file corresponding to the layout (file) - where your button-clicks and other UI-stuff will be handled.
Game1.cs, which is the game itself. It runs in it's own thread - you cannot simply use WP-UI-button-clicks and stuff here because that will maybe throw an Asyncronous-Exception. More about that later, when I know how to handle that myself.

The project should compile without errors.

If you get a blank screen, don't worry - that's a common issue with the MonoGame v3.2 template.
Follow this discussion to solve it:
http://community.monogame.net/t/3-2-on-windows-phone-8-just-shows-black-screen/278/12

I just uncommented the alternate grid on the bottom of GamePage.xaml and commented out the main one. Even if it should run now in portrait mode, it seems to be in landscape mode, though.

Some Static Functions

There are some methods which will be used through the whole app. Create a new class called Static.cs and put this methods in it:

using System.Windows;
using System.Windows.Controls;
...

// shows a standard text message.
public static void ShowMsg(string txt)
{
     MessageBox.Show(txt);
}

// go back to the last page or to the main page.
public static void GoBackOrMain(Frame frm)
{
     if(frm.CanGoBack)
          frm.GoBack();
    else
         frm.Navigate(new Uri("/GamePage.xaml", UriKind.Relative);
}


The first method, ShowMsg, is just here to get some info on the screen. You can use that for infos like "Loading failed, please try another ROM" or such stuff which only needs an OK-button.

The second method GoBackOrMain, tries to go back to the last opened page. If it cannot go back, it tries to open the main page. This method is for use with the back button and/or cancel buttons.

In WP 8.1 that works a little bit other but on WP 8.0 that's all you have to do.
That code is not tested yet (navigating).

The Back Button

The back button does not work like in other apps. You cannot use HardwareButtons.BackbuttonPressed += myFunc (WP 8.1?).

Open GamePage.xaml. Click on the events button in the properties window. Search for the event BackbuttonPressed or OnBackbuttonPressed and double click it.

You have now a method for your back button, use it like you want. I want to open a CommandBar with it, but first you should just exit the app with _game.Exit();

Other Stuff

There are other problems which I could not solve until now. I will post it here when I find a solution.
+ Cannot switch tasks, the game just shows the cleared screen after resuming.
+ Cannot even press the switch-task-button and then resume game directly.

Download

Download the Source for this Part:
Emu_01_WP_Setup.zip from Mirror 1 (OneDrive)
Emu_01_WP_Setup.zip from Mirror 2 (homeserver) (direct download)

It has some more static methods and draws a texture to the screen for testing.



In Part 2A we will set up the graphics for our emulators to have a "render device".

Part 2A: The Graphics Engine

You can skip the whole Part 2x stuff and just go to Part 3 if you do that on another Platform/Engine.

Donnerstag, 26. Februar 2015

How to write an emulator. (Part 1)

05.2015: I stopped working on this but I leave it online. Maybe I will continue that later.
05.2017: I started again working on this but I will do it with JavaScript now. This post totally needs an update for that approach but I will leave it as is and make a new post ( in german). So you can refer to this one for...stuff you may need.


I don't know. But I will write down, step by step, all what I do to accomplish it. (For my brains, can't hold all that. ;) )

This one is not for beginners in programming. Also, I will only cover how to make an old game console emulator. It's not about emulating a certain CPU - the CPU emulator will be included from third parties.

I am making a tutorial series about that. In this post we do some research. Actual work will be done in the next posts.

A friend of mine once wrote a Sega Master System Emulator. I did a graphical refresh for it.



Here is the Download (Windows exe and dll):
SMSEmu.zip on Mirror 1 (OneDrive)
SMSEmu.zip on Mirror 2 (homeserver) (direct download, maybe with left click/Save as..)

Since I lost the all the code and since I found out that WinPhone is an awesome platform to program with, I decided to do my own emulator and maybe a whole emulator pack. It could be fun.

First I want to re-do the SMS (Sega Master System), mostly because my friend has done it and...because I've got some ROMs.

Here are the SMS ROMs. Please ONLY use them for testing your emulator. DO NOT SHIP THEM with it. That would be illegal. I uploaded them only because they are relatively hard to find and you will need some ROMs at a certain point for further developing.

So, here's the ROM download:
SMSroms.zip on Mirror 1 (OneDrive)
SMSroms.zip on Mirror 2 (homeserver) (direct download)

Get The Basics

This is where I started. If you are new to the topic, have a look at it.

http://fms.komkon.org/EMUL8/HOWTO.html

But the links all are a little bit outdated. This tutorial came out when the internet just started, and all the newsgroups and stuff are mostly not actual and hip. ;)

Ok then, lets write that all down.
I want to do it with C#.
I HAVE to do it with C# if I want to port that to WinPhone.
(Actually, for using DirectX I would have to use C++. I hope, I find another solution.)

To develop WinPhone-Apps, you need something like this:
http://www.microsoft.com/de-ch/download/details.aspx?id=44914
(That's MS Visual Studio Express 2013 with Update 4 - WinPhone SDK should be included here.)

But there is a better version, Visual Studio Community. I don't know if that works with WinPhone, so I use the one recommended by Microsoft.

Some Theoretical Thoughts

I want to do a multi-purpose multi-platform emulator. It should be possible to emulate several consoles with one program and it should be possible to port the code to allmost any platform.

Best case scenario would be that you load any ROM and the application decides by filename and/or file signature, what emulator to create and start. You could put any supported ROM into your ROM folder and have to decide absolutely nothing (on the mobile phone, PC version needs an input configuration ;) ) and could just play the game - no matter if it's a Sega or Nintendo, MAME game and what console it actual is.

My platform decision is WindowsPhone, but I want to write the code as flexible as possible to include it in Unity3D or other Engines/Platforms. (With Unity3D, almost any platform can be reached, from PC/Mac/Linux over Android/iPhone/WP? up to *real* consoles like PS3/PS4/XBoxXXX/Wii. So, doing the emulator with Unity would be a great way to reach almost every people.)

Problem with Unity is that RTT (Render-To-Texture) is only possible with a paid version of Unity. You could not do RTT just for fun here. And that's what we need to render the old 2D-images on to a scaled texture which fits the whole screen.

[Edit] I am trying it with Unity, though. Maybe there is a possibility to, in any way, draw on the texture.

[Edit 2]: As of 2019, it is now possible to use RTT in Unity Free. I managed to do it with another project. It's not even hard to do. But I don't know exactly what I did. Just to note...RTT works with Unity Free now. So, Go for it.

But for the emulator, this is not a problem at all. The emulator just returns an array of pixels, which the graphics engine must use "outside" of the emulator. You can use just any graphics engine which can render pixels to a texture or directly to screen. If you want, you can try it with the Windows-Desktop-GUI-API. I will do it with the WinPhone API using Direct3D [MonoGame] and also try it with Unity.

Sound seems to be the most easy thing to emulate first from an old console [the SEGA Master System]. According to the tutorial ^ there was an SMS-emulator written in one Day - the only thing it could do was playing the sound from the ROM. So, I think, emulating the sound engine is more easy than the graphics itself.

Get The Facts


If you want to emulate something, you need to know about it.
I want to do an SMS emulator first. Friend gave me this links for it and mentioned the first (top) document, which he also used.

http://www.smspower.org/Development/Documents

This document will give more explanation than the other ones:
http://www.smspower.org/uploads/Development/richard.txt

I need to learn all I can about it...

Get The CPU

Most old - really old - consoles use the Z80-CPU as main CPU. That's the case for GameBoys, SEGA Master System, SEGA GameGear and I don't know what else. So, we will firstly use the Z80 CPU and maybe add some other CPUs later.

I did a search for a C# Z80 CPU Emulator and found this one:

https://code.google.com/p/cs80/source/checkout

Thank gods, it exists. We do not have to do it ourselves. Contributions go to: [Unknown]
It's released with the New BSD License.

I downloaded it using SlikSvn: https://sliksvn.com/download/

Friend told me we need only the Z80.cs file, all other stuff is (PC-?)hardware related addendum.



*(See below) I switched to Linux and try to do it now with Linux stuff. Please be patient.

More in the next parts,
[Not Done*]Basic Unity3D Setup
or
Basic Winphone Setup (with MonoGame).

You can skip that part if you want to use another Framework/Engine/Platform than WinPhone and Monogame. What you have to accomplish is to render pixels on the screen. I want to render them on an image (which could be stretched) and then show the whole image on the screen.

After that, we will Build Your Framework which is the interface between the engine and the emulators itself.