Sdl Version Of Visual Boy Advanced


gmiller1018

Member
Joined
Sep 21, 2006
Messages
336
Location
USA Florida
Website
Visit site
I have a version of the VBA code that I use in the class I teach at Full Sail where I took the 1.8.0 source and fixed a bunch of stuff to make it work for source code bebugging and the like. It has a core file in the emulation that on x86 machine is in assembly and I am going to rewite that for the ARM machine. There are some memory layout issues that I am looking for solutions.

The current code allows up to 32Mb of ROM code but on the current gp2x that would require using the upper 32Mb of memory (with the kernel module trick posted on the wiki). There appears to be sections of this memory that are used for frame buffers and the like. Are there any of these regions that it is unsafe to write over. I am trying to get some idea of the ROM size limits that I need to live with. I was thinking that using the cache memory on this region and an ARM core "might" make the performance of the VBA reasonable for use. I know there is a dynamic recompile thread here but I figured if my version of the emulator could run fast enough it might be a stop gap till the other project is done. Also in the mean time I get to learn something.

Any comments or suggestions?
 
This is what I have for the 1.7.2 vba in the file GBA.cpp

int CPULoadRom(const char *szFile)
{
int size = 0x2000000;
struct stat stat_buf;
if(rom != NULL) {
CPUCleanUp();
}

systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
//Try to apply MMU hack.
int mmufd = open("/dev/mmuhack", O_RDWR);
if(mmufd < 0) {
system("/sbin/insmod mmuhack.o");
mmufd = open("/dev/mmuhack", O_RDWR);
}
if(mmufd < 0)
{
printf("MMU hack failed\n");
}else{
close(mmufd);
}
stat(szFile, &stat_buf);
// rom = (u8 *)malloc(0x2000000);
// rom = (u8 *)malloc(stat_buf.st_size);
// unsigned char* UpperMem;
int Uppermemfd = open("/dev/mem", O_RDWR); //Open the memory for reading/writing
rom = (u8 *)mmap(0, 0x2000000, PROT_READ|PROT_WRITE, MAP_SHARED, Uppermemfd, 0x2000000); //mmap the upper 32MB.
if(rom == NULL) {
systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s %d"),
szFile, stat_buf.st_size);
return 0;
}

......
 
I had looked at this approach but the wiki and others here show that that there are frame buffers and sound buffers there so I was trying to avoid shooting SDL in the foot while implementing this. I started with the 1.8.1 version of the code and fixed it so it works on Linux and Windows with SDL. I repaired the gdb debug connection code and the disaassembly (only works in gui version) and added some new debug features to the development code. I have reduced the size of some of the structures to help the memory foot print and inprove some performance. I am working on the x86 core code to try to have a ARM version of it to hopefully keep the speed up. The 32 MB for ROM code was the major issue in memory allocation, I was considering dropping this to 16 MB to help keep the memory requirments smaller (not sure how many ROM's are bigger than 16 MB but I am going to check). I was tempted to do what you suggest and make sure the cache is working on the upper 32 MB but I was concerned on the impact to other code that uses this memory. Do the SDL code actually use the upper 32 MB as part of it's sound or other processing?
 
As far as I know, yes... Heres a list of things used in the upper 32mb

0x03000000 Video decoding firmware (currently 342812 bytes, but may change in size with various firmware releases)
0x03101000 Primary frame buffer (153600 bytes)
0x03381000 Secondary frame buffer (153600 bytes)
0x03600000 Sound buffer, at least in SDL. Size depends on multiple factors. 16384 bytes should always be enough.
0x03D00000 ~ 0x03FFFFFF is reserved for internal buffers of MPEG H/W decoder.

Excellent wiki article here:
http://wiki.gp2x.org/wiki/Using_the_upper_32MB_of_memory

It explains how to do it your self and how to do it with the mmuhack module.


And as for suggestions:
I think, if possible, frame and sound buffers are the way to go if were looking for max speed.

Good luck.
 
looks like the 1st 16mb of the upper 32mb is free to use. if you can get the last 16mb of ram and join together with this, you could still use a full 32mb for the rom. another alternative cold be to rewrite the sound part so you dont use sdl for it.
another unrelated suggestion. it may be interesting to look at the source for psp vba as well as the pocketpc versions.
 
pcklee123 posted on Oct 15 2006 at 02:32 AM said:
another alternative cold be to rewrite the sound part so you dont use sdl for it.
(I wrote the wiki page)
Not sure if that will get the soundbuffer out of there. Might be that the linux driver puts the sound buffer there, what I ment with "atleast in SDL" is that I didn't test it without SDL.
 
Last edited by a moderator:
Well I am using some of the #ifdef options to reduce the memory foot print for the "game playing" version. This will remove game profiling and some other game debugging from the emulator. I have the stuff from the wiki in with supoort for a 16 mb ROM in but not tested. This code will require a "ROM chooser" to select the game to play but that is a common issue. I am testing without the X86 core (using the C core) so once I have a working model I will try to create an ARM core piece to replace the "C core".
 
Gary Miller posted on Oct 15 2006 at 01:28 PM said:
Well I am using some of the #ifdef options to reduce the memory foot print for the "game playing" version. This will remove game profiling and some other game debugging from the emulator. I have the stuff from the wiki in with supoort for a 16 mb ROM in but not tested. This code will require a "ROM chooser" to select the game to play but that is a common issue. I am testing without the X86 core (using the C core) so once I have a working model I will try to create an ARM core piece to replace the "C core".
Can anyone give some examples of how to change the C to ARM?
e.g in C for two opcodes sub and subs

Code:
#define NEG(i) ((i) >> 31)
#define POS(i) ((~(i)) >> 31)
#define ADDCARRY(a, b, c) \
  C_FLAG = ((NEG(a) & NEG(b)) |\
			(NEG(a) & POS(c)) |\
			(NEG(b) & POS(c))) ? true : false;
#define ADDOVERFLOW(a, b, c) \
  V_FLAG = ((NEG(a) & NEG(b) & POS(c)) |\
			(POS(a) & POS(b) & NEG(c))) ? true : false;
#define SUBCARRY(a, b, c) \
  C_FLAG = ((NEG(a) & POS(b)) |\
			(NEG(a) & POS(c)) |\
			(POS(b) & POS(c))) ? true : false;
#define SUBOVERFLOW(a, b, c)\
  V_FLAG = ((NEG(a) & POS(b) & POS(c)) |\
			(POS(a) & NEG(b) & NEG(c))) ? true : false;
#define OP_SUB \
	{\
	  reg[dest].I = reg[base].I - value;\
	}
#define OP_SUBS \
   {\
	 u32 lhs = reg[base].I;\
	 u32 rhs = value;\
	 u32 res = lhs - rhs;\
	 reg[dest].I = res;\
	 Z_FLAG = (res == 0) ? true : false;\
	 N_FLAG = NEG(res) ? true : false;\
	 SUBCARRY(lhs, rhs, res);\
	 SUBOVERFLOW(lhs, rhs, res);\
   }
In x86 ASM this becomes
Code:
#define OP_SUB \
	 asm ("sub %1, %%ebx;"\
				  : "=b" (reg[dest].I)\
				  : "r" (value), "b" (reg[base].I));

#define OP_SUBS \
	 asm ("sub %1, %%ebx;"\
		  "setsb N_FLAG;"\
		  "setzb Z_FLAG;"\
		  "setncb C_FLAG;"\
		  "setob V_FLAG;"\
				  : "=b" (reg[dest].I)\
				  : "r" (value), "b" (reg[base].I));

What about in ARM ASM?
If someone can give some examples, I can try to incorporate into VBA
Thanks
 
Last edited by a moderator:
Code:
	#define OP_MOV \
	asm("mov %0, %1\n"
		: // Outputs //
		: "r" (reg[dest].I), "r" (value) // Inputs
		: "r0","r1","r2","r3" // Regs crushed & smushed
		);

Couldn't you use something like that for the MOV opcode? I only know basic asm so i would assume it should work
 
Normmatt posted on Oct 24 2006 at 03:51 AM said:
Code:
	#define OP_MOV \
	asm("mov %0, %1\n"
		: // Outputs //
		: "r" (reg[dest].I), "r" (value) // Inputs
		: "r0","r1","r2","r3" // Regs crushed & smushed
		);

Couldn't you use something like that for the MOV opcode? I only know basic asm so i would assume it should work
I replaced
Code:
#define OP_MOV \
reg[dest].I = value;
with
Code:
	#define OP_MOV \
	asm("mov %0, %1\n": : "r" (reg[dest].I), "r" (value) : "r0","r1","r2","r3" );
Its compiling will report back if it works
 
Last edited by a moderator:
I replaced
Code:
#define OP_MOV \
reg[dest].I = value;
with
Code:
	#define OP_MOV \
	asm("mov %0, %1\n": : "r" (reg[dest].I), "r" (value) : "r0","r1","r2","r3" );
Its compiling will report back if it works
[/quote]

Didn't work. Can someone explain? I think that "r"(reg[dest].I should be an output?
 
pcklee123 said:
I replaced
Code:
#define OP_MOV \
reg[dest].I = value;
with
Code:
	#define OP_MOV \
	asm("mov %0, %1\n": : "r" (reg[dest].I), "r" (value) : "r0","r1","r2","r3" );
Its compiling will report back if it works

Didn't work. Can someone explain? I think that "r"(reg[dest].I should be an output?
[/quote]
Yes, that does make sense i must have put it in inputs my mistake.

try this:
Code:
	#define OP_MOV \
	asm("mov %0, %1\n": "r" (reg[dest].I) : "r" (value) : "r0","r1","r2","r3" );
 
Last edited by a moderator:
I replaced
Code:
#define OP_MOV \
reg[dest].I = value;
with
Code:
	#define OP_MOV \
	asm("mov %0, %1\n": : "r" (reg[dest].I), "r" (value) : "r0","r1","r2","r3" );
Its compiling will report back if it works

Didn't work. Can someone explain? I think that "r"(reg[dest].I should be an output?
Changed it to
Code:
#define OP_MOV \
	asm("mov %0, %1\n": "=r" (reg[dest].I):"r" (value) : "r0","r1","r2","r3" );
and it works
 
nice to hear its working, now you just need to do that for all the other opcodes :p
 
Normmatt posted on Oct 29 2006 at 08:47 AM said:
nice to hear its working, now you just need to do that for all the other opcodes :p
Problem is I know next to nothing about Assembly language. Any other suggestions?
BTW it takes half an hour just to compile gba.cpp it also slows down my pc to a crawl while doing it. So its not something I can just do by trial and error.
 
Last edited by a moderator:
I'm hoping these work as I haven't bothered to try and get vba-r to compile under windows yet.
Code:
#define OP_AND \
	  asm("and %0, %1, %2\n": "=r" (reg[dest].I):"r" (reg[(opcode>>16)&15].I), "r" (value) : "r0","r1","r2","r3" ); 

#define OP_ANDS \
	  asm("and %0, %1, %2\n": "=r" (reg[dest].I):"r" (reg[(opcode>>16)&15].I), "r" (value) : "r0","r1","r2","r3" );\
	  \
	  N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\
	  Z_FLAG = (reg[dest].I) ? false : true;\
	  C_FLAG = C_OUT;

#define OP_EOR \
	  asm("eor %0, %1, %2\n": "=r" (reg[dest].I):"r" (reg[(opcode>>16)&15].I), "r" (value) : "r0","r1","r2","r3" );

#define OP_EORS \
	  asm("eor %0, %1, %2\n": "=r" (reg[dest].I):"r" (reg[(opcode>>16)&15].I), "r" (value) : "r0","r1","r2","r3" ); \
	  \
	  N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\
	  Z_FLAG = (reg[dest].I) ? false : true;\
	  C_FLAG = C_OUT;
#define OP_SUB \
	{\
	  asm("sub %0, %1, %2\n": "=r" (reg[dest].I):"r" (reg[base].I), "r" (value) : "r0","r1","r2","r3" ); 
	}
#define OP_RSB \
	{\
	  asm("rsb %0, %1, %2\n": "=r" (reg[dest].I):"r" (reg[base].I), "r" (value) : "r0","r1","r2","r3" ); 
	}
#define OP_ADD \
	{\
	  asm("add %0, %1, %2\n": "=r" (reg[dest].I):"r" (reg[base].I), "r" (value) : "r0","r1","r2","r3" ); 
	}

Not exactly sure if those will increase speed at all but it should be quicker than the C code
 
Normmatt posted on Oct 29 2006 at 10:02 AM said:
I'm hoping these work as I haven't bothered to try and get vba-r to compile under windows yet.
.....

Not exactly sure if those will increase speed at all but it should be quicker than the C code
OK I'll compile it and see
Yes it works.
 
Last edited by a moderator:
Back
Top