What's new

Two questions about programming/emulation

Dax Tsurugi

New member
I have most of the basic principles of emulation programming down, but two things really stump me and prevent me from trying out a simple emulator such as Space Invaders.

1. Could someone explain bit shifting to me in layman's terms, or provide a site that is in plain English? I've looked across the Interwebz for tutorials and such, but they only seem to really confuse me.

2. Sort of a subset or a subquestion of 1, but here goes: How does bit shifting allow you to read a rom's data, exactly? I know how to open a file, but how does bit shifting allow you to read the data of the rom, and how much are you supposed to know to shift by?

If anyone could provide me with an explanation, or a useful site, I'd appreciate it.
 

Toasty

Sony battery
Google is always good for this sort of thing. Wikipedia's entry on bitwise operations (the first search result) should be helpful. Of course, you'll need an understanding of the binary number system (or at least on/off switches :p) to appreciate what these operations do. I'm not sure why you'd use bit-shifting to read file data without seeing the context in which it's being used.
 

Doomulation

?????????????????????????
For question one... Know that one byte is 8 bits. Shifting involves "shifting" those bits.
Say that you have a byte like this: 1111 1111. Shift it right once and you have 0111 1111. Shift it left once and you have: 1111 1110 (because the entire contents was shifted one digit left or right).
Shifting can also be used to shift digits into one place from another. Let me explain by first giving you the number 0xFF00 (65280 in decimal, base 10). If we wanted to move those digits so they appeared first in that number (that is, to make it 0xFF00), then we would use shifting operations. By shifting 4 position, we can move the digits one digit (for example, 0xFF00 becomes 0xFF0).
How is this used? There are many advanced areas of use, such as combining two bytes to a word, or shifting digits to make a number smaller for use in a jump table.
There are also shifting opcodes in emulator, where games want to use shifting. You don't really need to think of these since the game handles it.

I cannot answer question 2 because I have no idea what you're referring to. If you would give an example...
 
OP
D

Dax Tsurugi

New member
I cannot answer question 2 because I have no idea what you're referring to. If you would give an example...

I meant something along the lines of: how do you use bit shifting, or binary operations to fetch opcodes, and things like that?
 

Garstyciuks

New member
You use binary operations to decode the information from an opcode. For example, say there is a chip8 opcode 0xD856. The first number (D) is the opcode type identifier, in this case, the type is "Draw sprite", the second number (8) is the height of the sprite, the third number (5) is the number of the register in which the X position is stored and the fourth number (6) is the number of the register in which the Y position is stored. Now to handle this opcode in C++ interpreter emulator you would have to do something like this:

Code:
void execute(unsigned short opcode)
{
    switch (opcode&0xF000)
    {
        //case ...:
        case 0xD000:
            int height = (opcode&0x0F00)>>8;
            int x = reg[(opcode&0x00F0)>>4]; //char reg[16]; is CPU registers
            int y = reg[(opcode&0x000F)];
            //draw a 8xheight sprite at (x;y)
            break;
        //case ...:
    }
}

Bit shifting is the same as multiplying or dividing by powers of 2.
 
Last edited:

Cyberman

Moderator
Moderator
Or...

a common processor architecture [FONT=&quot][/FONT](PS1/PS1/N64 are based on mips)
Noticed the upper 6 bits there determine a number of the instructions (IE ~ 64 because 2^6 is 64).
How do you find this numbers to make something to read the opcode information?
Well I suppose you could create a monster case statement (that would be just sad but I've seen it done).
How about Bit masking and shifting?
Code:
unsigned long Opcode;

switch(Opcode >> (32-6))
{
  case 0x00: // ADD-ADDU MUL-MULU DIV-DIVU JR ... etc.
    decode_group_0(Opcode);
    break;
  case 0x01: //
 //...
}
There was a bit shift and you could decode the upper 6 bits to get what group of opcodes you are dealing with.
Code:
void decode_group_0(unsigned long Opcode)
{
  switch(Opcode & 0x7FF)
  {
    case 0x020: // ADD
    case 0x021: // ADDU
      break;
  }
}
And there is a logical AND used to find opcodes.

Cyb

Have fun with programming.
 
Last edited:

Top