Code:
case 0xD:
//draw
if (memory.videoMode==0)
{
x = memory.reg[(opcode&0x0F00)>>8];
y = memory.reg[(opcode&0x00F0)>>4];
memory.reg[15] = 0;
height = opcode&0x000F;
if (height==0) height = 16;
memory.Push(memory.I);
for (j=0; j<height; j++)
{
for (i=0; i<8; i++)
{
xt = x % 64;
yt = y % 32;
if (memory.HWrap)
if (xt+i>=64) xt-=64;
if (memory.VWrap)
if (yt+j>=32) yt-=32;
if (xt+i<64 && yt+j<32)
{
if (memory.vram[(xt+i)<<1][(yt+j)<<1] && ((memory.ram[memory.I]&(128>>i))>>(7-i))) memory.reg[15]=1;
memory.vram[((xt+i)<<1)+0][((yt+j)<<1)+0] ^= (memory.ram[memory.I]&(128>>i))>>(7-i);
memory.vram[((xt+i)<<1)+1][((yt+j)<<1)+0] ^= (memory.ram[memory.I]&(128>>i))>>(7-i);
memory.vram[((xt+i)<<1)+1][((yt+j)<<1)+1] ^= (memory.ram[memory.I]&(128>>i))>>(7-i);
memory.vram[((xt+i)<<1)+0][((yt+j)<<1)+1] ^= (memory.ram[memory.I]&(128>>i))>>(7-i);
}
}
memory.I++;
}
memory.I = memory.Pop();
}
else
{
if ((opcode&0x000F)>0)
{
x = memory.reg[(opcode&0x0F00)>>8];
y = memory.reg[(opcode&0x00F0)>>4];
memory.reg[15] = 0;
height = opcode&0x000F;
memory.Push(memory.I);
for (j=0; j<height; j++)
{
for (i=0; i<8; i++)
{
xt = x % 128;
yt = y % 64;
if (memory.HWrap)
if (xt+i>=128) xt-=128;
if (memory.VWrap)
if (yt+j>=64) yt-=64;
if (xt+i<128 && yt+j<64)
{
if (memory.vram[xt+i][yt+j] && ((memory.ram[memory.I]&(128>>i))>>(7-i))) memory.reg[15]=1;
memory.vram[xt+i][yt+j] ^= (memory.ram[memory.I]&(128>>i))>>(7-i);
}
}
memory.I++;
}
memory.I = memory.Pop();
}
else
{
x = memory.reg[(opcode&0x0F00)>>8];
y = memory.reg[(opcode&0x00F0)>>4];
memory.reg[15] = 0;
memory.Push(memory.I);
for (j=0; j<16; j++)
{
for (i=0; i<8; i++)
{
xt = x % 128;
yt = y % 64;
if (memory.HWrap)
if (xt+i>=128) xt-=128;
if (memory.VWrap)
if (yt+j>=64) yt-=64;
if (yt+j<64)
{
if (xt+i<128)
{
if (memory.vram[xt+i][yt+j] && ((memory.ram[memory.I]&(128>>i))>>(7-i))) memory.reg[15]=1;
memory.vram[xt+i][yt+j] ^= (memory.ram[memory.I]&(128>>i))>>(7-i);
}
if (xt+i+8>=128) xt-=128 {
if (memory.vram[xt+i+8][yt+j] && ((memory.ram[memory.I+1]&(128>>i))>>(7-i))) memory.reg[15]=1;
memory.vram[xt+i+8][yt+j] ^= (memory.ram[memory.I+1]&(128>>i))>>(7-i);
}
}
}
memory.I+=2;
}
memory.I = memory.Pop();
}
}
memory.pos+=2;
break;
This is my drawing function. I think that it can be optimized a lot, etc... This was written almost a year ago

First it checks if the current video mode is chip 8, or schip. If the video mode is 0, then it's chip8. I'll comment about the chip8 part.
Code:
x = memory.reg[(opcode&0x0F00)>>8];
y = memory.reg[(opcode&0x00F0)>>4];
memory.reg[15] = 0;
height = opcode&0x000F;
if (height==0) height = 16;
memory.Push(memory.I);
This piece of code first finds all the arguments for the opcode, and stores Index register (because it will change in later code). It may be saved in a different place than the stack (0xDxxx instruction shouldn't change the stack), but I just liked this approach better. (the stack isn't changed, because the same value is popped to Index after done drawing).
Code:
for (j=0; j<height; j++)
{
for (i=0; i<8; i++)
{
xt = x % 64;
yt = y % 32;
if (memory.HWrap)
if (xt+i>=64) xt-=64;
if (memory.VWrap)
if (yt+j>=32) yt-=32;
xt and yt are transformed x and y positions. This piece starts the loops for drawing the image and makes sure that the sprite won't be drawn offscreen. If some pixels don't fit inside, and if my emulator specific wrapping options are set, the sprite will wrap around the other side of the screen. I found out that some games assumes that the graphics are drawn wrapped, others not. So I made a setting to select whether to wrap or not.
Code:
for (j=0; j<16; j++)
{
for (i=0; i<8; i++)
{
xt = x % 128;
yt = y % 64;
if (xt+i<64 && yt+j<32)
{
if (memory.vram[(xt+i)<<1][(yt+j)<<1] && ((memory.ram[memory.I]&(128>>i))>>(7-i))) memory.reg[15]=1;
memory.vram[((xt+i)<<1)+0][((yt+j)<<1)+0] ^= (memory.ram[memory.I]&(128>>i))>>(7-i);
memory.vram[((xt+i)<<1)+1][((yt+j)<<1)+0] ^= (memory.ram[memory.I]&(128>>i))>>(7-i);
memory.vram[((xt+i)<<1)+1][((yt+j)<<1)+1] ^= (memory.ram[memory.I]&(128>>i))>>(7-i);
memory.vram[((xt+i)<<1)+0][((yt+j)<<1)+1] ^= (memory.ram[memory.I]&(128>>i))>>(7-i);
}
}
memory.I++;
}
memory.I = memory.Pop();
This final piece of code updates the screen data (which is stored in memory.vram array). The chip8 images are 8xn size. It means that one row of pixels fit into one byte. And there are n rows. n maximum value is 8. If n value is 0, then the image height is 16. So this piece of code cycles through every bit of image data and updates the vram correspondingly. if (memory.vram[(xt+i)<<1][(yt+j)<<1] && ((memory.ram[memory.I]&(128>>i))>>(7-i))) memory.reg[15]=1; checks for collision. If there is collision, it sets 0xF register to 1. The other four lines update the screen data using xor. In my emulator vram dimmensions are 128x64. So in chip8 mode, to get 64x32 resolution, I had to set 4 pixels.
And once the vram is updated, you can draw the contents of it with any api you like. In my emulator, each value of the array stores the state of the screen pixel. So if vram[5][6] is 1, then you need to display a pixel at x=5, y=6.