Implemented 2SF format support
parent
9041ba977f
commit
24b53c6e71
|
@ -0,0 +1,459 @@
|
||||||
|
// !$*UTF8*$!
|
||||||
|
{
|
||||||
|
archiveVersion = 1;
|
||||||
|
classes = {
|
||||||
|
};
|
||||||
|
objectVersion = 46;
|
||||||
|
objects = {
|
||||||
|
|
||||||
|
/* Begin PBXBuildFile section */
|
||||||
|
83DE0C14180A9BD400269051 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 83DE0C12180A9BD400269051 /* InfoPlist.strings */; };
|
||||||
|
83DE0C81180A9CA400269051 /* ARM9.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DE0C46180A9CA400269051 /* ARM9.h */; };
|
||||||
|
83DE0C82180A9CA400269051 /* arm_instructions.c in Sources */ = {isa = PBXBuildFile; fileRef = 83DE0C47180A9CA400269051 /* arm_instructions.c */; };
|
||||||
|
83DE0C83180A9CA400269051 /* arm_instructions.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DE0C48180A9CA400269051 /* arm_instructions.h */; };
|
||||||
|
83DE0C84180A9CA400269051 /* armcpu.c in Sources */ = {isa = PBXBuildFile; fileRef = 83DE0C49180A9CA400269051 /* armcpu.c */; };
|
||||||
|
83DE0C85180A9CA400269051 /* armcpu.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DE0C4A180A9CA400269051 /* armcpu.h */; };
|
||||||
|
83DE0C86180A9CA400269051 /* bios.c in Sources */ = {isa = PBXBuildFile; fileRef = 83DE0C4B180A9CA400269051 /* bios.c */; };
|
||||||
|
83DE0C87180A9CA400269051 /* bios.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DE0C4C180A9CA400269051 /* bios.h */; };
|
||||||
|
83DE0C88180A9CA400269051 /* bits.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DE0C4D180A9CA400269051 /* bits.h */; };
|
||||||
|
83DE0C89180A9CA400269051 /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DE0C4E180A9CA400269051 /* config.h */; };
|
||||||
|
83DE0C8A180A9CA400269051 /* COPYING in Resources */ = {isa = PBXBuildFile; fileRef = 83DE0C4F180A9CA400269051 /* COPYING */; };
|
||||||
|
83DE0C8B180A9CA400269051 /* cp15.c in Sources */ = {isa = PBXBuildFile; fileRef = 83DE0C50180A9CA400269051 /* cp15.c */; };
|
||||||
|
83DE0C8C180A9CA400269051 /* cp15.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DE0C51180A9CA400269051 /* cp15.h */; };
|
||||||
|
83DE0C8D180A9CA400269051 /* debug.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DE0C52180A9CA400269051 /* debug.h */; };
|
||||||
|
83DE0C8E180A9CA400269051 /* dscard.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DE0C53180A9CA400269051 /* dscard.h */; };
|
||||||
|
83DE0C8F180A9CA400269051 /* FIFO.c in Sources */ = {isa = PBXBuildFile; fileRef = 83DE0C54180A9CA400269051 /* FIFO.c */; };
|
||||||
|
83DE0C90180A9CA400269051 /* FIFO.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DE0C55180A9CA400269051 /* FIFO.h */; };
|
||||||
|
83DE0C91180A9CA400269051 /* GPU.c in Sources */ = {isa = PBXBuildFile; fileRef = 83DE0C56180A9CA400269051 /* GPU.c */; };
|
||||||
|
83DE0C92180A9CA400269051 /* GPU.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DE0C57180A9CA400269051 /* GPU.h */; };
|
||||||
|
83DE0C93180A9CA400269051 /* instruction_tabdef.inc in Sources */ = {isa = PBXBuildFile; fileRef = 83DE0C58180A9CA400269051 /* instruction_tabdef.inc */; };
|
||||||
|
83DE0C94180A9CA400269051 /* matrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 83DE0C59180A9CA400269051 /* matrix.c */; };
|
||||||
|
83DE0C95180A9CA400269051 /* matrix.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DE0C5A180A9CA400269051 /* matrix.h */; };
|
||||||
|
83DE0C96180A9CA400269051 /* mc.c in Sources */ = {isa = PBXBuildFile; fileRef = 83DE0C5B180A9CA400269051 /* mc.c */; };
|
||||||
|
83DE0C97180A9CA400269051 /* mc.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DE0C5C180A9CA400269051 /* mc.h */; };
|
||||||
|
83DE0C98180A9CA400269051 /* mem.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DE0C5D180A9CA400269051 /* mem.h */; };
|
||||||
|
83DE0C99180A9CA400269051 /* MMU.c in Sources */ = {isa = PBXBuildFile; fileRef = 83DE0C5E180A9CA400269051 /* MMU.c */; };
|
||||||
|
83DE0C9A180A9CA400269051 /* MMU.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DE0C5F180A9CA400269051 /* MMU.h */; };
|
||||||
|
83DE0C9B180A9CA400269051 /* NDSSystem.c in Sources */ = {isa = PBXBuildFile; fileRef = 83DE0C60180A9CA400269051 /* NDSSystem.c */; };
|
||||||
|
83DE0C9C180A9CA400269051 /* NDSSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DE0C61180A9CA400269051 /* NDSSystem.h */; };
|
||||||
|
83DE0C9D180A9CA400269051 /* registers.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DE0C62180A9CA400269051 /* registers.h */; };
|
||||||
|
83DE0CA1180A9CA400269051 /* SPU.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83DE0C66180A9CA400269051 /* SPU.cpp */; };
|
||||||
|
83DE0CA2180A9CA400269051 /* SPU.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DE0C67180A9CA400269051 /* SPU.h */; };
|
||||||
|
83DE0CA3180A9CA400269051 /* spu_exports.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DE0C68180A9CA400269051 /* spu_exports.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
|
83DE0CA4180A9CA400269051 /* thumb_instructions.c in Sources */ = {isa = PBXBuildFile; fileRef = 83DE0C69180A9CA400269051 /* thumb_instructions.c */; };
|
||||||
|
83DE0CA5180A9CA400269051 /* thumb_instructions.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DE0C6A180A9CA400269051 /* thumb_instructions.h */; };
|
||||||
|
83DE0CA6180A9CA400269051 /* thumb_tabdef.inc in Sources */ = {isa = PBXBuildFile; fileRef = 83DE0C6B180A9CA400269051 /* thumb_tabdef.inc */; };
|
||||||
|
83DE0CA7180A9CA400269051 /* types.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DE0C6C180A9CA400269051 /* types.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
|
83DE0CB8180A9FD000269051 /* state.c in Sources */ = {isa = PBXBuildFile; fileRef = 83DE0CB7180A9FD000269051 /* state.c */; };
|
||||||
|
83DE0CBE180B21DD00269051 /* state.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DE0CB9180A9FE300269051 /* state.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
/* Begin PBXFileReference section */
|
||||||
|
83DE0C06180A9BD400269051 /* vio2sf.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = vio2sf.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
83DE0C11180A9BD400269051 /* vio2sf-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "vio2sf-Info.plist"; sourceTree = "<group>"; };
|
||||||
|
83DE0C13180A9BD400269051 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||||
|
83DE0C46180A9CA400269051 /* ARM9.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARM9.h; sourceTree = "<group>"; };
|
||||||
|
83DE0C47180A9CA400269051 /* arm_instructions.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = arm_instructions.c; sourceTree = "<group>"; };
|
||||||
|
83DE0C48180A9CA400269051 /* arm_instructions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = arm_instructions.h; sourceTree = "<group>"; };
|
||||||
|
83DE0C49180A9CA400269051 /* armcpu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = armcpu.c; sourceTree = "<group>"; };
|
||||||
|
83DE0C4A180A9CA400269051 /* armcpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = armcpu.h; sourceTree = "<group>"; };
|
||||||
|
83DE0C4B180A9CA400269051 /* bios.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bios.c; sourceTree = "<group>"; };
|
||||||
|
83DE0C4C180A9CA400269051 /* bios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bios.h; sourceTree = "<group>"; };
|
||||||
|
83DE0C4D180A9CA400269051 /* bits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bits.h; sourceTree = "<group>"; };
|
||||||
|
83DE0C4E180A9CA400269051 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; };
|
||||||
|
83DE0C4F180A9CA400269051 /* COPYING */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = COPYING; sourceTree = "<group>"; };
|
||||||
|
83DE0C50180A9CA400269051 /* cp15.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cp15.c; sourceTree = "<group>"; };
|
||||||
|
83DE0C51180A9CA400269051 /* cp15.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cp15.h; sourceTree = "<group>"; };
|
||||||
|
83DE0C52180A9CA400269051 /* debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = "<group>"; };
|
||||||
|
83DE0C53180A9CA400269051 /* dscard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dscard.h; sourceTree = "<group>"; };
|
||||||
|
83DE0C54180A9CA400269051 /* FIFO.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = FIFO.c; sourceTree = "<group>"; };
|
||||||
|
83DE0C55180A9CA400269051 /* FIFO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FIFO.h; sourceTree = "<group>"; };
|
||||||
|
83DE0C56180A9CA400269051 /* GPU.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = GPU.c; sourceTree = "<group>"; };
|
||||||
|
83DE0C57180A9CA400269051 /* GPU.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPU.h; sourceTree = "<group>"; };
|
||||||
|
83DE0C58180A9CA400269051 /* instruction_tabdef.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = instruction_tabdef.inc; sourceTree = "<group>"; };
|
||||||
|
83DE0C59180A9CA400269051 /* matrix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = matrix.c; sourceTree = "<group>"; };
|
||||||
|
83DE0C5A180A9CA400269051 /* matrix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = matrix.h; sourceTree = "<group>"; };
|
||||||
|
83DE0C5B180A9CA400269051 /* mc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mc.c; sourceTree = "<group>"; };
|
||||||
|
83DE0C5C180A9CA400269051 /* mc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mc.h; sourceTree = "<group>"; };
|
||||||
|
83DE0C5D180A9CA400269051 /* mem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mem.h; sourceTree = "<group>"; };
|
||||||
|
83DE0C5E180A9CA400269051 /* MMU.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = MMU.c; sourceTree = "<group>"; };
|
||||||
|
83DE0C5F180A9CA400269051 /* MMU.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MMU.h; sourceTree = "<group>"; };
|
||||||
|
83DE0C60180A9CA400269051 /* NDSSystem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = NDSSystem.c; sourceTree = "<group>"; };
|
||||||
|
83DE0C61180A9CA400269051 /* NDSSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NDSSystem.h; sourceTree = "<group>"; };
|
||||||
|
83DE0C62180A9CA400269051 /* registers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = registers.h; sourceTree = "<group>"; };
|
||||||
|
83DE0C66180A9CA400269051 /* SPU.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SPU.cpp; sourceTree = "<group>"; };
|
||||||
|
83DE0C67180A9CA400269051 /* SPU.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPU.h; sourceTree = "<group>"; };
|
||||||
|
83DE0C68180A9CA400269051 /* spu_exports.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = spu_exports.h; sourceTree = "<group>"; };
|
||||||
|
83DE0C69180A9CA400269051 /* thumb_instructions.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = thumb_instructions.c; sourceTree = "<group>"; };
|
||||||
|
83DE0C6A180A9CA400269051 /* thumb_instructions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = thumb_instructions.h; sourceTree = "<group>"; };
|
||||||
|
83DE0C6B180A9CA400269051 /* thumb_tabdef.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = thumb_tabdef.inc; sourceTree = "<group>"; };
|
||||||
|
83DE0C6C180A9CA400269051 /* types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = types.h; sourceTree = "<group>"; };
|
||||||
|
83DE0CB7180A9FD000269051 /* state.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = state.c; sourceTree = "<group>"; };
|
||||||
|
83DE0CB9180A9FE300269051 /* state.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = state.h; sourceTree = "<group>"; };
|
||||||
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
83DE0C02180A9BD400269051 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXGroup section */
|
||||||
|
83DE0BFC180A9BD400269051 = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
83DE0C0F180A9BD400269051 /* vio2sf */,
|
||||||
|
83DE0C08180A9BD400269051 /* Frameworks */,
|
||||||
|
83DE0C07180A9BD400269051 /* Products */,
|
||||||
|
);
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
83DE0C07180A9BD400269051 /* Products */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
83DE0C06180A9BD400269051 /* vio2sf.framework */,
|
||||||
|
);
|
||||||
|
name = Products;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
83DE0C08180A9BD400269051 /* Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
83DE0C0B180A9BD400269051 /* Other Frameworks */,
|
||||||
|
);
|
||||||
|
name = Frameworks;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
83DE0C0B180A9BD400269051 /* Other Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
);
|
||||||
|
name = "Other Frameworks";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
83DE0C0F180A9BD400269051 /* vio2sf */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
83DE0C44180A9CA400269051 /* vio2sf */,
|
||||||
|
83DE0C10180A9BD400269051 /* Supporting Files */,
|
||||||
|
);
|
||||||
|
path = vio2sf;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
83DE0C10180A9BD400269051 /* Supporting Files */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
83DE0C11180A9BD400269051 /* vio2sf-Info.plist */,
|
||||||
|
83DE0C12180A9BD400269051 /* InfoPlist.strings */,
|
||||||
|
);
|
||||||
|
name = "Supporting Files";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
83DE0C44180A9CA400269051 /* vio2sf */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
83DE0C45180A9CA400269051 /* desmume */,
|
||||||
|
);
|
||||||
|
name = vio2sf;
|
||||||
|
path = src/vio2sf;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
83DE0C45180A9CA400269051 /* desmume */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
83DE0C46180A9CA400269051 /* ARM9.h */,
|
||||||
|
83DE0C47180A9CA400269051 /* arm_instructions.c */,
|
||||||
|
83DE0C48180A9CA400269051 /* arm_instructions.h */,
|
||||||
|
83DE0C49180A9CA400269051 /* armcpu.c */,
|
||||||
|
83DE0C4A180A9CA400269051 /* armcpu.h */,
|
||||||
|
83DE0C4B180A9CA400269051 /* bios.c */,
|
||||||
|
83DE0C4C180A9CA400269051 /* bios.h */,
|
||||||
|
83DE0C4D180A9CA400269051 /* bits.h */,
|
||||||
|
83DE0C4E180A9CA400269051 /* config.h */,
|
||||||
|
83DE0C4F180A9CA400269051 /* COPYING */,
|
||||||
|
83DE0C50180A9CA400269051 /* cp15.c */,
|
||||||
|
83DE0C51180A9CA400269051 /* cp15.h */,
|
||||||
|
83DE0C52180A9CA400269051 /* debug.h */,
|
||||||
|
83DE0C53180A9CA400269051 /* dscard.h */,
|
||||||
|
83DE0C54180A9CA400269051 /* FIFO.c */,
|
||||||
|
83DE0C55180A9CA400269051 /* FIFO.h */,
|
||||||
|
83DE0C56180A9CA400269051 /* GPU.c */,
|
||||||
|
83DE0C57180A9CA400269051 /* GPU.h */,
|
||||||
|
83DE0C58180A9CA400269051 /* instruction_tabdef.inc */,
|
||||||
|
83DE0C59180A9CA400269051 /* matrix.c */,
|
||||||
|
83DE0C5A180A9CA400269051 /* matrix.h */,
|
||||||
|
83DE0C5B180A9CA400269051 /* mc.c */,
|
||||||
|
83DE0C5C180A9CA400269051 /* mc.h */,
|
||||||
|
83DE0C5D180A9CA400269051 /* mem.h */,
|
||||||
|
83DE0C5E180A9CA400269051 /* MMU.c */,
|
||||||
|
83DE0C5F180A9CA400269051 /* MMU.h */,
|
||||||
|
83DE0C60180A9CA400269051 /* NDSSystem.c */,
|
||||||
|
83DE0C61180A9CA400269051 /* NDSSystem.h */,
|
||||||
|
83DE0C62180A9CA400269051 /* registers.h */,
|
||||||
|
83DE0C66180A9CA400269051 /* SPU.cpp */,
|
||||||
|
83DE0C67180A9CA400269051 /* SPU.h */,
|
||||||
|
83DE0C68180A9CA400269051 /* spu_exports.h */,
|
||||||
|
83DE0C69180A9CA400269051 /* thumb_instructions.c */,
|
||||||
|
83DE0C6A180A9CA400269051 /* thumb_instructions.h */,
|
||||||
|
83DE0C6B180A9CA400269051 /* thumb_tabdef.inc */,
|
||||||
|
83DE0C6C180A9CA400269051 /* types.h */,
|
||||||
|
83DE0CB7180A9FD000269051 /* state.c */,
|
||||||
|
83DE0CB9180A9FE300269051 /* state.h */,
|
||||||
|
);
|
||||||
|
path = desmume;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXGroup section */
|
||||||
|
|
||||||
|
/* Begin PBXHeadersBuildPhase section */
|
||||||
|
83DE0C03180A9BD400269051 /* Headers */ = {
|
||||||
|
isa = PBXHeadersBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
83DE0CBE180B21DD00269051 /* state.h in Headers */,
|
||||||
|
83DE0CA3180A9CA400269051 /* spu_exports.h in Headers */,
|
||||||
|
83DE0CA7180A9CA400269051 /* types.h in Headers */,
|
||||||
|
83DE0C8E180A9CA400269051 /* dscard.h in Headers */,
|
||||||
|
83DE0C88180A9CA400269051 /* bits.h in Headers */,
|
||||||
|
83DE0C83180A9CA400269051 /* arm_instructions.h in Headers */,
|
||||||
|
83DE0C9D180A9CA400269051 /* registers.h in Headers */,
|
||||||
|
83DE0C97180A9CA400269051 /* mc.h in Headers */,
|
||||||
|
83DE0C8C180A9CA400269051 /* cp15.h in Headers */,
|
||||||
|
83DE0C95180A9CA400269051 /* matrix.h in Headers */,
|
||||||
|
83DE0C9C180A9CA400269051 /* NDSSystem.h in Headers */,
|
||||||
|
83DE0C89180A9CA400269051 /* config.h in Headers */,
|
||||||
|
83DE0C8D180A9CA400269051 /* debug.h in Headers */,
|
||||||
|
83DE0C98180A9CA400269051 /* mem.h in Headers */,
|
||||||
|
83DE0C90180A9CA400269051 /* FIFO.h in Headers */,
|
||||||
|
83DE0C92180A9CA400269051 /* GPU.h in Headers */,
|
||||||
|
83DE0CA2180A9CA400269051 /* SPU.h in Headers */,
|
||||||
|
83DE0C87180A9CA400269051 /* bios.h in Headers */,
|
||||||
|
83DE0C85180A9CA400269051 /* armcpu.h in Headers */,
|
||||||
|
83DE0CA5180A9CA400269051 /* thumb_instructions.h in Headers */,
|
||||||
|
83DE0C81180A9CA400269051 /* ARM9.h in Headers */,
|
||||||
|
83DE0C9A180A9CA400269051 /* MMU.h in Headers */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXHeadersBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXNativeTarget section */
|
||||||
|
83DE0C05180A9BD400269051 /* vio2sf */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 83DE0C2E180A9BD400269051 /* Build configuration list for PBXNativeTarget "vio2sf" */;
|
||||||
|
buildPhases = (
|
||||||
|
83DE0C01180A9BD400269051 /* Sources */,
|
||||||
|
83DE0C02180A9BD400269051 /* Frameworks */,
|
||||||
|
83DE0C03180A9BD400269051 /* Headers */,
|
||||||
|
83DE0C04180A9BD400269051 /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = vio2sf;
|
||||||
|
productName = vio2sf;
|
||||||
|
productReference = 83DE0C06180A9BD400269051 /* vio2sf.framework */;
|
||||||
|
productType = "com.apple.product-type.framework";
|
||||||
|
};
|
||||||
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
|
/* Begin PBXProject section */
|
||||||
|
83DE0BFD180A9BD400269051 /* Project object */ = {
|
||||||
|
isa = PBXProject;
|
||||||
|
attributes = {
|
||||||
|
LastUpgradeCheck = 0500;
|
||||||
|
ORGANIZATIONNAME = "Christopher Snowhill";
|
||||||
|
};
|
||||||
|
buildConfigurationList = 83DE0C00180A9BD400269051 /* Build configuration list for PBXProject "vio2sf" */;
|
||||||
|
compatibilityVersion = "Xcode 3.2";
|
||||||
|
developmentRegion = English;
|
||||||
|
hasScannedForEncodings = 0;
|
||||||
|
knownRegions = (
|
||||||
|
en,
|
||||||
|
);
|
||||||
|
mainGroup = 83DE0BFC180A9BD400269051;
|
||||||
|
productRefGroup = 83DE0C07180A9BD400269051 /* Products */;
|
||||||
|
projectDirPath = "";
|
||||||
|
projectRoot = "";
|
||||||
|
targets = (
|
||||||
|
83DE0C05180A9BD400269051 /* vio2sf */,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
/* End PBXProject section */
|
||||||
|
|
||||||
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
83DE0C04180A9BD400269051 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
83DE0C8A180A9CA400269051 /* COPYING in Resources */,
|
||||||
|
83DE0C14180A9BD400269051 /* InfoPlist.strings in Resources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
83DE0C01180A9BD400269051 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
83DE0C99180A9CA400269051 /* MMU.c in Sources */,
|
||||||
|
83DE0C8B180A9CA400269051 /* cp15.c in Sources */,
|
||||||
|
83DE0C8F180A9CA400269051 /* FIFO.c in Sources */,
|
||||||
|
83DE0CA1180A9CA400269051 /* SPU.cpp in Sources */,
|
||||||
|
83DE0C86180A9CA400269051 /* bios.c in Sources */,
|
||||||
|
83DE0CA6180A9CA400269051 /* thumb_tabdef.inc in Sources */,
|
||||||
|
83DE0C96180A9CA400269051 /* mc.c in Sources */,
|
||||||
|
83DE0C91180A9CA400269051 /* GPU.c in Sources */,
|
||||||
|
83DE0CA4180A9CA400269051 /* thumb_instructions.c in Sources */,
|
||||||
|
83DE0C84180A9CA400269051 /* armcpu.c in Sources */,
|
||||||
|
83DE0C94180A9CA400269051 /* matrix.c in Sources */,
|
||||||
|
83DE0C93180A9CA400269051 /* instruction_tabdef.inc in Sources */,
|
||||||
|
83DE0C9B180A9CA400269051 /* NDSSystem.c in Sources */,
|
||||||
|
83DE0CB8180A9FD000269051 /* state.c in Sources */,
|
||||||
|
83DE0C82180A9CA400269051 /* arm_instructions.c in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXVariantGroup section */
|
||||||
|
83DE0C12180A9BD400269051 /* InfoPlist.strings */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
83DE0C13180A9BD400269051 /* en */,
|
||||||
|
);
|
||||||
|
name = InfoPlist.strings;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXVariantGroup section */
|
||||||
|
|
||||||
|
/* Begin XCBuildConfiguration section */
|
||||||
|
83DE0C2C180A9BD400269051 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
|
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||||
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
|
"DEBUG=1",
|
||||||
|
"$(inherited)",
|
||||||
|
);
|
||||||
|
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
||||||
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
|
SDKROOT = macosx;
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
83DE0C2D180A9BD400269051 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
COPY_PHASE_STRIP = YES;
|
||||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
||||||
|
SDKROOT = macosx;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
83DE0C2F180A9BD400269051 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
|
DYLIB_CURRENT_VERSION = 1;
|
||||||
|
FRAMEWORK_VERSION = A;
|
||||||
|
INFOPLIST_FILE = "vio2sf/vio2sf-Info.plist";
|
||||||
|
INSTALL_PATH = "@loader_path/../Frameworks";
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
WRAPPER_EXTENSION = framework;
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
83DE0C30180A9BD400269051 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
|
DYLIB_CURRENT_VERSION = 1;
|
||||||
|
FRAMEWORK_VERSION = A;
|
||||||
|
INFOPLIST_FILE = "vio2sf/vio2sf-Info.plist";
|
||||||
|
INSTALL_PATH = "@loader_path/../Frameworks";
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
WRAPPER_EXTENSION = framework;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
|
/* Begin XCConfigurationList section */
|
||||||
|
83DE0C00180A9BD400269051 /* Build configuration list for PBXProject "vio2sf" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
83DE0C2C180A9BD400269051 /* Debug */,
|
||||||
|
83DE0C2D180A9BD400269051 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
83DE0C2E180A9BD400269051 /* Build configuration list for PBXNativeTarget "vio2sf" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
83DE0C2F180A9BD400269051 /* Debug */,
|
||||||
|
83DE0C30180A9BD400269051 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
};
|
||||||
|
/* End XCConfigurationList section */
|
||||||
|
};
|
||||||
|
rootObject = 83DE0BFD180A9BD400269051 /* Project object */;
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
/* Localized versions of Info.plist keys */
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef ARM9_H
|
||||||
|
#define ARM9_H
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
typedef struct ARM9_struct {
|
||||||
|
//ARM9 mem
|
||||||
|
u8 ARM9_ITCM[0x8000];
|
||||||
|
u8 ARM9_DTCM[0x4000];
|
||||||
|
u8 ARM9_WRAM[0x1000000];
|
||||||
|
u8 MAIN_MEM[0x400000];
|
||||||
|
u8 ARM9_REG[0x1000000];
|
||||||
|
u8 ARM9_BIOS[0x8000];
|
||||||
|
u8 ARM9_VMEM[0x800];
|
||||||
|
u8 ARM9_ABG[0x80000];
|
||||||
|
u8 ARM9_BBG[0x20000];
|
||||||
|
u8 ARM9_AOBJ[0x40000];
|
||||||
|
u8 ARM9_BOBJ[0x20000];
|
||||||
|
u8 ARM9_LCD[0xA4000];
|
||||||
|
u8 ARM9_OAM[0x800];
|
||||||
|
|
||||||
|
u8 * ExtPal[2][4];
|
||||||
|
u8 * ObjExtPal[2][2];
|
||||||
|
u8 * texPalSlot[4];
|
||||||
|
|
||||||
|
const u8 *textureSlotAddr[4];
|
||||||
|
|
||||||
|
u8 *blank_memory[0x20000];
|
||||||
|
} ARM9_struct;
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,340 @@
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||||
|
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Library General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Library General
|
||||||
|
Public License instead of this License.
|
|
@ -0,0 +1,65 @@
|
||||||
|
/* Copyright (C) 2006 yopyop
|
||||||
|
yopyop156@ifrance.com
|
||||||
|
yopyop156.ifrance.com
|
||||||
|
|
||||||
|
Copyright (C) 2007 shash
|
||||||
|
|
||||||
|
This file is part of DeSmuME
|
||||||
|
|
||||||
|
DeSmuME is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
DeSmuME is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with DeSmuME; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "FIFO.h"
|
||||||
|
|
||||||
|
void FIFOInit(FIFO * fifo)
|
||||||
|
{
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
fifo->begin = 0;
|
||||||
|
fifo->end = 0;
|
||||||
|
for(i = 0; i<0x8000; ++i)
|
||||||
|
fifo->data[i] = 0;
|
||||||
|
fifo->full = FALSE;
|
||||||
|
fifo->empty = TRUE;
|
||||||
|
fifo->error = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FIFOAdd(FIFO * fifo, u32 v)
|
||||||
|
{
|
||||||
|
if(fifo->full)
|
||||||
|
{
|
||||||
|
fifo->error = TRUE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fifo->data[fifo->end] = v;
|
||||||
|
fifo->end = (fifo->end + 1)& 0x7FFF;
|
||||||
|
fifo->full = (fifo->end == fifo->begin);
|
||||||
|
fifo->empty = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 FIFOValue(FIFO * fifo)
|
||||||
|
{
|
||||||
|
u32 v;
|
||||||
|
|
||||||
|
if(fifo->empty)
|
||||||
|
{
|
||||||
|
fifo->error = TRUE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
v = fifo->data[fifo->begin];
|
||||||
|
fifo->begin = (fifo->begin + 1)& 0x7FFF;
|
||||||
|
fifo->empty = (fifo->begin == fifo->end);
|
||||||
|
return v;
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/* Copyright (C) 2006 yopyop
|
||||||
|
yopyop156@ifrance.com
|
||||||
|
yopyop156.ifrance.com
|
||||||
|
|
||||||
|
Copyright (C) 2007 shash
|
||||||
|
|
||||||
|
This file is part of DeSmuME
|
||||||
|
|
||||||
|
DeSmuME is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
DeSmuME is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with DeSmuME; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FIFO_H
|
||||||
|
#define FIFO_H
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u32 data[0x8000];
|
||||||
|
u32 begin;
|
||||||
|
u32 end;
|
||||||
|
BOOL full;
|
||||||
|
BOOL empty;
|
||||||
|
BOOL error;
|
||||||
|
} FIFO;
|
||||||
|
|
||||||
|
void FIFOInit(FIFO * fifo);
|
||||||
|
void FIFOAdd(FIFO * fifo, u32 v);
|
||||||
|
u32 FIFOValue(FIFO * fifo);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,95 @@
|
||||||
|
/* Copyright (C) 2006 yopyop
|
||||||
|
yopyop156@ifrance.com
|
||||||
|
yopyop156.ifrance.com
|
||||||
|
|
||||||
|
Copyright (C) 2006-2007 Theo Berkau
|
||||||
|
Copyright (C) 2007 shash
|
||||||
|
|
||||||
|
This file is part of DeSmuME
|
||||||
|
|
||||||
|
DeSmuME is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
DeSmuME is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with DeSmuME; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
// CONTENTS
|
||||||
|
// INITIALIZATION
|
||||||
|
// ENABLING / DISABLING LAYERS
|
||||||
|
// PARAMETERS OF BACKGROUNDS
|
||||||
|
// PARAMETERS OF ROTOSCALE
|
||||||
|
// PARAMETERS OF EFFECTS
|
||||||
|
// PARAMETERS OF WINDOWS
|
||||||
|
// ROUTINES FOR INSIDE / OUTSIDE WINDOW CHECKS
|
||||||
|
// PIXEL RENDERING
|
||||||
|
// BACKGROUND RENDERING -TEXT-
|
||||||
|
// BACKGROUND RENDERING -ROTOSCALE-
|
||||||
|
// BACKGROUND RENDERING -HELPER FUNCTIONS-
|
||||||
|
// SPRITE RENDERING -HELPER FUNCTIONS-
|
||||||
|
// SPRITE RENDERING
|
||||||
|
// SCREEN FUNCTIONS
|
||||||
|
// GRAPHICS CORE
|
||||||
|
// GPU_ligne
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include "MMU.h"
|
||||||
|
#include "GPU.h"
|
||||||
|
|
||||||
|
#include "state.h"
|
||||||
|
|
||||||
|
//#define DEBUG_TRI
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
// INITIALIZATION
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
GPU * GPU_Init(u8 l)
|
||||||
|
{
|
||||||
|
GPU * g;
|
||||||
|
|
||||||
|
if ((g = (GPU *) malloc(sizeof(GPU))) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
GPU_Reset(g, l);
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GPU_Reset(GPU *g, u8 l)
|
||||||
|
{
|
||||||
|
memset(g, 0, sizeof(GPU));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GPU_DeInit(GPU * gpu)
|
||||||
|
{
|
||||||
|
if (gpu) free(gpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Screen_Init(NDS_state *state, int coreid) {
|
||||||
|
state->MainScreen->gpu = GPU_Init(0);
|
||||||
|
state->SubScreen->gpu = GPU_Init(1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Screen_Reset(NDS_state *state) {
|
||||||
|
GPU_Reset(state->MainScreen->gpu, 0);
|
||||||
|
GPU_Reset(state->SubScreen->gpu, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Screen_DeInit(NDS_state *state) {
|
||||||
|
GPU_DeInit(state->MainScreen->gpu);
|
||||||
|
GPU_DeInit(state->SubScreen->gpu);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,808 @@
|
||||||
|
/* Copyright (C) 2006 yopyop
|
||||||
|
yopyop156@ifrance.com
|
||||||
|
yopyop156.ifrance.com
|
||||||
|
|
||||||
|
Copyright (C) 2006-2007 Theo Berkau
|
||||||
|
Copyright (C) 2007 shash
|
||||||
|
|
||||||
|
This file is part of DeSmuME
|
||||||
|
|
||||||
|
DeSmuME is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
DeSmuME is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with DeSmuME; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GPU_H
|
||||||
|
#define GPU_H
|
||||||
|
|
||||||
|
#include "ARM9.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "mem.h"
|
||||||
|
#include "registers.h"
|
||||||
|
#include "FIFO.h"
|
||||||
|
#include "MMU.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
this structure is for display control,
|
||||||
|
it holds flags for general display
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
struct _DISPCNT
|
||||||
|
{
|
||||||
|
/* 7*/ u8 ForceBlank:1; // A+B:
|
||||||
|
/* 6*/ u8 OBJ_BMP_mapping:1; // A+B: 0=2D (128KB), 1=1D (128..256KB)
|
||||||
|
/* 5*/ u8 OBJ_BMP_2D_dim:1; // A+B: 0=128x512, 1=256x256 pixels
|
||||||
|
/* 4*/ u8 OBJ_Tile_1D:1; // A+B: 0=2D (32KB), 1=1D (32..256KB)
|
||||||
|
/* 3*/ u8 BG0_3D:1; // A : 0=2D, 1=3D
|
||||||
|
/* 0*/ u8 BG_Mode:3; // A+B:
|
||||||
|
/*15*/ u8 WinOBJ_Enable:1; // A+B: 0=disable, 1=Enable
|
||||||
|
/*14*/ u8 Win1_Enable:1; // A+B: 0=disable, 1=Enable
|
||||||
|
/*13*/ u8 Win0_Enable:1; // A+B: 0=disable, 1=Enable
|
||||||
|
/*12*/ u8 OBJ_Enable:1; // A+B: 0=disable, 1=Enable
|
||||||
|
/*11*/ u8 BG3_Enable:1; // A+B: 0=disable, 1=Enable
|
||||||
|
/*10*/ u8 BG2_Enable:1; // A+B: 0=disable, 1=Enable
|
||||||
|
/* 9*/ u8 BG1_Enable:1; // A+B: 0=disable, 1=Enable
|
||||||
|
/* 8*/ u8 BG0_Enable:1; // A+B: 0=disable, 1=Enable
|
||||||
|
/*23*/ u8 OBJ_HBlank_process:1; // A+B: OBJ processed during HBlank (GBA bit5)
|
||||||
|
/*22*/ u8 OBJ_BMP_1D_Bound:1; // A :
|
||||||
|
/*20*/ u8 OBJ_Tile_1D_Bound:2; // A+B:
|
||||||
|
/*18*/ u8 VRAM_Block:2; // A : VRAM block (0..3=A..D)
|
||||||
|
|
||||||
|
/*16*/ u8 DisplayMode:2; // A+B: coreA(0..3) coreB(0..1) GBA(Green Swap)
|
||||||
|
// 0=off (white screen)
|
||||||
|
// 1=on (normal BG & OBJ layers)
|
||||||
|
// 2=VRAM display (coreA only)
|
||||||
|
// 3=RAM display (coreA only, DMA transfers)
|
||||||
|
|
||||||
|
/*31*/ u8 ExOBJPalette_Enable:1; // A+B: 0=disable, 1=Enable OBJ extended Palette
|
||||||
|
/*30*/ u8 ExBGxPalette_Enable:1; // A+B: 0=disable, 1=Enable BG extended Palette
|
||||||
|
/*27*/ u8 ScreenBase_Block:3; // A : Screen Base (64K step)
|
||||||
|
/*24*/ u8 CharacBase_Block:3; // A : Character Base (64K step)
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
struct _DISPCNT
|
||||||
|
{
|
||||||
|
/* 0*/ u8 BG_Mode:3; // A+B:
|
||||||
|
/* 3*/ u8 BG0_3D:1; // A : 0=2D, 1=3D
|
||||||
|
/* 4*/ u8 OBJ_Tile_1D:1; // A+B: 0=2D (32KB), 1=1D (32..256KB)
|
||||||
|
/* 5*/ u8 OBJ_BMP_2D_dim:1; // A+B: 0=128x512, 1=256x256 pixels
|
||||||
|
/* 6*/ u8 OBJ_BMP_mapping:1; // A+B: 0=2D (128KB), 1=1D (128..256KB)
|
||||||
|
|
||||||
|
// 7-15 same as GBA
|
||||||
|
/* 7*/ u8 ForceBlank:1; // A+B:
|
||||||
|
/* 8*/ u8 BG0_Enable:1; // A+B: 0=disable, 1=Enable
|
||||||
|
/* 9*/ u8 BG1_Enable:1; // A+B: 0=disable, 1=Enable
|
||||||
|
/*10*/ u8 BG2_Enable:1; // A+B: 0=disable, 1=Enable
|
||||||
|
/*11*/ u8 BG3_Enable:1; // A+B: 0=disable, 1=Enable
|
||||||
|
/*12*/ u8 OBJ_Enable:1; // A+B: 0=disable, 1=Enable
|
||||||
|
/*13*/ u8 Win0_Enable:1; // A+B: 0=disable, 1=Enable
|
||||||
|
/*14*/ u8 Win1_Enable:1; // A+B: 0=disable, 1=Enable
|
||||||
|
/*15*/ u8 WinOBJ_Enable:1; // A+B: 0=disable, 1=Enable
|
||||||
|
|
||||||
|
/*16*/ u8 DisplayMode:2; // A+B: coreA(0..3) coreB(0..1) GBA(Green Swap)
|
||||||
|
// 0=off (white screen)
|
||||||
|
// 1=on (normal BG & OBJ layers)
|
||||||
|
// 2=VRAM display (coreA only)
|
||||||
|
// 3=RAM display (coreA only, DMA transfers)
|
||||||
|
|
||||||
|
/*18*/ u8 VRAM_Block:2; // A : VRAM block (0..3=A..D)
|
||||||
|
/*20*/ u8 OBJ_Tile_1D_Bound:2; // A+B:
|
||||||
|
/*22*/ u8 OBJ_BMP_1D_Bound:1; // A :
|
||||||
|
/*23*/ u8 OBJ_HBlank_process:1; // A+B: OBJ processed during HBlank (GBA bit5)
|
||||||
|
/*24*/ u8 CharacBase_Block:3; // A : Character Base (64K step)
|
||||||
|
/*27*/ u8 ScreenBase_Block:3; // A : Screen Base (64K step)
|
||||||
|
/*30*/ u8 ExBGxPalette_Enable:1; // A+B: 0=disable, 1=Enable BG extended Palette
|
||||||
|
/*31*/ u8 ExOBJPalette_Enable:1; // A+B: 0=disable, 1=Enable OBJ extended Palette
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
struct _DISPCNT bits;
|
||||||
|
u32 val;
|
||||||
|
} DISPCNT;
|
||||||
|
#define BGxENABLED(cnt,num) ((num<8)? ((cnt.val>>8) & num):0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
this structure is for display control of a specific layer,
|
||||||
|
there are 4 background layers
|
||||||
|
their priority indicate which one to draw on top of the other
|
||||||
|
some flags indicate special drawing mode, size, FX
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
struct _BGxCNT
|
||||||
|
{
|
||||||
|
/* 7*/ u8 Palette_256:1; // 0=16x16, 1=1*256 palette
|
||||||
|
/* 6*/ u8 Mosaic_Enable:1; // 0=disable, 1=Enable mosaic
|
||||||
|
/* 2*/ u8 CharacBase_Block:4; // individual character base offset (n*16KB)
|
||||||
|
/* 0*/ u8 Priority:2; // 0..3=high..low
|
||||||
|
/*14*/ u8 ScreenSize:2; // text : 256x256 512x256 256x512 512x512
|
||||||
|
// x/rot/s : 128x128 256x256 512x512 1024x1024
|
||||||
|
// bmp : 128x128 256x256 512x256 512x512
|
||||||
|
// large : 512x1024 1024x512 - -
|
||||||
|
/*13*/ u8 PaletteSet_Wrap:1; // BG0 extended palette set 0=set0, 1=set2
|
||||||
|
// BG1 extended palette set 0=set1, 1=set3
|
||||||
|
// BG2 overflow area wraparound 0=off, 1=wrap
|
||||||
|
// BG3 overflow area wraparound 0=off, 1=wrap
|
||||||
|
/* 8*/ u8 ScreenBase_Block:5; // individual screen base offset (text n*2KB, BMP n*16KB)
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
struct _BGxCNT
|
||||||
|
{
|
||||||
|
/* 0*/ u8 Priority:2; // 0..3=high..low
|
||||||
|
/* 2*/ u8 CharacBase_Block:4; // individual character base offset (n*16KB)
|
||||||
|
/* 6*/ u8 Mosaic_Enable:1; // 0=disable, 1=Enable mosaic
|
||||||
|
/* 7*/ u8 Palette_256:1; // 0=16x16, 1=1*256 palette
|
||||||
|
/* 8*/ u8 ScreenBase_Block:5; // individual screen base offset (text n*2KB, BMP n*16KB)
|
||||||
|
/*13*/ u8 PaletteSet_Wrap:1; // BG0 extended palette set 0=set0, 1=set2
|
||||||
|
// BG1 extended palette set 0=set1, 1=set3
|
||||||
|
// BG2 overflow area wraparound 0=off, 1=wrap
|
||||||
|
// BG3 overflow area wraparound 0=off, 1=wrap
|
||||||
|
/*14*/ u8 ScreenSize:2; // text : 256x256 512x256 256x512 512x512
|
||||||
|
// x/rot/s : 128x128 256x256 512x512 1024x1024
|
||||||
|
// bmp : 128x128 256x256 512x256 512x512
|
||||||
|
// large : 512x1024 1024x512 - -
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
struct _BGxCNT bits;
|
||||||
|
u16 val;
|
||||||
|
} BGxCNT;
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
this structure is for background offset
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u16 BGxHOFS;
|
||||||
|
u16 BGxVOFS;
|
||||||
|
} BGxOFS;
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
this structure is for rotoscale parameters
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
s16 BGxPA;
|
||||||
|
s16 BGxPB;
|
||||||
|
s16 BGxPC;
|
||||||
|
s16 BGxPD;
|
||||||
|
s32 BGxX;
|
||||||
|
s32 BGxY;
|
||||||
|
} BGxPARMS;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
these structures are for window description,
|
||||||
|
windows are square regions and can "subclass"
|
||||||
|
background layers or object layers (i.e window controls the layers)
|
||||||
|
|
||||||
|
screen
|
||||||
|
|
|
||||||
|
+-- Window0/Window1/OBJwindow/OutOfWindows
|
||||||
|
|
|
||||||
|
+-- BG0/BG1/BG2/BG3/OBJ
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
struct {
|
||||||
|
u8 end:8;
|
||||||
|
u8 start:8;
|
||||||
|
} bits ;
|
||||||
|
u16 val;
|
||||||
|
} WINxDIM;
|
||||||
|
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
typedef struct {
|
||||||
|
/* 6*/ u8 :2;
|
||||||
|
/* 5*/ u8 WINx_Effect_Enable:1;
|
||||||
|
/* 4*/ u8 WINx_OBJ_Enable:1;
|
||||||
|
/* 3*/ u8 WINx_BG3_Enable:1;
|
||||||
|
/* 2*/ u8 WINx_BG2_Enable:1;
|
||||||
|
/* 1*/ u8 WINx_BG1_Enable:1;
|
||||||
|
/* 0*/ u8 WINx_BG0_Enable:1;
|
||||||
|
} WINxBIT;
|
||||||
|
#else
|
||||||
|
typedef struct {
|
||||||
|
/* 0*/ u8 WINx_BG0_Enable:1;
|
||||||
|
/* 1*/ u8 WINx_BG1_Enable:1;
|
||||||
|
/* 2*/ u8 WINx_BG2_Enable:1;
|
||||||
|
/* 3*/ u8 WINx_BG3_Enable:1;
|
||||||
|
/* 4*/ u8 WINx_OBJ_Enable:1;
|
||||||
|
/* 5*/ u8 WINx_Effect_Enable:1;
|
||||||
|
/* 6*/ u8 :2;
|
||||||
|
} WINxBIT;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
typedef union {
|
||||||
|
struct {
|
||||||
|
WINxBIT win0;
|
||||||
|
WINxBIT win1;
|
||||||
|
} bits;
|
||||||
|
struct {
|
||||||
|
u8 :3;
|
||||||
|
u8 win0_en:5;
|
||||||
|
u8 :3;
|
||||||
|
u8 win1_en:5;
|
||||||
|
} packed_bits;
|
||||||
|
struct {
|
||||||
|
u8 low;
|
||||||
|
u8 high;
|
||||||
|
} bytes;
|
||||||
|
u16 val ;
|
||||||
|
} WINxCNT ;
|
||||||
|
#else
|
||||||
|
typedef union {
|
||||||
|
struct {
|
||||||
|
WINxBIT win0;
|
||||||
|
WINxBIT win1;
|
||||||
|
} bits;
|
||||||
|
struct {
|
||||||
|
u8 win0_en:5;
|
||||||
|
u8 :3;
|
||||||
|
u8 win1_en:5;
|
||||||
|
u8 :3;
|
||||||
|
} packed_bits;
|
||||||
|
struct {
|
||||||
|
u8 low;
|
||||||
|
u8 high;
|
||||||
|
} bytes;
|
||||||
|
u16 val ;
|
||||||
|
} WINxCNT ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
typedef struct {
|
||||||
|
WINxDIM WIN0H;
|
||||||
|
WINxDIM WIN1H;
|
||||||
|
WINxDIM WIN0V;
|
||||||
|
WINxDIM WIN1V;
|
||||||
|
WINxCNT WININ;
|
||||||
|
WINxCNT WINOUT;
|
||||||
|
} WINCNT;
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
this structure is for miscellanous settings
|
||||||
|
//TODO: needs further description
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u16 MOSAIC;
|
||||||
|
u16 unused1;
|
||||||
|
u16 unused2;//BLDCNT;
|
||||||
|
u16 unused3;//BLDALPHA;
|
||||||
|
u16 unused4;//BLDY;
|
||||||
|
u16 unused5;
|
||||||
|
/*
|
||||||
|
u16 unused6;
|
||||||
|
u16 unused7;
|
||||||
|
u16 unused8;
|
||||||
|
u16 unused9;
|
||||||
|
*/
|
||||||
|
} MISCCNT;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
this structure is for 3D settings
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
struct _DISP3DCNT
|
||||||
|
{
|
||||||
|
/* 0*/ u8 EnableTexMapping:1; //
|
||||||
|
/* 1*/ u8 PolygonShading:1; // 0=Toon Shading, 1=Highlight Shading
|
||||||
|
/* 2*/ u8 EnableAlphaTest:1; // see ALPHA_TEST_REF
|
||||||
|
/* 3*/ u8 EnableAlphaBlending:1; // see various Alpha values
|
||||||
|
/* 4*/ u8 EnableAntiAliasing:1; //
|
||||||
|
/* 5*/ u8 EnableEdgeMarking:1; // see EDGE_COLOR
|
||||||
|
/* 6*/ u8 FogOnlyAlpha:1; // 0=Alpha and Color, 1=Only Alpha (see FOG_COLOR)
|
||||||
|
/* 7*/ u8 EnableFog:1; // Fog Master Enable
|
||||||
|
/* 8*/ u8 FogShiftSHR:4; // 0..10 SHR-Divider (see FOG_OFFSET)
|
||||||
|
/*12*/ u8 AckColorBufferUnderflow:1; // Color Buffer RDLINES Underflow (0=None, 1=Underflow/Acknowledge)
|
||||||
|
/*13*/ u8 AckVertexRAMOverflow:1; // Polygon/Vertex RAM Overflow (0=None, 1=Overflow/Acknowledge)
|
||||||
|
/*14*/ u8 RearPlaneMode:1; // 0=Blank, 1=Bitmap
|
||||||
|
/*15*/ u8 :1;
|
||||||
|
/*16*/ u16 :16;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
struct _DISP3DCNT bits;
|
||||||
|
u32 val;
|
||||||
|
} DISP3DCNT;
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
this structure is for capture control (core A only)
|
||||||
|
|
||||||
|
source:
|
||||||
|
http://nocash.emubase.de/gbatek.htm#dsvideocaptureandmainmemorydisplaymode
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
struct _DISPCAPCNT
|
||||||
|
{
|
||||||
|
/* 0*/ u8 BlendFactor_A:5; // 0..16 = Blending Factor for Source A
|
||||||
|
/* 5*/ u8 :3; //
|
||||||
|
/* 8*/ u8 BlendFactor_B:5; // 0..16 = Blending Factor for Source B
|
||||||
|
/*13*/ u8 :3; //
|
||||||
|
/*16*/ u8 VRAM_Write_Block:2; // 0..3 = VRAM A..D
|
||||||
|
/*18*/ u8 VRAM_Write_Offset:2; // n x 0x08000
|
||||||
|
/*20*/ u8 Capture_Size:2; // 0=128x128, 1=256x64, 2=256x128, 3=256x192 dots
|
||||||
|
/*22*/ u8 :2; //
|
||||||
|
/*24*/ u8 Source_A:1; // 0=Graphics Screen BG+3D+OBJ, 1=3D Screen
|
||||||
|
/*25*/ u8 Source_B:1; // 0=VRAM, 1=Main Memory Display FIFO
|
||||||
|
/*26*/ u8 VRAM_Read_Offset:2; // n x 0x08000
|
||||||
|
/*28*/ u8 :1; //
|
||||||
|
/*29*/ u8 Capture_Source:2; // 0=Source A, 1=Source B, 2/3=Sources A+B blended
|
||||||
|
/*31*/ u8 Capture_Enable:1; // 0=Disable/Ready, 1=Enable/Busy
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
struct _DISPCAPCNT bits;
|
||||||
|
u32 val;
|
||||||
|
} DISPCAPCNT;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
this structure holds everything and should be mapped to
|
||||||
|
* core A : 0x04000000
|
||||||
|
* core B : 0x04001000
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
typedef struct _reg_dispx {
|
||||||
|
DISPCNT dispx_DISPCNT; // 0x0400x000
|
||||||
|
u16 dispA_DISPSTAT; // 0x04000004
|
||||||
|
u16 dispx_VCOUNT; // 0x0400x006
|
||||||
|
BGxCNT dispx_BGxCNT[4]; // 0x0400x008
|
||||||
|
BGxOFS dispx_BGxOFS[4]; // 0x0400x010
|
||||||
|
BGxPARMS dispx_BG2PARMS; // 0x0400x020
|
||||||
|
BGxPARMS dispx_BG3PARMS; // 0x0400x030
|
||||||
|
u8 filler[12]; // 0x0400x040
|
||||||
|
MISCCNT dispx_MISC; // 0x0400x04C
|
||||||
|
DISP3DCNT dispA_DISP3DCNT; // 0x04000060
|
||||||
|
DISPCAPCNT dispA_DISPCAPCNT; // 0x04000064
|
||||||
|
u32 dispA_DISPMMEMFIFO; // 0x04000068
|
||||||
|
} REG_DISPx ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef min
|
||||||
|
#define min(a,b) (((a)<(b))?(a):(b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef max
|
||||||
|
#define max(a,b) (((a)>(b))?(a):(b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef BOOL (*fun_gl_Begin) (int screen);
|
||||||
|
typedef void (*fun_gl_End) (int screen);
|
||||||
|
// the GUI should use this function prior to all gl calls
|
||||||
|
// if call to beg succeeds opengl draw
|
||||||
|
void register_gl_fun(fun_gl_Begin beg,fun_gl_End end);
|
||||||
|
|
||||||
|
#define GPU_MAIN 0
|
||||||
|
#define GPU_SUB 1
|
||||||
|
|
||||||
|
/* human readable bitmask names */
|
||||||
|
#define ADDRESS_STEP_512B 0x00200
|
||||||
|
#define ADDRESS_STEP_1KB 0x00400
|
||||||
|
#define ADDRESS_STEP_2KB 0x00800
|
||||||
|
#define ADDRESS_STEP_4KB 0x01000
|
||||||
|
#define ADDRESS_STEP_8KB 0x02000
|
||||||
|
#define ADDRESS_STEP_16KB 0x04000
|
||||||
|
#define ADDRESS_STEP_32KB 0x08000
|
||||||
|
#define ADDRESS_STEP_64kB 0x10000
|
||||||
|
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
struct _TILEENTRY
|
||||||
|
{
|
||||||
|
/*14*/ unsigned Palette:4;
|
||||||
|
/*13*/ unsigned VFlip:1; // VERTICAL FLIP (top<-->bottom)
|
||||||
|
/*12*/ unsigned HFlip:1; // HORIZONTAL FLIP (left<-->right)
|
||||||
|
/* 0*/ unsigned TileNum:10;
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
struct _TILEENTRY
|
||||||
|
{
|
||||||
|
/* 0*/ unsigned TileNum:10;
|
||||||
|
/*12*/ unsigned HFlip:1; // HORIZONTAL FLIP (left<-->right)
|
||||||
|
/*13*/ unsigned VFlip:1; // VERTICAL FLIP (top<-->bottom)
|
||||||
|
/*14*/ unsigned Palette:4;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
struct _TILEENTRY bits;
|
||||||
|
u16 val;
|
||||||
|
} TILEENTRY;
|
||||||
|
|
||||||
|
struct _ROTOCOORD
|
||||||
|
{
|
||||||
|
/* 0*/ unsigned Fraction:8;
|
||||||
|
/* 8*/ signed Integer:24;
|
||||||
|
// /*28*/ unsigned :4;
|
||||||
|
};
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
struct _ROTOCOORD bits;
|
||||||
|
s32 val;
|
||||||
|
} ROTOCOORD;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
this structure is for color representation,
|
||||||
|
it holds 5 meaningful bits per color channel (red,green,blue)
|
||||||
|
and 1 meaningful bit for alpha representation
|
||||||
|
this bit can be unused or used for special FX
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct _COLOR { // abgr x555
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
unsigned alpha:1; // sometimes it is unused (pad)
|
||||||
|
unsigned blue:5;
|
||||||
|
unsigned green:5;
|
||||||
|
unsigned red:5;
|
||||||
|
#else
|
||||||
|
unsigned red:5;
|
||||||
|
unsigned green:5;
|
||||||
|
unsigned blue:5;
|
||||||
|
unsigned alpha:1; // sometimes it is unused (pad)
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
struct _COLORx { // abgr x555
|
||||||
|
unsigned bgr:15;
|
||||||
|
unsigned alpha:1; // sometimes it is unused (pad)
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
struct _COLOR bits;
|
||||||
|
struct _COLORx bitx;
|
||||||
|
u16 val;
|
||||||
|
} COLOR;
|
||||||
|
|
||||||
|
struct _COLOR32 { // ARGB
|
||||||
|
unsigned :3;
|
||||||
|
unsigned blue:5;
|
||||||
|
unsigned :3;
|
||||||
|
unsigned green:5;
|
||||||
|
unsigned :3;
|
||||||
|
unsigned red:5;
|
||||||
|
unsigned :7;
|
||||||
|
unsigned alpha:1; // sometimes it is unused (pad)
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
struct _COLOR32 bits;
|
||||||
|
u32 val;
|
||||||
|
} COLOR32;
|
||||||
|
|
||||||
|
#define COLOR_16_32(w,i) \
|
||||||
|
/* doesnt matter who's 16bit who's 32bit */ \
|
||||||
|
i.bits.red = w.bits.red; \
|
||||||
|
i.bits.green = w.bits.green; \
|
||||||
|
i.bits.blue = w.bits.blue; \
|
||||||
|
i.bits.alpha = w.bits.alpha;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
this structure is for Sprite description,
|
||||||
|
it holds flags & transformations for 1 sprite
|
||||||
|
(max 128 OBJs / screen)
|
||||||
|
ref: http://www.bottledlight.com/ds/index.php/Video/Sprites
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
// attr0
|
||||||
|
/* 0*/ unsigned Y:8;
|
||||||
|
/*14*/ unsigned Shape:2; // (00: Square, 01: Wide, 10: Tall, 11: Illegal)
|
||||||
|
/*13*/ unsigned Depth:1; // (0: 16, 1: 256)
|
||||||
|
/*12*/ unsigned Mosaic:1; // (1: Enabled)
|
||||||
|
/*10*/ unsigned Mode:2; // (00: Normal, 01: Transparent, 10: Object window, 11: Bitmap)
|
||||||
|
/* 8*/ unsigned RotScale:2; // (00: Normal, 01: Rot/scale, 10: Disabled, 11: Double-size rot/scale)
|
||||||
|
// attr1
|
||||||
|
/* 0*/ signed X:9;
|
||||||
|
/*14*/ unsigned Size:2;
|
||||||
|
/*13*/ unsigned VFlip:1;
|
||||||
|
/*12*/ unsigned HFlip:1;
|
||||||
|
/* 9*/ unsigned RotScalIndex:3; // Rot/scale matrix index
|
||||||
|
// attr2
|
||||||
|
/* 0*/ unsigned TileIndex:10;
|
||||||
|
/*12*/ unsigned PaletteIndex:4;
|
||||||
|
/*10*/ unsigned Priority:2;
|
||||||
|
// attr3
|
||||||
|
unsigned attr3:16;
|
||||||
|
#else
|
||||||
|
// attr0
|
||||||
|
/* 0*/ unsigned Y:8;
|
||||||
|
/* 8*/ unsigned RotScale:2; // (00: Normal, 01: Rot/scale, 10: Disabled, 11: Double-size rot/scale)
|
||||||
|
/*10*/ unsigned Mode:2; // (00: Normal, 01: Transparent, 10: Object window, 11: Bitmap)
|
||||||
|
/*12*/ unsigned Mosaic:1; // (1: Enabled)
|
||||||
|
/*13*/ unsigned Depth:1; // (0: 16, 1: 256)
|
||||||
|
/*14*/ unsigned Shape:2; // (00: Square, 01: Wide, 10: Tall, 11: Illegal)
|
||||||
|
// attr1
|
||||||
|
/* 0*/ signed X:9;
|
||||||
|
/* 9*/ unsigned RotScalIndex:3; // Rot/scale matrix index
|
||||||
|
/*12*/ unsigned HFlip:1;
|
||||||
|
/*13*/ unsigned VFlip:1;
|
||||||
|
/*14*/ unsigned Size:2;
|
||||||
|
// attr2
|
||||||
|
/* 0*/ unsigned TileIndex:10;
|
||||||
|
/*10*/ unsigned Priority:2;
|
||||||
|
/*12*/ unsigned PaletteIndex:4;
|
||||||
|
// attr3
|
||||||
|
unsigned attr3:16;
|
||||||
|
#endif
|
||||||
|
} _OAM_;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u16 attr0;
|
||||||
|
u16 attr1;
|
||||||
|
u16 attr2;
|
||||||
|
u16 attr3;
|
||||||
|
} OAM;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
s16 x;
|
||||||
|
s16 y;
|
||||||
|
} size;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
this structure holds information
|
||||||
|
for rendering.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NB_PRIORITIES 4
|
||||||
|
#define NB_BG 4
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u8 BGs[NB_BG], nbBGs;
|
||||||
|
u8 PixelsX[256];
|
||||||
|
// doh ! yoda says : 256 pixels we can have...
|
||||||
|
u16 nbPixelsX;
|
||||||
|
} itemsForPriority_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _GPU GPU;
|
||||||
|
|
||||||
|
struct _GPU
|
||||||
|
{
|
||||||
|
// some structs are becoming redundant
|
||||||
|
// some functions too (no need to recopy some vars as it is done by MMU)
|
||||||
|
REG_DISPx * dispx_st;
|
||||||
|
|
||||||
|
DISPCAPCNT dispCapCnt;
|
||||||
|
BOOL LayersEnable[5];
|
||||||
|
itemsForPriority_t itemsForPriority[NB_PRIORITIES];
|
||||||
|
u8 sprWin[256][256];
|
||||||
|
|
||||||
|
#define BGBmpBB BG_bmp_ram
|
||||||
|
#define BGChBB BG_tile_ram
|
||||||
|
|
||||||
|
u8 *(BG_bmp_ram[4]);
|
||||||
|
u8 *(BG_tile_ram[4]);
|
||||||
|
u8 *(BG_map_ram[4]);
|
||||||
|
|
||||||
|
u8 BGExtPalSlot[4];
|
||||||
|
u32 BGSize[4][2];
|
||||||
|
|
||||||
|
u8 lcd;
|
||||||
|
u8 core;
|
||||||
|
|
||||||
|
u8 dispMode;
|
||||||
|
u8 vramBlock;
|
||||||
|
|
||||||
|
BOOL dispBG[4];
|
||||||
|
BOOL dispOBJ;
|
||||||
|
|
||||||
|
OAM * oam;
|
||||||
|
u8 * sprMem;
|
||||||
|
u8 sprBoundary;
|
||||||
|
u8 sprBMPBoundary;
|
||||||
|
u8 sprBMPMode;
|
||||||
|
u32 sprEnable;
|
||||||
|
|
||||||
|
u8 WIN0H0;
|
||||||
|
u8 WIN0H1;
|
||||||
|
u8 WIN0V0;
|
||||||
|
u8 WIN0V1;
|
||||||
|
|
||||||
|
u8 WIN1H0;
|
||||||
|
u8 WIN1H1;
|
||||||
|
u8 WIN1V0;
|
||||||
|
u8 WIN1V1;
|
||||||
|
|
||||||
|
u8 WININ0;
|
||||||
|
u8 WININ0_SPECIAL;
|
||||||
|
u8 WININ1;
|
||||||
|
u8 WININ1_SPECIAL;
|
||||||
|
|
||||||
|
u8 WINOUT;
|
||||||
|
u8 WINOUT_SPECIAL;
|
||||||
|
u8 WINOBJ;
|
||||||
|
u8 WINOBJ_SPECIAL;
|
||||||
|
|
||||||
|
u8 WIN0_ENABLED;
|
||||||
|
u8 WIN1_ENABLED;
|
||||||
|
u8 WINOBJ_ENABLED;
|
||||||
|
|
||||||
|
u16 BLDCNT;
|
||||||
|
u8 BLDALPHA_EVA;
|
||||||
|
u8 BLDALPHA_EVB;
|
||||||
|
u8 BLDY_EVY;
|
||||||
|
|
||||||
|
u8 MasterBrightMode;
|
||||||
|
u32 MasterBrightFactor;
|
||||||
|
|
||||||
|
BOOL (*setFinalColorSpr)(const GPU *gpu, u32 passing, u8 bgnum, u8 *dst, u16 color, u16 x, u16 y);
|
||||||
|
BOOL (*setFinalColorBck)(const GPU *gpu, u32 passing, u8 bgnum, u8 *dst, u16 color, u16 x, u16 y);
|
||||||
|
void (*spriteRender) (GPU * gpu, u16 l, u8 * dst, u8 * prioTab);
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
// normally should have same addresses
|
||||||
|
static void REG_DISPx_pack_test(GPU * gpu)
|
||||||
|
{
|
||||||
|
REG_DISPx * r = gpu->dispx_st;
|
||||||
|
printf ("%08x %02x\n", r, (long)(&r->dispx_DISPCNT) - (long)r);
|
||||||
|
printf ("\t%02x\n", (long)(&r->dispA_DISPSTAT) - (long)r);
|
||||||
|
printf ("\t%02x\n", (long)(&r->dispx_VCOUNT) - (long)r);
|
||||||
|
printf ("\t%02x\n", (long)(&r->dispx_BGxCNT[0]) - (long)r);
|
||||||
|
printf ("\t%02x\n", (long)(&r->dispx_BGxOFS[0]) - (long)r);
|
||||||
|
printf ("\t%02x\n", (long)(&r->dispx_BG2PARMS) - (long)r);
|
||||||
|
printf ("\t%02x\n", (long)(&r->dispx_BG3PARMS) - (long)r);
|
||||||
|
printf ("\t%02x\n", (long)(&r->dispx_WINCNT) - (long)r);
|
||||||
|
printf ("\t%02x\n", (long)(&r->dispx_MISC) - (long)r);
|
||||||
|
printf ("\t%02x\n", (long)(&r->dispA_DISP3DCNT) - (long)r);
|
||||||
|
printf ("\t%02x\n", (long)(&r->dispA_DISPCAPCNT) - (long)r);
|
||||||
|
printf ("\t%02x\n", (long)(&r->dispA_DISPMMEMFIFO) - (long)r);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern u8 GPU_screen[4*256*192];
|
||||||
|
|
||||||
|
|
||||||
|
GPU * GPU_Init(u8 l);
|
||||||
|
void GPU_Reset(GPU *g, u8 l);
|
||||||
|
void GPU_DeInit(GPU *);
|
||||||
|
|
||||||
|
void textBG(const GPU * gpu, u8 num, u8 * DST); //Draw text based background
|
||||||
|
void rotBG(GPU * gpu, u8 num, u8 * DST);
|
||||||
|
void extRotBG(GPU * gpu, u8 num, u8 * DST);
|
||||||
|
void sprite1D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab);
|
||||||
|
void sprite2D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab);
|
||||||
|
|
||||||
|
extern short sizeTab[4][4][2];
|
||||||
|
extern size sprSizeTab[4][4];
|
||||||
|
extern s8 mode2type[8][4];
|
||||||
|
extern void (*modeRender[8][4])(GPU * gpu, u8 num, u16 l, u8 * DST);
|
||||||
|
|
||||||
|
typedef struct NDS_Screen {
|
||||||
|
GPU * gpu;
|
||||||
|
u16 offset;
|
||||||
|
} NDS_Screen;
|
||||||
|
|
||||||
|
int Screen_Init(NDS_state *state, int coreid);
|
||||||
|
void Screen_Reset(NDS_state *state);
|
||||||
|
void Screen_DeInit(NDS_state *state);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define GFXCORE_DEFAULT -1
|
||||||
|
#define GFXCORE_DUMMY 0
|
||||||
|
|
||||||
|
#define GFXCORE_FULLSCREEN (1 << 0)
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int id; // ID number for core(see above defines)
|
||||||
|
const char *Name; // Name of core
|
||||||
|
int flags; // What features the core supports(full screen, etc.)
|
||||||
|
int (*Init)(); // Initializes stuff related to core
|
||||||
|
void (*DeInit)(); // Deinitializes stuff related to core
|
||||||
|
void (*Resize)(int width, int height, BOOL fullscreen); // Resizes window or fullscreen
|
||||||
|
void (*OnScreenText)(char *string, ...); // For handling save state messages, etc.
|
||||||
|
} GraphicsInterface_struct;
|
||||||
|
|
||||||
|
extern GraphicsInterface_struct GFXDummy;
|
||||||
|
|
||||||
|
void GPU_setVideoProp(GPU *, u32 p);
|
||||||
|
void GPU_setBGProp(GPU *, u16 num, u16 p);
|
||||||
|
|
||||||
|
void GPU_setBLDCNT(GPU *gpu, u16 v) ;
|
||||||
|
void GPU_setBLDALPHA(GPU *gpu, u16 v) ;
|
||||||
|
void GPU_setBLDY(GPU *gpu, u16 v) ;
|
||||||
|
void GPU_setMOSAIC(GPU *gpu, u16 v) ;
|
||||||
|
|
||||||
|
|
||||||
|
void GPU_remove(GPU *, u8 num);
|
||||||
|
void GPU_addBack(GPU *, u8 num);
|
||||||
|
|
||||||
|
int GPU_ChangeGraphicsCore(int coreid);
|
||||||
|
|
||||||
|
void GPU_set_DISPCAPCNT(GPU * gpu, u32 val) ;
|
||||||
|
void GPU_ligne(NDS_Screen * screen, u16 l) ;
|
||||||
|
void GPU_setMasterBrightness (GPU *gpu, u16 val);
|
||||||
|
|
||||||
|
void GPU_setWIN0_H (GPU *gpu, u16 val);
|
||||||
|
void GPU_setWIN0_H0 (GPU *gpu, u8 val);
|
||||||
|
void GPU_setWIN0_H1 (GPU *gpu, u8 val);
|
||||||
|
|
||||||
|
void GPU_setWIN0_V (GPU *gpu, u16 val);
|
||||||
|
void GPU_setWIN0_V0 (GPU *gpu, u8 val);
|
||||||
|
void GPU_setWIN0_V1 (GPU *gpu, u8 val);
|
||||||
|
|
||||||
|
void GPU_setWIN1_H (GPU *gpu, u16 val);
|
||||||
|
void GPU_setWIN1_H0 (GPU *gpu, u8 val);
|
||||||
|
void GPU_setWIN1_H1 (GPU *gpu, u8 val);
|
||||||
|
|
||||||
|
void GPU_setWIN1_V (GPU *gpu, u16 val);
|
||||||
|
void GPU_setWIN1_V0 (GPU *gpu, u8 val);
|
||||||
|
void GPU_setWIN1_V1 (GPU *gpu, u8 val);
|
||||||
|
|
||||||
|
void GPU_setWININ (GPU *gpu, u16 val);
|
||||||
|
void GPU_setWININ0 (GPU *gpu, u8 val);
|
||||||
|
void GPU_setWININ1 (GPU *gpu, u8 val);
|
||||||
|
|
||||||
|
void GPU_setWINOUT16(GPU *gpu, u16 val);
|
||||||
|
void GPU_setWINOUT (GPU *gpu, u8 val);
|
||||||
|
void GPU_setWINOBJ (GPU *gpu, u8 val);
|
||||||
|
|
||||||
|
void GPU_setBLDCNT_LOW (GPU *gpu, u8 val);
|
||||||
|
void GPU_setBLDCNT_HIGH (GPU *gpu, u8 val);
|
||||||
|
void GPU_setBLDCNT (GPU *gpu, u16 val);
|
||||||
|
|
||||||
|
void GPU_setBLDALPHA (GPU *gpu, u16 val);
|
||||||
|
void GPU_setBLDALPHA_EVA(GPU *gpu, u8 val);
|
||||||
|
void GPU_setBLDALPHA_EVB(GPU *gpu, u8 val);
|
||||||
|
|
||||||
|
void GPU_setBLDY_EVY (GPU *gpu, u8 val);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,194 @@
|
||||||
|
/* Copyright (C) 2006 yopyop
|
||||||
|
yopyop156@ifrance.com
|
||||||
|
yopyop156.ifrance.com
|
||||||
|
|
||||||
|
Copyright (C) 2007 shash
|
||||||
|
|
||||||
|
This file is part of DeSmuME
|
||||||
|
|
||||||
|
DeSmuME is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
DeSmuME is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with DeSmuME; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MMU_H
|
||||||
|
#define MMU_H
|
||||||
|
|
||||||
|
#include "FIFO.h"
|
||||||
|
#include "dscard.h"
|
||||||
|
|
||||||
|
#include "ARM9.h"
|
||||||
|
#include "mc.h"
|
||||||
|
|
||||||
|
#include "state.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* theses macros are designed for reading/writing in memory (m is a pointer to memory, like cpu->state->MMUMMU_MEM[proc], and a is an adress, like 0x04000000 */
|
||||||
|
#define MEM_8(m, a) (((u8*)(m[((a)>>20)&0xff]))[((a)&0xfff)])
|
||||||
|
|
||||||
|
/* theses ones for reading in rom data */
|
||||||
|
#define ROM_8(m, a) (((u8*)(m))[(a)])
|
||||||
|
|
||||||
|
#define IPCFIFO 0
|
||||||
|
#define MAIN_MEMORY_DISP_FIFO 2
|
||||||
|
|
||||||
|
typedef struct MMU_struct {
|
||||||
|
//ARM7 mem
|
||||||
|
u8 ARM7_BIOS[0x4000];
|
||||||
|
u8 ARM7_ERAM[0x10000];
|
||||||
|
u8 ARM7_REG[0x10000];
|
||||||
|
u8 ARM7_WIRAM[0x10000];
|
||||||
|
|
||||||
|
u8 vram_mode[9];
|
||||||
|
u8 vScreen;
|
||||||
|
|
||||||
|
//Shared ram
|
||||||
|
u8 SWIRAM[0x8000];
|
||||||
|
|
||||||
|
//Card rom & ram
|
||||||
|
u8 * CART_ROM;
|
||||||
|
u8 CART_RAM[0x10000];
|
||||||
|
|
||||||
|
//Unused ram
|
||||||
|
u8 UNUSED_RAM[4];
|
||||||
|
|
||||||
|
u8 * * MMU_MEM[2];
|
||||||
|
u32 * MMU_MASK[2];
|
||||||
|
|
||||||
|
u8 ARM9_RW_MODE;
|
||||||
|
|
||||||
|
FIFO fifos[16];
|
||||||
|
|
||||||
|
const u32 * MMU_WAIT16[2];
|
||||||
|
const u32 * MMU_WAIT32[2];
|
||||||
|
|
||||||
|
u32 DTCMRegion;
|
||||||
|
u32 ITCMRegion;
|
||||||
|
|
||||||
|
u16 timer[2][4];
|
||||||
|
s32 timerMODE[2][4];
|
||||||
|
u32 timerON[2][4];
|
||||||
|
u32 timerRUN[2][4];
|
||||||
|
u16 timerReload[2][4];
|
||||||
|
|
||||||
|
u32 reg_IME[2];
|
||||||
|
u32 reg_IE[2];
|
||||||
|
u32 reg_IF[2];
|
||||||
|
|
||||||
|
u32 DMAStartTime[2][4];
|
||||||
|
s32 DMACycle[2][4];
|
||||||
|
u32 DMACrt[2][4];
|
||||||
|
BOOL DMAing[2][4];
|
||||||
|
|
||||||
|
memory_chip_t fw;
|
||||||
|
memory_chip_t bupmem;
|
||||||
|
|
||||||
|
nds_dscard dscard[2];
|
||||||
|
u32 CheckTimers;
|
||||||
|
u32 CheckDMAs;
|
||||||
|
|
||||||
|
} MMU_struct;
|
||||||
|
|
||||||
|
struct armcpu_memory_iface {
|
||||||
|
/** the 32 bit instruction prefetch */
|
||||||
|
u32 FASTCALL (*prefetch32)( void *data, u32 adr);
|
||||||
|
|
||||||
|
/** the 16 bit instruction prefetch */
|
||||||
|
u16 FASTCALL (*prefetch16)( void *data, u32 adr);
|
||||||
|
|
||||||
|
/** read 8 bit data value */
|
||||||
|
u8 FASTCALL (*read8)( void *data, u32 adr);
|
||||||
|
/** read 16 bit data value */
|
||||||
|
u16 FASTCALL (*read16)( void *data, u32 adr);
|
||||||
|
/** read 32 bit data value */
|
||||||
|
u32 FASTCALL (*read32)( void *data, u32 adr);
|
||||||
|
|
||||||
|
/** write 8 bit data value */
|
||||||
|
void FASTCALL (*write8)( void *data, u32 adr, u8 val);
|
||||||
|
/** write 16 bit data value */
|
||||||
|
void FASTCALL (*write16)( void *data, u32 adr, u16 val);
|
||||||
|
/** write 32 bit data value */
|
||||||
|
void FASTCALL (*write32)( void *data, u32 adr, u32 val);
|
||||||
|
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void mmu_select_savetype(NDS_state *state, int type, int *bmemtype, u32 *bmemsize) {
|
||||||
|
if (type<0 || type > 5) return;
|
||||||
|
*bmemtype=save_types[type][0];
|
||||||
|
*bmemsize=save_types[type][1];
|
||||||
|
mc_realloc(&state->MMU->bupmem, *bmemtype, *bmemsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MMU_Init(NDS_state *);
|
||||||
|
void MMU_DeInit(NDS_state *);
|
||||||
|
|
||||||
|
void MMU_clearMem(NDS_state *);
|
||||||
|
|
||||||
|
void MMU_setRom(NDS_state *, u8 * rom, u32 mask);
|
||||||
|
void MMU_unsetRom(NDS_state *);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Memory reading
|
||||||
|
*/
|
||||||
|
u8 FASTCALL MMU_read8(NDS_state *, u32 proc, u32 adr);
|
||||||
|
u16 FASTCALL MMU_read16(NDS_state *, u32 proc, u32 adr);
|
||||||
|
u32 FASTCALL MMU_read32(NDS_state *, u32 proc, u32 adr);
|
||||||
|
|
||||||
|
#ifdef MMU_ENABLE_ACL
|
||||||
|
u8 FASTCALL MMU_read8_acl(NDS_state *, u32 proc, u32 adr, u32 access);
|
||||||
|
u16 FASTCALL MMU_read16_acl(NDS_state *, u32 proc, u32 adr, u32 access);
|
||||||
|
u32 FASTCALL MMU_read32_acl(NDS_state *, u32 proc, u32 adr, u32 access);
|
||||||
|
#else
|
||||||
|
#define MMU_read8_acl(state,proc,adr,access) MMU_read8(state,proc,adr)
|
||||||
|
#define MMU_read16_acl(state,proc,adr,access) MMU_read16(state,proc,adr)
|
||||||
|
#define MMU_read32_acl(state,proc,adr,access) MMU_read32(state,proc,adr)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Memory writing
|
||||||
|
*/
|
||||||
|
void FASTCALL MMU_write8(NDS_state *, u32 proc, u32 adr, u8 val);
|
||||||
|
void FASTCALL MMU_write16(NDS_state *, u32 proc, u32 adr, u16 val);
|
||||||
|
void FASTCALL MMU_write32(NDS_state *, u32 proc, u32 adr, u32 val);
|
||||||
|
|
||||||
|
#ifdef MMU_ENABLE_ACL
|
||||||
|
void FASTCALL MMU_write8_acl(NDS_state *, u32 proc, u32 adr, u8 val);
|
||||||
|
void FASTCALL MMU_write16_acl(NDS_state *, u32 proc, u32 adr, u16 val);
|
||||||
|
void FASTCALL MMU_write32_acl(NDS_state *, u32 proc, u32 adr, u32 val);
|
||||||
|
#else
|
||||||
|
#define MMU_write8_acl MMU_write8
|
||||||
|
#define MMU_write16_acl MMU_write16
|
||||||
|
#define MMU_write32_acl MMU_write32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void FASTCALL MMU_doDMA(NDS_state *, u32 proc, u32 num);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The base ARM memory interfaces
|
||||||
|
*/
|
||||||
|
extern struct armcpu_memory_iface arm9_base_memory_iface;
|
||||||
|
extern struct armcpu_memory_iface arm7_base_memory_iface;
|
||||||
|
extern struct armcpu_memory_iface arm9_direct_memory_iface;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,750 @@
|
||||||
|
/* Copyright (C) 2006 yopyop
|
||||||
|
yopyop156@ifrance.com
|
||||||
|
yopyop156.ifrance.com
|
||||||
|
|
||||||
|
This file is part of DeSmuME
|
||||||
|
|
||||||
|
DeSmuME is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
DeSmuME is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with DeSmuME; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "state.h"
|
||||||
|
|
||||||
|
#include "NDSSystem.h"
|
||||||
|
#include "MMU.h"
|
||||||
|
//#include "cflash.h"
|
||||||
|
#include "spu_exports.h"
|
||||||
|
|
||||||
|
//#include "ROMReader.h"
|
||||||
|
|
||||||
|
/* the count of bytes copied from the firmware into memory */
|
||||||
|
#define NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT 0x70
|
||||||
|
|
||||||
|
static u32
|
||||||
|
calc_CRC16( u32 start, const u8 *data, int count) {
|
||||||
|
int i,j;
|
||||||
|
u32 crc = start & 0xffff;
|
||||||
|
static u16 val[] = { 0xC0C1,0xC181,0xC301,0xC601,0xCC01,0xD801,0xF001,0xA001 };
|
||||||
|
for(i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
crc = crc ^ data[i];
|
||||||
|
|
||||||
|
for(j = 0; j < 8; j++) {
|
||||||
|
int do_bit = 0;
|
||||||
|
|
||||||
|
if ( crc & 0x1)
|
||||||
|
do_bit = 1;
|
||||||
|
|
||||||
|
crc = crc >> 1;
|
||||||
|
|
||||||
|
if ( do_bit) {
|
||||||
|
crc = crc ^ (val[j] << (7-j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
copy_firmware_user_data( u8 *dest_buffer, const u8 *fw_data) {
|
||||||
|
/*
|
||||||
|
* Determine which of the two user settings in the firmware is the current
|
||||||
|
* and valid one and then copy this into the destination buffer.
|
||||||
|
*
|
||||||
|
* The current setting will have a greater count.
|
||||||
|
* Settings are only valid if its CRC16 is correct.
|
||||||
|
*/
|
||||||
|
int user1_valid = 0;
|
||||||
|
int user2_valid = 0;
|
||||||
|
u32 user_settings_offset;
|
||||||
|
u32 fw_crc;
|
||||||
|
u32 crc;
|
||||||
|
int copy_good = 0;
|
||||||
|
|
||||||
|
user_settings_offset = fw_data[0x20];
|
||||||
|
user_settings_offset |= fw_data[0x21] << 8;
|
||||||
|
user_settings_offset <<= 3;
|
||||||
|
|
||||||
|
if ( user_settings_offset <= 0x3FE00) {
|
||||||
|
s32 copy_settings_offset = -1;
|
||||||
|
|
||||||
|
crc = calc_CRC16( 0xffff, &fw_data[user_settings_offset],
|
||||||
|
NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT);
|
||||||
|
fw_crc = fw_data[user_settings_offset + 0x72];
|
||||||
|
fw_crc |= fw_data[user_settings_offset + 0x73] << 8;
|
||||||
|
if ( crc == fw_crc) {
|
||||||
|
user1_valid = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
crc = calc_CRC16( 0xffff, &fw_data[user_settings_offset + 0x100],
|
||||||
|
NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT);
|
||||||
|
fw_crc = fw_data[user_settings_offset + 0x100 + 0x72];
|
||||||
|
fw_crc |= fw_data[user_settings_offset + 0x100 + 0x73] << 8;
|
||||||
|
if ( crc == fw_crc) {
|
||||||
|
user2_valid = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( user1_valid) {
|
||||||
|
if ( user2_valid) {
|
||||||
|
u16 count1, count2;
|
||||||
|
|
||||||
|
count1 = fw_data[user_settings_offset + 0x70];
|
||||||
|
count1 |= fw_data[user_settings_offset + 0x71] << 8;
|
||||||
|
|
||||||
|
count2 = fw_data[user_settings_offset + 0x100 + 0x70];
|
||||||
|
count2 |= fw_data[user_settings_offset + 0x100 + 0x71] << 8;
|
||||||
|
|
||||||
|
if ( count2 > count1) {
|
||||||
|
copy_settings_offset = user_settings_offset + 0x100;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
copy_settings_offset = user_settings_offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
copy_settings_offset = user_settings_offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( user2_valid) {
|
||||||
|
/* copy the second user settings */
|
||||||
|
copy_settings_offset = user_settings_offset + 0x100;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( copy_settings_offset > 0) {
|
||||||
|
memcpy( dest_buffer, &fw_data[copy_settings_offset],
|
||||||
|
NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT);
|
||||||
|
copy_good = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return copy_good;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
int NDS_Init( NDS_state *state,
|
||||||
|
struct armcpu_memory_iface *arm9_mem_if,
|
||||||
|
struct armcpu_ctrl_iface **arm9_ctrl_iface,
|
||||||
|
struct armcpu_memory_iface *arm7_mem_if,
|
||||||
|
struct armcpu_ctrl_iface **arm7_ctrl_iface) {
|
||||||
|
#else
|
||||||
|
int NDS_Init( NDS_state *state) {
|
||||||
|
#endif
|
||||||
|
state->nds->ARM9Cycle = 0;
|
||||||
|
state->nds->ARM7Cycle = 0;
|
||||||
|
state->nds->cycles = 0;
|
||||||
|
MMU_Init(state);
|
||||||
|
state->nds->nextHBlank = 3168;
|
||||||
|
state->nds->VCount = 0;
|
||||||
|
state->nds->lignerendu = FALSE;
|
||||||
|
|
||||||
|
if (Screen_Init(state, GFXCORE_DUMMY) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
armcpu_new(state,state->NDS_ARM7,1, arm7_mem_if, arm7_ctrl_iface);
|
||||||
|
armcpu_new(state,state->NDS_ARM9,0, arm9_mem_if, arm9_ctrl_iface);
|
||||||
|
#else
|
||||||
|
armcpu_new(state,state->NDS_ARM7,1);
|
||||||
|
armcpu_new(state,state->NDS_ARM9,0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (SPU_Init(state, 0, 0) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
#ifdef EXPERIMENTAL_WIFI
|
||||||
|
WIFI_Init(&state->wifiMac) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void armcpu_deinit(armcpu_t *armcpu)
|
||||||
|
{
|
||||||
|
if(armcpu->coproc[15])
|
||||||
|
{
|
||||||
|
free(armcpu->coproc[15]);
|
||||||
|
armcpu->coproc[15] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NDS_DeInit(NDS_state *state) {
|
||||||
|
if(state->MMU->CART_ROM != state->MMU->UNUSED_RAM)
|
||||||
|
NDS_FreeROM(state);
|
||||||
|
|
||||||
|
armcpu_deinit(state->NDS_ARM7);
|
||||||
|
armcpu_deinit(state->NDS_ARM9);
|
||||||
|
|
||||||
|
state->nds->nextHBlank = 3168;
|
||||||
|
SPU_DeInit(state);
|
||||||
|
Screen_DeInit(state);
|
||||||
|
MMU_DeInit(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL NDS_SetROM(NDS_state *state, u8 * rom, u32 mask)
|
||||||
|
{
|
||||||
|
MMU_setRom(state, rom, mask);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
NDS_header * NDS_getROMHeader(NDS_state *state)
|
||||||
|
{
|
||||||
|
NDS_header * header = malloc(sizeof(NDS_header));
|
||||||
|
|
||||||
|
memcpy(header->gameTile, state->MMU->CART_ROM, 12);
|
||||||
|
memcpy(header->gameCode, state->MMU->CART_ROM + 12, 4);
|
||||||
|
header->makerCode = T1ReadWord(state->MMU->CART_ROM, 16);
|
||||||
|
header->unitCode = state->MMU->CART_ROM[18];
|
||||||
|
header->deviceCode = state->MMU->CART_ROM[19];
|
||||||
|
header->cardSize = state->MMU->CART_ROM[20];
|
||||||
|
memcpy(header->cardInfo, state->MMU->CART_ROM + 21, 8);
|
||||||
|
header->flags = state->MMU->CART_ROM[29];
|
||||||
|
header->ARM9src = T1ReadLong(state->MMU->CART_ROM, 32);
|
||||||
|
header->ARM9exe = T1ReadLong(state->MMU->CART_ROM, 36);
|
||||||
|
header->ARM9cpy = T1ReadLong(state->MMU->CART_ROM, 40);
|
||||||
|
header->ARM9binSize = T1ReadLong(state->MMU->CART_ROM, 44);
|
||||||
|
header->ARM7src = T1ReadLong(state->MMU->CART_ROM, 48);
|
||||||
|
header->ARM7exe = T1ReadLong(state->MMU->CART_ROM, 52);
|
||||||
|
header->ARM7cpy = T1ReadLong(state->MMU->CART_ROM, 56);
|
||||||
|
header->ARM7binSize = T1ReadLong(state->MMU->CART_ROM, 60);
|
||||||
|
header->FNameTblOff = T1ReadLong(state->MMU->CART_ROM, 64);
|
||||||
|
header->FNameTblSize = T1ReadLong(state->MMU->CART_ROM, 68);
|
||||||
|
header->FATOff = T1ReadLong(state->MMU->CART_ROM, 72);
|
||||||
|
header->FATSize = T1ReadLong(state->MMU->CART_ROM, 76);
|
||||||
|
header->ARM9OverlayOff = T1ReadLong(state->MMU->CART_ROM, 80);
|
||||||
|
header->ARM9OverlaySize = T1ReadLong(state->MMU->CART_ROM, 84);
|
||||||
|
header->ARM7OverlayOff = T1ReadLong(state->MMU->CART_ROM, 88);
|
||||||
|
header->ARM7OverlaySize = T1ReadLong(state->MMU->CART_ROM, 92);
|
||||||
|
header->unknown2a = T1ReadLong(state->MMU->CART_ROM, 96);
|
||||||
|
header->unknown2b = T1ReadLong(state->MMU->CART_ROM, 100);
|
||||||
|
header->IconOff = T1ReadLong(state->MMU->CART_ROM, 104);
|
||||||
|
header->CRC16 = T1ReadWord(state->MMU->CART_ROM, 108);
|
||||||
|
header->ROMtimeout = T1ReadWord(state->MMU->CART_ROM, 110);
|
||||||
|
header->ARM9unk = T1ReadLong(state->MMU->CART_ROM, 112);
|
||||||
|
header->ARM7unk = T1ReadLong(state->MMU->CART_ROM, 116);
|
||||||
|
memcpy(header->unknown3c, state->MMU->CART_ROM + 120, 8);
|
||||||
|
header->ROMSize = T1ReadLong(state->MMU->CART_ROM, 128);
|
||||||
|
header->HeaderSize = T1ReadLong(state->MMU->CART_ROM, 132);
|
||||||
|
memcpy(header->unknown5, state->MMU->CART_ROM + 136, 56);
|
||||||
|
memcpy(header->logo, state->MMU->CART_ROM + 192, 156);
|
||||||
|
header->logoCRC16 = T1ReadWord(state->MMU->CART_ROM, 348);
|
||||||
|
header->headerCRC16 = T1ReadWord(state->MMU->CART_ROM, 350);
|
||||||
|
memcpy(header->reserved, state->MMU->CART_ROM + 352, 160);
|
||||||
|
|
||||||
|
return header;
|
||||||
|
|
||||||
|
//return (NDS_header *)MMU->CART_ROM;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void NDS_FreeROM(NDS_state *state)
|
||||||
|
{
|
||||||
|
if (state->MMU->CART_ROM != state->MMU->UNUSED_RAM)
|
||||||
|
free(state->MMU->CART_ROM);
|
||||||
|
MMU_unsetRom(state);
|
||||||
|
// if (MMU->bupmem.fp)
|
||||||
|
// fclose(MMU->bupmem.fp);
|
||||||
|
// cpu->state->MMUbupmem.fp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void NDS_Reset( NDS_state *state)
|
||||||
|
{
|
||||||
|
BOOL oldexecute=state->execute;
|
||||||
|
int i;
|
||||||
|
u32 src;
|
||||||
|
u32 dst;
|
||||||
|
NDS_header * header = NDS_getROMHeader(state);
|
||||||
|
|
||||||
|
if (!header) return ;
|
||||||
|
|
||||||
|
state->execute = FALSE;
|
||||||
|
|
||||||
|
MMU_clearMem(state);
|
||||||
|
|
||||||
|
src = header->ARM9src;
|
||||||
|
dst = header->ARM9cpy;
|
||||||
|
|
||||||
|
for(i = 0; i < (header->ARM9binSize>>2); ++i)
|
||||||
|
{
|
||||||
|
MMU_write32(state, 0, dst, T1ReadLong(state->MMU->CART_ROM, src));
|
||||||
|
dst += 4;
|
||||||
|
src += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
src = header->ARM7src;
|
||||||
|
dst = header->ARM7cpy;
|
||||||
|
|
||||||
|
for(i = 0; i < (header->ARM7binSize>>2); ++i)
|
||||||
|
{
|
||||||
|
MMU_write32(state, 1, dst, T1ReadLong(state->MMU->CART_ROM, src));
|
||||||
|
dst += 4;
|
||||||
|
src += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
armcpu_init(state->NDS_ARM7, header->ARM7exe);
|
||||||
|
armcpu_init(state->NDS_ARM9, header->ARM9exe);
|
||||||
|
|
||||||
|
state->nds->ARM9Cycle = 0;
|
||||||
|
state->nds->ARM7Cycle = 0;
|
||||||
|
state->nds->cycles = 0;
|
||||||
|
memset(state->nds->timerCycle, 0, sizeof(s32) * 2 * 4);
|
||||||
|
memset(state->nds->timerOver, 0, sizeof(BOOL) * 2 * 4);
|
||||||
|
state->nds->nextHBlank = 3168;
|
||||||
|
state->nds->VCount = 0;
|
||||||
|
state->nds->old = 0;
|
||||||
|
state->nds->diff = 0;
|
||||||
|
state->nds->lignerendu = FALSE;
|
||||||
|
state->nds->touchX = state->nds->touchY = 0;
|
||||||
|
|
||||||
|
MMU_write16(state, 0, 0x04000130, 0x3FF);
|
||||||
|
MMU_write16(state, 1, 0x04000130, 0x3FF);
|
||||||
|
MMU_write8(state, 1, 0x04000136, 0x43);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup a copy of the firmware user settings in memory.
|
||||||
|
* (this is what the DS firmware would do).
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
u8 temp_buffer[NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT];
|
||||||
|
int fw_index;
|
||||||
|
|
||||||
|
if ( copy_firmware_user_data( temp_buffer, state->MMU->fw.data)) {
|
||||||
|
for ( fw_index = 0; fw_index < NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT; fw_index++) {
|
||||||
|
MMU_write8( state, 0, 0x027FFC80 + fw_index, temp_buffer[fw_index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the whole header to Main RAM 0x27FFE00 on startup.
|
||||||
|
// Reference: http://nocash.emubase.de/gbatek.htm#dscartridgeheader
|
||||||
|
for (i = 0; i < ((0x170+0x90)/4); i++)
|
||||||
|
{
|
||||||
|
MMU_write32 (state, 0, 0x027FFE00+i*4, LE_TO_LOCAL_32(((u32*)state->MMU->CART_ROM)[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
state->MainScreen->offset = 0;
|
||||||
|
state->SubScreen->offset = 192;
|
||||||
|
|
||||||
|
//MMU_write32(state, 0, 0x02007FFC, 0xE92D4030);
|
||||||
|
|
||||||
|
//ARM7 BIOS IRQ HANDLER
|
||||||
|
MMU_write32(state, 1, 0x00, 0xE25EF002);
|
||||||
|
MMU_write32(state, 1, 0x04, 0xEAFFFFFE);
|
||||||
|
MMU_write32(state, 1, 0x18, 0xEA000000);
|
||||||
|
MMU_write32(state, 1, 0x20, 0xE92D500F);
|
||||||
|
MMU_write32(state, 1, 0x24, 0xE3A00301);
|
||||||
|
MMU_write32(state, 1, 0x28, 0xE28FE000);
|
||||||
|
MMU_write32(state, 1, 0x2C, 0xE510F004);
|
||||||
|
MMU_write32(state, 1, 0x30, 0xE8BD500F);
|
||||||
|
MMU_write32(state, 1, 0x34, 0xE25EF004);
|
||||||
|
|
||||||
|
//ARM9 BIOS IRQ HANDLER
|
||||||
|
MMU_write32(state, 0, 0xFFFF0018, 0xEA000000);
|
||||||
|
MMU_write32(state, 0, 0xFFFF0020, 0xE92D500F);
|
||||||
|
MMU_write32(state, 0, 0xFFFF0024, 0xEE190F11);
|
||||||
|
MMU_write32(state, 0, 0xFFFF0028, 0xE1A00620);
|
||||||
|
MMU_write32(state, 0, 0xFFFF002C, 0xE1A00600);
|
||||||
|
MMU_write32(state, 0, 0xFFFF0030, 0xE2800C40);
|
||||||
|
MMU_write32(state, 0, 0xFFFF0034, 0xE28FE000);
|
||||||
|
MMU_write32(state, 0, 0xFFFF0038, 0xE510F004);
|
||||||
|
MMU_write32(state, 0, 0xFFFF003C, 0xE8BD500F);
|
||||||
|
MMU_write32(state, 0, 0xFFFF0040, 0xE25EF004);
|
||||||
|
|
||||||
|
MMU_write32(state, 0, 0x0000004, 0xE3A0010E);
|
||||||
|
MMU_write32(state, 0, 0x0000008, 0xE3A01020);
|
||||||
|
// MMU_write32(state, 0, 0x000000C, 0xE1B02110);
|
||||||
|
MMU_write32(state, 0, 0x000000C, 0xE1B02040);
|
||||||
|
MMU_write32(state, 0, 0x0000010, 0xE3B02020);
|
||||||
|
// MMU_write32(state, 0, 0x0000010, 0xE2100202);
|
||||||
|
|
||||||
|
free(header);
|
||||||
|
|
||||||
|
GPU_Reset(state->MainScreen->gpu, 0);
|
||||||
|
GPU_Reset(state->SubScreen->gpu, 1);
|
||||||
|
SPU_Reset(state);
|
||||||
|
|
||||||
|
state->execute = oldexecute;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dma_check(NDS_state *state)
|
||||||
|
{
|
||||||
|
if((state->MMU->DMAing[0][0])&&(state->MMU->DMACycle[0][0]<=state->nds->cycles))
|
||||||
|
{
|
||||||
|
T1WriteLong(state->ARM9Mem->ARM9_REG, 0xB8 + (0xC*0), T1ReadLong(state->ARM9Mem->ARM9_REG, 0xB8 + (0xC*0)) & 0x7FFFFFFF);
|
||||||
|
if((state->MMU->DMACrt[0][0])&(1<<30)) NDS_makeARM9Int(state, 8);
|
||||||
|
state->MMU->DMAing[0][0] = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((state->MMU->DMAing[0][1])&&(state->MMU->DMACycle[0][1]<=state->nds->cycles))
|
||||||
|
{
|
||||||
|
T1WriteLong(state->ARM9Mem->ARM9_REG, 0xB8 + (0xC*1), T1ReadLong(state->ARM9Mem->ARM9_REG, 0xB8 + (0xC*1)) & 0x7FFFFFFF);
|
||||||
|
if((state->MMU->DMACrt[0][1])&(1<<30)) NDS_makeARM9Int(state, 9);
|
||||||
|
state->MMU->DMAing[0][1] = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((state->MMU->DMAing[0][2])&&(state->MMU->DMACycle[0][2]<=state->nds->cycles))
|
||||||
|
{
|
||||||
|
T1WriteLong(state->ARM9Mem->ARM9_REG, 0xB8 + (0xC*2), T1ReadLong(state->ARM9Mem->ARM9_REG, 0xB8 + (0xC*2)) & 0x7FFFFFFF);
|
||||||
|
if((state->MMU->DMACrt[0][2])&(1<<30)) NDS_makeARM9Int(state, 10);
|
||||||
|
state->MMU->DMAing[0][2] = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((state->MMU->DMAing[0][3])&&(state->MMU->DMACycle[0][3]<=state->nds->cycles))
|
||||||
|
{
|
||||||
|
T1WriteLong(state->ARM9Mem->ARM9_REG, 0xB8 + (0xC*3), T1ReadLong(state->ARM9Mem->ARM9_REG, 0xB8 + (0xC*3)) & 0x7FFFFFFF);
|
||||||
|
if((state->MMU->DMACrt[0][3])&(1<<30)) NDS_makeARM9Int(state, 11);
|
||||||
|
state->MMU->DMAing[0][3] = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((state->MMU->DMAing[1][0])&&(state->MMU->DMACycle[1][0]<=state->nds->cycles))
|
||||||
|
{
|
||||||
|
T1WriteLong(state->MMU->ARM7_REG, 0xB8 + (0xC*0), T1ReadLong(state->MMU->ARM7_REG, 0xB8 + (0xC*0)) & 0x7FFFFFFF);
|
||||||
|
if((state->MMU->DMACrt[1][0])&(1<<30)) NDS_makeARM7Int(state, 8);
|
||||||
|
state->MMU->DMAing[1][0] = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((state->MMU->DMAing[1][1])&&(state->MMU->DMACycle[1][1]<=state->nds->cycles))
|
||||||
|
{
|
||||||
|
T1WriteLong(state->MMU->ARM7_REG, 0xB8 + (0xC*1), T1ReadLong(state->MMU->ARM7_REG, 0xB8 + (0xC*1)) & 0x7FFFFFFF);
|
||||||
|
if((state->MMU->DMACrt[1][1])&(1<<30)) NDS_makeARM7Int(state, 9);
|
||||||
|
state->MMU->DMAing[1][1] = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((state->MMU->DMAing[1][2])&&(state->MMU->DMACycle[1][2]<=state->nds->cycles))
|
||||||
|
{
|
||||||
|
T1WriteLong(state->MMU->ARM7_REG, 0xB8 + (0xC*2), T1ReadLong(state->MMU->ARM7_REG, 0xB8 + (0xC*2)) & 0x7FFFFFFF);
|
||||||
|
if((state->MMU->DMACrt[1][2])&(1<<30)) NDS_makeARM7Int(state, 10);
|
||||||
|
state->MMU->DMAing[1][2] = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((state->MMU->DMAing[1][3])&&(state->MMU->DMACycle[1][3]<=state->nds->cycles))
|
||||||
|
{
|
||||||
|
T1WriteLong(state->MMU->ARM7_REG, 0xB8 + (0xC*3), T1ReadLong(state->MMU->ARM7_REG, 0xB8 + (0xC*3)) & 0x7FFFFFFF);
|
||||||
|
if((state->MMU->DMACrt[1][3])&(1<<30)) NDS_makeARM7Int(state, 11);
|
||||||
|
state->MMU->DMAing[1][3] = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((state->MMU->reg_IF[0]&state->MMU->reg_IE[0]) && (state->MMU->reg_IME[0]))
|
||||||
|
{
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
if ( armcpu_flagIrq( state->NDS_ARM9))
|
||||||
|
#else
|
||||||
|
if ( armcpu_irqExeption(state->NDS_ARM9))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
state->nds->ARM9Cycle = state->nds->cycles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if((state->MMU->reg_IF[1]&state->MMU->reg_IE[1]) && (state->MMU->reg_IME[1]))
|
||||||
|
{
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
if ( armcpu_flagIrq( state->NDS_ARM7))
|
||||||
|
#else
|
||||||
|
if ( armcpu_irqExeption(state->NDS_ARM7))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
state->nds->ARM7Cycle = state->nds->cycles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void timer_check(NDS_state *state)
|
||||||
|
{
|
||||||
|
int p, t;
|
||||||
|
for (p = 0; p < 2; p++)
|
||||||
|
{
|
||||||
|
for (t = 0; t < 4; t++)
|
||||||
|
{
|
||||||
|
state->nds->timerOver[p][t] = 0;
|
||||||
|
if(state->MMU->timerON[p][t])
|
||||||
|
{
|
||||||
|
if(state->MMU->timerRUN[p][t])
|
||||||
|
{
|
||||||
|
switch(state->MMU->timerMODE[p][t])
|
||||||
|
{
|
||||||
|
case 0xFFFF :
|
||||||
|
if(t > 0 && state->nds->timerOver[p][t - 1])
|
||||||
|
{
|
||||||
|
++(state->MMU->timer[p][t]);
|
||||||
|
state->nds->timerOver[p][t] = !state->MMU->timer[p][t];
|
||||||
|
if (state->nds->timerOver[p][t])
|
||||||
|
{
|
||||||
|
if (p == 0)
|
||||||
|
{
|
||||||
|
if(T1ReadWord(state->ARM9Mem->ARM9_REG, 0x102 + (t << 2)) & 0x40)
|
||||||
|
NDS_makeARM9Int(state, 3 + t);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(T1ReadWord(state->MMU->ARM7_REG, 0x102 + (t << 2)) & 0x40)
|
||||||
|
NDS_makeARM7Int(state, 3 + t);
|
||||||
|
}
|
||||||
|
state->MMU->timer[p][t] = state->MMU->timerReload[p][t];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
{
|
||||||
|
state->nds->diff = (state->nds->cycles >> state->MMU->timerMODE[p][t]) - (state->nds->timerCycle[p][t] >> state->MMU->timerMODE[p][t]);
|
||||||
|
state->nds->old = state->MMU->timer[p][t];
|
||||||
|
state->MMU->timer[p][t] += state->nds->diff;
|
||||||
|
state->nds->timerCycle[p][t] += state->nds->diff << state->MMU->timerMODE[p][t];
|
||||||
|
state->nds->timerOver[p][t] = state->nds->old >= state->MMU->timer[p][t];
|
||||||
|
if(state->nds->timerOver[p][t])
|
||||||
|
{
|
||||||
|
if (p == 0)
|
||||||
|
{
|
||||||
|
if(T1ReadWord(state->ARM9Mem->ARM9_REG, 0x102 + (t << 2)) & 0x40)
|
||||||
|
NDS_makeARM9Int(state, 3 + t);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(T1ReadWord(state->MMU->ARM7_REG, 0x102 + (t << 2)) & 0x40)
|
||||||
|
NDS_makeARM7Int(state, 3 + t);
|
||||||
|
}
|
||||||
|
state->MMU->timer[p][t] = state->MMU->timerReload[p][t] + state->MMU->timer[p][t] - state->nds->old;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state->MMU->timerRUN[p][t] = TRUE;
|
||||||
|
state->nds->timerCycle[p][t] = state->nds->cycles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NDS_exec_hframe(NDS_state *state, int cpu_clockdown_level_arm9, int cpu_clockdown_level_arm7)
|
||||||
|
{
|
||||||
|
int h;
|
||||||
|
for (h = 0; h < 2; h++)
|
||||||
|
{
|
||||||
|
s32 nb = state->nds->cycles + (h ? (99 * 12) : (256 * 12));
|
||||||
|
|
||||||
|
while (nb > state->nds->ARM9Cycle && !state->NDS_ARM9->waitIRQ)
|
||||||
|
state->nds->ARM9Cycle += armcpu_exec(state->NDS_ARM9) << (cpu_clockdown_level_arm9);
|
||||||
|
if (state->NDS_ARM9->waitIRQ) state->nds->ARM9Cycle = nb;
|
||||||
|
while (nb > state->nds->ARM7Cycle && !state->NDS_ARM7->waitIRQ)
|
||||||
|
state->nds->ARM7Cycle += armcpu_exec(state->NDS_ARM7) << (1 + (cpu_clockdown_level_arm7));
|
||||||
|
if (state->NDS_ARM7->waitIRQ) state->nds->ARM7Cycle = nb;
|
||||||
|
state->nds->cycles = (state->nds->ARM9Cycle<state->nds->ARM7Cycle)?state->nds->ARM9Cycle : state->nds->ARM7Cycle;
|
||||||
|
|
||||||
|
/* HBLANK */
|
||||||
|
if (h)
|
||||||
|
{
|
||||||
|
T1WriteWord(state->ARM9Mem->ARM9_REG, 4, T1ReadWord(state->ARM9Mem->ARM9_REG, 4) | 2);
|
||||||
|
T1WriteWord(state->MMU->ARM7_REG, 4, T1ReadWord(state->MMU->ARM7_REG, 4) | 2);
|
||||||
|
NDS_ARM9HBlankInt(state);
|
||||||
|
NDS_ARM7HBlankInt(state);
|
||||||
|
|
||||||
|
if(state->nds->VCount<192)
|
||||||
|
{
|
||||||
|
if(state->MMU->DMAStartTime[0][0] == 2)
|
||||||
|
MMU_doDMA(state, 0, 0);
|
||||||
|
if(state->MMU->DMAStartTime[0][1] == 2)
|
||||||
|
MMU_doDMA(state, 0, 1);
|
||||||
|
if(state->MMU->DMAStartTime[0][2] == 2)
|
||||||
|
MMU_doDMA(state, 0, 2);
|
||||||
|
if(state->MMU->DMAStartTime[0][3] == 2)
|
||||||
|
MMU_doDMA(state, 0, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* HDISP */
|
||||||
|
u32 vmatch;
|
||||||
|
|
||||||
|
state->nds->nextHBlank += 4260;
|
||||||
|
++state->nds->VCount;
|
||||||
|
T1WriteWord(state->ARM9Mem->ARM9_REG, 4, T1ReadWord(state->ARM9Mem->ARM9_REG, 4) & 0xFFFD);
|
||||||
|
T1WriteWord(state->MMU->ARM7_REG, 4, T1ReadWord(state->MMU->ARM7_REG, 4) & 0xFFFD);
|
||||||
|
|
||||||
|
if(state->MMU->DMAStartTime[0][0] == 3)
|
||||||
|
MMU_doDMA(state, 0, 0);
|
||||||
|
if(state->MMU->DMAStartTime[0][1] == 3)
|
||||||
|
MMU_doDMA(state, 0, 1);
|
||||||
|
if(state->MMU->DMAStartTime[0][2] == 3)
|
||||||
|
MMU_doDMA(state, 0, 2);
|
||||||
|
if(state->MMU->DMAStartTime[0][3] == 3)
|
||||||
|
MMU_doDMA(state, 0, 3);
|
||||||
|
|
||||||
|
// Main memory display
|
||||||
|
if(state->MMU->DMAStartTime[0][0] == 4)
|
||||||
|
{
|
||||||
|
MMU_doDMA(state, 0, 0);
|
||||||
|
state->MMU->DMAStartTime[0][0] = 0;
|
||||||
|
}
|
||||||
|
if(state->MMU->DMAStartTime[0][1] == 4)
|
||||||
|
{
|
||||||
|
MMU_doDMA(state, 0, 1);
|
||||||
|
state->MMU->DMAStartTime[0][1] = 0;
|
||||||
|
}
|
||||||
|
if(state->MMU->DMAStartTime[0][2] == 4)
|
||||||
|
{
|
||||||
|
MMU_doDMA(state, 0, 2);
|
||||||
|
state->MMU->DMAStartTime[0][2] = 0;
|
||||||
|
}
|
||||||
|
if(state->MMU->DMAStartTime[0][3] == 4)
|
||||||
|
{
|
||||||
|
MMU_doDMA(state, 0, 3);
|
||||||
|
state->MMU->DMAStartTime[0][3] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(state->MMU->DMAStartTime[1][0] == 4)
|
||||||
|
{
|
||||||
|
MMU_doDMA(state, 1, 0);
|
||||||
|
state->MMU->DMAStartTime[1][0] = 0;
|
||||||
|
}
|
||||||
|
if(state->MMU->DMAStartTime[1][1] == 4)
|
||||||
|
{
|
||||||
|
MMU_doDMA(state, 1, 1);
|
||||||
|
state->MMU->DMAStartTime[0][1] = 0;
|
||||||
|
}
|
||||||
|
if(state->MMU->DMAStartTime[1][2] == 4)
|
||||||
|
{
|
||||||
|
MMU_doDMA(state, 1, 2);
|
||||||
|
state->MMU->DMAStartTime[1][2] = 0;
|
||||||
|
}
|
||||||
|
if(state->MMU->DMAStartTime[1][3] == 4)
|
||||||
|
{
|
||||||
|
MMU_doDMA(state, 1, 3);
|
||||||
|
state->MMU->DMAStartTime[1][3] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(state->nds->VCount == 192)
|
||||||
|
{
|
||||||
|
/* VBLANK */
|
||||||
|
T1WriteWord(state->ARM9Mem->ARM9_REG, 4, T1ReadWord(state->ARM9Mem->ARM9_REG, 4) | 1);
|
||||||
|
T1WriteWord(state->MMU->ARM7_REG, 4, T1ReadWord(state->MMU->ARM7_REG, 4) | 1);
|
||||||
|
NDS_ARM9VBlankInt(state);
|
||||||
|
NDS_ARM7VBlankInt(state);
|
||||||
|
|
||||||
|
if(state->MMU->DMAStartTime[0][0] == 1)
|
||||||
|
MMU_doDMA(state, 0, 0);
|
||||||
|
if(state->MMU->DMAStartTime[0][1] == 1)
|
||||||
|
MMU_doDMA(state, 0, 1);
|
||||||
|
if(state->MMU->DMAStartTime[0][2] == 1)
|
||||||
|
MMU_doDMA(state, 0, 2);
|
||||||
|
if(state->MMU->DMAStartTime[0][3] == 1)
|
||||||
|
MMU_doDMA(state, 0, 3);
|
||||||
|
|
||||||
|
if(state->MMU->DMAStartTime[1][0] == 1)
|
||||||
|
MMU_doDMA(state, 1, 0);
|
||||||
|
if(state->MMU->DMAStartTime[1][1] == 1)
|
||||||
|
MMU_doDMA(state, 1, 1);
|
||||||
|
if(state->MMU->DMAStartTime[1][2] == 1)
|
||||||
|
MMU_doDMA(state, 1, 2);
|
||||||
|
if(state->MMU->DMAStartTime[1][3] == 1)
|
||||||
|
MMU_doDMA(state, 1, 3);
|
||||||
|
}
|
||||||
|
else if(state->nds->VCount == 263)
|
||||||
|
{
|
||||||
|
const int cycles_per_frame = (263 * (99 * 12 + 256 * 12));
|
||||||
|
/* VDISP */
|
||||||
|
state->nds->nextHBlank = 3168;
|
||||||
|
state->nds->VCount = 0;
|
||||||
|
T1WriteWord(state->ARM9Mem->ARM9_REG, 4, T1ReadWord(state->ARM9Mem->ARM9_REG, 4) & 0xFFFE);
|
||||||
|
T1WriteWord(state->MMU->ARM7_REG, 4, T1ReadWord(state->MMU->ARM7_REG, 4) & 0xFFFE);
|
||||||
|
|
||||||
|
state->nds->cycles -= cycles_per_frame;
|
||||||
|
state->nds->ARM9Cycle -= cycles_per_frame;
|
||||||
|
state->nds->ARM7Cycle -= cycles_per_frame;
|
||||||
|
nb -= cycles_per_frame;
|
||||||
|
if(state->MMU->timerON[0][0])
|
||||||
|
state->nds->timerCycle[0][0] -= cycles_per_frame;
|
||||||
|
if(state->MMU->timerON[0][1])
|
||||||
|
state->nds->timerCycle[0][1] -= cycles_per_frame;
|
||||||
|
if(state->MMU->timerON[0][2])
|
||||||
|
state->nds->timerCycle[0][2] -= cycles_per_frame;
|
||||||
|
if(state->MMU->timerON[0][3])
|
||||||
|
state->nds->timerCycle[0][3] -= cycles_per_frame;
|
||||||
|
|
||||||
|
if(state->MMU->timerON[1][0])
|
||||||
|
state->nds->timerCycle[1][0] -= cycles_per_frame;
|
||||||
|
if(state->MMU->timerON[1][1])
|
||||||
|
state->nds->timerCycle[1][1] -= cycles_per_frame;
|
||||||
|
if(state->MMU->timerON[1][2])
|
||||||
|
state->nds->timerCycle[1][2] -= cycles_per_frame;
|
||||||
|
if(state->MMU->timerON[1][3])
|
||||||
|
state->nds->timerCycle[1][3] -= cycles_per_frame;
|
||||||
|
if(state->MMU->DMAing[0][0])
|
||||||
|
state->MMU->DMACycle[0][0] -= cycles_per_frame;
|
||||||
|
if(state->MMU->DMAing[0][1])
|
||||||
|
state->MMU->DMACycle[0][1] -= cycles_per_frame;
|
||||||
|
if(state->MMU->DMAing[0][2])
|
||||||
|
state->MMU->DMACycle[0][2] -= cycles_per_frame;
|
||||||
|
if(state->MMU->DMAing[0][3])
|
||||||
|
state->MMU->DMACycle[0][3] -= cycles_per_frame;
|
||||||
|
if(state->MMU->DMAing[1][0])
|
||||||
|
state->MMU->DMACycle[1][0] -= cycles_per_frame;
|
||||||
|
if(state->MMU->DMAing[1][1])
|
||||||
|
state->MMU->DMACycle[1][1] -= cycles_per_frame;
|
||||||
|
if(state->MMU->DMAing[1][2])
|
||||||
|
state->MMU->DMACycle[1][2] -= cycles_per_frame;
|
||||||
|
if(state->MMU->DMAing[1][3])
|
||||||
|
state->MMU->DMACycle[1][3] -= cycles_per_frame;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
T1WriteWord(state->ARM9Mem->ARM9_REG, 6, state->nds->VCount);
|
||||||
|
T1WriteWord(state->MMU->ARM7_REG, 6, state->nds->VCount);
|
||||||
|
|
||||||
|
vmatch = T1ReadWord(state->ARM9Mem->ARM9_REG, 4);
|
||||||
|
if((state->nds->VCount==(vmatch>>8)|((vmatch<<1)&(1<<8))))
|
||||||
|
{
|
||||||
|
T1WriteWord(state->ARM9Mem->ARM9_REG, 4, T1ReadWord(state->ARM9Mem->ARM9_REG, 4) | 4);
|
||||||
|
if(T1ReadWord(state->ARM9Mem->ARM9_REG, 4) & 32)
|
||||||
|
NDS_makeARM9Int(state, 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
T1WriteWord(state->ARM9Mem->ARM9_REG, 4, T1ReadWord(state->ARM9Mem->ARM9_REG, 4) & 0xFFFB);
|
||||||
|
|
||||||
|
vmatch = T1ReadWord(state->MMU->ARM7_REG, 4);
|
||||||
|
if((state->nds->VCount==(vmatch>>8)|((vmatch<<1)&(1<<8))))
|
||||||
|
{
|
||||||
|
T1WriteWord(state->MMU->ARM7_REG, 4, T1ReadWord(state->MMU->ARM7_REG, 4) | 4);
|
||||||
|
if(T1ReadWord(state->MMU->ARM7_REG, 4) & 32)
|
||||||
|
NDS_makeARM7Int(state, 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
T1WriteWord(state->MMU->ARM7_REG, 4, T1ReadWord(state->MMU->ARM7_REG, 4) & 0xFFFB);
|
||||||
|
|
||||||
|
timer_check(state);
|
||||||
|
dma_check(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NDS_exec_frame(NDS_state *state, int cpu_clockdown_level_arm9, int cpu_clockdown_level_arm7)
|
||||||
|
{
|
||||||
|
int v;
|
||||||
|
for (v = 0; v < 263; v++)
|
||||||
|
{
|
||||||
|
NDS_exec_hframe(state, cpu_clockdown_level_arm9, cpu_clockdown_level_arm7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,250 @@
|
||||||
|
/* Copyright (C) 2006 yopyop
|
||||||
|
yopyop156@ifrance.com
|
||||||
|
yopyop156.ifrance.com
|
||||||
|
|
||||||
|
This file is part of DeSmuME
|
||||||
|
|
||||||
|
DeSmuME is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
DeSmuME is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with DeSmuME; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NDSSYSTEM_H
|
||||||
|
#define NDSSYSTEM_H
|
||||||
|
|
||||||
|
#include "armcpu.h"
|
||||||
|
#include "MMU.h"
|
||||||
|
|
||||||
|
#include "GPU.h"
|
||||||
|
|
||||||
|
#include "mem.h"
|
||||||
|
//#include "wifi.h"
|
||||||
|
|
||||||
|
#include "ARM9.h"
|
||||||
|
|
||||||
|
#include "state.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
extern volatile BOOL execute;
|
||||||
|
extern BOOL click;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The firmware language values
|
||||||
|
*/
|
||||||
|
#define NDS_FW_LANG_JAP 0
|
||||||
|
#define NDS_FW_LANG_ENG 1
|
||||||
|
#define NDS_FW_LANG_FRE 2
|
||||||
|
#define NDS_FW_LANG_GER 3
|
||||||
|
#define NDS_FW_LANG_ITA 4
|
||||||
|
#define NDS_FW_LANG_SPA 5
|
||||||
|
#define NDS_FW_LANG_CHI 6
|
||||||
|
#define NDS_FW_LANG_RES 7
|
||||||
|
|
||||||
|
|
||||||
|
//#define LOG_ARM9
|
||||||
|
//#define LOG_ARM7
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char gameTile[12];
|
||||||
|
char gameCode[4];
|
||||||
|
u16 makerCode;
|
||||||
|
u8 unitCode;
|
||||||
|
u8 deviceCode;
|
||||||
|
u8 cardSize;
|
||||||
|
u8 cardInfo[8];
|
||||||
|
u8 flags;
|
||||||
|
|
||||||
|
u32 ARM9src;
|
||||||
|
u32 ARM9exe;
|
||||||
|
u32 ARM9cpy;
|
||||||
|
u32 ARM9binSize;
|
||||||
|
|
||||||
|
u32 ARM7src;
|
||||||
|
u32 ARM7exe;
|
||||||
|
u32 ARM7cpy;
|
||||||
|
u32 ARM7binSize;
|
||||||
|
|
||||||
|
u32 FNameTblOff;
|
||||||
|
u32 FNameTblSize;
|
||||||
|
|
||||||
|
u32 FATOff;
|
||||||
|
u32 FATSize;
|
||||||
|
|
||||||
|
u32 ARM9OverlayOff;
|
||||||
|
u32 ARM9OverlaySize;
|
||||||
|
u32 ARM7OverlayOff;
|
||||||
|
u32 ARM7OverlaySize;
|
||||||
|
|
||||||
|
u32 unknown2a;
|
||||||
|
u32 unknown2b;
|
||||||
|
|
||||||
|
u32 IconOff;
|
||||||
|
u16 CRC16;
|
||||||
|
u16 ROMtimeout;
|
||||||
|
u32 ARM9unk;
|
||||||
|
u32 ARM7unk;
|
||||||
|
|
||||||
|
u8 unknown3c[8];
|
||||||
|
u32 ROMSize;
|
||||||
|
u32 HeaderSize;
|
||||||
|
u8 unknown5[56];
|
||||||
|
u8 logo[156];
|
||||||
|
u16 logoCRC16;
|
||||||
|
u16 headerCRC16;
|
||||||
|
u8 reserved[160];
|
||||||
|
} NDS_header;
|
||||||
|
|
||||||
|
typedef struct NDSSystem
|
||||||
|
{
|
||||||
|
s32 ARM9Cycle;
|
||||||
|
s32 ARM7Cycle;
|
||||||
|
s32 cycles;
|
||||||
|
s32 timerCycle[2][4];
|
||||||
|
BOOL timerOver[2][4];
|
||||||
|
s32 nextHBlank;
|
||||||
|
u32 VCount;
|
||||||
|
u32 old;
|
||||||
|
s32 diff;
|
||||||
|
BOOL lignerendu;
|
||||||
|
|
||||||
|
u16 touchX;
|
||||||
|
u16 touchY;
|
||||||
|
} NDSSystem;
|
||||||
|
|
||||||
|
/** /brief A touchscreen calibration point.
|
||||||
|
*/
|
||||||
|
struct NDS_fw_touchscreen_cal {
|
||||||
|
u16 adc_x;
|
||||||
|
u16 adc_y;
|
||||||
|
|
||||||
|
u8 screen_x;
|
||||||
|
u8 screen_y;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** /brief The type of DS
|
||||||
|
*/
|
||||||
|
enum nds_fw_ds_type {
|
||||||
|
NDS_FW_DS_TYPE_FAT,
|
||||||
|
NDS_FW_DS_TYPE_LITE
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MAX_FW_NICKNAME_LENGTH 10
|
||||||
|
#define MAX_FW_MESSAGE_LENGTH 26
|
||||||
|
|
||||||
|
struct NDS_fw_config_data {
|
||||||
|
enum nds_fw_ds_type ds_type;
|
||||||
|
|
||||||
|
u8 fav_colour;
|
||||||
|
u8 birth_month;
|
||||||
|
u8 birth_day;
|
||||||
|
|
||||||
|
u16 nickname[MAX_FW_NICKNAME_LENGTH];
|
||||||
|
u8 nickname_len;
|
||||||
|
|
||||||
|
u16 message[MAX_FW_MESSAGE_LENGTH];
|
||||||
|
u8 message_len;
|
||||||
|
|
||||||
|
u8 language;
|
||||||
|
|
||||||
|
/* touchscreen calibration */
|
||||||
|
struct NDS_fw_touchscreen_cal touch_cal[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
int NDS_Init( NDS_state *,
|
||||||
|
struct armcpu_memory_iface *arm9_mem_if,
|
||||||
|
struct armcpu_ctrl_iface **arm9_ctrl_iface,
|
||||||
|
struct armcpu_memory_iface *arm7_mem_if,
|
||||||
|
struct armcpu_ctrl_iface **arm7_ctrl_iface);
|
||||||
|
#else
|
||||||
|
int NDS_Init ( NDS_state * );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void NDS_DeInit(NDS_state *);
|
||||||
|
void
|
||||||
|
NDS_FillDefaultFirmwareConfigData( NDS_state *, struct NDS_fw_config_data *fw_config);
|
||||||
|
|
||||||
|
BOOL NDS_SetROM(NDS_state *, u8 * rom, u32 mask);
|
||||||
|
NDS_header * NDS_getROMHeader(NDS_state *);
|
||||||
|
|
||||||
|
void NDS_setTouchPos(NDS_state *, u16 x, u16 y);
|
||||||
|
void NDS_releasTouch(NDS_state *);
|
||||||
|
|
||||||
|
void NDS_FreeROM(NDS_state *);
|
||||||
|
void NDS_Reset(NDS_state *);
|
||||||
|
|
||||||
|
int NDS_CreateDummyFirmware( NDS_state *, struct NDS_fw_config_data *user_settings);
|
||||||
|
u32
|
||||||
|
NDS_exec(NDS_state *, s32 nb, BOOL force);
|
||||||
|
|
||||||
|
static INLINE void NDS_ARM9HBlankInt(NDS_state *state)
|
||||||
|
{
|
||||||
|
if(T1ReadWord(state->ARM9Mem->ARM9_REG, 4) & 0x10)
|
||||||
|
{
|
||||||
|
state->MMU->reg_IF[0] |= 2;// & (MMU->reg_IME[0] << 1);// (MMU->reg_IE[0] & (1<<1));
|
||||||
|
state->NDS_ARM9->wIRQ = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE void NDS_ARM7HBlankInt(NDS_state *state)
|
||||||
|
{
|
||||||
|
if(T1ReadWord(state->MMU->ARM7_REG, 4) & 0x10)
|
||||||
|
{
|
||||||
|
state->MMU->reg_IF[1] |= 2;// & (MMU->reg_IME[1] << 1);// (MMU->reg_IE[1] & (1<<1));
|
||||||
|
state->NDS_ARM7->wIRQ = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE void NDS_ARM9VBlankInt(NDS_state *state)
|
||||||
|
{
|
||||||
|
if(T1ReadWord(state->ARM9Mem->ARM9_REG, 4) & 0x8)
|
||||||
|
{
|
||||||
|
state->MMU->reg_IF[0] |= 1;// & (MMU->reg_IME[0]);// (MMU->reg_IE[0] & 1);
|
||||||
|
state->NDS_ARM9->wIRQ = TRUE;
|
||||||
|
//execute = FALSE;
|
||||||
|
/*logcount++;*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE void NDS_ARM7VBlankInt(NDS_state *state)
|
||||||
|
{
|
||||||
|
if(T1ReadWord(state->MMU->ARM7_REG, 4) & 0x8)
|
||||||
|
state->MMU->reg_IF[1] |= 1;// & (MMU->reg_IME[1]);// (MMU->reg_IE[1] & 1);
|
||||||
|
state->NDS_ARM7->wIRQ = TRUE;
|
||||||
|
//execute = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE void NDS_swapScreen(NDS_state *state)
|
||||||
|
{
|
||||||
|
u16 tmp = state->MainScreen->offset;
|
||||||
|
state->MainScreen->offset = state->SubScreen->offset;
|
||||||
|
state->SubScreen->offset = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void NDS_exec_frame(NDS_state *, int cpu_clockdown_level_arm9, int cpu_clockdown_level_arm7);
|
||||||
|
void NDS_exec_hframe(NDS_state *, int cpu_clockdown_level_arm9, int cpu_clockdown_level_arm7);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,186 @@
|
||||||
|
/* SPU.h
|
||||||
|
|
||||||
|
Copyright 2006 Theo Berkau
|
||||||
|
Copyright (C) 2006-2009 DeSmuME team
|
||||||
|
|
||||||
|
This file is part of DeSmuME
|
||||||
|
|
||||||
|
DeSmuME is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
DeSmuME is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with DeSmuME; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SPU_H
|
||||||
|
#define SPU_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "types.h"
|
||||||
|
#include <math.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#define FORCEINLINE __forceinline
|
||||||
|
|
||||||
|
FORCEINLINE u32 u32floor(float f)
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_SSE2
|
||||||
|
return (u32)_mm_cvtt_ss2si(_mm_set_ss(f));
|
||||||
|
#else
|
||||||
|
return (u32)f;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
FORCEINLINE u32 u32floor(double d)
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_SSE2
|
||||||
|
return (u32)_mm_cvttsd_si32(_mm_set_sd(d));
|
||||||
|
#else
|
||||||
|
return (u32)d;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//same as above but works for negative values too.
|
||||||
|
//be sure that the results are the same thing as floorf!
|
||||||
|
FORCEINLINE s32 s32floor(float f)
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_SSE2
|
||||||
|
return _mm_cvtss_si32( _mm_add_ss(_mm_set_ss(-0.5f),_mm_add_ss(_mm_set_ss(f), _mm_set_ss(f))) ) >> 1;
|
||||||
|
#else
|
||||||
|
return (s32)floorf(f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static FORCEINLINE u32 sputrunc(float f) { return u32floor(f); }
|
||||||
|
static FORCEINLINE u32 sputrunc(double d) { return u32floor(d); }
|
||||||
|
static FORCEINLINE s32 spumuldiv7(s32 val, u8 multiplier) {
|
||||||
|
assert(multiplier <= 127);
|
||||||
|
return (multiplier == 127) ? val : ((val * multiplier) >> 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SNDCORE_DEFAULT -1
|
||||||
|
#define SNDCORE_DUMMY 0
|
||||||
|
|
||||||
|
#define CHANSTAT_STOPPED 0
|
||||||
|
#define CHANSTAT_PLAY 1
|
||||||
|
|
||||||
|
typedef struct NDS_state;
|
||||||
|
|
||||||
|
enum SPUInterpolationMode
|
||||||
|
{
|
||||||
|
SPUInterpolation_None = 0,
|
||||||
|
SPUInterpolation_Linear = 1,
|
||||||
|
SPUInterpolation_Cosine = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct NDS_state NDS_state;
|
||||||
|
|
||||||
|
typedef struct SoundInterface_struct
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
const char *Name;
|
||||||
|
int (*Init)(NDS_state *, int buffersize);
|
||||||
|
void (*DeInit)(NDS_state *);
|
||||||
|
void (*UpdateAudio)(NDS_state *, s16 *buffer, u32 num_samples);
|
||||||
|
u32 (*GetAudioSpace)(NDS_state *);
|
||||||
|
void (*MuteAudio)(NDS_state *);
|
||||||
|
void (*UnMuteAudio)(NDS_state *);
|
||||||
|
void (*SetVolume)(NDS_state *, int volume);
|
||||||
|
} SoundInterface_struct;
|
||||||
|
|
||||||
|
extern SoundInterface_struct SNDDummy;
|
||||||
|
extern SoundInterface_struct SNDFile;
|
||||||
|
|
||||||
|
struct channel_struct
|
||||||
|
{
|
||||||
|
channel_struct()
|
||||||
|
{}
|
||||||
|
u32 num;
|
||||||
|
u8 vol;
|
||||||
|
u8 datashift;
|
||||||
|
u8 hold;
|
||||||
|
u8 pan;
|
||||||
|
u8 waveduty;
|
||||||
|
u8 repeat;
|
||||||
|
u8 format;
|
||||||
|
u8 status;
|
||||||
|
u32 addr;
|
||||||
|
u16 timer;
|
||||||
|
u16 loopstart;
|
||||||
|
u32 length;
|
||||||
|
u32 totlength;
|
||||||
|
double double_totlength_shifted;
|
||||||
|
union {
|
||||||
|
s8 *buf8;
|
||||||
|
s16 *buf16;
|
||||||
|
};
|
||||||
|
double sampcnt;
|
||||||
|
double sampinc;
|
||||||
|
// ADPCM specific
|
||||||
|
u32 lastsampcnt;
|
||||||
|
s16 pcm16b, pcm16b_last;
|
||||||
|
s16 loop_pcm16b;
|
||||||
|
int index;
|
||||||
|
int loop_index;
|
||||||
|
u16 x;
|
||||||
|
s16 psgnoise_last;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
class SPU_struct
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SPU_struct(NDS_state *state, int buffersize);
|
||||||
|
u32 bufpos;
|
||||||
|
u32 buflength;
|
||||||
|
s32 *sndbuf;
|
||||||
|
s16 *outbuf;
|
||||||
|
u32 bufsize;
|
||||||
|
NDS_state *state;
|
||||||
|
channel_struct channels[16];
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
~SPU_struct();
|
||||||
|
void KeyOn(int channel);
|
||||||
|
void WriteByte(u32 addr, u8 val);
|
||||||
|
void WriteWord(u32 addr, u16 val);
|
||||||
|
void WriteLong(u32 addr, u32 val);
|
||||||
|
|
||||||
|
//kills all channels but leaves SPU otherwise running normally
|
||||||
|
void ShutUp();
|
||||||
|
};
|
||||||
|
|
||||||
|
SoundInterface_struct *SPU_SoundCore(NDS_state *);
|
||||||
|
|
||||||
|
void SPU_Pause(NDS_state *, int pause);
|
||||||
|
void SPU_SetVolume(NDS_state *, int volume);
|
||||||
|
void SPU_KeyOn(NDS_state *, int channel);
|
||||||
|
void SPU_Emulate_core(NDS_state *);
|
||||||
|
void SPU_Emulate_user(NDS_state *, bool mix = true);
|
||||||
|
|
||||||
|
class WavWriter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WavWriter();
|
||||||
|
bool open(const std::string & fname);
|
||||||
|
void close();
|
||||||
|
void update(void* soundData, int numSamples);
|
||||||
|
bool isRecording() const;
|
||||||
|
private:
|
||||||
|
FILE *spufp;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void WAV_End(NDS_state *);
|
||||||
|
bool WAV_Begin(NDS_state *, const char* fname);
|
||||||
|
bool WAV_IsRecording(NDS_state *);
|
||||||
|
void WAV_WavSoundUpdate(NDS_state *, void* soundData, int numSamples);
|
||||||
|
|
||||||
|
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,31 @@
|
||||||
|
/* Copyright (C) 2006 yopyop
|
||||||
|
yopyop156@ifrance.com
|
||||||
|
yopyop156.ifrance.com
|
||||||
|
|
||||||
|
This file is part of DeSmuME
|
||||||
|
|
||||||
|
DeSmuME is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
DeSmuME is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with DeSmuME; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ARMINSTRUCTION_H
|
||||||
|
#define ARMINSTRUCTION_H
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
#include "armcpu.h"
|
||||||
|
|
||||||
|
extern u32 (FASTCALL* arm_instructions_set[4096])(armcpu_t * cpu);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,582 @@
|
||||||
|
/* Copyright (C) 2006 yopyop
|
||||||
|
yopyop156@ifrance.com
|
||||||
|
yopyop156.ifrance.com
|
||||||
|
|
||||||
|
This file is part of DeSmuME
|
||||||
|
|
||||||
|
DeSmuME is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
DeSmuME is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with DeSmuME; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "arm_instructions.h"
|
||||||
|
#include "thumb_instructions.h"
|
||||||
|
#include "cp15.h"
|
||||||
|
#include "bios.h"
|
||||||
|
#include "MMU.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
const unsigned char arm_cond_table[16*16] = {
|
||||||
|
/* N=0, Z=0, C=0, V=0 */
|
||||||
|
0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
|
||||||
|
0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20,
|
||||||
|
/* N=0, Z=0, C=0, V=1 */
|
||||||
|
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x00,
|
||||||
|
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
|
||||||
|
/* N=0, Z=0, C=1, V=0 */
|
||||||
|
0x00,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF,
|
||||||
|
0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20,
|
||||||
|
/* N=0, Z=0, C=1, V=1 */
|
||||||
|
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00,
|
||||||
|
0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20,
|
||||||
|
/* N=0, Z=1, C=0, V=0 */
|
||||||
|
0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,
|
||||||
|
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
|
||||||
|
/* N=0, Z=1, C=0, V=1 */
|
||||||
|
0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x00,
|
||||||
|
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
|
||||||
|
/* N=0, Z=1, C=1, V=0 */
|
||||||
|
0xFF,0x00,0xFF,0x00,0x00,0xFF,0x00,0xFF,
|
||||||
|
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
|
||||||
|
/* N=0, Z=1, C=1, V=1 */
|
||||||
|
0xFF,0x00,0xFF,0x00,0x00,0xFF,0xFF,0x00,
|
||||||
|
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
|
||||||
|
/* N=1, Z=0, C=0, V=0 */
|
||||||
|
0x00,0xFF,0x00,0xFF,0xFF,0x00,0x00,0xFF,
|
||||||
|
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
|
||||||
|
/* N=1, Z=0, C=0, V=1 */
|
||||||
|
0x00,0xFF,0x00,0xFF,0xFF,0x00,0xFF,0x00,
|
||||||
|
0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20,
|
||||||
|
/* N=1, Z=0, C=1, V=0 */
|
||||||
|
0x00,0xFF,0xFF,0x00,0xFF,0x00,0x00,0xFF,
|
||||||
|
0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20,
|
||||||
|
/* N=1, Z=0, C=1, V=1 */
|
||||||
|
0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x00,
|
||||||
|
0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20,
|
||||||
|
/* N=1, Z=1, C=0, V=0 */
|
||||||
|
0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF,
|
||||||
|
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
|
||||||
|
/* N=1, Z=1, C=0, V=1 */
|
||||||
|
0xFF,0x00,0x00,0xFF,0xFF,0x00,0xFF,0x00,
|
||||||
|
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
|
||||||
|
/* N=1, Z=1, C=1, V=0 */
|
||||||
|
0xFF,0x00,0xFF,0x00,0xFF,0x00,0x00,0xFF,
|
||||||
|
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
|
||||||
|
/* N=1, Z=1, C=1, V=1 */
|
||||||
|
0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,
|
||||||
|
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
|
||||||
|
};
|
||||||
|
|
||||||
|
armcpu_t NDS_ARM7;
|
||||||
|
armcpu_t NDS_ARM9;
|
||||||
|
|
||||||
|
#define SWAP(a, b, c) do \
|
||||||
|
{ \
|
||||||
|
c=a; \
|
||||||
|
a=b; \
|
||||||
|
b=c; \
|
||||||
|
} \
|
||||||
|
while(0)
|
||||||
|
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
|
||||||
|
#define STALLED_CYCLE_COUNT 10
|
||||||
|
|
||||||
|
static void
|
||||||
|
stall_cpu( void *instance) {
|
||||||
|
armcpu_t *armcpu = (armcpu_t *)instance;
|
||||||
|
|
||||||
|
armcpu->stalled = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
unstall_cpu( void *instance) {
|
||||||
|
armcpu_t *armcpu = (armcpu_t *)instance;
|
||||||
|
|
||||||
|
armcpu->stalled = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
install_post_exec_fn( void *instance,
|
||||||
|
void (*ex_fn)( void *, u32 adr, int thumb),
|
||||||
|
void *fn_data) {
|
||||||
|
armcpu_t *armcpu = (armcpu_t *)instance;
|
||||||
|
|
||||||
|
armcpu->post_ex_fn = ex_fn;
|
||||||
|
armcpu->post_ex_fn_data = fn_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
remove_post_exec_fn( void *instance) {
|
||||||
|
armcpu_t *armcpu = (armcpu_t *)instance;
|
||||||
|
|
||||||
|
armcpu->post_ex_fn = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static u32
|
||||||
|
read_cpu_reg( void *instance, u32 reg_num) {
|
||||||
|
armcpu_t *armcpu = (armcpu_t *)instance;
|
||||||
|
u32 reg_value = 0;
|
||||||
|
|
||||||
|
if ( reg_num <= 14) {
|
||||||
|
reg_value = armcpu->R[reg_num];
|
||||||
|
}
|
||||||
|
else if ( reg_num == 15) {
|
||||||
|
reg_value = armcpu->next_instruction;
|
||||||
|
}
|
||||||
|
else if ( reg_num == 16) {
|
||||||
|
/* CPSR */
|
||||||
|
reg_value = armcpu->CPSR.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reg_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_cpu_reg( void *instance, u32 reg_num, u32 value) {
|
||||||
|
armcpu_t *armcpu = (armcpu_t *)instance;
|
||||||
|
|
||||||
|
if ( reg_num <= 14) {
|
||||||
|
armcpu->R[reg_num] = value;
|
||||||
|
}
|
||||||
|
else if ( reg_num == 15) {
|
||||||
|
armcpu->next_instruction = value;
|
||||||
|
}
|
||||||
|
else if ( reg_num == 16) {
|
||||||
|
/* FIXME: setting the CPSR */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
int armcpu_new( NDS_state *state, armcpu_t *armcpu, u32 id,
|
||||||
|
struct armcpu_memory_iface *mem_if,
|
||||||
|
struct armcpu_ctrl_iface **ctrl_iface_ret)
|
||||||
|
#else
|
||||||
|
int armcpu_new( NDS_state *state, armcpu_t *armcpu, u32 id)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
armcpu->state = state;
|
||||||
|
|
||||||
|
armcpu->proc_ID = id;
|
||||||
|
|
||||||
|
if(id==0)
|
||||||
|
armcpu->swi_tab = ARM9_swi_tab;
|
||||||
|
else
|
||||||
|
armcpu->swi_tab = ARM7_swi_tab;
|
||||||
|
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
armcpu->mem_if = mem_if;
|
||||||
|
|
||||||
|
/* populate the control interface */
|
||||||
|
armcpu->ctrl_iface.stall = stall_cpu;
|
||||||
|
armcpu->ctrl_iface.unstall = unstall_cpu;
|
||||||
|
armcpu->ctrl_iface.read_reg = read_cpu_reg;
|
||||||
|
armcpu->ctrl_iface.set_reg = set_cpu_reg;
|
||||||
|
armcpu->ctrl_iface.install_post_ex_fn = install_post_exec_fn;
|
||||||
|
armcpu->ctrl_iface.remove_post_ex_fn = remove_post_exec_fn;
|
||||||
|
armcpu->ctrl_iface.data = armcpu;
|
||||||
|
|
||||||
|
*ctrl_iface_ret = &armcpu->ctrl_iface;
|
||||||
|
|
||||||
|
armcpu->stalled = 0;
|
||||||
|
armcpu->post_ex_fn = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
armcpu_init(armcpu, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void armcpu_init(armcpu_t *armcpu, u32 adr)
|
||||||
|
{
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
armcpu->LDTBit = (armcpu->proc_ID==0); //Si ARM9 utiliser le syte v5 pour le load
|
||||||
|
armcpu->intVector = 0xFFFF0000 * (armcpu->proc_ID==0);
|
||||||
|
armcpu->waitIRQ = FALSE;
|
||||||
|
armcpu->wirq = FALSE;
|
||||||
|
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
armcpu->irq_flag = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(armcpu->coproc[15]) free(armcpu->coproc[15]);
|
||||||
|
|
||||||
|
for(i = 0; i < 15; ++i)
|
||||||
|
{
|
||||||
|
armcpu->R[i] = 0;
|
||||||
|
armcpu->coproc[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
armcpu->CPSR.val = armcpu->SPSR.val = SYS;
|
||||||
|
|
||||||
|
armcpu->R13_usr = armcpu->R14_usr = 0;
|
||||||
|
armcpu->R13_svc = armcpu->R14_svc = 0;
|
||||||
|
armcpu->R13_abt = armcpu->R14_abt = 0;
|
||||||
|
armcpu->R13_und = armcpu->R14_und = 0;
|
||||||
|
armcpu->R13_irq = armcpu->R14_irq = 0;
|
||||||
|
armcpu->R8_fiq = armcpu->R9_fiq = armcpu->R10_fiq = armcpu->R11_fiq = armcpu->R12_fiq = armcpu->R13_fiq = armcpu->R14_fiq = 0;
|
||||||
|
|
||||||
|
armcpu->SPSR_svc.val = armcpu->SPSR_abt.val = armcpu->SPSR_und.val = armcpu->SPSR_irq.val = armcpu->SPSR_fiq.val = 0;
|
||||||
|
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
armcpu->instruct_adr = adr;
|
||||||
|
armcpu->R[15] = adr + 8;
|
||||||
|
#else
|
||||||
|
armcpu->R[15] = adr;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
armcpu->next_instruction = adr;
|
||||||
|
|
||||||
|
armcpu->coproc[15] = (armcp_t*)armcp15_new(armcpu);
|
||||||
|
|
||||||
|
#ifndef GDB_STUB
|
||||||
|
armcpu_prefetch(armcpu);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 armcpu_switchMode(armcpu_t *armcpu, u8 mode)
|
||||||
|
{
|
||||||
|
u32 oldmode = armcpu->CPSR.bits.mode;
|
||||||
|
|
||||||
|
switch(oldmode)
|
||||||
|
{
|
||||||
|
case USR :
|
||||||
|
case SYS :
|
||||||
|
armcpu->R13_usr = armcpu->R[13];
|
||||||
|
armcpu->R14_usr = armcpu->R[14];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FIQ :
|
||||||
|
{
|
||||||
|
u32 tmp;
|
||||||
|
SWAP(armcpu->R[8], armcpu->R8_fiq, tmp);
|
||||||
|
SWAP(armcpu->R[9], armcpu->R9_fiq, tmp);
|
||||||
|
SWAP(armcpu->R[10], armcpu->R10_fiq, tmp);
|
||||||
|
SWAP(armcpu->R[11], armcpu->R11_fiq, tmp);
|
||||||
|
SWAP(armcpu->R[12], armcpu->R12_fiq, tmp);
|
||||||
|
armcpu->R13_fiq = armcpu->R[13];
|
||||||
|
armcpu->R14_fiq = armcpu->R[14];
|
||||||
|
armcpu->SPSR_fiq = armcpu->SPSR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IRQ :
|
||||||
|
armcpu->R13_irq = armcpu->R[13];
|
||||||
|
armcpu->R14_irq = armcpu->R[14];
|
||||||
|
armcpu->SPSR_irq = armcpu->SPSR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SVC :
|
||||||
|
armcpu->R13_svc = armcpu->R[13];
|
||||||
|
armcpu->R14_svc = armcpu->R[14];
|
||||||
|
armcpu->SPSR_svc = armcpu->SPSR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ABT :
|
||||||
|
armcpu->R13_abt = armcpu->R[13];
|
||||||
|
armcpu->R14_abt = armcpu->R[14];
|
||||||
|
armcpu->SPSR_abt = armcpu->SPSR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UND :
|
||||||
|
armcpu->R13_und = armcpu->R[13];
|
||||||
|
armcpu->R14_und = armcpu->R[14];
|
||||||
|
armcpu->SPSR_und = armcpu->SPSR;
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(mode)
|
||||||
|
{
|
||||||
|
case USR :
|
||||||
|
case SYS :
|
||||||
|
armcpu->R[13] = armcpu->R13_usr;
|
||||||
|
armcpu->R[14] = armcpu->R14_usr;
|
||||||
|
//SPSR = CPSR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FIQ :
|
||||||
|
{
|
||||||
|
u32 tmp;
|
||||||
|
SWAP(armcpu->R[8], armcpu->R8_fiq, tmp);
|
||||||
|
SWAP(armcpu->R[9], armcpu->R9_fiq, tmp);
|
||||||
|
SWAP(armcpu->R[10], armcpu->R10_fiq, tmp);
|
||||||
|
SWAP(armcpu->R[11], armcpu->R11_fiq, tmp);
|
||||||
|
SWAP(armcpu->R[12], armcpu->R12_fiq, tmp);
|
||||||
|
armcpu->R[13] = armcpu->R13_fiq;
|
||||||
|
armcpu->R[14] = armcpu->R14_fiq;
|
||||||
|
armcpu->SPSR = armcpu->SPSR_fiq;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IRQ :
|
||||||
|
armcpu->R[13] = armcpu->R13_irq;
|
||||||
|
armcpu->R[14] = armcpu->R14_irq;
|
||||||
|
armcpu->SPSR = armcpu->SPSR_irq;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SVC :
|
||||||
|
armcpu->R[13] = armcpu->R13_svc;
|
||||||
|
armcpu->R[14] = armcpu->R14_svc;
|
||||||
|
armcpu->SPSR = armcpu->SPSR_svc;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ABT :
|
||||||
|
armcpu->R[13] = armcpu->R13_abt;
|
||||||
|
armcpu->R[14] = armcpu->R14_abt;
|
||||||
|
armcpu->SPSR = armcpu->SPSR_abt;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UND :
|
||||||
|
armcpu->R[13] = armcpu->R13_und;
|
||||||
|
armcpu->R[14] = armcpu->R14_und;
|
||||||
|
armcpu->SPSR = armcpu->SPSR_und;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default :
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
armcpu->CPSR.bits.mode = mode & 0x1F;
|
||||||
|
return oldmode;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32
|
||||||
|
armcpu_prefetch(armcpu_t *armcpu)
|
||||||
|
{
|
||||||
|
u32 temp_instruction;
|
||||||
|
|
||||||
|
if(armcpu->CPSR.bits.T == 0)
|
||||||
|
{
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
temp_instruction =
|
||||||
|
armcpu->mem_if->prefetch32( armcpu->mem_if->data,
|
||||||
|
armcpu->next_instruction);
|
||||||
|
|
||||||
|
if ( !armcpu->stalled) {
|
||||||
|
armcpu->instruction = temp_instruction;
|
||||||
|
armcpu->instruct_adr = armcpu->next_instruction;
|
||||||
|
armcpu->next_instruction += 4;
|
||||||
|
armcpu->R[15] = armcpu->next_instruction + 4;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
armcpu->instruction = MMU_read32_acl(armcpu->state, armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE);
|
||||||
|
|
||||||
|
armcpu->instruct_adr = armcpu->next_instruction;
|
||||||
|
armcpu->next_instruction += 4;
|
||||||
|
armcpu->R[15] = armcpu->next_instruction + 4;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return armcpu->state->MMU->MMU_WAIT32[armcpu->proc_ID][(armcpu->instruct_adr>>24)&0xF];
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
temp_instruction =
|
||||||
|
armcpu->mem_if->prefetch16( armcpu->mem_if->data,
|
||||||
|
armcpu->next_instruction);
|
||||||
|
|
||||||
|
if ( !armcpu->stalled) {
|
||||||
|
armcpu->instruction = temp_instruction;
|
||||||
|
armcpu->instruct_adr = armcpu->next_instruction;
|
||||||
|
armcpu->next_instruction = armcpu->next_instruction + 2;
|
||||||
|
armcpu->R[15] = armcpu->next_instruction + 2;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
armcpu->instruction = MMU_read16_acl(armcpu->state, armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE);
|
||||||
|
|
||||||
|
armcpu->instruct_adr = armcpu->next_instruction;
|
||||||
|
armcpu->next_instruction += 2;
|
||||||
|
armcpu->R[15] = armcpu->next_instruction + 2;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return armcpu->state->MMU->MMU_WAIT16[armcpu->proc_ID][(armcpu->instruct_adr>>24)&0xF];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static BOOL FASTCALL test_EQ(Status_Reg CPSR) { return ( CPSR.bits.Z); }
|
||||||
|
static BOOL FASTCALL test_NE(Status_Reg CPSR) { return (!CPSR.bits.Z); }
|
||||||
|
static BOOL FASTCALL test_CS(Status_Reg CPSR) { return ( CPSR.bits.C); }
|
||||||
|
static BOOL FASTCALL test_CC(Status_Reg CPSR) { return (!CPSR.bits.C); }
|
||||||
|
static BOOL FASTCALL test_MI(Status_Reg CPSR) { return ( CPSR.bits.N); }
|
||||||
|
static BOOL FASTCALL test_PL(Status_Reg CPSR) { return (!CPSR.bits.N); }
|
||||||
|
static BOOL FASTCALL test_VS(Status_Reg CPSR) { return ( CPSR.bits.V); }
|
||||||
|
static BOOL FASTCALL test_VC(Status_Reg CPSR) { return (!CPSR.bits.V); }
|
||||||
|
static BOOL FASTCALL test_HI(Status_Reg CPSR) { return (CPSR.bits.C) && (!CPSR.bits.Z); }
|
||||||
|
static BOOL FASTCALL test_LS(Status_Reg CPSR) { return (CPSR.bits.Z) || (!CPSR.bits.C); }
|
||||||
|
static BOOL FASTCALL test_GE(Status_Reg CPSR) { return (CPSR.bits.N==CPSR.bits.V); }
|
||||||
|
static BOOL FASTCALL test_LT(Status_Reg CPSR) { return (CPSR.bits.N!=CPSR.bits.V); }
|
||||||
|
static BOOL FASTCALL test_GT(Status_Reg CPSR) { return (!CPSR.bits.Z) && (CPSR.bits.N==CPSR.bits.V); }
|
||||||
|
static BOOL FASTCALL test_LE(Status_Reg CPSR) { return ( CPSR.bits.Z) || (CPSR.bits.N!=CPSR.bits.V); }
|
||||||
|
static BOOL FASTCALL test_AL(Status_Reg CPSR) { return 1; }
|
||||||
|
|
||||||
|
static BOOL (FASTCALL* test_conditions[])(Status_Reg CPSR)= {
|
||||||
|
test_EQ , test_NE ,
|
||||||
|
test_CS , test_CC ,
|
||||||
|
test_MI , test_PL ,
|
||||||
|
test_VS , test_VC ,
|
||||||
|
test_HI , test_LS ,
|
||||||
|
test_GE , test_LT ,
|
||||||
|
test_GT , test_LE ,
|
||||||
|
test_AL
|
||||||
|
};
|
||||||
|
#define TEST_COND2(cond, CPSR) \
|
||||||
|
(cond<15&&test_conditions[cond](CPSR))
|
||||||
|
|
||||||
|
|
||||||
|
BOOL armcpu_irqExeption(armcpu_t *armcpu)
|
||||||
|
{
|
||||||
|
Status_Reg tmp;
|
||||||
|
|
||||||
|
if(armcpu->CPSR.bits.I) return FALSE;
|
||||||
|
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
armcpu->irq_flag = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
tmp = armcpu->CPSR;
|
||||||
|
armcpu_switchMode(armcpu, IRQ);
|
||||||
|
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
armcpu->R[14] = armcpu->next_instruction + 4;
|
||||||
|
#else
|
||||||
|
armcpu->R[14] = armcpu->instruct_adr + 4;
|
||||||
|
#endif
|
||||||
|
armcpu->SPSR = tmp;
|
||||||
|
armcpu->CPSR.bits.T = 0;
|
||||||
|
armcpu->CPSR.bits.I = 1;
|
||||||
|
armcpu->next_instruction = armcpu->intVector + 0x18;
|
||||||
|
armcpu->waitIRQ = 0;
|
||||||
|
|
||||||
|
#ifndef GDB_STUB
|
||||||
|
armcpu->R[15] = armcpu->next_instruction + 8;
|
||||||
|
armcpu_prefetch(armcpu);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
static BOOL armcpu_prefetchExeption(armcpu_t *armcpu)
|
||||||
|
{
|
||||||
|
Status_Reg tmp;
|
||||||
|
if(armcpu->CPSR.bits.I) return FALSE;
|
||||||
|
tmp = armcpu->CPSR;
|
||||||
|
armcpu_switchMode(armcpu, ABT);
|
||||||
|
armcpu->R[14] = armcpu->next_instruction + 4;
|
||||||
|
armcpu->SPSR = tmp;
|
||||||
|
armcpu->CPSR.bits.T = 0;
|
||||||
|
armcpu->CPSR.bits.I = 1;
|
||||||
|
armcpu->next_instruction = armcpu->intVector + 0xC;
|
||||||
|
armcpu->R[15] = armcpu->next_instruction + 8;
|
||||||
|
armcpu->waitIRQ = 0;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
static BOOL armcpu_prefetchExeption(armcpu_t *armcpu)
|
||||||
|
{
|
||||||
|
Status_Reg tmp;
|
||||||
|
if(armcpu->CPSR.bits.I) return FALSE;
|
||||||
|
tmp = armcpu->CPSR;
|
||||||
|
armcpu_switchMode(armcpu, ABT);
|
||||||
|
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
armcpu->R[14] = armcpu->next_instruction + 4;
|
||||||
|
#else
|
||||||
|
armcpu->R[14] = armcpu->instruct_adr + 4;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
armcpu->SPSR = tmp;
|
||||||
|
armcpu->CPSR.bits.T = 0;
|
||||||
|
armcpu->CPSR.bits.I = 1;
|
||||||
|
armcpu->next_instruction = armcpu->intVector + 0xC;
|
||||||
|
armcpu->waitIRQ = 0;
|
||||||
|
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
armcpu->R[15] = armcpu->next_instruction + 8;
|
||||||
|
#else
|
||||||
|
armcpu->R[15] = armcpu->next_instruction;
|
||||||
|
armcpu_prefetch(armcpu);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
armcpu_flagIrq( armcpu_t *armcpu) {
|
||||||
|
if(armcpu->CPSR.bits.I) return FALSE;
|
||||||
|
|
||||||
|
armcpu->waitIRQ = 0;
|
||||||
|
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
armcpu->irq_flag = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
u32 armcpu_exec(armcpu_t *armcpu)
|
||||||
|
{
|
||||||
|
u32 c = 1;
|
||||||
|
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
if ( armcpu->stalled)
|
||||||
|
return STALLED_CYCLE_COUNT;
|
||||||
|
|
||||||
|
/* check for interrupts */
|
||||||
|
if ( armcpu->irq_flag) {
|
||||||
|
armcpu_irqExeption( armcpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
c = armcpu_prefetch(armcpu);
|
||||||
|
|
||||||
|
if ( armcpu->stalled) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(armcpu->CPSR.bits.T == 0)
|
||||||
|
{
|
||||||
|
/* if((TEST_COND(CONDITION(armcpu->instruction), armcpu->CPSR)) || ((CONDITION(armcpu->instruction)==0xF)&&(CODE(armcpu->instruction)==0x5)))*/
|
||||||
|
if((TEST_COND(CONDITION(armcpu->instruction), CODE(armcpu->instruction), armcpu->CPSR)))
|
||||||
|
{
|
||||||
|
c += arm_instructions_set[INSTRUCTION_INDEX(armcpu->instruction)](armcpu);
|
||||||
|
}
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
if ( armcpu->post_ex_fn != NULL) {
|
||||||
|
/* call the external post execute function */
|
||||||
|
armcpu->post_ex_fn( armcpu->post_ex_fn_data,
|
||||||
|
armcpu->instruct_adr, 0);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
c += armcpu_prefetch(armcpu);
|
||||||
|
#endif
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
c += thumb_instructions_set[armcpu->instruction>>6](armcpu);
|
||||||
|
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
if ( armcpu->post_ex_fn != NULL) {
|
||||||
|
/* call the external post execute function */
|
||||||
|
armcpu->post_ex_fn( armcpu->post_ex_fn_data, armcpu->instruct_adr, 1);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
c += armcpu_prefetch(armcpu);
|
||||||
|
#endif
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,290 @@
|
||||||
|
/* Copyright (C) 2006 yopyop
|
||||||
|
yopyop156@ifrance.com
|
||||||
|
yopyop156.ifrance.com
|
||||||
|
|
||||||
|
This file is part of DeSmuME
|
||||||
|
|
||||||
|
DeSmuME is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
DeSmuME is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with DeSmuME; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ARM_CPU
|
||||||
|
#define ARM_CPU
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
#include "bits.h"
|
||||||
|
#include "MMU.h"
|
||||||
|
|
||||||
|
#include "state.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ARMCPU_ARM7 1
|
||||||
|
#define ARMCPU_ARM9 0
|
||||||
|
|
||||||
|
#define CODE(i) (((i)>>25)&0X7)
|
||||||
|
#define OPCODE(i) (((i)>>21)&0xF)
|
||||||
|
#define SIGNEBIT(i) BIT_N(i,20)
|
||||||
|
|
||||||
|
#define INSTRUCTION_INDEX(i) ((((i)>>16)&0xFF0)|(((i)>>4)&0xF))
|
||||||
|
|
||||||
|
#define ROR(i, j) ((((u32)(i))>>(j)) | (((u32)(i))<<(32-(j))))
|
||||||
|
|
||||||
|
#define UNSIGNED_OVERFLOW(a,b,c) ((BIT31(a)&BIT31(b)) | \
|
||||||
|
((BIT31(a)|BIT31(b))&BIT31(~c)))
|
||||||
|
|
||||||
|
#define UNSIGNED_UNDERFLOW(a,b,c) ((BIT31(~a)&BIT31(b)) | \
|
||||||
|
((BIT31(~a)|BIT31(b))&BIT31(c)))
|
||||||
|
|
||||||
|
#define SIGNED_OVERFLOW(a,b,c) ((BIT31(a)&BIT31(b)&BIT31(~c))|\
|
||||||
|
(BIT31(~a)&BIT31(~(b))&BIT31(c)))
|
||||||
|
|
||||||
|
#define SIGNED_UNDERFLOW(a,b,c) ((BIT31(a)&BIT31(~(b))&BIT31(~c))|\
|
||||||
|
(BIT31(~a)&BIT31(b)&BIT31(c)))
|
||||||
|
|
||||||
|
#define EQ 0x0
|
||||||
|
#define NE 0x1
|
||||||
|
#define CS 0x2
|
||||||
|
#define CC 0x3
|
||||||
|
#define MI 0x4
|
||||||
|
#define PL 0x5
|
||||||
|
#define VS 0x6
|
||||||
|
#define VC 0x7
|
||||||
|
#define HI 0x8
|
||||||
|
#define LS 0x9
|
||||||
|
#define GE 0xA
|
||||||
|
#define LT 0xB
|
||||||
|
#define GT 0xC
|
||||||
|
#define LE 0xD
|
||||||
|
#define AL 0xE
|
||||||
|
|
||||||
|
/*
|
||||||
|
#define TEST_COND(cond, CPSR) (((cond)==AL) ||\
|
||||||
|
(((cond)==EQ) && ( CPSR.bits.Z))||\
|
||||||
|
(((cond)==NE) && (!CPSR.bits.Z))||\
|
||||||
|
(((cond)==CS) && ( CPSR.bits.C))||\
|
||||||
|
(((cond)==CC) && (!CPSR.bits.C))||\
|
||||||
|
(((cond)==MI) && ( CPSR.bits.N))||\
|
||||||
|
(((cond)==PL) && (!CPSR.bits.N))||\
|
||||||
|
(((cond)==VS) && ( CPSR.bits.V))||\
|
||||||
|
(((cond)==VC) && (!CPSR.bits.V))||\
|
||||||
|
(((cond)==HI) && (CPSR.bits.C) && (!CPSR.bits.Z))||\
|
||||||
|
(((cond)==LS) && ((CPSR.bits.Z) || (!CPSR.bits.C)))||\
|
||||||
|
(((cond)==GE) && (CPSR.bits.N==CPSR.bits.V))||\
|
||||||
|
(((cond)==LT) && (CPSR.bits.N!=CPSR.bits.V))||\
|
||||||
|
(((cond)==GT) && (CPSR.bits.Z==0) && (CPSR.bits.N==CPSR.bits.V))||\
|
||||||
|
(((cond)==LE) && ((CPSR.bits.Z) || (CPSR.bits.N!=CPSR.bits.V))))
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern const unsigned char arm_cond_table[16*16];
|
||||||
|
|
||||||
|
#define TEST_COND(cond, inst, CPSR) ((arm_cond_table[((CPSR.val >> 24) & 0xf0)+(cond)] >> (inst)) & 1)
|
||||||
|
|
||||||
|
|
||||||
|
enum Mode
|
||||||
|
{
|
||||||
|
USR = 0x10,
|
||||||
|
FIQ = 0x11,
|
||||||
|
IRQ = 0x12,
|
||||||
|
SVC = 0x13,
|
||||||
|
ABT = 0x17,
|
||||||
|
UND = 0x1B,
|
||||||
|
SYS = 0x1F
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u32 N : 1,
|
||||||
|
Z : 1,
|
||||||
|
C : 1,
|
||||||
|
V : 1,
|
||||||
|
Q : 1,
|
||||||
|
RAZ : 19,
|
||||||
|
I : 1,
|
||||||
|
F : 1,
|
||||||
|
T : 1,
|
||||||
|
mode : 5;
|
||||||
|
} bits;
|
||||||
|
u32 val;
|
||||||
|
} Status_Reg;
|
||||||
|
#else
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u32 mode : 5,
|
||||||
|
T : 1,
|
||||||
|
F : 1,
|
||||||
|
I : 1,
|
||||||
|
RAZ : 19,
|
||||||
|
Q : 1,
|
||||||
|
V : 1,
|
||||||
|
C : 1,
|
||||||
|
Z : 1,
|
||||||
|
N : 1;
|
||||||
|
} bits;
|
||||||
|
u32 val;
|
||||||
|
} Status_Reg;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The control interface to a CPU
|
||||||
|
*/
|
||||||
|
struct armcpu_ctrl_iface {
|
||||||
|
/** stall the processor */
|
||||||
|
void (*stall)( void *instance);
|
||||||
|
|
||||||
|
/** unstall the processor */
|
||||||
|
void (*unstall)( void *instance);
|
||||||
|
|
||||||
|
/** read a register value */
|
||||||
|
u32 (*read_reg)( void *instance, u32 reg_num);
|
||||||
|
|
||||||
|
/** set a register value */
|
||||||
|
void (*set_reg)( void *instance, u32 reg_num, u32 value);
|
||||||
|
|
||||||
|
/** install the post execute function */
|
||||||
|
void (*install_post_ex_fn)( void *instance,
|
||||||
|
void (*fn)( void *, u32 adr, int thumb),
|
||||||
|
void *fn_data);
|
||||||
|
|
||||||
|
/** remove the post execute function */
|
||||||
|
void (*remove_post_ex_fn)( void *instance);
|
||||||
|
|
||||||
|
/** the private data passed to all interface functions */
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef void* armcp_t;
|
||||||
|
|
||||||
|
typedef struct armcpu_t
|
||||||
|
{
|
||||||
|
u32 proc_ID;
|
||||||
|
u32 instruction; //4
|
||||||
|
u32 instruct_adr; //8
|
||||||
|
u32 next_instruction; //12
|
||||||
|
|
||||||
|
u32 R[16]; //16
|
||||||
|
Status_Reg CPSR; //80
|
||||||
|
Status_Reg SPSR;
|
||||||
|
|
||||||
|
u32 R13_usr, R14_usr;
|
||||||
|
u32 R13_svc, R14_svc;
|
||||||
|
u32 R13_abt, R14_abt;
|
||||||
|
u32 R13_und, R14_und;
|
||||||
|
u32 R13_irq, R14_irq;
|
||||||
|
u32 R8_fiq, R9_fiq, R10_fiq, R11_fiq, R12_fiq, R13_fiq, R14_fiq;
|
||||||
|
Status_Reg SPSR_svc, SPSR_abt, SPSR_und, SPSR_irq, SPSR_fiq;
|
||||||
|
|
||||||
|
armcp_t *coproc[16];
|
||||||
|
|
||||||
|
u32 intVector;
|
||||||
|
u8 LDTBit; //1 : ARMv5 style 0 : non ARMv5
|
||||||
|
BOOL waitIRQ;
|
||||||
|
BOOL wIRQ;
|
||||||
|
BOOL wirq;
|
||||||
|
|
||||||
|
u32 (* *swi_tab)(struct armcpu_t * cpu);
|
||||||
|
|
||||||
|
NDS_state *state;
|
||||||
|
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
/** there is a pending irq for the cpu */
|
||||||
|
int irq_flag;
|
||||||
|
|
||||||
|
/** the post executed function (if installed) */
|
||||||
|
void (*post_ex_fn)( void *, u32 adr, int thumb);
|
||||||
|
|
||||||
|
/** data for the post executed function */
|
||||||
|
void *post_ex_fn_data;
|
||||||
|
|
||||||
|
|
||||||
|
/** flag indicating if the processor is stalled */
|
||||||
|
int stalled;
|
||||||
|
|
||||||
|
/** the memory interface */
|
||||||
|
struct armcpu_memory_iface *mem_if;
|
||||||
|
|
||||||
|
/** the ctrl interface */
|
||||||
|
struct armcpu_ctrl_iface ctrl_iface;
|
||||||
|
#endif
|
||||||
|
} armcpu_t;
|
||||||
|
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
int armcpu_new( NDS_state *, armcpu_t *armcpu, u32 id, struct armcpu_memory_iface *mem_if,
|
||||||
|
struct armcpu_ctrl_iface **ctrl_iface_ret);
|
||||||
|
#else
|
||||||
|
int armcpu_new( NDS_state *, armcpu_t *armcpu, u32 id);
|
||||||
|
#endif
|
||||||
|
void armcpu_init(armcpu_t *armcpu, u32 adr);
|
||||||
|
u32 armcpu_switchMode(armcpu_t *armcpu, u8 mode);
|
||||||
|
static u32 armcpu_prefetch(armcpu_t *armcpu);
|
||||||
|
u32 armcpu_exec(armcpu_t *armcpu);
|
||||||
|
BOOL armcpu_irqExeption(armcpu_t *armcpu);
|
||||||
|
//BOOL armcpu_prefetchExeption(armcpu_t *armcpu);
|
||||||
|
BOOL
|
||||||
|
armcpu_flagIrq( armcpu_t *armcpu);
|
||||||
|
|
||||||
|
|
||||||
|
static INLINE void NDS_makeARM9Int(NDS_state *state, u32 num)
|
||||||
|
{
|
||||||
|
/* flag the interrupt request source */
|
||||||
|
state->MMU->reg_IF[0] |= (1<<num);
|
||||||
|
|
||||||
|
/* generate the interrupt if enabled */
|
||||||
|
if ((state->MMU->reg_IE[0] & (1 << num)) && state->MMU->reg_IME[0])
|
||||||
|
{
|
||||||
|
state->NDS_ARM9->wIRQ = TRUE;
|
||||||
|
state->NDS_ARM9->waitIRQ = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE void NDS_makeARM7Int(NDS_state *state, u32 num)
|
||||||
|
{
|
||||||
|
/* flag the interrupt request source */
|
||||||
|
state->MMU->reg_IF[1] |= (1<<num);
|
||||||
|
|
||||||
|
/* generate the interrupt if enabled */
|
||||||
|
if ((state->MMU->reg_IE[1] & (1 << num)) && state->MMU->reg_IME[1])
|
||||||
|
{
|
||||||
|
state->NDS_ARM7->wIRQ = TRUE;
|
||||||
|
state->NDS_ARM7->waitIRQ = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE void NDS_makeInt(NDS_state *state, u8 proc_ID,u32 num)
|
||||||
|
{
|
||||||
|
switch (proc_ID)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
NDS_makeARM9Int(state, num) ;
|
||||||
|
break ;
|
||||||
|
case 1:
|
||||||
|
NDS_makeARM7Int(state, num) ;
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,32 @@
|
||||||
|
/* Copyright (C) 2006 yopyop
|
||||||
|
yopyop156@ifrance.com
|
||||||
|
yopyop156.ifrance.com
|
||||||
|
|
||||||
|
This file is part of DeSmuME
|
||||||
|
|
||||||
|
DeSmuME is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
DeSmuME is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with DeSmuME; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BIOS_H
|
||||||
|
#define BIOS_H
|
||||||
|
|
||||||
|
#include "armcpu.h"
|
||||||
|
|
||||||
|
extern u32 (* ARM9_swi_tab[32])(armcpu_t * cpu);
|
||||||
|
extern u32 (* ARM7_swi_tab[32])(armcpu_t * cpu);
|
||||||
|
extern u32 wait4IRQ(armcpu_t * cpu);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
#ifndef BITS_H
|
||||||
|
#define BITS_H
|
||||||
|
|
||||||
|
#define BIT(n) (1<<(n))
|
||||||
|
|
||||||
|
#define BIT_N(i,n) (((i)>>(n))&1)
|
||||||
|
#define BIT0(i) ((i)&1)
|
||||||
|
#define BIT1(i) BIT_N(i,1)
|
||||||
|
#define BIT2(i) BIT_N(i,2)
|
||||||
|
#define BIT3(i) BIT_N(i,3)
|
||||||
|
#define BIT4(i) BIT_N(i,4)
|
||||||
|
#define BIT5(i) BIT_N(i,5)
|
||||||
|
#define BIT6(i) BIT_N(i,6)
|
||||||
|
#define BIT7(i) BIT_N(i,7)
|
||||||
|
#define BIT8(i) BIT_N(i,8)
|
||||||
|
#define BIT9(i) BIT_N(i,9)
|
||||||
|
#define BIT10(i) BIT_N(i,10)
|
||||||
|
#define BIT11(i) BIT_N(i,11)
|
||||||
|
#define BIT12(i) BIT_N(i,12)
|
||||||
|
#define BIT13(i) BIT_N(i,13)
|
||||||
|
#define BIT14(i) BIT_N(i,14)
|
||||||
|
#define BIT15(i) BIT_N(i,15)
|
||||||
|
#define BIT16(i) BIT_N(i,16)
|
||||||
|
#define BIT17(i) BIT_N(i,17)
|
||||||
|
#define BIT18(i) BIT_N(i,18)
|
||||||
|
#define BIT19(i) BIT_N(i,19)
|
||||||
|
#define BIT20(i) BIT_N(i,20)
|
||||||
|
#define BIT21(i) BIT_N(i,21)
|
||||||
|
#define BIT22(i) BIT_N(i,22)
|
||||||
|
#define BIT23(i) BIT_N(i,23)
|
||||||
|
#define BIT24(i) BIT_N(i,24)
|
||||||
|
#define BIT25(i) BIT_N(i,25)
|
||||||
|
#define BIT26(i) BIT_N(i,26)
|
||||||
|
#define BIT27(i) BIT_N(i,27)
|
||||||
|
#define BIT28(i) BIT_N(i,28)
|
||||||
|
#define BIT29(i) BIT_N(i,29)
|
||||||
|
#define BIT30(i) BIT_N(i,30)
|
||||||
|
#define BIT31(i) ((i)>>31)
|
||||||
|
|
||||||
|
#define CONDITION(i) (i)>>28
|
||||||
|
|
||||||
|
#define REG_POS(i,n) (((i)>>n)&0xF)
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,28 @@
|
||||||
|
/* Copyright (C) 2006 thoduv
|
||||||
|
|
||||||
|
This file is part of DeSmuME
|
||||||
|
|
||||||
|
DeSmuME is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
DeSmuME is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with DeSmuME; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CONFIG_H__
|
||||||
|
#define __CONFIG_H__
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#endif /*__CONFIG_H__*/
|
||||||
|
|
|
@ -0,0 +1,592 @@
|
||||||
|
/* Copyright (C) 2006 yopyop
|
||||||
|
yopyop156@ifrance.com
|
||||||
|
yopyop156.ifrance.com
|
||||||
|
|
||||||
|
This file is part of DeSmuME
|
||||||
|
|
||||||
|
DeSmuME is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
DeSmuME is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with DeSmuME; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "cp15.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "MMU.h"
|
||||||
|
|
||||||
|
#include "state.h"
|
||||||
|
|
||||||
|
armcp15_t *armcp15_new(armcpu_t * c)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
armcp15_t *armcp15 = (armcp15_t*)malloc(sizeof(armcp15_t));
|
||||||
|
if(!armcp15) return NULL;
|
||||||
|
|
||||||
|
armcp15->cpu = c;
|
||||||
|
armcp15->IDCode = 0x41049460;
|
||||||
|
armcp15->cacheType = 0x0F0D2112;
|
||||||
|
armcp15->TCMSize = 0x00140140;
|
||||||
|
armcp15->ctrl = 0x00000000;
|
||||||
|
armcp15->DCConfig = 0x0;
|
||||||
|
armcp15->ICConfig = 0x0;
|
||||||
|
armcp15->writeBuffCtrl = 0x0;
|
||||||
|
armcp15->und = 0x0;
|
||||||
|
armcp15->DaccessPerm = 0x22222222;
|
||||||
|
armcp15->IaccessPerm = 0x22222222;
|
||||||
|
armcp15->protectBaseSize0 = 0x0;
|
||||||
|
armcp15->protectBaseSize1 = 0x0;
|
||||||
|
armcp15->protectBaseSize2 = 0x0;
|
||||||
|
armcp15->protectBaseSize3 = 0x0;
|
||||||
|
armcp15->protectBaseSize4 = 0x0;
|
||||||
|
armcp15->protectBaseSize5 = 0x0;
|
||||||
|
armcp15->protectBaseSize6 = 0x0;
|
||||||
|
armcp15->protectBaseSize7 = 0x0;
|
||||||
|
armcp15->cacheOp = 0x0;
|
||||||
|
armcp15->DcacheLock = 0x0;
|
||||||
|
armcp15->IcacheLock = 0x0;
|
||||||
|
armcp15->ITCMRegion = 0x0C;
|
||||||
|
armcp15->DTCMRegion = 0x0080000A;
|
||||||
|
armcp15->processID = 0;
|
||||||
|
|
||||||
|
/* preset calculated regionmasks */
|
||||||
|
for (i=0;i<8;i++) {
|
||||||
|
armcp15->regionWriteMask_USR[i] = 0 ;
|
||||||
|
armcp15->regionWriteMask_SYS[i] = 0 ;
|
||||||
|
armcp15->regionReadMask_USR[i] = 0 ;
|
||||||
|
armcp15->regionReadMask_SYS[i] = 0 ;
|
||||||
|
armcp15->regionExecuteMask_USR[i] = 0 ;
|
||||||
|
armcp15->regionExecuteMask_SYS[i] = 0 ;
|
||||||
|
armcp15->regionWriteSet_USR[i] = 0 ;
|
||||||
|
armcp15->regionWriteSet_SYS[i] = 0 ;
|
||||||
|
armcp15->regionReadSet_USR[i] = 0 ;
|
||||||
|
armcp15->regionReadSet_SYS[i] = 0 ;
|
||||||
|
armcp15->regionExecuteSet_USR[i] = 0 ;
|
||||||
|
armcp15->regionExecuteSet_SYS[i] = 0 ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
return armcp15;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ACCESSTYPE(val,n) (((val) >> (4*n)) & 0x0F)
|
||||||
|
#define SIZEIDENTIFIER(val) ((((val) >> 1) & 0x1F))
|
||||||
|
#define SIZEBINARY(val) (1 << (SIZEIDENTIFIER(val)+1))
|
||||||
|
#define MASKFROMREG(val) (~((SIZEBINARY(val)-1) | 0x3F))
|
||||||
|
#define SETFROMREG(val) ((val) & MASKFROMREG(val))
|
||||||
|
/* sets the precalculated regions to mask,set for the affected accesstypes */
|
||||||
|
void armcp15_setSingleRegionAccess(armcp15_t *armcp15,unsigned long dAccess,unsigned long iAccess,unsigned char num, unsigned long mask,unsigned long set) {
|
||||||
|
|
||||||
|
switch (ACCESSTYPE(dAccess,num)) {
|
||||||
|
case 4: /* UNP */
|
||||||
|
case 7: /* UNP */
|
||||||
|
case 8: /* UNP */
|
||||||
|
case 9: /* UNP */
|
||||||
|
case 10: /* UNP */
|
||||||
|
case 11: /* UNP */
|
||||||
|
case 12: /* UNP */
|
||||||
|
case 13: /* UNP */
|
||||||
|
case 14: /* UNP */
|
||||||
|
case 15: /* UNP */
|
||||||
|
case 0: /* no access at all */
|
||||||
|
armcp15->regionWriteMask_USR[num] = 0 ;
|
||||||
|
armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ;
|
||||||
|
armcp15->regionReadMask_USR[num] = 0 ;
|
||||||
|
armcp15->regionReadSet_USR[num] = 0xFFFFFFFF ;
|
||||||
|
armcp15->regionWriteMask_SYS[num] = 0 ;
|
||||||
|
armcp15->regionWriteSet_SYS[num] = 0xFFFFFFFF ;
|
||||||
|
armcp15->regionReadMask_SYS[num] = 0 ;
|
||||||
|
armcp15->regionReadSet_SYS[num] = 0xFFFFFFFF ;
|
||||||
|
break ;
|
||||||
|
case 1: /* no access at USR, all to sys */
|
||||||
|
armcp15->regionWriteMask_USR[num] = 0 ;
|
||||||
|
armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ;
|
||||||
|
armcp15->regionReadMask_USR[num] = 0 ;
|
||||||
|
armcp15->regionReadSet_USR[num] = 0xFFFFFFFF ;
|
||||||
|
armcp15->regionWriteMask_SYS[num] = mask ;
|
||||||
|
armcp15->regionWriteSet_SYS[num] = set ;
|
||||||
|
armcp15->regionReadMask_SYS[num] = mask ;
|
||||||
|
armcp15->regionReadSet_SYS[num] = set ;
|
||||||
|
break ;
|
||||||
|
case 2: /* read at USR, all to sys */
|
||||||
|
armcp15->regionWriteMask_USR[num] = 0 ;
|
||||||
|
armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ;
|
||||||
|
armcp15->regionReadMask_USR[num] = mask ;
|
||||||
|
armcp15->regionReadSet_USR[num] = set ;
|
||||||
|
armcp15->regionWriteMask_SYS[num] = mask ;
|
||||||
|
armcp15->regionWriteSet_SYS[num] = set ;
|
||||||
|
armcp15->regionReadMask_SYS[num] = mask ;
|
||||||
|
armcp15->regionReadSet_SYS[num] = set ;
|
||||||
|
break ;
|
||||||
|
case 3: /* all to USR, all to sys */
|
||||||
|
armcp15->regionWriteMask_USR[num] = mask ;
|
||||||
|
armcp15->regionWriteSet_USR[num] = set ;
|
||||||
|
armcp15->regionReadMask_USR[num] = mask ;
|
||||||
|
armcp15->regionReadSet_USR[num] = set ;
|
||||||
|
armcp15->regionWriteMask_SYS[num] = mask ;
|
||||||
|
armcp15->regionWriteSet_SYS[num] = set ;
|
||||||
|
armcp15->regionReadMask_SYS[num] = mask ;
|
||||||
|
armcp15->regionReadSet_SYS[num] = set ;
|
||||||
|
break ;
|
||||||
|
case 5: /* no access at USR, read to sys */
|
||||||
|
armcp15->regionWriteMask_USR[num] = 0 ;
|
||||||
|
armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ;
|
||||||
|
armcp15->regionReadMask_USR[num] = 0 ;
|
||||||
|
armcp15->regionReadSet_USR[num] = 0xFFFFFFFF ;
|
||||||
|
armcp15->regionWriteMask_SYS[num] = 0 ;
|
||||||
|
armcp15->regionWriteSet_SYS[num] = 0xFFFFFFFF ;
|
||||||
|
armcp15->regionReadMask_SYS[num] = mask ;
|
||||||
|
armcp15->regionReadSet_SYS[num] = set ;
|
||||||
|
break ;
|
||||||
|
case 6: /* read at USR, read to sys */
|
||||||
|
armcp15->regionWriteMask_USR[num] = 0 ;
|
||||||
|
armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ;
|
||||||
|
armcp15->regionReadMask_USR[num] = mask ;
|
||||||
|
armcp15->regionReadSet_USR[num] = set ;
|
||||||
|
armcp15->regionWriteMask_SYS[num] = 0 ;
|
||||||
|
armcp15->regionWriteSet_SYS[num] = 0xFFFFFFFF ;
|
||||||
|
armcp15->regionReadMask_SYS[num] = mask ;
|
||||||
|
armcp15->regionReadSet_SYS[num] = set ;
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
switch (ACCESSTYPE(iAccess,num)) {
|
||||||
|
case 4: /* UNP */
|
||||||
|
case 7: /* UNP */
|
||||||
|
case 8: /* UNP */
|
||||||
|
case 9: /* UNP */
|
||||||
|
case 10: /* UNP */
|
||||||
|
case 11: /* UNP */
|
||||||
|
case 12: /* UNP */
|
||||||
|
case 13: /* UNP */
|
||||||
|
case 14: /* UNP */
|
||||||
|
case 15: /* UNP */
|
||||||
|
case 0: /* no access at all */
|
||||||
|
armcp15->regionExecuteMask_USR[num] = 0 ;
|
||||||
|
armcp15->regionExecuteSet_USR[num] = 0xFFFFFFFF ;
|
||||||
|
armcp15->regionExecuteMask_SYS[num] = 0 ;
|
||||||
|
armcp15->regionExecuteSet_SYS[num] = 0xFFFFFFFF ;
|
||||||
|
break ;
|
||||||
|
case 1:
|
||||||
|
armcp15->regionExecuteMask_USR[num] = 0 ;
|
||||||
|
armcp15->regionExecuteSet_USR[num] = 0xFFFFFFFF ;
|
||||||
|
armcp15->regionExecuteMask_SYS[num] = mask ;
|
||||||
|
armcp15->regionExecuteSet_SYS[num] = set ;
|
||||||
|
break ;
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
case 6:
|
||||||
|
armcp15->regionExecuteMask_USR[num] = mask ;
|
||||||
|
armcp15->regionExecuteSet_USR[num] = set ;
|
||||||
|
armcp15->regionExecuteMask_SYS[num] = mask ;
|
||||||
|
armcp15->regionExecuteSet_SYS[num] = set ;
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* precalculate region masks/sets from cp15 register */
|
||||||
|
void armcp15_maskPrecalc(armcp15_t *armcp15)
|
||||||
|
{
|
||||||
|
#define precalc(num) { \
|
||||||
|
u32 mask = 0, set = 0xFFFFFFFF ; /* (x & 0) == 0xFF..FF is allways false (disabled) */ \
|
||||||
|
if (BIT_N(armcp15->protectBaseSize##num,0)) /* if region is enabled */ \
|
||||||
|
{ /* reason for this define: naming includes var */ \
|
||||||
|
mask = MASKFROMREG(armcp15->protectBaseSize##num) ; \
|
||||||
|
set = SETFROMREG(armcp15->protectBaseSize##num) ; \
|
||||||
|
if (SIZEIDENTIFIER(armcp15->protectBaseSize##num)==0x1F) \
|
||||||
|
{ /* for the 4GB region, u32 suffers wraparound */ \
|
||||||
|
mask = 0 ; set = 0 ; /* (x & 0) == 0 is allways true (enabled) */ \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
armcp15_setSingleRegionAccess(armcp15,armcp15->DaccessPerm,armcp15->IaccessPerm,num,mask,set) ; \
|
||||||
|
}
|
||||||
|
precalc(0) ;
|
||||||
|
precalc(1) ;
|
||||||
|
precalc(2) ;
|
||||||
|
precalc(3) ;
|
||||||
|
precalc(4) ;
|
||||||
|
precalc(5) ;
|
||||||
|
precalc(6) ;
|
||||||
|
precalc(7) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE BOOL armcp15_isAccessAllowed(armcp15_t *armcp15,u32 address,u32 access)
|
||||||
|
{
|
||||||
|
int i ;
|
||||||
|
if (!(armcp15->ctrl & 1)) return TRUE ; /* protection checking is not enabled */
|
||||||
|
for (i=0;i<8;i++) {
|
||||||
|
switch (access) {
|
||||||
|
case CP15_ACCESS_WRITEUSR:
|
||||||
|
if ((address & armcp15->regionWriteMask_USR[i]) == armcp15->regionWriteSet_USR[i]) return TRUE ;
|
||||||
|
break ;
|
||||||
|
case CP15_ACCESS_WRITESYS:
|
||||||
|
if ((address & armcp15->regionWriteMask_SYS[i]) == armcp15->regionWriteSet_SYS[i]) return TRUE ;
|
||||||
|
break ;
|
||||||
|
case CP15_ACCESS_READUSR:
|
||||||
|
if ((address & armcp15->regionReadMask_USR[i]) == armcp15->regionReadSet_USR[i]) return TRUE ;
|
||||||
|
break ;
|
||||||
|
case CP15_ACCESS_READSYS:
|
||||||
|
if ((address & armcp15->regionReadMask_SYS[i]) == armcp15->regionReadSet_SYS[i]) return TRUE ;
|
||||||
|
break ;
|
||||||
|
case CP15_ACCESS_EXECUSR:
|
||||||
|
if ((address & armcp15->regionExecuteMask_USR[i]) == armcp15->regionExecuteSet_USR[i]) return TRUE ;
|
||||||
|
break ;
|
||||||
|
case CP15_ACCESS_EXECSYS:
|
||||||
|
if ((address & armcp15->regionExecuteMask_SYS[i]) == armcp15->regionExecuteSet_SYS[i]) return TRUE ;
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* when protections are enabled, but no region allows access, deny access */
|
||||||
|
return FALSE ;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL armcp15_dataProcess(armcp15_t *armcp15, u8 CRd, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL armcp15_load(armcp15_t *armcp15, u8 CRd, u8 adr)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL armcp15_store(armcp15_t *armcp15, u8 CRd, u8 adr)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
|
||||||
|
{
|
||||||
|
if(armcp15->cpu->CPSR.bits.mode == USR) return FALSE;
|
||||||
|
|
||||||
|
switch(CRn)
|
||||||
|
{
|
||||||
|
case 0 :
|
||||||
|
if((opcode1 == 0)&&(CRm==0))
|
||||||
|
{
|
||||||
|
switch(opcode2)
|
||||||
|
{
|
||||||
|
case 1 :
|
||||||
|
*R = armcp15->cacheType;
|
||||||
|
return TRUE;
|
||||||
|
case 2 :
|
||||||
|
*R = armcp15->TCMSize;
|
||||||
|
return TRUE;
|
||||||
|
default :
|
||||||
|
*R = armcp15->IDCode;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
case 1 :
|
||||||
|
if((opcode1==0) && (opcode2==0) && (CRm==0))
|
||||||
|
{
|
||||||
|
*R = armcp15->ctrl;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
case 2 :
|
||||||
|
if((opcode1==0) && (CRm==0))
|
||||||
|
{
|
||||||
|
switch(opcode2)
|
||||||
|
{
|
||||||
|
case 0 :
|
||||||
|
*R = armcp15->DCConfig;
|
||||||
|
return TRUE;
|
||||||
|
case 1 :
|
||||||
|
*R = armcp15->ICConfig;
|
||||||
|
return TRUE;
|
||||||
|
default :
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
case 3 :
|
||||||
|
if((opcode1==0) && (opcode2==0) && (CRm==0))
|
||||||
|
{
|
||||||
|
*R = armcp15->writeBuffCtrl;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
case 5 :
|
||||||
|
if((opcode1==0) && (CRm==0))
|
||||||
|
{
|
||||||
|
switch(opcode2)
|
||||||
|
{
|
||||||
|
case 2 :
|
||||||
|
*R = armcp15->DaccessPerm;
|
||||||
|
return TRUE;
|
||||||
|
case 3 :
|
||||||
|
*R = armcp15->IaccessPerm;
|
||||||
|
return TRUE;
|
||||||
|
default :
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
case 6 :
|
||||||
|
if((opcode1==0) && (opcode2==0))
|
||||||
|
{
|
||||||
|
switch(CRm)
|
||||||
|
{
|
||||||
|
case 0 :
|
||||||
|
*R = armcp15->protectBaseSize0;
|
||||||
|
return TRUE;
|
||||||
|
case 1 :
|
||||||
|
*R = armcp15->protectBaseSize1;
|
||||||
|
return TRUE;
|
||||||
|
case 2 :
|
||||||
|
*R = armcp15->protectBaseSize2;
|
||||||
|
return TRUE;
|
||||||
|
case 3 :
|
||||||
|
*R = armcp15->protectBaseSize3;
|
||||||
|
return TRUE;
|
||||||
|
case 4 :
|
||||||
|
*R = armcp15->protectBaseSize4;
|
||||||
|
return TRUE;
|
||||||
|
case 5 :
|
||||||
|
*R = armcp15->protectBaseSize5;
|
||||||
|
return TRUE;
|
||||||
|
case 6 :
|
||||||
|
*R = armcp15->protectBaseSize6;
|
||||||
|
return TRUE;
|
||||||
|
case 7 :
|
||||||
|
*R = armcp15->protectBaseSize7;
|
||||||
|
return TRUE;
|
||||||
|
default :
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
case 9 :
|
||||||
|
if((opcode1==0))
|
||||||
|
{
|
||||||
|
switch(CRm)
|
||||||
|
{
|
||||||
|
case 0 :
|
||||||
|
switch(opcode2)
|
||||||
|
{
|
||||||
|
case 0 :
|
||||||
|
*R = armcp15->DcacheLock;
|
||||||
|
return TRUE;
|
||||||
|
case 1 :
|
||||||
|
*R = armcp15->IcacheLock;
|
||||||
|
return TRUE;
|
||||||
|
default :
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
case 1 :
|
||||||
|
switch(opcode2)
|
||||||
|
{
|
||||||
|
case 0 :
|
||||||
|
*R = armcp15->DTCMRegion;
|
||||||
|
return TRUE;
|
||||||
|
case 1 :
|
||||||
|
*R = armcp15->ITCMRegion;
|
||||||
|
return TRUE;
|
||||||
|
default :
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
default :
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
u32 CP15wait4IRQ(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
/* on the first call, wirq is not set */
|
||||||
|
if(cpu->wirq)
|
||||||
|
{
|
||||||
|
/* check wether an irq was issued */
|
||||||
|
if(!cpu->waitIRQ)
|
||||||
|
{
|
||||||
|
cpu->waitIRQ = 0;
|
||||||
|
cpu->wirq = 0;
|
||||||
|
return 1; /* return execution */
|
||||||
|
}
|
||||||
|
/* otherwise, repeat this instruction */
|
||||||
|
cpu->R[15] = cpu->instruct_adr;
|
||||||
|
cpu->next_instruction = cpu->R[15];
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* first run, set us into waiting state */
|
||||||
|
cpu->waitIRQ = 1;
|
||||||
|
cpu->wirq = 1;
|
||||||
|
/* and set next instruction to repeat this */
|
||||||
|
cpu->R[15] = cpu->instruct_adr;
|
||||||
|
cpu->next_instruction = cpu->R[15];
|
||||||
|
/* CHECKME: IME shouldn't be modified (?) */
|
||||||
|
cpu->state->MMU->reg_IME[0] = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
|
||||||
|
{
|
||||||
|
if(armcp15->cpu->CPSR.bits.mode == USR) return FALSE;
|
||||||
|
|
||||||
|
switch(CRn)
|
||||||
|
{
|
||||||
|
case 1 :
|
||||||
|
if((opcode1==0) && (opcode2==0) && (CRm==0))
|
||||||
|
{
|
||||||
|
armcp15->ctrl = val;
|
||||||
|
armcp15->cpu->state->MMU->ARM9_RW_MODE = BIT7(val);
|
||||||
|
armcp15->cpu->intVector = 0x0FFF0000 * (BIT13(val));
|
||||||
|
armcp15->cpu->LDTBit = !BIT15(val); //TBit
|
||||||
|
/*if(BIT17(val))
|
||||||
|
{
|
||||||
|
log::ajouter("outch !!!!!!!");
|
||||||
|
}
|
||||||
|
if(BIT19(val))
|
||||||
|
{
|
||||||
|
log::ajouter("outch !!!!!!!");
|
||||||
|
}*/
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
case 2 :
|
||||||
|
if((opcode1==0) && (CRm==0))
|
||||||
|
{
|
||||||
|
switch(opcode2)
|
||||||
|
{
|
||||||
|
case 0 :
|
||||||
|
armcp15->DCConfig = val;
|
||||||
|
return TRUE;
|
||||||
|
case 1 :
|
||||||
|
armcp15->ICConfig = val;
|
||||||
|
return TRUE;
|
||||||
|
default :
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
case 3 :
|
||||||
|
if((opcode1==0) && (opcode2==0) && (CRm==0))
|
||||||
|
{
|
||||||
|
armcp15->writeBuffCtrl = val;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
if((opcode1==0) && (CRm==0))
|
||||||
|
{
|
||||||
|
switch(opcode2)
|
||||||
|
{
|
||||||
|
case 2 :
|
||||||
|
armcp15->DaccessPerm = val;
|
||||||
|
armcp15_maskPrecalc(armcp15);
|
||||||
|
return TRUE;
|
||||||
|
case 3 :
|
||||||
|
armcp15->IaccessPerm = val;
|
||||||
|
armcp15_maskPrecalc(armcp15);
|
||||||
|
return TRUE;
|
||||||
|
default :
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
case 6 :
|
||||||
|
if((opcode1==0) && (opcode2==0))
|
||||||
|
{
|
||||||
|
switch(CRm)
|
||||||
|
{
|
||||||
|
case 0 :
|
||||||
|
armcp15->protectBaseSize0 = val;
|
||||||
|
armcp15_maskPrecalc(armcp15) ;
|
||||||
|
return TRUE;
|
||||||
|
case 1 :
|
||||||
|
armcp15->protectBaseSize1 = val;
|
||||||
|
armcp15_maskPrecalc(armcp15) ;
|
||||||
|
return TRUE;
|
||||||
|
case 2 :
|
||||||
|
armcp15->protectBaseSize2 = val;
|
||||||
|
armcp15_maskPrecalc(armcp15) ;
|
||||||
|
return TRUE;
|
||||||
|
case 3 :
|
||||||
|
armcp15->protectBaseSize3 = val;
|
||||||
|
armcp15_maskPrecalc(armcp15) ;
|
||||||
|
return TRUE;
|
||||||
|
case 4 :
|
||||||
|
armcp15->protectBaseSize4 = val;
|
||||||
|
armcp15_maskPrecalc(armcp15) ;
|
||||||
|
return TRUE;
|
||||||
|
case 5 :
|
||||||
|
armcp15->protectBaseSize5 = val;
|
||||||
|
armcp15_maskPrecalc(armcp15) ;
|
||||||
|
return TRUE;
|
||||||
|
case 6 :
|
||||||
|
armcp15->protectBaseSize6 = val;
|
||||||
|
armcp15_maskPrecalc(armcp15) ;
|
||||||
|
return TRUE;
|
||||||
|
case 7 :
|
||||||
|
armcp15->protectBaseSize7 = val;
|
||||||
|
armcp15_maskPrecalc(armcp15) ;
|
||||||
|
return TRUE;
|
||||||
|
default :
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
case 7 :
|
||||||
|
if((CRm==0)&&(opcode1==0)&&((opcode2==4)))
|
||||||
|
{
|
||||||
|
CP15wait4IRQ(armcp15->cpu);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
case 9 :
|
||||||
|
if((opcode1==0))
|
||||||
|
{
|
||||||
|
switch(CRm)
|
||||||
|
{
|
||||||
|
case 0 :
|
||||||
|
switch(opcode2)
|
||||||
|
{
|
||||||
|
case 0 :
|
||||||
|
armcp15->DcacheLock = val;
|
||||||
|
return TRUE;
|
||||||
|
case 1 :
|
||||||
|
armcp15->IcacheLock = val;
|
||||||
|
return TRUE;
|
||||||
|
default :
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
case 1 :
|
||||||
|
switch(opcode2)
|
||||||
|
{
|
||||||
|
case 0 :
|
||||||
|
armcp15->DTCMRegion = val;
|
||||||
|
armcp15->cpu->state->MMU->DTCMRegion = val & 0x0FFFFFFC0;
|
||||||
|
/*sprintf(logbuf, "%08X", val);
|
||||||
|
log::ajouter(logbuf);*/
|
||||||
|
return TRUE;
|
||||||
|
case 1 :
|
||||||
|
armcp15->ITCMRegion = val;
|
||||||
|
/* ITCM base is not writeable! */
|
||||||
|
armcp15->cpu->state->MMU->ITCMRegion = 0;
|
||||||
|
return TRUE;
|
||||||
|
default :
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
default :
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
/* Copyright (C) 2006 yopyop
|
||||||
|
yopyop156@ifrance.com
|
||||||
|
yopyop156.ifrance.com
|
||||||
|
|
||||||
|
This file is part of DeSmuME
|
||||||
|
|
||||||
|
DeSmuME is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
DeSmuME is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with DeSmuME; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CP15_H__
|
||||||
|
#define __CP15_H__
|
||||||
|
|
||||||
|
#include "armcpu.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u32 IDCode;
|
||||||
|
u32 cacheType;
|
||||||
|
u32 TCMSize;
|
||||||
|
u32 ctrl;
|
||||||
|
u32 DCConfig;
|
||||||
|
u32 ICConfig;
|
||||||
|
u32 writeBuffCtrl;
|
||||||
|
u32 und;
|
||||||
|
u32 DaccessPerm;
|
||||||
|
u32 IaccessPerm;
|
||||||
|
u32 protectBaseSize0;
|
||||||
|
u32 protectBaseSize1;
|
||||||
|
u32 protectBaseSize2;
|
||||||
|
u32 protectBaseSize3;
|
||||||
|
u32 protectBaseSize4;
|
||||||
|
u32 protectBaseSize5;
|
||||||
|
u32 protectBaseSize6;
|
||||||
|
u32 protectBaseSize7;
|
||||||
|
u32 cacheOp;
|
||||||
|
u32 DcacheLock;
|
||||||
|
u32 IcacheLock;
|
||||||
|
u32 ITCMRegion;
|
||||||
|
u32 DTCMRegion;
|
||||||
|
u32 processID;
|
||||||
|
u32 RAM_TAG;
|
||||||
|
u32 testState;
|
||||||
|
u32 cacheDbg;
|
||||||
|
/* calculated bitmasks for the regions to decide rights uppon */
|
||||||
|
/* calculation is done in the MCR instead of on mem access for performance */
|
||||||
|
u32 regionWriteMask_USR[8] ;
|
||||||
|
u32 regionWriteMask_SYS[8] ;
|
||||||
|
u32 regionReadMask_USR[8] ;
|
||||||
|
u32 regionReadMask_SYS[8] ;
|
||||||
|
u32 regionExecuteMask_USR[8] ;
|
||||||
|
u32 regionExecuteMask_SYS[8] ;
|
||||||
|
u32 regionWriteSet_USR[8] ;
|
||||||
|
u32 regionWriteSet_SYS[8] ;
|
||||||
|
u32 regionReadSet_USR[8] ;
|
||||||
|
u32 regionReadSet_SYS[8] ;
|
||||||
|
u32 regionExecuteSet_USR[8] ;
|
||||||
|
u32 regionExecuteSet_SYS[8] ;
|
||||||
|
|
||||||
|
armcpu_t * cpu;
|
||||||
|
|
||||||
|
} armcp15_t;
|
||||||
|
|
||||||
|
armcp15_t *armcp15_new(armcpu_t *c);
|
||||||
|
BOOL armcp15_dataProcess(armcp15_t *armcp15, u8 CRd, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2);
|
||||||
|
BOOL armcp15_load(armcp15_t *armcp15, u8 CRd, u8 adr);
|
||||||
|
BOOL armcp15_store(armcp15_t *armcp15, u8 CRd, u8 adr);
|
||||||
|
BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2);
|
||||||
|
BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2);
|
||||||
|
INLINE BOOL armcp15_isAccessAllowed(armcp15_t *armcp15,u32 address,u32 access) ;
|
||||||
|
|
||||||
|
|
||||||
|
#define CP15_ACCESS_WRITE 0
|
||||||
|
#define CP15_ACCESS_READ 2
|
||||||
|
#define CP15_ACCESS_EXECUTE 4
|
||||||
|
#define CP15_ACCESS_WRITEUSR CP15_ACCESS_WRITE
|
||||||
|
#define CP15_ACCESS_WRITESYS 1
|
||||||
|
#define CP15_ACCESS_READUSR CP15_ACCESS_READ
|
||||||
|
#define CP15_ACCESS_READSYS 3
|
||||||
|
#define CP15_ACCESS_EXECUSR CP15_ACCESS_EXECUTE
|
||||||
|
#define CP15_ACCESS_EXECSYS 5
|
||||||
|
|
||||||
|
#endif /* __CP15_H__*/
|
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef DEBUG_H
|
||||||
|
#define DEBUG_H
|
||||||
|
|
||||||
|
#define LOG(...)
|
||||||
|
#define GPULOG(...)
|
||||||
|
#define DIVLOG(...)
|
||||||
|
#define SQRTLOG(...)
|
||||||
|
#define CARDLOG(...)
|
||||||
|
#define DMALOG(...)
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,34 @@
|
||||||
|
/* Copyright (C) 2006 thoduv
|
||||||
|
|
||||||
|
This file is part of DeSmuME
|
||||||
|
|
||||||
|
DeSmuME is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
DeSmuME is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with DeSmuME; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DSCARD_H__
|
||||||
|
#define __DSCARD_H__
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
|
||||||
|
u32 adress;
|
||||||
|
u32 transfer_count;
|
||||||
|
|
||||||
|
} nds_dscard;
|
||||||
|
|
||||||
|
#endif /*__DSCARD_H__*/
|
||||||
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,257 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2006-2007 shash
|
||||||
|
|
||||||
|
This file is part of DeSmuME
|
||||||
|
|
||||||
|
DeSmuME is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
DeSmuME is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with DeSmuME; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "matrix.h"
|
||||||
|
|
||||||
|
void MatrixInit (float *matrix)
|
||||||
|
{
|
||||||
|
memset (matrix, 0, sizeof(float)*16);
|
||||||
|
|
||||||
|
matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatrixMultVec4x4 (float *matrix, float *vecPtr)
|
||||||
|
{
|
||||||
|
float x = vecPtr[0];
|
||||||
|
float y = vecPtr[1];
|
||||||
|
float z = vecPtr[2];
|
||||||
|
|
||||||
|
vecPtr[0] = x * matrix[0] + y * matrix[4] + z * matrix[ 8] + matrix[12];
|
||||||
|
vecPtr[1] = x * matrix[1] + y * matrix[5] + z * matrix[ 9] + matrix[13];
|
||||||
|
vecPtr[2] = x * matrix[2] + y * matrix[6] + z * matrix[10] + matrix[14];
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatrixMultVec3x3 (float *matrix, float *vecPtr)
|
||||||
|
{
|
||||||
|
float x = vecPtr[0];
|
||||||
|
float y = vecPtr[1];
|
||||||
|
float z = vecPtr[2];
|
||||||
|
|
||||||
|
vecPtr[0] = x * matrix[0] + y * matrix[4] + z * matrix[ 8];
|
||||||
|
vecPtr[1] = x * matrix[1] + y * matrix[5] + z * matrix[ 9];
|
||||||
|
vecPtr[2] = x * matrix[2] + y * matrix[6] + z * matrix[10];
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatrixIdentity (float *matrix)
|
||||||
|
{
|
||||||
|
memset (matrix, 0, sizeof(float)*16);
|
||||||
|
|
||||||
|
matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatrixMultiply (float *matrix, float *rightMatrix)
|
||||||
|
{
|
||||||
|
float tmpMatrix[16];
|
||||||
|
|
||||||
|
tmpMatrix[0] = (matrix[0]*rightMatrix[0])+(matrix[4]*rightMatrix[1])+(matrix[8]*rightMatrix[2])+(matrix[12]*rightMatrix[3]);
|
||||||
|
tmpMatrix[1] = (matrix[1]*rightMatrix[0])+(matrix[5]*rightMatrix[1])+(matrix[9]*rightMatrix[2])+(matrix[13]*rightMatrix[3]);
|
||||||
|
tmpMatrix[2] = (matrix[2]*rightMatrix[0])+(matrix[6]*rightMatrix[1])+(matrix[10]*rightMatrix[2])+(matrix[14]*rightMatrix[3]);
|
||||||
|
tmpMatrix[3] = (matrix[3]*rightMatrix[0])+(matrix[7]*rightMatrix[1])+(matrix[11]*rightMatrix[2])+(matrix[15]*rightMatrix[3]);
|
||||||
|
|
||||||
|
tmpMatrix[4] = (matrix[0]*rightMatrix[4])+(matrix[4]*rightMatrix[5])+(matrix[8]*rightMatrix[6])+(matrix[12]*rightMatrix[7]);
|
||||||
|
tmpMatrix[5] = (matrix[1]*rightMatrix[4])+(matrix[5]*rightMatrix[5])+(matrix[9]*rightMatrix[6])+(matrix[13]*rightMatrix[7]);
|
||||||
|
tmpMatrix[6] = (matrix[2]*rightMatrix[4])+(matrix[6]*rightMatrix[5])+(matrix[10]*rightMatrix[6])+(matrix[14]*rightMatrix[7]);
|
||||||
|
tmpMatrix[7] = (matrix[3]*rightMatrix[4])+(matrix[7]*rightMatrix[5])+(matrix[11]*rightMatrix[6])+(matrix[15]*rightMatrix[7]);
|
||||||
|
|
||||||
|
tmpMatrix[8] = (matrix[0]*rightMatrix[8])+(matrix[4]*rightMatrix[9])+(matrix[8]*rightMatrix[10])+(matrix[12]*rightMatrix[11]);
|
||||||
|
tmpMatrix[9] = (matrix[1]*rightMatrix[8])+(matrix[5]*rightMatrix[9])+(matrix[9]*rightMatrix[10])+(matrix[13]*rightMatrix[11]);
|
||||||
|
tmpMatrix[10] = (matrix[2]*rightMatrix[8])+(matrix[6]*rightMatrix[9])+(matrix[10]*rightMatrix[10])+(matrix[14]*rightMatrix[11]);
|
||||||
|
tmpMatrix[11] = (matrix[3]*rightMatrix[8])+(matrix[7]*rightMatrix[9])+(matrix[11]*rightMatrix[10])+(matrix[15]*rightMatrix[11]);
|
||||||
|
|
||||||
|
tmpMatrix[12] = (matrix[0]*rightMatrix[12])+(matrix[4]*rightMatrix[13])+(matrix[8]*rightMatrix[14])+(matrix[12]*rightMatrix[15]);
|
||||||
|
tmpMatrix[13] = (matrix[1]*rightMatrix[12])+(matrix[5]*rightMatrix[13])+(matrix[9]*rightMatrix[14])+(matrix[13]*rightMatrix[15]);
|
||||||
|
tmpMatrix[14] = (matrix[2]*rightMatrix[12])+(matrix[6]*rightMatrix[13])+(matrix[10]*rightMatrix[14])+(matrix[14]*rightMatrix[15]);
|
||||||
|
tmpMatrix[15] = (matrix[3]*rightMatrix[12])+(matrix[7]*rightMatrix[13])+(matrix[11]*rightMatrix[14])+(matrix[15]*rightMatrix[15]);
|
||||||
|
|
||||||
|
memcpy (matrix, tmpMatrix, sizeof(float)*16);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
void MatrixMulti (float* right)
|
||||||
|
{
|
||||||
|
float tmpMatrix[16];
|
||||||
|
|
||||||
|
tmpMatrix[0] = (matrix[0]*right[0])+(matrix[4]*right[1])+(matrix[8]*right[2])+(matrix[12]*right[3]);
|
||||||
|
tmpMatrix[1] = (matrix[1]*right[0])+(matrix[5]*right[1])+(matrix[9]*right[2])+(matrix[13]*right[3]);
|
||||||
|
tmpMatrix[2] = (matrix[2]*right[0])+(matrix[6]*right[1])+(matrix[10]*right[2])+(matrix[14]*right[3]);
|
||||||
|
tmpMatrix[3] = (matrix[3]*right[0])+(matrix[7]*right[1])+(matrix[11]*right[2])+(matrix[15]*right[3]);
|
||||||
|
|
||||||
|
tmpMatrix[4] = (matrix[0]*right[4])+(matrix[4]*right[5])+(matrix[8]*right[6])+(matrix[12]*right[7]);
|
||||||
|
tmpMatrix[5] = (matrix[1]*right[4])+(matrix[5]*right[5])+(matrix[9]*right[6])+(matrix[13]*right[7]);
|
||||||
|
tmpMatrix[6] = (matrix[2]*right[4])+(matrix[6]*right[5])+(matrix[10]*right[6])+(matrix[14]*right[7]);
|
||||||
|
tmpMatrix[7] = (matrix[3]*right[4])+(matrix[7]*right[5])+(matrix[11]*right[6])+(matrix[15]*right[7]);
|
||||||
|
|
||||||
|
tmpMatrix[8] = (matrix[0]*right[8])+(matrix[4]*right[9])+(matrix[8]*right[10])+(matrix[12]*right[11]);
|
||||||
|
tmpMatrix[9] = (matrix[1]*right[8])+(matrix[5]*right[9])+(matrix[9]*right[10])+(matrix[13]*right[11]);
|
||||||
|
tmpMatrix[10] = (matrix[2]*right[8])+(matrix[6]*right[9])+(matrix[10]*right[10])+(matrix[14]*right[11]);
|
||||||
|
tmpMatrix[11] = (matrix[3]*right[8])+(matrix[7]*right[9])+(matrix[11]*right[10])+(matrix[15]*right[11]);
|
||||||
|
|
||||||
|
tmpMatrix[12] = (matrix[0]*right[12])+(matrix[4]*right[13])+(matrix[8]*right[14])+(matrix[12]*right[15]);
|
||||||
|
tmpMatrix[13] = (matrix[1]*right[12])+(matrix[5]*right[13])+(matrix[9]*right[14])+(matrix[13]*right[15]);
|
||||||
|
tmpMatrix[14] = (matrix[2]*right[12])+(matrix[6]*right[13])+(matrix[10]*right[14])+(matrix[14]*right[15]);
|
||||||
|
tmpMatrix[15] = (matrix[3]*right[12])+(matrix[7]*right[13])+(matrix[11]*right[14])+(matrix[15]*right[15]);
|
||||||
|
|
||||||
|
memcpy (matrix, tmpMatrix, sizeof(float)*16);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float* Matrix::Get (void)
|
||||||
|
{
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
float MatrixGet (float *matrix, int index)
|
||||||
|
{
|
||||||
|
return matrix[index];
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
float MatrixGetMultipliedIndex (int index, float *matrix, float *rightMatrix)
|
||||||
|
{
|
||||||
|
int iMod = index%4, iDiv = (index>>2)<<2;
|
||||||
|
|
||||||
|
return (matrix[iMod ]*rightMatrix[iDiv ])+(matrix[iMod+ 4]*rightMatrix[iDiv+1])+
|
||||||
|
(matrix[iMod+8]*rightMatrix[iDiv+2])+(matrix[iMod+12]*rightMatrix[iDiv+3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatrixSet (float *matrix, int x, int y, float value)
|
||||||
|
{
|
||||||
|
matrix [x+(y<<2)] = value;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
void Matrix::Set (int pos, float value)
|
||||||
|
{
|
||||||
|
matrix [pos] = value;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
void MatrixCopy (float *matrixDST, float *matrixSRC)
|
||||||
|
{
|
||||||
|
memcpy (matrixDST, matrixSRC, sizeof(float)*16);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatrixTranslate (float *matrix, float *ptr)
|
||||||
|
{
|
||||||
|
matrix[12] += (matrix[0]*ptr[0])+(matrix[4]*ptr[1])+(matrix[ 8]*ptr[2]);
|
||||||
|
matrix[13] += (matrix[1]*ptr[0])+(matrix[5]*ptr[1])+(matrix[ 9]*ptr[2]);
|
||||||
|
matrix[14] += (matrix[2]*ptr[0])+(matrix[6]*ptr[1])+(matrix[10]*ptr[2]);
|
||||||
|
matrix[15] += (matrix[3]*ptr[0])+(matrix[7]*ptr[1])+(matrix[11]*ptr[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatrixScale (float *matrix, float *ptr)
|
||||||
|
{
|
||||||
|
matrix[0] *= ptr[0];
|
||||||
|
matrix[1] *= ptr[0];
|
||||||
|
matrix[2] *= ptr[0];
|
||||||
|
matrix[3] *= ptr[0];
|
||||||
|
|
||||||
|
matrix[4] *= ptr[1];
|
||||||
|
matrix[5] *= ptr[1];
|
||||||
|
matrix[6] *= ptr[1];
|
||||||
|
matrix[7] *= ptr[1];
|
||||||
|
|
||||||
|
matrix[8] *= ptr[2];
|
||||||
|
matrix[9] *= ptr[2];
|
||||||
|
matrix[10] *= ptr[2];
|
||||||
|
matrix[11] *= ptr[2];
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
void Matrix::Set (float a11, float a21, float a31, float a41,
|
||||||
|
float a12, float a22, float a32, float a42,
|
||||||
|
float a13, float a23, float a33, float a43,
|
||||||
|
float a14, float a24, float a34, float a44)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------
|
||||||
|
|
||||||
|
void MatrixStackInit (MatrixStack *stack)
|
||||||
|
{
|
||||||
|
stack->matrix = NULL;
|
||||||
|
stack->position = 0;
|
||||||
|
stack->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatrixStackSetMaxSize (MatrixStack *stack, int size)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
stack->size = size;
|
||||||
|
|
||||||
|
if (stack->matrix == NULL)
|
||||||
|
{
|
||||||
|
stack->matrix = (float*) malloc (stack->size*16*sizeof(float));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
free (stack->matrix);
|
||||||
|
stack->matrix = (float*) malloc (stack->size*16*sizeof(float));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < stack->size; i++)
|
||||||
|
{
|
||||||
|
MatrixInit (&stack->matrix[i*16]);
|
||||||
|
}
|
||||||
|
|
||||||
|
stack->size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MatrixStackSetStackPosition (MatrixStack *stack, int pos)
|
||||||
|
{
|
||||||
|
stack->position += pos;
|
||||||
|
|
||||||
|
if (stack->position < 0)
|
||||||
|
stack->position = 0;
|
||||||
|
else if (stack->position > stack->size)
|
||||||
|
stack->position = stack->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatrixStackPushMatrix (MatrixStack *stack, float *ptr)
|
||||||
|
{
|
||||||
|
MatrixCopy (&stack->matrix[stack->position*16], ptr);
|
||||||
|
|
||||||
|
MatrixStackSetStackPosition (stack, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
float * MatrixStackPopMatrix (MatrixStack *stack, int size)
|
||||||
|
{
|
||||||
|
MatrixStackSetStackPosition(stack, -size);
|
||||||
|
|
||||||
|
return &stack->matrix[stack->position*16];
|
||||||
|
}
|
||||||
|
|
||||||
|
float * MatrixStackGetPos (MatrixStack *stack, int pos)
|
||||||
|
{
|
||||||
|
return &stack->matrix[pos*16];
|
||||||
|
}
|
||||||
|
|
||||||
|
float * MatrixStackGet (MatrixStack *stack)
|
||||||
|
{
|
||||||
|
return &stack->matrix[stack->position*16];
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatrixStackLoadMatrix (MatrixStack *stack, int pos, float *ptr)
|
||||||
|
{
|
||||||
|
MatrixCopy (&stack->matrix[pos*16], ptr);
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2006-2007 shash
|
||||||
|
|
||||||
|
This file is part of DeSmuME
|
||||||
|
|
||||||
|
DeSmuME is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
DeSmuME is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with DeSmuME; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MATRIX_H
|
||||||
|
#define MATRIX_H
|
||||||
|
|
||||||
|
typedef struct MatrixStack
|
||||||
|
{
|
||||||
|
float *matrix;
|
||||||
|
int position;
|
||||||
|
int size;
|
||||||
|
} MatrixStack;
|
||||||
|
|
||||||
|
void MatrixInit (float *matrix);
|
||||||
|
void MatrixMultVec3x3 (float *matrix, float *vecPtr);
|
||||||
|
void MatrixMultVec4x4 (float *matrix, float *vecPtr);
|
||||||
|
void MatrixIdentity (float *matrix);
|
||||||
|
void MatrixMultiply (float *matrix, float *rightMatrix);
|
||||||
|
float MatrixGetMultipliedIndex(int index, float *matrix, float *rightMatrix);
|
||||||
|
void MatrixSet (float *matrix, int x, int y, float value);
|
||||||
|
void MatrixCopy (float *matrixDST, float *matrixSRC);
|
||||||
|
void MatrixTranslate (float *matrix, float *ptr);
|
||||||
|
void MatrixScale (float *matrix, float *ptr);
|
||||||
|
|
||||||
|
void MatrixStackInit (MatrixStack *stack);
|
||||||
|
void MatrixStackSetMaxSize (MatrixStack *stack, int size);
|
||||||
|
void MatrixStackSetStackPosition (MatrixStack *stack, int pos);
|
||||||
|
void MatrixStackPushMatrix (MatrixStack *stack, float *ptr);
|
||||||
|
float* MatrixStackPopMatrix (MatrixStack *stack, int size);
|
||||||
|
float* MatrixStackGetPos (MatrixStack *stack, int pos);
|
||||||
|
float* MatrixStackGet (MatrixStack *stack);
|
||||||
|
void MatrixStackLoadMatrix (MatrixStack *stack, int pos, float *ptr);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,121 @@
|
||||||
|
/* Copyright (C) 2006 thoduv
|
||||||
|
Copyright (C) 2006-2007 Theo Berkau
|
||||||
|
|
||||||
|
This file is part of DeSmuME
|
||||||
|
|
||||||
|
DeSmuME is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
DeSmuME is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with DeSmuME; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "debug.h"
|
||||||
|
#include "types.h"
|
||||||
|
#include "mc.h"
|
||||||
|
|
||||||
|
#define FW_CMD_READ 0x3
|
||||||
|
#define FW_CMD_WRITEDISABLE 0x4
|
||||||
|
#define FW_CMD_READSTATUS 0x5
|
||||||
|
#define FW_CMD_WRITEENABLE 0x6
|
||||||
|
#define FW_CMD_PAGEWRITE 0xA
|
||||||
|
|
||||||
|
#define BM_CMD_AUTODETECT 0xFF
|
||||||
|
#define BM_CMD_WRITESTATUS 0x1
|
||||||
|
#define BM_CMD_WRITELOW 0x2
|
||||||
|
#define BM_CMD_READLOW 0x3
|
||||||
|
#define BM_CMD_WRITEDISABLE 0x4
|
||||||
|
#define BM_CMD_READSTATUS 0x5
|
||||||
|
#define BM_CMD_WRITEENABLE 0x6
|
||||||
|
#define BM_CMD_WRITEHIGH 0xA
|
||||||
|
#define BM_CMD_READHIGH 0xB
|
||||||
|
|
||||||
|
/* FLASH*/
|
||||||
|
#define COMM_PAGE_WRITE 0x0A
|
||||||
|
#define COMM_PAGE_ERASE 0xDB
|
||||||
|
#define COMM_SECTOR_ERASE 0xD8
|
||||||
|
#define COMM_CHIP_ERASE 0xC7
|
||||||
|
#define CARDFLASH_READ_BYTES_FAST 0x0B /* Not used*/
|
||||||
|
#define CARDFLASH_DEEP_POWDOWN 0xB9 /* Not used*/
|
||||||
|
#define CARDFLASH_WAKEUP 0xAB /* Not used*/
|
||||||
|
|
||||||
|
void mc_init(memory_chip_t *mc, int type)
|
||||||
|
{
|
||||||
|
mc->com = 0;
|
||||||
|
mc->addr = 0;
|
||||||
|
mc->addr_shift = 0;
|
||||||
|
mc->data = NULL;
|
||||||
|
mc->size = 0;
|
||||||
|
mc->write_enable = FALSE;
|
||||||
|
mc->writeable_buffer = FALSE;
|
||||||
|
mc->type = type;
|
||||||
|
mc->autodetectsize = 0;
|
||||||
|
|
||||||
|
switch(mc->type)
|
||||||
|
{
|
||||||
|
case MC_TYPE_EEPROM1:
|
||||||
|
mc->addr_size = 1;
|
||||||
|
break;
|
||||||
|
case MC_TYPE_EEPROM2:
|
||||||
|
case MC_TYPE_FRAM:
|
||||||
|
mc->addr_size = 2;
|
||||||
|
break;
|
||||||
|
case MC_TYPE_FLASH:
|
||||||
|
mc->addr_size = 3;
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 *mc_alloc(memory_chip_t *mc, u32 size)
|
||||||
|
{
|
||||||
|
u8 *buffer;
|
||||||
|
buffer = malloc(size);
|
||||||
|
|
||||||
|
mc->data = buffer;
|
||||||
|
if(!buffer) { return NULL; }
|
||||||
|
mc->size = size;
|
||||||
|
mc->writeable_buffer = TRUE;
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mc_free(memory_chip_t *mc)
|
||||||
|
{
|
||||||
|
if(mc->data)
|
||||||
|
{
|
||||||
|
free(mc->data);
|
||||||
|
mc->data = 0;
|
||||||
|
}
|
||||||
|
mc_init(mc, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mc_realloc(memory_chip_t *mc, int type, u32 size)
|
||||||
|
{
|
||||||
|
mc_free(mc);
|
||||||
|
mc_init(mc, type);
|
||||||
|
mc_alloc(mc, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mc_reset_com(memory_chip_t *mc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
u8 fw_transfer(memory_chip_t *mc, u8 data)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
u8 bm_transfer(memory_chip_t *mc, u8 data)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
/* Copyright (C) 2006 thoduv
|
||||||
|
Copyright (C) 2006 Theo Berkau
|
||||||
|
|
||||||
|
This file is part of DeSmuME
|
||||||
|
|
||||||
|
DeSmuME is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
DeSmuME is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with DeSmuME; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FW_H__
|
||||||
|
#define __FW_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
#define MC_TYPE_AUTODETECT 0x0
|
||||||
|
#define MC_TYPE_EEPROM1 0x1
|
||||||
|
#define MC_TYPE_EEPROM2 0x2
|
||||||
|
#define MC_TYPE_FLASH 0x3
|
||||||
|
#define MC_TYPE_FRAM 0x4
|
||||||
|
|
||||||
|
#define MC_SIZE_4KBITS 0x000200
|
||||||
|
#define MC_SIZE_64KBITS 0x002000
|
||||||
|
#define MC_SIZE_256KBITS 0x008000
|
||||||
|
#define MC_SIZE_512KBITS 0x010000
|
||||||
|
#define MC_SIZE_1MBITS 0x020000
|
||||||
|
#define MC_SIZE_2MBITS 0x040000
|
||||||
|
#define MC_SIZE_4MBITS 0x080000
|
||||||
|
#define MC_SIZE_8MBITS 0x100000
|
||||||
|
#define MC_SIZE_16MBITS 0x200000
|
||||||
|
#define MC_SIZE_64MBITS 0x800000
|
||||||
|
|
||||||
|
static int save_types[6][2] = {
|
||||||
|
{MC_TYPE_AUTODETECT,1},
|
||||||
|
{MC_TYPE_EEPROM1,MC_SIZE_4KBITS},
|
||||||
|
{MC_TYPE_EEPROM2,MC_SIZE_64KBITS},
|
||||||
|
{MC_TYPE_EEPROM2,MC_SIZE_512KBITS},
|
||||||
|
{MC_TYPE_FLASH,MC_SIZE_256KBITS},
|
||||||
|
{MC_TYPE_FRAM,MC_SIZE_2MBITS}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u8 com; /* persistent command actually handled */
|
||||||
|
u32 addr; /* current address for reading/writing */
|
||||||
|
u8 addr_shift; /* shift for address (since addresses are transfered by 3 bytes units) */
|
||||||
|
u8 addr_size; /* size of addr when writing/reading */
|
||||||
|
|
||||||
|
BOOL write_enable; /* is write enabled ? */
|
||||||
|
|
||||||
|
u8 *data; /* memory data */
|
||||||
|
u32 size; /* memory size */
|
||||||
|
BOOL writeable_buffer; /* is "data" writeable ? */
|
||||||
|
int type; /* type of Memory */
|
||||||
|
char *filename;
|
||||||
|
FILE *fp;
|
||||||
|
u8 autodetectbuf[32768];
|
||||||
|
int autodetectsize;
|
||||||
|
} memory_chip_t;
|
||||||
|
|
||||||
|
#define NDS_FW_SIZE_V1 (256 * 1024) /* size of fw memory on nds v1 */
|
||||||
|
#define NDS_FW_SIZE_V2 (512 * 1024) /* size of fw memory on nds v2 */
|
||||||
|
|
||||||
|
void mc_init(memory_chip_t *mc, int type); /* reset and init values for memory struct */
|
||||||
|
u8 *mc_alloc(memory_chip_t *mc, u32 size); /* alloc mc memory */
|
||||||
|
void mc_realloc(memory_chip_t *mc, int type, u32 size); /* realloc mc memory */
|
||||||
|
void mc_load_file(memory_chip_t *mc, const char* filename); /* load save file and setup fp */
|
||||||
|
int mc_load_duc(memory_chip_t *mc, const char* filename); /* load Action Replay DS save file */
|
||||||
|
void mc_free(memory_chip_t *mc); /* delete mc memory */
|
||||||
|
void mc_reset_com(memory_chip_t *mc); /* reset communication with mc */
|
||||||
|
u8 fw_transfer(memory_chip_t *mc, u8 data); /* transfer to, then receive data from firmware */
|
||||||
|
u8 bm_transfer(memory_chip_t *mc, u8 data); /* transfer to, then receive data from backup memory */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*__FW_H__*/
|
||||||
|
|
|
@ -0,0 +1,141 @@
|
||||||
|
/* Copyright 2005-2006 Guillaume Duhamel
|
||||||
|
Copyright 2005 Theo Berkau
|
||||||
|
|
||||||
|
This file is part of Yabause.
|
||||||
|
|
||||||
|
Yabause is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Yabause is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Yabause; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MEM_H
|
||||||
|
#define MEM_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
/* Type 1 Memory, faster for byte (8 bits) accesses */
|
||||||
|
|
||||||
|
static INLINE u8 T1ReadByte(u8 * mem, u32 addr)
|
||||||
|
{
|
||||||
|
return mem[addr];
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE u16 T1ReadWord(u8 * mem, u32 addr)
|
||||||
|
{
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
return (mem[addr + 1] << 8) | mem[addr];
|
||||||
|
#else
|
||||||
|
return *((u16 *) (mem + addr));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE u32 T1ReadLong(u8 * mem, u32 addr)
|
||||||
|
{
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
return (mem[addr + 3] << 24 | mem[addr + 2] << 16 |
|
||||||
|
mem[addr + 1] << 8 | mem[addr]);
|
||||||
|
#else
|
||||||
|
return *((u32 *)mem + (addr>>2));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE u64 T1ReadQuad(u8 * mem, u32 addr)
|
||||||
|
{
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
return (mem[addr + 7] << 56 | mem[addr + 6] << 48 |
|
||||||
|
mem[addr + 5] << 40 | mem[addr + 4] << 32 |
|
||||||
|
mem[addr + 3] << 24 | mem[addr + 2] << 16 |
|
||||||
|
mem[addr + 1] << 8 | mem[addr]);
|
||||||
|
#else
|
||||||
|
return *((u64 *) (mem + addr));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE void T1WriteByte(u8 * mem, u32 addr, u8 val)
|
||||||
|
{
|
||||||
|
mem[addr] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE void T1WriteWord(u8 * mem, u32 addr, u16 val)
|
||||||
|
{
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
mem[addr + 1] = val >> 8;
|
||||||
|
mem[addr] = val & 0xFF;
|
||||||
|
#else
|
||||||
|
*((u16 *) (mem + addr)) = val;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE void T1WriteLong(u8 * mem, u32 addr, u32 val)
|
||||||
|
{
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
mem[addr + 3] = val >> 24;
|
||||||
|
mem[addr + 2] = (val >> 16) & 0xFF;
|
||||||
|
mem[addr + 1] = (val >> 8) & 0xFF;
|
||||||
|
mem[addr] = val & 0xFF;
|
||||||
|
#else
|
||||||
|
*((u32 *) (mem + addr)) = val;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Type 2 Memory, faster for word (16 bits) accesses */
|
||||||
|
|
||||||
|
static INLINE u8 T2ReadByte(u8 * mem, u32 addr)
|
||||||
|
{
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
return mem[addr ^ 1];
|
||||||
|
#else
|
||||||
|
return mem[addr];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE u16 T2ReadWord(u8 * mem, u32 addr)
|
||||||
|
{
|
||||||
|
return *((u16 *) (mem + addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE u32 T2ReadLong(u8 * mem, u32 addr)
|
||||||
|
{
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
return *((u16 *) (mem + addr + 2)) << 16 | *((u16 *) (mem + addr));
|
||||||
|
#else
|
||||||
|
return *((u32 *) (mem + addr));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE void T2WriteByte(u8 * mem, u32 addr, u8 val)
|
||||||
|
{
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
mem[addr ^ 1] = val;
|
||||||
|
#else
|
||||||
|
mem[addr] = val;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE void T2WriteWord(u8 * mem, u32 addr, u16 val)
|
||||||
|
{
|
||||||
|
*((u16 *) (mem + addr)) = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE void T2WriteLong(u8 * mem, u32 addr, u32 val)
|
||||||
|
{
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
*((u16 *) (mem + addr + 2)) = val >> 16;
|
||||||
|
*((u16 *) (mem + addr)) = val & 0xFFFF;
|
||||||
|
#else
|
||||||
|
*((u32 *) (mem + addr)) = val;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,333 @@
|
||||||
|
/* Copyright (C) 2006 Theo Berkau
|
||||||
|
|
||||||
|
Ideas borrowed from Stephane Dallongeville's SCSP core
|
||||||
|
|
||||||
|
This file is part of DeSmuME
|
||||||
|
|
||||||
|
DeSmuME is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
DeSmuME is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with DeSmuME; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef REGISTERS_H
|
||||||
|
#define REGISTERS_H
|
||||||
|
|
||||||
|
#define REG_REGION_MASK 0x0FFFEF80
|
||||||
|
#define REG_BASE_DISPx 0x04000000
|
||||||
|
#define REG_BASE_DISPA 0x04000000
|
||||||
|
#define REG_BASE_DISPB 0x04001000
|
||||||
|
#define REG_BASE_DMA 0x04000080
|
||||||
|
#define REG_BASE_SIORTCTIMERS 0x04000100
|
||||||
|
#define REG_BASE_ROMIPC 0x04000180
|
||||||
|
#define REG_BASE_MEMIRQ 0x04000200
|
||||||
|
#define REG_BASE_MATH 0x04000280
|
||||||
|
#define REG_BASE_OTHER 0x04000300
|
||||||
|
#define REG_BASE_RCVPORTS 0x04100000
|
||||||
|
|
||||||
|
// Display Engine A
|
||||||
|
#define REG_DISPA_DISPCNT 0x04000000
|
||||||
|
#define REG_DISPA_VCOUNT 0x04000006
|
||||||
|
#define REG_DISPA_BG0CNT 0x04000008
|
||||||
|
#define REG_DISPA_BG1CNT 0x0400000A
|
||||||
|
#define REG_DISPA_BG2CNT 0x0400000C
|
||||||
|
#define REG_DISPA_BG3CNT 0x0400000E
|
||||||
|
#define REG_DISPA_BG0HOFS 0x04000010
|
||||||
|
#define REG_DISPA_BG0VOFS 0x04000012
|
||||||
|
#define REG_DISPA_BG1HOFS 0x04000014
|
||||||
|
#define REG_DISPA_BG1VOFS 0x04000016
|
||||||
|
#define REG_DISPA_BG2HOFS 0x04000018
|
||||||
|
#define REG_DISPA_BG2VOFS 0x0400001A
|
||||||
|
#define REG_DISPA_BG3HOFS 0x0400001C
|
||||||
|
#define REG_DISPA_BG3VOFS 0x0400001E
|
||||||
|
#define REG_DISPA_BG2PA 0x04000020
|
||||||
|
#define REG_DISPA_BG2PB 0x04000022
|
||||||
|
#define REG_DISPA_BG2PC 0x04000024
|
||||||
|
#define REG_DISPA_BG2PD 0x04000026
|
||||||
|
#define REG_DISPA_BG2XL 0x04000028
|
||||||
|
#define REG_DISPA_BG2XH 0x0400002A
|
||||||
|
#define REG_DISPA_BG2YL 0x0400002C
|
||||||
|
#define REG_DISPA_BG2YH 0x0400002E
|
||||||
|
#define REG_DISPA_BG3PA 0x04000030
|
||||||
|
#define REG_DISPA_BG3PB 0x04000032
|
||||||
|
#define REG_DISPA_BG3PC 0x04000034
|
||||||
|
#define REG_DISPA_BG3PD 0x04000036
|
||||||
|
#define REG_DISPA_BG3XL 0x04000038
|
||||||
|
#define REG_DISPA_BG3XH 0x0400003A
|
||||||
|
#define REG_DISPA_BG3YL 0x0400003C
|
||||||
|
#define REG_DISPA_BG3YH 0x0400003E
|
||||||
|
#define REG_DISPA_WIN0H 0x04000040
|
||||||
|
#define REG_DISPA_WIN1H 0x04000042
|
||||||
|
#define REG_DISPA_WIN0V 0x04000044
|
||||||
|
#define REG_DISPA_WIN1V 0x04000046
|
||||||
|
#define REG_DISPA_WININ 0x04000048
|
||||||
|
#define REG_DISPA_WINOUT 0x0400004A
|
||||||
|
#define REG_DISPA_MOSAIC 0x0400004C
|
||||||
|
#define REG_DISPA_BLDCNT 0x04000050
|
||||||
|
#define REG_DISPA_BLDALPHA 0x04000052
|
||||||
|
#define REG_DISPA_BLDY 0x04000054
|
||||||
|
#define REG_DISPA_MASTERBRIGHT 0x0400006C
|
||||||
|
|
||||||
|
// DMA
|
||||||
|
#define REG_DMA0SAD 0x040000B0
|
||||||
|
#define REG_DMA0DAD 0x040000B4
|
||||||
|
#define REG_DMA0CNTL 0x040000B8
|
||||||
|
#define REG_DMA0CNTH 0x040000BA
|
||||||
|
#define REG_DMA1SAD 0x040000BC
|
||||||
|
#define REG_DMA1DAD 0x040000C0
|
||||||
|
#define REG_DMA1CNTL 0x040000C4
|
||||||
|
#define REG_DMA1CNTH 0x040000C6
|
||||||
|
#define REG_DMA2SAD 0x040000C8
|
||||||
|
#define REG_DMA2DAD 0x040000CC
|
||||||
|
#define REG_DMA2CNTL 0x040000D0
|
||||||
|
#define REG_DMA2CNTH 0x040000D2
|
||||||
|
#define REG_DMA3SAD 0x040000D4
|
||||||
|
#define REG_DMA3DAD 0x040000D8
|
||||||
|
#define REG_DMA3CNTL 0x040000DC
|
||||||
|
#define REG_DMA3CNTH 0x040000DE
|
||||||
|
#define REG_DMA0FILL 0x040000E0
|
||||||
|
#define REG_DMA1FILL 0x040000E4
|
||||||
|
#define REG_DMA2FILL 0x040000E8
|
||||||
|
#define REG_DMA3FILL 0x040000EC
|
||||||
|
|
||||||
|
// Timers
|
||||||
|
#define REG_TM0CNTL 0x04000100
|
||||||
|
#define REG_TM0CNTH 0x04000102
|
||||||
|
#define REG_TM1CNTL 0x04000104
|
||||||
|
#define REG_TM1CNTH 0x04000106
|
||||||
|
#define REG_TM2CNTL 0x04000108
|
||||||
|
#define REG_TM2CNTH 0x0400010A
|
||||||
|
#define REG_TM3CNTL 0x0400010C
|
||||||
|
#define REG_TM3CNTH 0x0400010E
|
||||||
|
|
||||||
|
// SIO/Keypad Input/RTC
|
||||||
|
#define REG_SIODATA32 0x04000120
|
||||||
|
#define REG_SIOCNT 0x04000128
|
||||||
|
#define REG_KEYINPUT 0x04000130
|
||||||
|
#define REG_KEYCNT 0x04000132
|
||||||
|
#define REG_RCNT 0x04000134
|
||||||
|
#define REG_EXTKEYIN 0x04000136
|
||||||
|
#define REG_RTC 0x04000138
|
||||||
|
|
||||||
|
// IPC
|
||||||
|
#define REG_IPCSYNC 0x04000180
|
||||||
|
#define REG_IPCFIFOCNT 0x04000184
|
||||||
|
#define REG_IPCFIFOSEND 0x04000188
|
||||||
|
|
||||||
|
// ROM
|
||||||
|
#define REG_AUXSPICNT 0x040001A0
|
||||||
|
#define REG_AUXSPIDATA 0x040001A2
|
||||||
|
#define REG_GCROMCTRL 0x040001A4
|
||||||
|
#define REG_GCCMDOUT 0x040001A8
|
||||||
|
#define REG_ENCSEED0L 0x040001B0
|
||||||
|
#define REG_ENCSEED1L 0x040001B4
|
||||||
|
#define REG_ENCSEED0H 0x040001B8
|
||||||
|
#define REG_ENCSEED1H 0x040001BC
|
||||||
|
#define REG_SPICNT 0x040001C0
|
||||||
|
#define REG_SPIDATA 0x040001C2
|
||||||
|
|
||||||
|
// Memory/IRQ
|
||||||
|
#define REG_EXMEMCNT 0x04000204
|
||||||
|
#define REG_WIFIWAITCNT 0x04000206
|
||||||
|
#define REG_IME 0x04000208
|
||||||
|
#define REG_IE 0x04000210
|
||||||
|
#define REG_IF 0x04000214
|
||||||
|
#define REG_VRAMCNTA 0x04000240
|
||||||
|
#define REG_VRAMSTAT 0x04000240
|
||||||
|
#define REG_VRAMCNTB 0x04000241
|
||||||
|
#define REG_WRAMSTAT 0x04000241
|
||||||
|
#define REG_VRAMCNTC 0x04000242
|
||||||
|
#define REG_VRAMCNTD 0x04000243
|
||||||
|
#define REG_VRAMCNTE 0x04000244
|
||||||
|
#define REG_VRAMCNTF 0x04000245
|
||||||
|
#define REG_VRAMCNTG 0x04000246
|
||||||
|
#define REG_WRAMCNT 0x04000247
|
||||||
|
#define REG_VRAMCNTH 0x04000248
|
||||||
|
#define REG_VRAMCNTI 0x04000249
|
||||||
|
|
||||||
|
// Math
|
||||||
|
#define REG_DIVCNT 0x04000280
|
||||||
|
#define REG_DIVNUMER 0x04000290
|
||||||
|
#define REG_DIVDENOM 0x04000298
|
||||||
|
#define REG_DIVRESULT 0x040002A0
|
||||||
|
#define REG_DIVREMRESULT 0x040002A8
|
||||||
|
#define REG_SQRTCNT 0x040002B0
|
||||||
|
#define REG_SQRTRESULT 0x040002B4
|
||||||
|
#define REG_SQRTPARAM 0x040002B8
|
||||||
|
|
||||||
|
// Other
|
||||||
|
#define REG_POSTFLG 0x04000300
|
||||||
|
#define REG_HALTCNT 0x04000301
|
||||||
|
#define REG_POWCNT1 0x04000304
|
||||||
|
#define REG_POWCNT2 0x04000304
|
||||||
|
#define REG_BIOSPROT 0x04000308
|
||||||
|
|
||||||
|
#define REG_DISPB_DISPCNT 0x04001000
|
||||||
|
#define REG_DISPB_BG0CNT 0x04001008
|
||||||
|
#define REG_DISPB_BG1CNT 0x0400100A
|
||||||
|
#define REG_DISPB_BG2CNT 0x0400100C
|
||||||
|
#define REG_DISPB_BG3CNT 0x0400100E
|
||||||
|
#define REG_DISPB_BG0HOFS 0x04001010
|
||||||
|
#define REG_DISPB_BG0VOFS 0x04001012
|
||||||
|
#define REG_DISPB_BG1HOFS 0x04001014
|
||||||
|
#define REG_DISPB_BG1VOFS 0x04001016
|
||||||
|
#define REG_DISPB_BG2HOFS 0x04001018
|
||||||
|
#define REG_DISPB_BG2VOFS 0x0400101A
|
||||||
|
#define REG_DISPB_BG3HOFS 0x0400101C
|
||||||
|
#define REG_DISPB_BG3VOFS 0x0400101E
|
||||||
|
#define REG_DISPB_BG2PA 0x04001020
|
||||||
|
#define REG_DISPB_BG2PB 0x04001022
|
||||||
|
#define REG_DISPB_BG2PC 0x04001024
|
||||||
|
#define REG_DISPB_BG2PD 0x04001026
|
||||||
|
#define REG_DISPB_BG2XL 0x04001028
|
||||||
|
#define REG_DISPB_BG2XH 0x0400102A
|
||||||
|
#define REG_DISPB_BG2YL 0x0400102C
|
||||||
|
#define REG_DISPB_BG2YH 0x0400102E
|
||||||
|
#define REG_DISPB_BG3PA 0x04001030
|
||||||
|
#define REG_DISPB_BG3PB 0x04001032
|
||||||
|
#define REG_DISPB_BG3PC 0x04001034
|
||||||
|
#define REG_DISPB_BG3PD 0x04001036
|
||||||
|
#define REG_DISPB_BG3XL 0x04001038
|
||||||
|
#define REG_DISPB_BG3XH 0x0400103A
|
||||||
|
#define REG_DISPB_BG3YL 0x0400103C
|
||||||
|
#define REG_DISPB_BG3YH 0x0400103E
|
||||||
|
#define REG_DISPB_WIN0H 0x04001040
|
||||||
|
#define REG_DISPB_WIN1H 0x04001042
|
||||||
|
#define REG_DISPB_WIN0V 0x04001044
|
||||||
|
#define REG_DISPB_WIN1V 0x04001046
|
||||||
|
#define REG_DISPB_WININ 0x04001048
|
||||||
|
#define REG_DISPB_WINOUT 0x0400104A
|
||||||
|
#define REG_DISPB_MOSAIC 0x0400104C
|
||||||
|
#define REG_DISPB_BLDCNT 0x04001050
|
||||||
|
#define REG_DISPB_BLDALPHA 0x04001052
|
||||||
|
#define REG_DISPB_BLDY 0x04001054
|
||||||
|
#define REG_DISPB_MASTERBRIGHT 0x0400106C
|
||||||
|
|
||||||
|
// Receive ports
|
||||||
|
#define REG_IPCFIFORECV 0x04100000
|
||||||
|
#define REG_GCDATAIN 0x04100010
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define REG_DISPB 0x00001000
|
||||||
|
// core A and B specific
|
||||||
|
#define REG_DISPx_DISPCNT 0x04000000
|
||||||
|
#define REG_DISPx_VCOUNT 0x04000006
|
||||||
|
#define REG_DISPx_BG0CNT 0x04000008
|
||||||
|
#define REG_DISPx_BG1CNT 0x0400000A
|
||||||
|
#define REG_DISPx_BG2CNT 0x0400000C
|
||||||
|
#define REG_DISPx_BG3CNT 0x0400000E
|
||||||
|
#define REG_DISPx_BG0HOFS 0x04000010
|
||||||
|
#define REG_DISPx_BG0VOFS 0x04000012
|
||||||
|
#define REG_DISPx_BG1HOFS 0x04000014
|
||||||
|
#define REG_DISPx_BG1VOFS 0x04000016
|
||||||
|
#define REG_DISPx_BG2HOFS 0x04000018
|
||||||
|
#define REG_DISPx_BG2VOFS 0x0400001A
|
||||||
|
#define REG_DISPx_BG3HOFS 0x0400001C
|
||||||
|
#define REG_DISPx_BG3VOFS 0x0400001E
|
||||||
|
#define REG_DISPx_BG2PA 0x04000020
|
||||||
|
#define REG_DISPx_BG2PB 0x04000022
|
||||||
|
#define REG_DISPx_BG2PC 0x04000024
|
||||||
|
#define REG_DISPx_BG2PD 0x04000026
|
||||||
|
#define REG_DISPx_BG2XL 0x04000028
|
||||||
|
#define REG_DISPx_BG2XH 0x0400002A
|
||||||
|
#define REG_DISPx_BG2YL 0x0400002C
|
||||||
|
#define REG_DISPx_BG2YH 0x0400002E
|
||||||
|
#define REG_DISPx_BG3PA 0x04000030
|
||||||
|
#define REG_DISPx_BG3PB 0x04000032
|
||||||
|
#define REG_DISPx_BG3PC 0x04000034
|
||||||
|
#define REG_DISPx_BG3PD 0x04000036
|
||||||
|
#define REG_DISPx_BG3XL 0x04000038
|
||||||
|
#define REG_DISPx_BG3XH 0x0400003A
|
||||||
|
#define REG_DISPx_BG3YL 0x0400003C
|
||||||
|
#define REG_DISPx_BG3YH 0x0400003E
|
||||||
|
#define REG_DISPx_WIN0H 0x04000040
|
||||||
|
#define REG_DISPx_WIN1H 0x04000042
|
||||||
|
#define REG_DISPx_WIN0V 0x04000044
|
||||||
|
#define REG_DISPx_WIN1V 0x04000046
|
||||||
|
#define REG_DISPx_WININ 0x04000048
|
||||||
|
#define REG_DISPx_WINOUT 0x0400004A
|
||||||
|
#define REG_DISPx_MOSAIC 0x0400004C
|
||||||
|
#define REG_DISPx_BLDCNT 0x04000050
|
||||||
|
#define REG_DISPx_BLDALPHA 0x04000052
|
||||||
|
#define REG_DISPx_BLDY 0x04000054
|
||||||
|
#define REG_DISPx_MASTERBRIGHT 0x0400006C
|
||||||
|
// core A specific
|
||||||
|
#define REG_DISPA_DISPSTAT 0x04000004
|
||||||
|
#define REG_DISPA_DISP3DCNT 0x04000060
|
||||||
|
#define REG_DISPA_DISPCAPCNT 0x04000064
|
||||||
|
#define REG_DISPA_DISPMMEMFIFO 0x04000068
|
||||||
|
|
||||||
|
|
||||||
|
#define eng_3D_RDLINES_COUNT 0x04000320
|
||||||
|
#define eng_3D_EDGE_COLOR 0x04000330
|
||||||
|
#define eng_3D_ALPHA_TEST_REF 0x04000340
|
||||||
|
#define eng_3D_CLEAR_COLOR 0x04000350
|
||||||
|
#define eng_3D_CLEAR_DEPTH 0x04000354
|
||||||
|
#define eng_3D_CLRIMAGE_OFFSET 0x04000356
|
||||||
|
#define eng_3D_FOG_COLOR 0x04000358
|
||||||
|
#define eng_3D_FOG_OFFSET 0x0400035C
|
||||||
|
#define eng_3D_FOG_TABLE 0x04000360
|
||||||
|
#define eng_3D_TOON_TABLE 0x04000380
|
||||||
|
#define eng_3D_GXFIFO 0x04000400
|
||||||
|
|
||||||
|
// 3d commands
|
||||||
|
#define cmd_3D_MTX_MODE 0x04000440
|
||||||
|
#define cmd_3D_MTX_PUSH 0x04000444
|
||||||
|
#define cmd_3D_MTX_POP 0x04000448
|
||||||
|
#define cmd_3D_MTX_STORE 0x0400044C
|
||||||
|
#define cmd_3D_MTX_RESTORE 0x04000450
|
||||||
|
#define cmd_3D_MTX_IDENTITY 0x04000454
|
||||||
|
#define cmd_3D_MTX_LOAD_4x4 0x04000458
|
||||||
|
#define cmd_3D_MTX_LOAD_4x3 0x0400045C
|
||||||
|
#define cmd_3D_MTX_MULT_4x4 0x04000460
|
||||||
|
#define cmd_3D_MTX_MULT_4x3 0x04000464
|
||||||
|
#define cmd_3D_MTX_MULT_3x3 0x04000468
|
||||||
|
#define cmd_3D_MTX_SCALE 0x0400046C
|
||||||
|
#define cmd_3D_MTX_TRANS 0x04000470
|
||||||
|
#define cmd_3D_COLOR 0x04000480
|
||||||
|
#define cmd_3D_NORMA 0x04000484
|
||||||
|
#define cmd_3D_TEXCOORD 0x04000488
|
||||||
|
#define cmd_3D_VTX_16 0x0400048C
|
||||||
|
#define cmd_3D_VTX_10 0x04000490
|
||||||
|
#define cmd_3D_VTX_XY 0x04000494
|
||||||
|
#define cmd_3D_VTX_XZ 0x04000498
|
||||||
|
#define cmd_3D_VTX_YZ 0x0400049C
|
||||||
|
#define cmd_3D_VTX_DIFF 0x040004A0
|
||||||
|
#define cmd_3D_POLYGON_ATTR 0x040004A4
|
||||||
|
#define cmd_3D_TEXIMAGE_PARAM 0x040004A8
|
||||||
|
#define cmd_3D_PLTT_BASE 0x040004AC
|
||||||
|
#define cmd_3D_DIF_AMB 0x040004C0
|
||||||
|
#define cmd_3D_SPE_EMI 0x040004C4
|
||||||
|
#define cmd_3D_LIGHT_VECTOR 0x040004C8
|
||||||
|
#define cmd_3D_LIGHT_COLOR 0x040004CC
|
||||||
|
#define cmd_3D_SHININESS 0x040004D0
|
||||||
|
#define cmd_3D_BEGIN_VTXS 0x04000500
|
||||||
|
#define cmd_3D_END_VTXS 0x04000504
|
||||||
|
#define cmd_3D_SWAP_BUFFERS 0x04000540
|
||||||
|
#define cmd_3D_VIEWPORT 0x04000580
|
||||||
|
#define cmd_3D_BOX_TEST 0x040005C0
|
||||||
|
#define cmd_3D_POS_TEST 0x040005C4
|
||||||
|
#define cmd_3D_VEC_TEST 0x040005C8
|
||||||
|
|
||||||
|
#define eng_3D_GXSTAT 0x04000600
|
||||||
|
#define eng_3D_RAM_COUNT 0x04000604
|
||||||
|
#define eng_3D_DISP_1DOT_DEPTH 0x04000610
|
||||||
|
#define eng_3D_POS_RESULT 0x04000620
|
||||||
|
#define eng_3D_VEC_RESULT 0x04000630
|
||||||
|
#define eng_3D_CLIPMTX_RESULT 0x04000640
|
||||||
|
#define eng_3D_VECMTX_RESULT 0x04000680
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef _SPU_EXPORTS_H
|
||||||
|
#define _SPU_EXPORTS_H
|
||||||
|
|
||||||
|
#ifndef _SPU_CPP_
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
typedef struct NDS_state NDS_state;
|
||||||
|
|
||||||
|
void SPU_WriteLong(NDS_state *, u32 addr, u32 val);
|
||||||
|
void SPU_WriteByte(NDS_state *, u32 addr, u8 val);
|
||||||
|
void SPU_WriteWord(NDS_state *, u32 addr, u16 val);
|
||||||
|
void SPU_EmulateSamples(NDS_state *, int numsamples);
|
||||||
|
int SPU_ChangeSoundCore(NDS_state *, int coreid, int buffersize);
|
||||||
|
void SPU_Reset(NDS_state *);
|
||||||
|
int SPU_Init(NDS_state *, int, int);
|
||||||
|
void SPU_DeInit(NDS_state *);
|
||||||
|
void SPU_Pause(NDS_state *state, int pause);
|
||||||
|
void SPU_SetVolume(NDS_state *state, int volume);
|
||||||
|
|
||||||
|
typedef struct SoundInterface_struct
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
const char *Name;
|
||||||
|
int (*Init)(NDS_state *, int buffersize);
|
||||||
|
void (*DeInit)(NDS_state *);
|
||||||
|
void (*UpdateAudio)(NDS_state *, s16 *buffer, u32 num_samples);
|
||||||
|
u32 (*GetAudioSpace)(NDS_state *);
|
||||||
|
void (*MuteAudio)(NDS_state *);
|
||||||
|
void (*UnMuteAudio)(NDS_state *);
|
||||||
|
void (*SetVolume)(NDS_state *, int volume);
|
||||||
|
} SoundInterface_struct;
|
||||||
|
|
||||||
|
#endif _SPU_CPP_
|
||||||
|
|
||||||
|
#endif //_SPU_EXPORTS_H
|
|
@ -0,0 +1,766 @@
|
||||||
|
//
|
||||||
|
// state.c
|
||||||
|
// vio2sf
|
||||||
|
//
|
||||||
|
// Created by Christopher Snowhill on 10/13/13.
|
||||||
|
// Copyright (c) 2013 Christopher Snowhill. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "NDSSystem.h"
|
||||||
|
#include "MMU.h"
|
||||||
|
#include "GPU.h"
|
||||||
|
#include "armcpu.h"
|
||||||
|
#include "cp15.h"
|
||||||
|
#include "spu_exports.h"
|
||||||
|
|
||||||
|
#include "state.h"
|
||||||
|
|
||||||
|
#define ROM_MASK 3
|
||||||
|
|
||||||
|
#define SNDCORE_DUMMY 0
|
||||||
|
#define SNDCORE_STATE 0
|
||||||
|
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
static struct armcpu_ctrl_iface *arm9_ctrl_iface = 0;
|
||||||
|
static struct armcpu_ctrl_iface *arm7_ctrl_iface = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int state_init(struct NDS_state *state)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
memset(state, 0, sizeof(NDS_state));
|
||||||
|
|
||||||
|
state->nds = (NDSSystem *) calloc(1, sizeof(NDSSystem));
|
||||||
|
if (!state->nds)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
state->NDS_ARM7 = (armcpu_t *) calloc(1, sizeof(armcpu_t));
|
||||||
|
if (!state->NDS_ARM7)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
state->NDS_ARM9 = (armcpu_t *) calloc(1, sizeof(armcpu_t));
|
||||||
|
if (!state->NDS_ARM9)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
state->MMU = (MMU_struct *) calloc(1, sizeof(MMU_struct));
|
||||||
|
if (!state->MMU)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
state->ARM9Mem = (ARM9_struct *) calloc(1, sizeof(ARM9_struct));
|
||||||
|
if (!state->ARM9Mem)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
state->MainScreen = (NDS_Screen *) calloc(1, sizeof(NDS_Screen));
|
||||||
|
if (!state->MainScreen)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
state->SubScreen = (NDS_Screen *) calloc(1, sizeof(NDS_Screen));
|
||||||
|
if (!state->SubScreen)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (i = 0; i < 0x10; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM9_MEM_MAP[i] = state->ARM9Mem->ARM9_ITCM;
|
||||||
|
state->MMU_ARM9_MEM_MASK[i] = 0x00007FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0x20; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM9_MEM_MAP[i] = state->ARM9Mem->ARM9_WRAM;
|
||||||
|
state->MMU_ARM9_MEM_MASK[i] = 0x00FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0x30; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM9_MEM_MAP[i] = state->ARM9Mem->MAIN_MEM;
|
||||||
|
state->MMU_ARM9_MEM_MASK[i] = 0x003FFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0x40; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM9_MEM_MAP[i] = state->MMU->SWIRAM;
|
||||||
|
state->MMU_ARM9_MEM_MASK[i] = 0x00007FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0x50; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM9_MEM_MAP[i] = state->ARM9Mem->ARM9_REG;
|
||||||
|
state->MMU_ARM9_MEM_MASK[i] = 0x00FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0x60; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM9_MEM_MAP[i] = state->ARM9Mem->ARM9_VMEM;
|
||||||
|
state->MMU_ARM9_MEM_MASK[i] = 0x000007FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0x62; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM9_MEM_MAP[i] = state->ARM9Mem->ARM9_ABG;
|
||||||
|
state->MMU_ARM9_MEM_MASK[i] = 0x0007FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0x64; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM9_MEM_MAP[i] = state->ARM9Mem->ARM9_BBG;
|
||||||
|
state->MMU_ARM9_MEM_MASK[i] = 0x0001FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0x66; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM9_MEM_MAP[i] = state->ARM9Mem->ARM9_AOBJ;
|
||||||
|
state->MMU_ARM9_MEM_MASK[i] = 0x0003FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0x68; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM9_MEM_MAP[i] = state->ARM9Mem->ARM9_BOBJ;
|
||||||
|
state->MMU_ARM9_MEM_MASK[i] = 0x0001FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0x70; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM9_MEM_MAP[i] = state->ARM9Mem->ARM9_OAM;
|
||||||
|
state->MMU_ARM9_MEM_MASK[i] = 0x000FFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0x80; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM9_MEM_MAP[i] = state->ARM9Mem->ARM9_OAM;
|
||||||
|
state->MMU_ARM9_MEM_MASK[i] = 0x000007FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0xA0; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM9_MEM_MAP[i] = NULL;
|
||||||
|
state->MMU_ARM9_MEM_MASK[i] = ROM_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0xB0; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM9_MEM_MAP[i] = state->MMU->CART_RAM;
|
||||||
|
state->MMU_ARM9_MEM_MASK[i] = 0x0000FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0xF0; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM9_MEM_MAP[i] = state->MMU->UNUSED_RAM;
|
||||||
|
state->MMU_ARM9_MEM_MASK[i] = 0x00000003;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0x100; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM9_MEM_MAP[i] = state->ARM9Mem->ARM9_BIOS;
|
||||||
|
state->MMU_ARM9_MEM_MASK[i] = 0x00007FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 0x10; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM7_MEM_MAP[i] = state->MMU->ARM7_BIOS;
|
||||||
|
state->MMU_ARM7_MEM_MASK[i] = 0x00003FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0x20; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM7_MEM_MAP[i] = state->MMU->UNUSED_RAM;
|
||||||
|
state->MMU_ARM7_MEM_MASK[i] = 0x00000003;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0x30; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM7_MEM_MAP[i] = state->ARM9Mem->MAIN_MEM;
|
||||||
|
state->MMU_ARM7_MEM_MASK[i] = 0x003FFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0x38; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM7_MEM_MAP[i] = state->MMU->SWIRAM;
|
||||||
|
state->MMU_ARM7_MEM_MASK[i] = 0x00007FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0x40; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM7_MEM_MAP[i] = state->MMU->ARM7_ERAM;
|
||||||
|
state->MMU_ARM7_MEM_MASK[i] = 0x0000FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0x48; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM7_MEM_MAP[i] = state->MMU->ARM7_REG;
|
||||||
|
state->MMU_ARM7_MEM_MASK[i] = 0x00FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0x50; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM7_MEM_MAP[i] = state->MMU->ARM7_WIRAM;
|
||||||
|
state->MMU_ARM7_MEM_MASK[i] = 0x0000FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0x60; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM7_MEM_MAP[i] = state->MMU->UNUSED_RAM;
|
||||||
|
state->MMU_ARM7_MEM_MASK[i] = 0x00000003;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0x70; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM7_MEM_MAP[i] = state->ARM9Mem->ARM9_ABG;
|
||||||
|
state->MMU_ARM7_MEM_MASK[i] = 0x0003FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0x80; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM7_MEM_MAP[i] = state->MMU->UNUSED_RAM;
|
||||||
|
state->MMU_ARM7_MEM_MASK[i] = 0x00000003;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0xA0; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM7_MEM_MAP[i] = NULL;
|
||||||
|
state->MMU_ARM7_MEM_MASK[i] = ROM_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0xB0; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM7_MEM_MAP[i] = state->MMU->CART_RAM;
|
||||||
|
state->MMU_ARM7_MEM_MASK[i] = 0x0000FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 0x100; ++i)
|
||||||
|
{
|
||||||
|
state->MMU_ARM7_MEM_MAP[i] = state->MMU->UNUSED_RAM;
|
||||||
|
state->MMU_ARM7_MEM_MASK[i] = 0x00000003;
|
||||||
|
}
|
||||||
|
|
||||||
|
state->partie = 1;
|
||||||
|
|
||||||
|
state->SPU_currentCoreNum = SNDCORE_DUMMY;
|
||||||
|
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
if (NDS_Init(state, &arm9_base_memory_iface, &arm9_ctrl_iface, &arm7_base_memory_iface, &arm7_ctrl_iface))
|
||||||
|
#else
|
||||||
|
if (NDS_Init(state))
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
SPU_ChangeSoundCore(state, 0, 44100);
|
||||||
|
|
||||||
|
state->execute = FALSE;
|
||||||
|
|
||||||
|
MMU_unsetRom(state);
|
||||||
|
|
||||||
|
state->cycles = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void state_deinit(struct NDS_state *state)
|
||||||
|
{
|
||||||
|
MMU_unsetRom(state);
|
||||||
|
NDS_DeInit(state);
|
||||||
|
if (state->nds) free(state->nds);
|
||||||
|
state->nds = NULL;
|
||||||
|
if (state->NDS_ARM7) free(state->NDS_ARM7);
|
||||||
|
state->NDS_ARM7 = NULL;
|
||||||
|
if (state->NDS_ARM9) free(state->NDS_ARM9);
|
||||||
|
state->NDS_ARM9 = NULL;
|
||||||
|
if (state->MMU) free(state->MMU);
|
||||||
|
state->MMU = NULL;
|
||||||
|
if (state->ARM9Mem) free(state->ARM9Mem);
|
||||||
|
state->ARM9Mem = NULL;
|
||||||
|
if (state->MainScreen) free(state->MainScreen);
|
||||||
|
state->MainScreen = NULL;
|
||||||
|
if (state->SubScreen) free(state->SubScreen);
|
||||||
|
state->SubScreen = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void state_setrom(struct NDS_state *state, const u8 * rom, u32 rom_size)
|
||||||
|
{
|
||||||
|
assert(!(rom_size & (rom_size - 1)));
|
||||||
|
NDS_SetROM(state, rom, rom_size - 1);
|
||||||
|
NDS_Reset(state);
|
||||||
|
state->execute = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void load_setstate(struct NDS_state *state, const u8 *ss, u32 ss_size);
|
||||||
|
|
||||||
|
void state_loadstate(struct NDS_state *state, const u8 *ss, u32 ss_size)
|
||||||
|
{
|
||||||
|
if (ss && ss_size)
|
||||||
|
{
|
||||||
|
armcp15_t *c9 = (armcp15_t *)state->NDS_ARM9->coproc[15];
|
||||||
|
int proc;
|
||||||
|
if (state->initial_frames == -1)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* set initial ARM9 coprocessor state */
|
||||||
|
|
||||||
|
armcp15_moveARM2CP(c9, 0x00000000, 0x01, 0x00, 0, 0);
|
||||||
|
armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x05, 0, 0);
|
||||||
|
armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x06, 0, 0);
|
||||||
|
armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x0a, 0, 4);
|
||||||
|
armcp15_moveARM2CP(c9, 0x04000033, 0x06, 0x00, 0, 4);
|
||||||
|
armcp15_moveARM2CP(c9, 0x0200002d, 0x06, 0x01, 0, 0);
|
||||||
|
armcp15_moveARM2CP(c9, 0x027e0021, 0x06, 0x02, 0, 0);
|
||||||
|
armcp15_moveARM2CP(c9, 0x08000035, 0x06, 0x03, 0, 0);
|
||||||
|
armcp15_moveARM2CP(c9, 0x027e001b, 0x06, 0x04, 0, 0);
|
||||||
|
armcp15_moveARM2CP(c9, 0x0100002f, 0x06, 0x05, 0, 0);
|
||||||
|
armcp15_moveARM2CP(c9, 0xffff001d, 0x06, 0x06, 0, 0);
|
||||||
|
armcp15_moveARM2CP(c9, 0x027ff017, 0x06, 0x07, 0, 0);
|
||||||
|
armcp15_moveARM2CP(c9, 0x00000020, 0x09, 0x01, 0, 1);
|
||||||
|
|
||||||
|
armcp15_moveARM2CP(c9, 0x027e000a, 0x09, 0x01, 0, 0);
|
||||||
|
|
||||||
|
armcp15_moveARM2CP(c9, 0x00000042, 0x02, 0x00, 0, 1);
|
||||||
|
armcp15_moveARM2CP(c9, 0x00000042, 0x02, 0x00, 0, 0);
|
||||||
|
armcp15_moveARM2CP(c9, 0x00000002, 0x03, 0x00, 0, 0);
|
||||||
|
armcp15_moveARM2CP(c9, 0x05100011, 0x05, 0x00, 0, 3);
|
||||||
|
armcp15_moveARM2CP(c9, 0x15111011, 0x05, 0x00, 0, 2);
|
||||||
|
armcp15_moveARM2CP(c9, 0x07dd1e10, 0x01, 0x00, 0, 0);
|
||||||
|
armcp15_moveARM2CP(c9, 0x0005707d, 0x01, 0x00, 0, 0);
|
||||||
|
|
||||||
|
armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x0a, 0, 4);
|
||||||
|
armcp15_moveARM2CP(c9, 0x02004000, 0x07, 0x05, 0, 1);
|
||||||
|
armcp15_moveARM2CP(c9, 0x02004000, 0x07, 0x0e, 0, 1);
|
||||||
|
|
||||||
|
/* set initial timer state */
|
||||||
|
|
||||||
|
MMU_write16(state, 0, REG_TM0CNTL, 0x0000);
|
||||||
|
MMU_write16(state, 0, REG_TM0CNTH, 0x00C1);
|
||||||
|
MMU_write16(state, 1, REG_TM0CNTL, 0x0000);
|
||||||
|
MMU_write16(state, 1, REG_TM0CNTH, 0x00C1);
|
||||||
|
MMU_write16(state, 1, REG_TM1CNTL, 0xf7e7);
|
||||||
|
MMU_write16(state, 1, REG_TM1CNTH, 0x00C1);
|
||||||
|
|
||||||
|
/* set initial interrupt state */
|
||||||
|
|
||||||
|
state->MMU->reg_IME[0] = 0x00000001;
|
||||||
|
state->MMU->reg_IE[0] = 0x00042001;
|
||||||
|
state->MMU->reg_IME[1] = 0x00000001;
|
||||||
|
state->MMU->reg_IE[1] = 0x0104009d;
|
||||||
|
}
|
||||||
|
else if (state->initial_frames > 0)
|
||||||
|
{
|
||||||
|
/* execute boot code */
|
||||||
|
int i;
|
||||||
|
for (i=0; i<state->initial_frames; i++)
|
||||||
|
NDS_exec_frame(state, 0, 0);
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* load state */
|
||||||
|
|
||||||
|
load_setstate(state, ss, ss_size);
|
||||||
|
|
||||||
|
if (state->initial_frames == -1)
|
||||||
|
{
|
||||||
|
armcp15_moveARM2CP(c9, (state->NDS_ARM9->R13_irq & 0x0fff0000) | 0x0a, 0x09, 0x01, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* restore timer state */
|
||||||
|
|
||||||
|
for (proc = 0; proc < 2; proc++)
|
||||||
|
{
|
||||||
|
MMU_write16(state, proc, REG_TM0CNTH, T1ReadWord(state->MMU->MMU_MEM[proc][0x40], REG_TM0CNTH & 0xFFF));
|
||||||
|
MMU_write16(state, proc, REG_TM1CNTH, T1ReadWord(state->MMU->MMU_MEM[proc][0x40], REG_TM1CNTH & 0xFFF));
|
||||||
|
MMU_write16(state, proc, REG_TM2CNTH, T1ReadWord(state->MMU->MMU_MEM[proc][0x40], REG_TM2CNTH & 0xFFF));
|
||||||
|
MMU_write16(state, proc, REG_TM3CNTH, T1ReadWord(state->MMU->MMU_MEM[proc][0x40], REG_TM3CNTH & 0xFFF));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (state->initial_frames > 0)
|
||||||
|
{
|
||||||
|
/* skip 1 sec */
|
||||||
|
int i;
|
||||||
|
for (i=0; i<state->initial_frames; i++)
|
||||||
|
NDS_exec_frame(state, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
state->execute = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void state_render(struct NDS_state *state, s16 * buffer, int sample_count)
|
||||||
|
{
|
||||||
|
s16 * ptr = buffer;
|
||||||
|
|
||||||
|
while (sample_count)
|
||||||
|
{
|
||||||
|
unsigned remain_samples = state->sample_pointer;
|
||||||
|
if (remain_samples > 0)
|
||||||
|
{
|
||||||
|
if (remain_samples > sample_count)
|
||||||
|
{
|
||||||
|
memcpy(ptr, state->sample_buffer, sample_count * sizeof(s16) * 2);
|
||||||
|
memmove(state->sample_buffer, state->sample_buffer + sample_count * 2, ( remain_samples - sample_count ) * sizeof(s16) * 2 );
|
||||||
|
state->sample_pointer -= sample_count;
|
||||||
|
ptr += sample_count * 2;
|
||||||
|
remain_samples -= sample_count; /**/
|
||||||
|
sample_count = 0; /**/
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(ptr, state->sample_buffer, remain_samples * sizeof(s16) * 2);
|
||||||
|
state->sample_pointer = 0;
|
||||||
|
ptr += remain_samples * 2;
|
||||||
|
sample_count -= remain_samples;
|
||||||
|
remain_samples = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (remain_samples == 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
#define HBASE_CYCLES (16756000*2)
|
||||||
|
#define HBASE_CYCLES (33512000*1)
|
||||||
|
#define HBASE_CYCLES (33509300.322234)
|
||||||
|
*/
|
||||||
|
#define HBASE_CYCLES (33509300.322234)
|
||||||
|
#define HLINE_CYCLES (6 * (99 + 256))
|
||||||
|
#define HSAMPLES ((u32)((44100.0 * HLINE_CYCLES) / HBASE_CYCLES))
|
||||||
|
#define VDIVISION 100
|
||||||
|
#define VLINES 263
|
||||||
|
#define VBASE_CYCLES (((double)HBASE_CYCLES) / VDIVISION)
|
||||||
|
#define VSAMPLES ((u32)((44100.0 * HLINE_CYCLES * VLINES) / HBASE_CYCLES))
|
||||||
|
|
||||||
|
int numsamples;
|
||||||
|
if (state->sync_type == 1)
|
||||||
|
{
|
||||||
|
/* vsync */
|
||||||
|
state->cycles += ((44100 / VDIVISION) * HLINE_CYCLES * VLINES);
|
||||||
|
if (state->cycles >= (u32)(VBASE_CYCLES * (VSAMPLES + 1)))
|
||||||
|
{
|
||||||
|
numsamples = (VSAMPLES + 1);
|
||||||
|
state->cycles -= (u32)(VBASE_CYCLES * (VSAMPLES + 1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
numsamples = (VSAMPLES + 0);
|
||||||
|
state->cycles -= (u32)(VBASE_CYCLES * (VSAMPLES + 0));
|
||||||
|
}
|
||||||
|
NDS_exec_frame(state, state->arm9_clockdown_level, state->arm7_clockdown_level);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* hsync */
|
||||||
|
state->cycles += (44100 * HLINE_CYCLES);
|
||||||
|
if (state->cycles >= (u32)(HBASE_CYCLES * (HSAMPLES + 1)))
|
||||||
|
{
|
||||||
|
numsamples = (HSAMPLES + 1);
|
||||||
|
state->cycles -= (u32)(HBASE_CYCLES * (HSAMPLES + 1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
numsamples = (HSAMPLES + 0);
|
||||||
|
state->cycles -= (u32)(HBASE_CYCLES * (HSAMPLES + 0));
|
||||||
|
}
|
||||||
|
NDS_exec_hframe(state, state->arm9_clockdown_level, state->arm7_clockdown_level);
|
||||||
|
}
|
||||||
|
SPU_EmulateSamples(state, numsamples);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int SNDStateInit(NDS_state *state, int buffersize)
|
||||||
|
{
|
||||||
|
state->sample_buffer = (s16 *) malloc(buffersize * sizeof(s16) * 2);
|
||||||
|
state->sample_pointer = 0;
|
||||||
|
state->sample_size = buffersize;
|
||||||
|
|
||||||
|
return state->sample_buffer == NULL ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SNDStateDeInit(NDS_state *state)
|
||||||
|
{
|
||||||
|
if ( state->sample_buffer ) free( state->sample_buffer );
|
||||||
|
state->sample_buffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SNDStateUpdateAudio(NDS_state *state, s16 *buffer, u32 num_samples)
|
||||||
|
{
|
||||||
|
memcpy( state->sample_buffer + state->sample_pointer * 2, buffer, num_samples * sizeof(s16) * 2);
|
||||||
|
state->sample_pointer += num_samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 SNDStateGetAudioSpace(NDS_state *state)
|
||||||
|
{
|
||||||
|
return state->sample_size - state->sample_pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SNDStateMuteAudio(NDS_state *state)
|
||||||
|
{
|
||||||
|
(void)state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SNDStateUnMuteAudio(NDS_state *state)
|
||||||
|
{
|
||||||
|
(void)state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SNDStateSetVolume(NDS_state *state, int volume)
|
||||||
|
{
|
||||||
|
(void)state;
|
||||||
|
(void)volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundInterface_struct SNDState = {
|
||||||
|
SNDCORE_STATE,
|
||||||
|
"State Sound Interface",
|
||||||
|
SNDStateInit,
|
||||||
|
SNDStateDeInit,
|
||||||
|
SNDStateUpdateAudio,
|
||||||
|
SNDStateGetAudioSpace,
|
||||||
|
SNDStateMuteAudio,
|
||||||
|
SNDStateUnMuteAudio,
|
||||||
|
SNDStateSetVolume
|
||||||
|
};
|
||||||
|
|
||||||
|
SoundInterface_struct *SNDCoreList[2] = {
|
||||||
|
&SNDState,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static u16 getwordle(const unsigned char *pData)
|
||||||
|
{
|
||||||
|
return pData[0] | (((u16)pData[1]) << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 getdwordle(const unsigned char *pData)
|
||||||
|
{
|
||||||
|
return pData[0] | (((u32)pData[1]) << 8) | (((u32)pData[2]) << 16) | (((u32)pData[3]) << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void load_getsta(Status_Reg *ptr, unsigned l, const u8 **ss, const u8 *sse)
|
||||||
|
{
|
||||||
|
unsigned s = l << 2;
|
||||||
|
unsigned i;
|
||||||
|
if ((*ss >= sse) || ((*ss + s) > sse))
|
||||||
|
return;
|
||||||
|
for (i = 0; i < l; i++)
|
||||||
|
{
|
||||||
|
u32 st = getdwordle(*ss + (i << 2));
|
||||||
|
ptr[i].bits.N = (st >> 31) & 1;
|
||||||
|
ptr[i].bits.Z = (st >> 30) & 1;
|
||||||
|
ptr[i].bits.C = (st >> 29) & 1;
|
||||||
|
ptr[i].bits.V = (st >> 28) & 1;
|
||||||
|
ptr[i].bits.Q = (st >> 27) & 1;
|
||||||
|
ptr[i].bits.RAZ = (st >> 8) & ((1 << 19) - 1);
|
||||||
|
ptr[i].bits.I = (st >> 7) & 1;
|
||||||
|
ptr[i].bits.F = (st >> 6) & 1;
|
||||||
|
ptr[i].bits.T = (st >> 5) & 1;
|
||||||
|
ptr[i].bits.mode = (st >> 0) & 0x1f;
|
||||||
|
}
|
||||||
|
*ss += s;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void load_getbool(BOOL *ptr, unsigned l, const u8 **ss, const u8 *sse)
|
||||||
|
{
|
||||||
|
unsigned s = l << 2;
|
||||||
|
unsigned i;
|
||||||
|
if ((*ss >= sse) || ((*ss + s) > sse))
|
||||||
|
return;
|
||||||
|
for (i = 0; i < l; i++)
|
||||||
|
ptr[i] = (BOOL)getdwordle(*ss + (i << 2));
|
||||||
|
*ss += s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(SIGNED_IS_NOT_2S_COMPLEMENT)
|
||||||
|
/* 2's complement */
|
||||||
|
#define u32tos32(v) ((s32)((((s64)(v)) ^ 0x80000000) - 0x80000000))
|
||||||
|
#else
|
||||||
|
/* 2's complement */
|
||||||
|
#define u32tos32(v) ((s32)v)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void load_gets32(s32 *ptr, unsigned l, const u8 **ss, const u8 *sse)
|
||||||
|
{
|
||||||
|
unsigned s = l << 2;
|
||||||
|
unsigned i;
|
||||||
|
if ((*ss >= sse) || ((*ss + s) > sse))
|
||||||
|
return;
|
||||||
|
for (i = 0; i < l; i++)
|
||||||
|
ptr[i] = u32tos32(getdwordle(*ss + (i << 2)));
|
||||||
|
*ss += s;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void load_getu32(u32 *ptr, unsigned l, const u8 **ss, const u8 *sse)
|
||||||
|
{
|
||||||
|
unsigned s = l << 2;
|
||||||
|
unsigned i;
|
||||||
|
if ((*ss >= sse) || ((*ss + s) > sse))
|
||||||
|
return;
|
||||||
|
for (i = 0; i < l; i++)
|
||||||
|
ptr[i] = getdwordle(*ss + (i << 2));
|
||||||
|
*ss += s;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void load_getu16(u16 *ptr, unsigned l, const u8 **ss, const u8 *sse)
|
||||||
|
{
|
||||||
|
unsigned s = l << 1;
|
||||||
|
unsigned i;
|
||||||
|
if ((*ss >= sse) || ((*ss + s) > sse))
|
||||||
|
return;
|
||||||
|
for (i = 0; i < l; i++)
|
||||||
|
ptr[i] = getwordle(*ss + (i << 1));
|
||||||
|
*ss += s;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void load_getu8(u8 *ptr, unsigned l, const u8 **ss, const u8 *sse)
|
||||||
|
{
|
||||||
|
unsigned s = l;
|
||||||
|
unsigned i;
|
||||||
|
if ((*ss >= sse) || ((*ss + s) > sse))
|
||||||
|
return;
|
||||||
|
for (i = 0; i < l; i++)
|
||||||
|
ptr[i] = *ss[i];
|
||||||
|
*ss += s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gdb_stub_fix(armcpu_t *armcpu)
|
||||||
|
{
|
||||||
|
/* armcpu->R[15] = armcpu->instruct_adr; */
|
||||||
|
armcpu->next_instruction = armcpu->instruct_adr;
|
||||||
|
if(armcpu->CPSR.bits.T == 0)
|
||||||
|
{
|
||||||
|
armcpu->instruction = MMU_read32_acl(armcpu->state, armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE);
|
||||||
|
armcpu->instruct_adr = armcpu->next_instruction;
|
||||||
|
armcpu->next_instruction += 4;
|
||||||
|
armcpu->R[15] = armcpu->next_instruction + 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
armcpu->instruction = MMU_read16_acl(armcpu->state, armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE);
|
||||||
|
armcpu->instruct_adr = armcpu->next_instruction;
|
||||||
|
armcpu->next_instruction += 2;
|
||||||
|
armcpu->R[15] = armcpu->next_instruction + 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void load_setstate(struct NDS_state *state, const u8 *ss, u32 ss_size)
|
||||||
|
{
|
||||||
|
const u8 *sse = ss + ss_size;
|
||||||
|
|
||||||
|
if (!ss || !ss_size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Skip over "Desmume Save File" crap */
|
||||||
|
ss += 0x17;
|
||||||
|
|
||||||
|
/* Read ARM7 cpu registers */
|
||||||
|
load_getu32(&state->NDS_ARM7->proc_ID, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM7->instruction, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM7->instruct_adr, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM7->next_instruction, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM7->R, 16, &ss, sse);
|
||||||
|
load_getsta(&state->NDS_ARM7->CPSR, 1, &ss, sse);
|
||||||
|
load_getsta(&state->NDS_ARM7->SPSR, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM7->R13_usr, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM7->R14_usr, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM7->R13_svc, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM7->R14_svc, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM7->R13_abt, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM7->R14_abt, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM7->R13_und, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM7->R14_und, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM7->R13_irq, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM7->R14_irq, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM7->R8_fiq, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM7->R9_fiq, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM7->R10_fiq, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM7->R11_fiq, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM7->R12_fiq, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM7->R13_fiq, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM7->R14_fiq, 1, &ss, sse);
|
||||||
|
load_getsta(&state->NDS_ARM7->SPSR_svc, 1, &ss, sse);
|
||||||
|
load_getsta(&state->NDS_ARM7->SPSR_abt, 1, &ss, sse);
|
||||||
|
load_getsta(&state->NDS_ARM7->SPSR_und, 1, &ss, sse);
|
||||||
|
load_getsta(&state->NDS_ARM7->SPSR_irq, 1, &ss, sse);
|
||||||
|
load_getsta(&state->NDS_ARM7->SPSR_fiq, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM7->intVector, 1, &ss, sse);
|
||||||
|
load_getu8(&state->NDS_ARM7->LDTBit, 1, &ss, sse);
|
||||||
|
load_getbool(&state->NDS_ARM7->waitIRQ, 1, &ss, sse);
|
||||||
|
load_getbool(&state->NDS_ARM7->wIRQ, 1, &ss, sse);
|
||||||
|
load_getbool(&state->NDS_ARM7->wirq, 1, &ss, sse);
|
||||||
|
|
||||||
|
/* Read ARM9 cpu registers */
|
||||||
|
load_getu32(&state->NDS_ARM9->proc_ID, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM9->instruction, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM9->instruct_adr, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM9->next_instruction, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM9->R, 16, &ss, sse);
|
||||||
|
load_getsta(&state->NDS_ARM9->CPSR, 1, &ss, sse);
|
||||||
|
load_getsta(&state->NDS_ARM9->SPSR, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM9->R13_usr, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM9->R14_usr, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM9->R13_svc, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM9->R14_svc, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM9->R13_abt, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM9->R14_abt, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM9->R13_und, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM9->R14_und, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM9->R13_irq, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM9->R14_irq, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM9->R8_fiq, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM9->R9_fiq, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM9->R10_fiq, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM9->R11_fiq, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM9->R12_fiq, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM9->R13_fiq, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM9->R14_fiq, 1, &ss, sse);
|
||||||
|
load_getsta(&state->NDS_ARM9->SPSR_svc, 1, &ss, sse);
|
||||||
|
load_getsta(&state->NDS_ARM9->SPSR_abt, 1, &ss, sse);
|
||||||
|
load_getsta(&state->NDS_ARM9->SPSR_und, 1, &ss, sse);
|
||||||
|
load_getsta(&state->NDS_ARM9->SPSR_irq, 1, &ss, sse);
|
||||||
|
load_getsta(&state->NDS_ARM9->SPSR_fiq, 1, &ss, sse);
|
||||||
|
load_getu32(&state->NDS_ARM9->intVector, 1, &ss, sse);
|
||||||
|
load_getu8(&state->NDS_ARM9->LDTBit, 1, &ss, sse);
|
||||||
|
load_getbool(&state->NDS_ARM9->waitIRQ, 1, &ss, sse);
|
||||||
|
load_getbool(&state->NDS_ARM9->wIRQ, 1, &ss, sse);
|
||||||
|
load_getbool(&state->NDS_ARM9->wirq, 1, &ss, sse);
|
||||||
|
|
||||||
|
/* Read in other internal variables that are important */
|
||||||
|
load_gets32(&state->nds->ARM9Cycle, 1, &ss, sse);
|
||||||
|
load_gets32(&state->nds->ARM7Cycle, 1, &ss, sse);
|
||||||
|
load_gets32(&state->nds->cycles, 1, &ss, sse);
|
||||||
|
load_gets32(&state->nds->timerCycle[0], 4, &ss, sse);
|
||||||
|
load_gets32(&state->nds->timerCycle[1], 4, &ss, sse);
|
||||||
|
load_getbool(&state->nds->timerOver[0], 4, &ss, sse);
|
||||||
|
load_getbool(&state->nds->timerOver[1], 4, &ss, sse);
|
||||||
|
load_gets32(&state->nds->nextHBlank, 1, &ss, sse);
|
||||||
|
load_getu32(&state->nds->VCount, 1, &ss, sse);
|
||||||
|
load_getu32(&state->nds->old, 1, &ss, sse);
|
||||||
|
load_gets32(&state->nds->diff, 1, &ss, sse);
|
||||||
|
load_getbool(&state->nds->lignerendu, 1, &ss, sse);
|
||||||
|
load_getu16(&state->nds->touchX, 1, &ss, sse);
|
||||||
|
load_getu16(&state->nds->touchY, 1, &ss, sse);
|
||||||
|
|
||||||
|
/* Read in memory/registers specific to the ARM9 */
|
||||||
|
load_getu8 (state->ARM9Mem->ARM9_ITCM, 0x8000, &ss, sse);
|
||||||
|
load_getu8 (state->ARM9Mem->ARM9_DTCM, 0x4000, &ss, sse);
|
||||||
|
load_getu8 (state->ARM9Mem->ARM9_WRAM, 0x1000000, &ss, sse);
|
||||||
|
load_getu8 (state->ARM9Mem->MAIN_MEM, 0x400000, &ss, sse);
|
||||||
|
load_getu8 (state->ARM9Mem->ARM9_REG, 0x10000, &ss, sse);
|
||||||
|
load_getu8 (state->ARM9Mem->ARM9_VMEM, 0x800, &ss, sse);
|
||||||
|
load_getu8 (state->ARM9Mem->ARM9_OAM, 0x800, &ss, sse);
|
||||||
|
load_getu8 (state->ARM9Mem->ARM9_ABG, 0x80000, &ss, sse);
|
||||||
|
load_getu8 (state->ARM9Mem->ARM9_BBG, 0x20000, &ss, sse);
|
||||||
|
load_getu8 (state->ARM9Mem->ARM9_AOBJ, 0x40000, &ss, sse);
|
||||||
|
load_getu8 (state->ARM9Mem->ARM9_BOBJ, 0x20000, &ss, sse);
|
||||||
|
load_getu8 (state->ARM9Mem->ARM9_LCD, 0xA4000, &ss, sse);
|
||||||
|
|
||||||
|
/* Read in memory/registers specific to the ARM7 */
|
||||||
|
load_getu8 (state->MMU->ARM7_ERAM, 0x10000, &ss, sse);
|
||||||
|
load_getu8 (state->MMU->ARM7_REG, 0x10000, &ss, sse);
|
||||||
|
load_getu8 (state->MMU->ARM7_WIRAM, 0x10000, &ss, sse);
|
||||||
|
|
||||||
|
/* Read in shared memory */
|
||||||
|
load_getu8 (state->MMU->SWIRAM, 0x8000, &ss, sse);
|
||||||
|
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
#else
|
||||||
|
gdb_stub_fix(state->NDS_ARM9);
|
||||||
|
gdb_stub_fix(state->NDS_ARM7);
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
//
|
||||||
|
// state.h
|
||||||
|
// vio2sf
|
||||||
|
//
|
||||||
|
// Created by Christopher Snowhill on 10/13/13.
|
||||||
|
// Copyright (c) 2013 Christopher Snowhill. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef vio2sf_state_h
|
||||||
|
#define vio2sf_state_h
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
#include "spu_exports.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct SoundInterface_struct SoundInterface_struct;
|
||||||
|
|
||||||
|
extern SoundInterface_struct *SNDCoreList[2];
|
||||||
|
|
||||||
|
typedef struct NDS_state
|
||||||
|
{
|
||||||
|
// configuration
|
||||||
|
unsigned long dwInterpolation;
|
||||||
|
unsigned long dwChannelMute;
|
||||||
|
|
||||||
|
// state setup info, from tags
|
||||||
|
int initial_frames;
|
||||||
|
int sync_type;
|
||||||
|
int arm9_clockdown_level;
|
||||||
|
int arm7_clockdown_level;
|
||||||
|
|
||||||
|
u32 cycles;
|
||||||
|
|
||||||
|
struct NDSSystem * nds;
|
||||||
|
|
||||||
|
struct armcpu_t * NDS_ARM7;
|
||||||
|
struct armcpu_t * NDS_ARM9;
|
||||||
|
|
||||||
|
struct MMU_struct * MMU;
|
||||||
|
|
||||||
|
struct ARM9_struct * ARM9Mem;
|
||||||
|
|
||||||
|
struct NDS_Screen * MainScreen;
|
||||||
|
struct NDS_Screen * SubScreen;
|
||||||
|
|
||||||
|
u8 * MMU_ARM9_MEM_MAP[256];
|
||||||
|
u32 MMU_ARM9_MEM_MASK[256];
|
||||||
|
u8 * MMU_ARM7_MEM_MAP[256];
|
||||||
|
u32 MMU_ARM7_MEM_MASK[256];
|
||||||
|
|
||||||
|
BOOL execute;
|
||||||
|
|
||||||
|
u16 partie; /* = 1; */
|
||||||
|
|
||||||
|
u16 SPI_CNT; /* = 0;*/
|
||||||
|
u16 SPI_CMD; /* = 0;*/
|
||||||
|
u16 AUX_SPI_CNT; /* = 0;*/
|
||||||
|
u16 AUX_SPI_CMD; /* = 0;*/
|
||||||
|
|
||||||
|
u32 rom_mask; /* = 0;*/
|
||||||
|
|
||||||
|
u32 DMASrc[2][4]; /* = {{0, 0, 0, 0}, {0, 0, 0, 0}};*/
|
||||||
|
u32 DMADst[2][4]; /* = {{0, 0, 0, 0}, {0, 0, 0, 0}};*/
|
||||||
|
|
||||||
|
struct SPU_struct *SPU_core;
|
||||||
|
struct SPU_struct *SPU_user;
|
||||||
|
double samples;
|
||||||
|
int SPU_currentCoreNum; /* = SNDCORE_DUMMY;*/
|
||||||
|
int spu_core_samples;
|
||||||
|
long tot_samples;
|
||||||
|
|
||||||
|
SoundInterface_struct *SNDCore;
|
||||||
|
|
||||||
|
s16 *sample_buffer;
|
||||||
|
unsigned long sample_pointer;
|
||||||
|
unsigned long sample_size;
|
||||||
|
} NDS_state;
|
||||||
|
|
||||||
|
int state_init(NDS_state *state);
|
||||||
|
|
||||||
|
void state_deinit(NDS_state *state);
|
||||||
|
|
||||||
|
void state_setrom(NDS_state *state, const u8 * rom, u32 rom_size);
|
||||||
|
|
||||||
|
void state_loadstate(NDS_state *state, const u8 * ss, u32 ss_size);
|
||||||
|
|
||||||
|
void state_render(NDS_state *state, s16 * buffer, int sample_count);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,944 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2006 yopyop
|
||||||
|
yopyop156@ifrance.com
|
||||||
|
yopyop156.ifrance.com
|
||||||
|
|
||||||
|
Code added on 18/08/2006 by shash
|
||||||
|
- Missing missaligned addresses correction
|
||||||
|
(reference in http://nocash.emubase.de/gbatek.htm#cpumemoryalignments)
|
||||||
|
|
||||||
|
This file is part of DeSmuME
|
||||||
|
|
||||||
|
DeSmuME is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
DeSmuME is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with DeSmuME; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "bios.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "MMU.h"
|
||||||
|
|
||||||
|
#include "state.h"
|
||||||
|
|
||||||
|
#define REG_NUM(i, n) (((i)>>n)&0x7)
|
||||||
|
|
||||||
|
// Use this macros for reading/writing, so the GDB stub isn't broken
|
||||||
|
#ifdef GDB_STUB
|
||||||
|
#define READ32(a,b) cpu->mem_if->read32(a,b)
|
||||||
|
#define WRITE32(a,b,c) cpu->mem_if->write32(a,b,c)
|
||||||
|
#define READ16(a,b) cpu->mem_if->read16(a,b)
|
||||||
|
#define WRITE16(a,b,c) cpu->mem_if->write16(a,b,c)
|
||||||
|
#define READ8(a,b) cpu->mem_if->read8(a,b)
|
||||||
|
#define WRITE8(a,b,c) cpu->mem_if->write8(a,b,c)
|
||||||
|
#else
|
||||||
|
#define READ32(a,b) MMU_read32(cpu->state, cpu->proc_ID, b)
|
||||||
|
#define WRITE32(a,b,c) MMU_write32(cpu->state, cpu->proc_ID,b,c)
|
||||||
|
#define READ16(a,b) MMU_read16(cpu->state, cpu->proc_ID, b)
|
||||||
|
#define WRITE16(a,b,c) MMU_write16(cpu->state, cpu->proc_ID,b,c)
|
||||||
|
#define READ8(a,b) MMU_read8(cpu->state, cpu->proc_ID, b)
|
||||||
|
#define WRITE8(a,b,c) MMU_write8(cpu->state, cpu->proc_ID,b,c)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_UND_THUMB(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
cpu->state->execute = FALSE;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_LSL_0(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
cpu->R[REG_NUM(i, 0)] = cpu->R[REG_NUM(i, 3)];
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_LSL(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 v = (i>>6) & 0x1F;
|
||||||
|
cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 3)], 32-v);
|
||||||
|
cpu->R[REG_NUM(i, 0)] = (cpu->R[REG_NUM(i, 3)] << v);
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_LSR_0(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
// cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 3)]);
|
||||||
|
cpu->R[REG_NUM(i, 0)] = 0;
|
||||||
|
cpu->CPSR.bits.N = 0;
|
||||||
|
cpu->CPSR.bits.Z = 1;
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_LSR(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 v = (i>>6) & 0x1F;
|
||||||
|
cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1);
|
||||||
|
cpu->R[REG_NUM(i, 0)] = (cpu->R[REG_NUM(i, 3)] >> v);
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_ASR_0(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 3)]);
|
||||||
|
cpu->R[REG_NUM(i, 0)] = BIT31(cpu->R[REG_NUM(i, 3)])*0xFFFFFFFF;
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_ASR(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 v = (i>>6) & 0x1F;
|
||||||
|
cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 3)], v-1);
|
||||||
|
cpu->R[REG_NUM(i, 0)] = (((s32)cpu->R[REG_NUM(i, 3)]) >> v);
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_ADD_REG(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 a = cpu->R[REG_NUM(i, 3)];
|
||||||
|
u32 b = cpu->R[REG_NUM(i, 6)];
|
||||||
|
cpu->R[REG_NUM(i, 0)] = a + b;
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(a, b, cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.V = SIGNED_OVERFLOW(a, b, cpu->R[REG_NUM(i, 0)]);
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_SUB_REG(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 a = cpu->R[REG_NUM(i, 3)];
|
||||||
|
u32 b = cpu->R[REG_NUM(i, 6)];
|
||||||
|
cpu->R[REG_NUM(i, 0)] = a - b;
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(a, b, cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.V = SIGNED_UNDERFLOW(a, b, cpu->R[REG_NUM(i, 0)]);
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_ADD_IMM3(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 a = cpu->R[REG_NUM(i, 3)];
|
||||||
|
cpu->R[REG_NUM(i, 0)] = a + REG_NUM(i, 6);
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.V = SIGNED_OVERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]);
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_SUB_IMM3(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 a = cpu->R[REG_NUM(i, 3)];
|
||||||
|
cpu->R[REG_NUM(i, 0)] = a - REG_NUM(i, 6);
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.V = SIGNED_UNDERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]);
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_MOV_IMM8(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
cpu->R[REG_NUM(i, 8)] = i & 0xFF;
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 8)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 8)] == 0;
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_CMP_IMM8(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 tmp = cpu->R[REG_NUM(i, 8)] - (i & 0xFF);
|
||||||
|
cpu->CPSR.bits.N = BIT31(tmp);
|
||||||
|
cpu->CPSR.bits.Z = tmp == 0;
|
||||||
|
cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp);
|
||||||
|
cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp);
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_ADD_IMM8(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 tmp = cpu->R[REG_NUM(i, 8)] + (i & 0xFF);
|
||||||
|
cpu->CPSR.bits.N = BIT31(tmp);
|
||||||
|
cpu->CPSR.bits.Z = tmp == 0;
|
||||||
|
cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp);
|
||||||
|
cpu->CPSR.bits.V = SIGNED_OVERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp);
|
||||||
|
cpu->R[REG_NUM(i, 8)] = tmp;
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_SUB_IMM8(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 tmp = cpu->R[REG_NUM(i, 8)] - (i & 0xFF);
|
||||||
|
cpu->CPSR.bits.N = BIT31(tmp);
|
||||||
|
cpu->CPSR.bits.Z = tmp == 0;
|
||||||
|
cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp);
|
||||||
|
cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp);
|
||||||
|
cpu->R[REG_NUM(i, 8)] = tmp;
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_AND(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
cpu->R[REG_NUM(i, 0)] &= cpu->R[REG_NUM(i, 3)];
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_EOR(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
cpu->R[REG_NUM(i, 0)] ^= cpu->R[REG_NUM(i, 3)];
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_LSL_REG(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 v = cpu->R[REG_NUM(i, 3)]&0xFF;
|
||||||
|
|
||||||
|
if(!v)
|
||||||
|
{
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
if(v<32)
|
||||||
|
{
|
||||||
|
cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], 32-v);
|
||||||
|
cpu->R[REG_NUM(i, 0)] <<= v;
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
if(v==32)
|
||||||
|
cpu->CPSR.bits.C = BIT0(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
else
|
||||||
|
cpu->CPSR.bits.C = 0;
|
||||||
|
cpu->R[REG_NUM(i, 0)] = 0;
|
||||||
|
cpu->CPSR.bits.N = 0;
|
||||||
|
cpu->CPSR.bits.Z = 1;
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_LSR_REG(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 v = cpu->R[REG_NUM(i, 3)]&0xFF;
|
||||||
|
|
||||||
|
if(!v)
|
||||||
|
{
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
if(v<32)
|
||||||
|
{
|
||||||
|
cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1);
|
||||||
|
cpu->R[REG_NUM(i, 0)] >>= v;
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
if(v==32)
|
||||||
|
cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
else
|
||||||
|
cpu->CPSR.bits.C = 0;
|
||||||
|
cpu->R[REG_NUM(i, 0)] = 0;
|
||||||
|
cpu->CPSR.bits.N = 0;
|
||||||
|
cpu->CPSR.bits.Z = 1;
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_ASR_REG(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 v = cpu->R[REG_NUM(i, 3)]&0xFF;
|
||||||
|
|
||||||
|
if(!v)
|
||||||
|
{
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
if(v<32)
|
||||||
|
{
|
||||||
|
cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1);
|
||||||
|
cpu->R[REG_NUM(i, 0)] = (u32)(((s32)cpu->R[REG_NUM(i, 0)]) >> v);
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->R[REG_NUM(i, 0)] = BIT31(cpu->R[REG_NUM(i, 0)])*0xFFFFFFFF;
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_ADC_REG(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 a = cpu->R[REG_NUM(i, 0)];
|
||||||
|
u32 b = cpu->R[REG_NUM(i, 3)];
|
||||||
|
u32 tmp = b + cpu->CPSR.bits.C;
|
||||||
|
u32 res = a + tmp;
|
||||||
|
|
||||||
|
cpu->R[REG_NUM(i, 0)] = res;
|
||||||
|
|
||||||
|
cpu->CPSR.bits.N = BIT31(res);
|
||||||
|
cpu->CPSR.bits.Z = res == 0;
|
||||||
|
|
||||||
|
cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(b, cpu->CPSR.bits.C, tmp) | UNSIGNED_OVERFLOW(tmp, a, res);
|
||||||
|
cpu->CPSR.bits.V = SIGNED_OVERFLOW(b, cpu->CPSR.bits.C, tmp) | SIGNED_OVERFLOW(tmp, a, res);
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_SBC_REG(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 a = cpu->R[REG_NUM(i, 0)];
|
||||||
|
u32 b = cpu->R[REG_NUM(i, 3)];
|
||||||
|
u32 tmp = a - (!cpu->CPSR.bits.C);
|
||||||
|
u32 res = tmp - b;
|
||||||
|
cpu->R[REG_NUM(i, 0)] = res;
|
||||||
|
|
||||||
|
cpu->CPSR.bits.N = BIT31(res);
|
||||||
|
cpu->CPSR.bits.Z = res == 0;
|
||||||
|
|
||||||
|
cpu->CPSR.bits.C = (!UNSIGNED_UNDERFLOW(a, !cpu->CPSR.bits.C, tmp)) & (!UNSIGNED_OVERFLOW(tmp, b, res));
|
||||||
|
cpu->CPSR.bits.V = SIGNED_UNDERFLOW(a, !cpu->CPSR.bits.C, tmp) | SIGNED_OVERFLOW(tmp, b, res);
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_ROR_REG(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 v = cpu->R[REG_NUM(i, 3)]&0xFF;
|
||||||
|
|
||||||
|
if(v == 0)
|
||||||
|
{
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
v &= 0xF;
|
||||||
|
if(v == 0)
|
||||||
|
{
|
||||||
|
cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1);
|
||||||
|
cpu->R[REG_NUM(i, 0)] = ROR(cpu->R[REG_NUM(i, 0)], v);
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_TST(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 tmp = cpu->R[REG_NUM(i, 0)] & cpu->R[REG_NUM(i, 3)];
|
||||||
|
cpu->CPSR.bits.N = BIT31(tmp);
|
||||||
|
cpu->CPSR.bits.Z = tmp == 0;
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_NEG(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 a = cpu->R[REG_NUM(i, 3)];
|
||||||
|
cpu->R[REG_NUM(i, 0)] = -((signed int)a);
|
||||||
|
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(0, a, cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.V = SIGNED_UNDERFLOW(0, a, cpu->R[REG_NUM(i, 0)]);
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_CMP(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 tmp = cpu->R[REG_NUM(i, 0)] -cpu->R[REG_NUM(i, 3)];
|
||||||
|
|
||||||
|
cpu->CPSR.bits.N = BIT31(tmp);
|
||||||
|
cpu->CPSR.bits.Z = tmp == 0;
|
||||||
|
cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp);
|
||||||
|
cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp);
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_CMN(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 tmp = cpu->R[REG_NUM(i, 0)] + cpu->R[REG_NUM(i, 3)];
|
||||||
|
|
||||||
|
//cpu->state->execute = FALSE;
|
||||||
|
//log::ajouter("OP_CMN THUMB");
|
||||||
|
cpu->CPSR.bits.N = BIT31(tmp);
|
||||||
|
cpu->CPSR.bits.Z = tmp == 0;
|
||||||
|
cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp);
|
||||||
|
cpu->CPSR.bits.V = SIGNED_OVERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp);
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_ORR(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
cpu->R[REG_NUM(i, 0)] |= cpu->R[REG_NUM(i, 3)];
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_MUL_REG(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
cpu->R[REG_NUM(i, 0)] *= cpu->R[REG_NUM(i, 3)];
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_BIC(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
cpu->R[REG_NUM(i, 0)] &= (~cpu->R[REG_NUM(i, 3)]);
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_MVN(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
cpu->R[REG_NUM(i, 0)] = (~cpu->R[REG_NUM(i, 3)]);
|
||||||
|
cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
|
||||||
|
cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_ADD_SPE(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 Rd = (i&7) | ((i>>4)&8);
|
||||||
|
cpu->R[Rd] += cpu->R[REG_POS(i, 3)];
|
||||||
|
|
||||||
|
if(Rd==15)
|
||||||
|
cpu->next_instruction = cpu->R[15];
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_CMP_SPE(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 Rn = (i&7) | ((i>>4)&8);
|
||||||
|
u32 tmp = cpu->R[Rn] -cpu->R[REG_POS(i, 3)];
|
||||||
|
|
||||||
|
cpu->CPSR.bits.N = BIT31(tmp);
|
||||||
|
cpu->CPSR.bits.Z = tmp == 0;
|
||||||
|
cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[Rn], cpu->R[REG_POS(i, 3)], tmp);
|
||||||
|
cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[Rn], cpu->R[REG_POS(i, 3)], tmp);
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_MOV_SPE(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 Rd = (i&7) | ((i>>4)&8);
|
||||||
|
cpu->R[Rd] = cpu->R[REG_POS(i, 3)];
|
||||||
|
|
||||||
|
if(Rd==15)
|
||||||
|
cpu->next_instruction = cpu->R[15];
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_BX_THUMB(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 Rm = cpu->R[REG_POS(cpu->instruction, 3)];
|
||||||
|
|
||||||
|
cpu->CPSR.bits.T = BIT0(Rm);
|
||||||
|
cpu->R[15] = (Rm & 0xFFFFFFFE);
|
||||||
|
cpu->next_instruction = cpu->R[15];
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_BLX_THUMB(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 Rm = cpu->R[REG_POS(cpu->instruction, 3)];
|
||||||
|
|
||||||
|
cpu->CPSR.bits.T = BIT0(Rm);
|
||||||
|
cpu->R[14] = cpu->next_instruction | 1;
|
||||||
|
cpu->R[15] = (Rm & 0xFFFFFFFE);
|
||||||
|
cpu->next_instruction = cpu->R[15];
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_LDR_PCREL(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 adr = (cpu->R[15]&0xFFFFFFFC) + ((cpu->instruction&0xFF)<<2);
|
||||||
|
|
||||||
|
cpu->R[REG_NUM(cpu->instruction, 8)] = READ32(cpu->mem_if->data, adr);
|
||||||
|
|
||||||
|
return 3 + cpu->state->MMU->MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_STR_REG_OFF(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 adr = cpu->R[REG_NUM(i, 6)] + cpu->R[REG_NUM(i, 3)];
|
||||||
|
WRITE32(cpu->mem_if->data, adr, cpu->R[REG_NUM(i, 0)]);
|
||||||
|
|
||||||
|
return 2 + cpu->state->MMU->MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_STRH_REG_OFF(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
|
||||||
|
WRITE16(cpu->mem_if->data, adr, ((u16)cpu->R[REG_NUM(i, 0)]));
|
||||||
|
|
||||||
|
return 2 + cpu->state->MMU->MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_STRB_REG_OFF(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
|
||||||
|
WRITE8(cpu->mem_if->data, adr, ((u8)cpu->R[REG_NUM(i, 0)]));
|
||||||
|
|
||||||
|
return 2 + cpu->state->MMU->MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_LDRSB_REG_OFF(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
|
||||||
|
cpu->R[REG_NUM(i, 0)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
|
||||||
|
|
||||||
|
return 3 + cpu->state->MMU->MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_LDR_REG_OFF(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 adr = (cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]);
|
||||||
|
u32 tempValue = READ32(cpu->mem_if->data, adr&0xFFFFFFFC);
|
||||||
|
|
||||||
|
adr = (adr&3)*8;
|
||||||
|
tempValue = (tempValue>>adr) | (tempValue<<(32-adr));
|
||||||
|
cpu->R[REG_NUM(i, 0)] = tempValue;
|
||||||
|
|
||||||
|
return 3 + cpu->state->MMU->MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_LDRH_REG_OFF(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
|
||||||
|
cpu->R[REG_NUM(i, 0)] = (u32)READ16(cpu->mem_if->data, adr);
|
||||||
|
|
||||||
|
return 3 + cpu->state->MMU->MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_LDRB_REG_OFF(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
|
||||||
|
cpu->R[REG_NUM(i, 0)] = (u32)READ8(cpu->mem_if->data, adr);
|
||||||
|
|
||||||
|
return 3 + cpu->state->MMU->MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_LDRSH_REG_OFF(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
|
||||||
|
cpu->R[REG_NUM(i, 0)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
|
||||||
|
|
||||||
|
return 3 + cpu->state->MMU->MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_STR_IMM_OFF(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>4)&0x7C);
|
||||||
|
WRITE32(cpu->mem_if->data, adr, cpu->R[REG_NUM(i, 0)]);
|
||||||
|
|
||||||
|
return 2 + cpu->state->MMU->MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_LDR_IMM_OFF(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>4)&0x7C);
|
||||||
|
u32 tempValue = READ32(cpu->mem_if->data, adr&0xFFFFFFFC);
|
||||||
|
adr = (adr&3)*8;
|
||||||
|
tempValue = (tempValue>>adr) | (tempValue<<(32-adr));
|
||||||
|
cpu->R[REG_NUM(i, 0)] = tempValue;
|
||||||
|
|
||||||
|
return 3 + cpu->state->MMU->MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_STRB_IMM_OFF(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>6)&0x1F);
|
||||||
|
WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_NUM(i, 0)]);
|
||||||
|
|
||||||
|
return 2 + cpu->state->MMU->MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_LDRB_IMM_OFF(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>6)&0x1F);
|
||||||
|
cpu->R[REG_NUM(i, 0)] = READ8(cpu->mem_if->data, adr);
|
||||||
|
|
||||||
|
return 3 + cpu->state->MMU->MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_STRH_IMM_OFF(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>5)&0x3E);
|
||||||
|
WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_NUM(i, 0)]);
|
||||||
|
|
||||||
|
return 2 + cpu->state->MMU->MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_LDRH_IMM_OFF(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>5)&0x3E);
|
||||||
|
cpu->R[REG_NUM(i, 0)] = READ16(cpu->mem_if->data, adr);
|
||||||
|
|
||||||
|
return 3 + cpu->state->MMU->MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_STR_SPREL(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 adr = cpu->R[13] + ((i&0xFF)<<2);
|
||||||
|
WRITE32(cpu->mem_if->data, adr, cpu->R[REG_NUM(i, 8)]);
|
||||||
|
|
||||||
|
return 2 + cpu->state->MMU->MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_LDR_SPREL(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 adr = cpu->R[13] + ((i&0xFF)<<2);
|
||||||
|
cpu->R[REG_NUM(i, 8)] = READ32(cpu->mem_if->data, adr);
|
||||||
|
|
||||||
|
return 3 + cpu->state->MMU->MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_ADD_2PC(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
cpu->R[REG_NUM(i, 8)] = (cpu->R[15]&0xFFFFFFFC) + ((i&0xFF)<<2);
|
||||||
|
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_ADD_2SP(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
cpu->R[REG_NUM(i, 8)] = cpu->R[13] + ((i&0xFF)<<2);
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_ADJUST_P_SP(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
cpu->R[13] += ((cpu->instruction&0x7F)<<2);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_ADJUST_M_SP(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
cpu->R[13] -= ((cpu->instruction&0x7F)<<2);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_PUSH(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 adr = cpu->R[13] - 4;
|
||||||
|
u32 c = 0, j;
|
||||||
|
|
||||||
|
for(j = 0; j<8; ++j)
|
||||||
|
if(BIT_N(i, 7-j))
|
||||||
|
{
|
||||||
|
WRITE32(cpu->mem_if->data, adr, cpu->R[7-j]);
|
||||||
|
c += cpu->state->MMU->MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
|
||||||
|
adr -= 4;
|
||||||
|
}
|
||||||
|
cpu->R[13] = adr + 4;
|
||||||
|
|
||||||
|
return c + 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_PUSH_LR(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 adr = cpu->R[13] - 4;
|
||||||
|
u32 c = 0, j;
|
||||||
|
|
||||||
|
WRITE32(cpu->mem_if->data, adr, cpu->R[14]);
|
||||||
|
c += cpu->state->MMU->MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
|
||||||
|
adr -= 4;
|
||||||
|
|
||||||
|
for(j = 0; j<8; ++j)
|
||||||
|
if(BIT_N(i, 7-j))
|
||||||
|
{
|
||||||
|
WRITE32(cpu->mem_if->data, adr, cpu->R[7-j]);
|
||||||
|
c += cpu->state->MMU->MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
|
||||||
|
adr -= 4;
|
||||||
|
}
|
||||||
|
cpu->R[13] = adr + 4;
|
||||||
|
|
||||||
|
return c + 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_POP(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 adr = cpu->R[13];
|
||||||
|
u32 c = 0, j;
|
||||||
|
|
||||||
|
for(j = 0; j<8; ++j)
|
||||||
|
if(BIT_N(i, j))
|
||||||
|
{
|
||||||
|
cpu->R[j] = READ32(cpu->mem_if->data, adr);
|
||||||
|
c += cpu->state->MMU->MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
|
||||||
|
adr += 4;
|
||||||
|
}
|
||||||
|
cpu->R[13] = adr;
|
||||||
|
|
||||||
|
return c + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_POP_PC(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 adr = cpu->R[13];
|
||||||
|
u32 c = 0, j;
|
||||||
|
u32 v;
|
||||||
|
|
||||||
|
for(j = 0; j<8; ++j)
|
||||||
|
if(BIT_N(i, j))
|
||||||
|
{
|
||||||
|
cpu->R[j] = READ32(cpu->mem_if->data, adr);
|
||||||
|
c += cpu->state->MMU->MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
|
||||||
|
adr += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
v = READ32(cpu->mem_if->data, adr);
|
||||||
|
c += cpu->state->MMU->MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
|
||||||
|
cpu->R[15] = v & 0xFFFFFFFE;
|
||||||
|
cpu->next_instruction = v & 0xFFFFFFFE;
|
||||||
|
if(cpu->proc_ID==0)
|
||||||
|
cpu->CPSR.bits.T = BIT0(v);
|
||||||
|
adr += 4;
|
||||||
|
|
||||||
|
cpu->R[13] = adr;
|
||||||
|
return c + 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_BKPT_THUMB(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_STMIA_THUMB(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 adr = cpu->R[REG_NUM(i, 8)];
|
||||||
|
u32 c = 0, j;
|
||||||
|
|
||||||
|
for(j = 0; j<8; ++j)
|
||||||
|
if(BIT_N(i, j))
|
||||||
|
{
|
||||||
|
WRITE32(cpu->mem_if->data, adr, cpu->R[j]);
|
||||||
|
c += cpu->state->MMU->MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
|
||||||
|
adr += 4;
|
||||||
|
}
|
||||||
|
cpu->R[REG_NUM(i, 8)] = adr;
|
||||||
|
return c + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_LDMIA_THUMB(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
u32 adr = cpu->R[REG_NUM(i, 8)];
|
||||||
|
u32 c = 0, j;
|
||||||
|
|
||||||
|
for(j = 0; j<8; ++j)
|
||||||
|
if(BIT_N(i, j))
|
||||||
|
{
|
||||||
|
cpu->R[j] = READ32(cpu->mem_if->data, adr);
|
||||||
|
c += cpu->state->MMU->MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
|
||||||
|
adr += 4;
|
||||||
|
}
|
||||||
|
cpu->R[REG_NUM(i, 8)] = adr;
|
||||||
|
return c + 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_B_COND(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
if(!TEST_COND((i>>8)&0xF, 0, cpu->CPSR))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
cpu->R[15] += ((s32)((s8)(i&0xFF)))<<1;
|
||||||
|
cpu->next_instruction = cpu->R[15];
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_SWI_THUMB(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
if (((cpu->intVector != 0) ^ (cpu->proc_ID == ARMCPU_ARM9)))
|
||||||
|
{
|
||||||
|
/* we use an irq thats not in the irq tab, as
|
||||||
|
it was replaced duie to a changed intVector */
|
||||||
|
Status_Reg tmp = cpu->CPSR;
|
||||||
|
armcpu_switchMode(cpu, SVC); /* enter svc mode */
|
||||||
|
cpu->R[14] = cpu->R[15] - 4; /* jump to swi Vector */
|
||||||
|
cpu->SPSR = tmp; /* save old CPSR as new SPSR */
|
||||||
|
cpu->CPSR.bits.T = 0; /* handle as ARM32 code */
|
||||||
|
cpu->CPSR.bits.I = cpu->SPSR.bits.I; /* keep int disable flag */
|
||||||
|
cpu->R[15] = cpu->intVector + 0x08;
|
||||||
|
cpu->next_instruction = cpu->R[15];
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u32 swinum = cpu->instruction & 0xFF;
|
||||||
|
return cpu->swi_tab[swinum](cpu) + 3;
|
||||||
|
}
|
||||||
|
//return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SIGNEEXT_IMM11(i) (((i)&0x7FF) | (BIT10(i) * 0xFFFFF800))
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_B_UNCOND(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
cpu->R[15] += (SIGNEEXT_IMM11(i)<<1);
|
||||||
|
cpu->next_instruction = cpu->R[15];
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_BLX(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
cpu->R[15] = (cpu->R[14] + ((i&0x7FF)<<1))&0xFFFFFFFC;
|
||||||
|
cpu->R[14] = cpu->next_instruction | 1;
|
||||||
|
cpu->next_instruction = cpu->R[15];
|
||||||
|
cpu->CPSR.bits.T = 0;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_BL_10(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
cpu->R[14] = cpu->R[15] + (SIGNEEXT_IMM11(i)<<12);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 FASTCALL OP_BL_THUMB(armcpu_t *cpu)
|
||||||
|
{
|
||||||
|
u32 i = cpu->instruction;
|
||||||
|
cpu->R[15] = (cpu->R[14] + ((i&0x7FF)<<1));
|
||||||
|
cpu->R[14] = cpu->next_instruction | 1;
|
||||||
|
cpu->next_instruction = cpu->R[15];
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TYPE_RETOUR u32
|
||||||
|
#define CALLTYPE FASTCALL
|
||||||
|
#define PARAMETRES armcpu_t *cpu
|
||||||
|
#define NOM_THUMB_TAB thumb_instructions_set
|
||||||
|
|
||||||
|
#include "thumb_tabdef.inc"
|
|
@ -0,0 +1,30 @@
|
||||||
|
/* Copyright (C) 2006 yopyop
|
||||||
|
yopyop156@ifrance.com
|
||||||
|
yopyop156.ifrance.com
|
||||||
|
|
||||||
|
This file is part of DeSmuME
|
||||||
|
|
||||||
|
DeSmuME is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
DeSmuME is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with DeSmuME; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef THUMB_INSTRUCTIONS_H
|
||||||
|
#define THUMB_INSTRUCTIONS_H
|
||||||
|
|
||||||
|
#include "armcpu.h"
|
||||||
|
|
||||||
|
extern u32 (FASTCALL* thumb_instructions_set[1024])(armcpu_t * cpu);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,151 @@
|
||||||
|
/* Copyright (C) 2005 Guillaume Duhamel
|
||||||
|
|
||||||
|
This file is part of DeSmuME
|
||||||
|
|
||||||
|
DeSmuME is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
DeSmuME is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with DeSmuME; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TYPES_HPP
|
||||||
|
#define TYPES_HPP
|
||||||
|
|
||||||
|
#ifndef FASTCALL
|
||||||
|
#ifdef __MINGW32__
|
||||||
|
#define FASTCALL __attribute__((fastcall))
|
||||||
|
#elif defined (__i386__)
|
||||||
|
#define FASTCALL __attribute__((regparm(3)))
|
||||||
|
#else
|
||||||
|
#define FASTCALL
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef INLINE
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define INLINE _inline
|
||||||
|
#else
|
||||||
|
#define INLINE inline
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DESMUME_COCOA
|
||||||
|
#ifdef __BIG_ENDIAN__
|
||||||
|
#define WORDS_BIGENDIAN
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
typedef uint8_t u8;
|
||||||
|
typedef uint16_t u16;
|
||||||
|
typedef uint32_t u32;
|
||||||
|
typedef uint64_t u64;
|
||||||
|
typedef uintptr_t pointer;
|
||||||
|
|
||||||
|
typedef int8_t s8;
|
||||||
|
typedef int16_t s16;
|
||||||
|
typedef int32_t s32;
|
||||||
|
typedef int64_t s64;
|
||||||
|
|
||||||
|
typedef u8 uint8;
|
||||||
|
typedef u16 uint16;
|
||||||
|
|
||||||
|
#ifndef OBJ_C
|
||||||
|
typedef u32 uint32;
|
||||||
|
#else
|
||||||
|
#define uint32 u32 //uint32 is defined in Leopard somewhere, avoid conflicts
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*---------- GPU3D fixed-points types -----------*/
|
||||||
|
|
||||||
|
typedef s32 f32;
|
||||||
|
#define inttof32(n) ((n) << 12)
|
||||||
|
#define f32toint(n) ((n) >> 12)
|
||||||
|
#define floattof32(n) ((int32)((n) * (1 << 12)))
|
||||||
|
#define f32tofloat(n) (((float)(n)) / (float)(1<<12))
|
||||||
|
|
||||||
|
typedef s16 t16;
|
||||||
|
#define f32tot16(n) ((t16)(n >> 8))
|
||||||
|
#define inttot16(n) ((n) << 4)
|
||||||
|
#define t16toint(n) ((n) >> 4)
|
||||||
|
#define floattot16(n) ((t16)((n) * (1 << 4)))
|
||||||
|
#define t16ofloat(n) (((float)(n)) / (float)(1<<4))
|
||||||
|
|
||||||
|
typedef s16 v16;
|
||||||
|
#define inttov16(n) ((n) << 12)
|
||||||
|
#define f32tov16(n) (n)
|
||||||
|
#define floattov16(n) ((v16)((n) * (1 << 12)))
|
||||||
|
#define v16toint(n) ((n) >> 12)
|
||||||
|
#define v16tofloat(n) (((float)(n)) / (float)(1<<12))
|
||||||
|
|
||||||
|
typedef s16 v10;
|
||||||
|
#define inttov10(n) ((n) << 9)
|
||||||
|
#define f32tov10(n) ((v10)(n >> 3))
|
||||||
|
#define v10toint(n) ((n) >> 9)
|
||||||
|
#define floattov10(n) ((v10)((n) * (1 << 9)))
|
||||||
|
#define v10tofloat(n) (((float)(n)) / (float)(1<<9))
|
||||||
|
|
||||||
|
/*----------------------*/
|
||||||
|
|
||||||
|
#ifndef OBJ_C
|
||||||
|
typedef signed char BOOL;
|
||||||
|
#else
|
||||||
|
//apple also defines BOOL
|
||||||
|
typedef int desmume_BOOL;
|
||||||
|
#define BOOL desmume_BOOL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define PACKED __attribute__((packed))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
# define LOCAL_BE
|
||||||
|
#else
|
||||||
|
# define LOCAL_LE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* little endian (ds' endianess) to local endianess convert macros */
|
||||||
|
#ifdef LOCAL_BE /* local arch is big endian */
|
||||||
|
# define LE_TO_LOCAL_16(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff))
|
||||||
|
# define LE_TO_LOCAL_32(x) ((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)>>8)&0xff00)|(((x)>>24)&0xff))
|
||||||
|
# define LOCAL_TO_LE_16(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff))
|
||||||
|
# define LOCAL_TO_LE_32(x) ((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)>>8)&0xff00)|(((x)>>24)&0xff))
|
||||||
|
#else /* local arch is little endian */
|
||||||
|
# define LE_TO_LOCAL_16(x) (x)
|
||||||
|
# define LE_TO_LOCAL_32(x) (x)
|
||||||
|
# define LOCAL_TO_LE_16(x) (x)
|
||||||
|
# define LOCAL_TO_LE_32(x) (x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* kilobytes and megabytes macro */
|
||||||
|
#define MB(x) ((x)*1024*1024)
|
||||||
|
#define KB(x) ((x)*1024)
|
||||||
|
|
||||||
|
#define CPU_STR(c) ((c==ARM9)?"ARM9":"ARM7")
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
ARM9 = 0,
|
||||||
|
ARM7 = 1
|
||||||
|
} cpu_id_t;
|
||||||
|
|
||||||
|
#define __PACKED __attribute__((__packed__))
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>English</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>${EXECUTABLE_NAME}</string>
|
||||||
|
<key>CFBundleIconFile</key>
|
||||||
|
<string></string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>net.kode54.vio2sf</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>${PRODUCT_NAME}</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>FMWK</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1</string>
|
||||||
|
<key>NSHumanReadableCopyright</key>
|
||||||
|
<string>Copyright © 2013 Christopher Snowhill. All rights reserved.</string>
|
||||||
|
<key>NSPrincipalClass</key>
|
||||||
|
<string></string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
15
Info.plist
15
Info.plist
|
@ -22,6 +22,21 @@
|
||||||
<key>CFBundleTypeRole</key>
|
<key>CFBundleTypeRole</key>
|
||||||
<string>None</string>
|
<string>None</string>
|
||||||
</dict>
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeExtensions</key>
|
||||||
|
<array>
|
||||||
|
<string>2sf</string>
|
||||||
|
<string>mini2sf</string>
|
||||||
|
</array>
|
||||||
|
<key>LSTypeIsPackage</key>
|
||||||
|
<false/>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Viewer</string>
|
||||||
|
<key>CFBundleTypeIconFile</key>
|
||||||
|
<string>vg.icns</string>
|
||||||
|
<key>CFBundleTypeName</key>
|
||||||
|
<string>Nintendo DS Audio File</string>
|
||||||
|
</dict>
|
||||||
<dict>
|
<dict>
|
||||||
<key>CFBundleTypeExtensions</key>
|
<key>CFBundleTypeExtensions</key>
|
||||||
<array>
|
<array>
|
||||||
|
|
|
@ -21,6 +21,9 @@
|
||||||
8360EF6E17F92E86005208A4 /* HighlyExperimental.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8360EF4417F92C92005208A4 /* HighlyExperimental.framework */; };
|
8360EF6E17F92E86005208A4 /* HighlyExperimental.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8360EF4417F92C92005208A4 /* HighlyExperimental.framework */; };
|
||||||
8384904A180764B500E7332D /* SSEQPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83848FEC1807624000E7332D /* SSEQPlayer.framework */; };
|
8384904A180764B500E7332D /* SSEQPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83848FEC1807624000E7332D /* SSEQPlayer.framework */; };
|
||||||
8384904B180764C200E7332D /* SSEQPlayer.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83848FEC1807624000E7332D /* SSEQPlayer.framework */; };
|
8384904B180764C200E7332D /* SSEQPlayer.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83848FEC1807624000E7332D /* SSEQPlayer.framework */; };
|
||||||
|
83DE0CBC180B02CC00269051 /* vio2sf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83DE0C3A180A9BD500269051 /* vio2sf.framework */; };
|
||||||
|
83DE0CBD180B02D800269051 /* vio2sf.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83DE0C3A180A9BD500269051 /* vio2sf.framework */; };
|
||||||
|
83DE0CC0180B27C200269051 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 83DE0CBF180B27C200269051 /* libz.dylib */; };
|
||||||
83F18C3917F9301400471B6C /* HighlyExperimental.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8360EF4417F92C92005208A4 /* HighlyExperimental.framework */; };
|
83F18C3917F9301400471B6C /* HighlyExperimental.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8360EF4417F92C92005208A4 /* HighlyExperimental.framework */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
@ -109,6 +112,20 @@
|
||||||
remoteGlobalIDString = 83848FB71807623F00E7332D;
|
remoteGlobalIDString = 83848FB71807623F00E7332D;
|
||||||
remoteInfo = SSEQPlayer;
|
remoteInfo = SSEQPlayer;
|
||||||
};
|
};
|
||||||
|
83DE0C39180A9BD500269051 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 83DE0C34180A9BD400269051 /* vio2sf.xcodeproj */;
|
||||||
|
proxyType = 2;
|
||||||
|
remoteGlobalIDString = 83DE0C06180A9BD400269051;
|
||||||
|
remoteInfo = vio2sf;
|
||||||
|
};
|
||||||
|
83DE0CBA180B02C500269051 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 83DE0C34180A9BD400269051 /* vio2sf.xcodeproj */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = 83DE0C05180A9BD400269051;
|
||||||
|
remoteInfo = vio2sf;
|
||||||
|
};
|
||||||
/* End PBXContainerItemProxy section */
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
|
@ -118,6 +135,7 @@
|
||||||
dstPath = "";
|
dstPath = "";
|
||||||
dstSubfolderSpec = 10;
|
dstSubfolderSpec = 10;
|
||||||
files = (
|
files = (
|
||||||
|
83DE0CBD180B02D800269051 /* vio2sf.framework in CopyFiles */,
|
||||||
8384904B180764C200E7332D /* SSEQPlayer.framework in CopyFiles */,
|
8384904B180764C200E7332D /* SSEQPlayer.framework in CopyFiles */,
|
||||||
834379A617F97EB000584396 /* HighlyAdvanced.framework in CopyFiles */,
|
834379A617F97EB000584396 /* HighlyAdvanced.framework in CopyFiles */,
|
||||||
8343792A17F96F2600584396 /* HighlyQuixotic.framework in CopyFiles */,
|
8343792A17F96F2600584396 /* HighlyQuixotic.framework in CopyFiles */,
|
||||||
|
@ -148,6 +166,8 @@
|
||||||
8360EEF317F92AC8005208A4 /* HighlyComplete-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "HighlyComplete-Prefix.pch"; sourceTree = "<group>"; };
|
8360EEF317F92AC8005208A4 /* HighlyComplete-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "HighlyComplete-Prefix.pch"; sourceTree = "<group>"; };
|
||||||
8360EF3E17F92C91005208A4 /* HighlyExperimental.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = HighlyExperimental.xcodeproj; path = ../../Frameworks/HighlyExperimental/HighlyExperimental.xcodeproj; sourceTree = "<group>"; };
|
8360EF3E17F92C91005208A4 /* HighlyExperimental.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = HighlyExperimental.xcodeproj; path = ../../Frameworks/HighlyExperimental/HighlyExperimental.xcodeproj; sourceTree = "<group>"; };
|
||||||
83848FE61807623F00E7332D /* SSEQPlayer.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SSEQPlayer.xcodeproj; path = ../../Frameworks/SSEQPlayer/SSEQPlayer.xcodeproj; sourceTree = "<group>"; };
|
83848FE61807623F00E7332D /* SSEQPlayer.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SSEQPlayer.xcodeproj; path = ../../Frameworks/SSEQPlayer/SSEQPlayer.xcodeproj; sourceTree = "<group>"; };
|
||||||
|
83DE0C34180A9BD400269051 /* vio2sf.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = vio2sf.xcodeproj; path = ../../Frameworks/vio2sf/vio2sf.xcodeproj; sourceTree = "<group>"; };
|
||||||
|
83DE0CBF180B27C200269051 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
@ -155,6 +175,8 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
83DE0CC0180B27C200269051 /* libz.dylib in Frameworks */,
|
||||||
|
83DE0CBC180B02CC00269051 /* vio2sf.framework in Frameworks */,
|
||||||
8384904A180764B500E7332D /* SSEQPlayer.framework in Frameworks */,
|
8384904A180764B500E7332D /* SSEQPlayer.framework in Frameworks */,
|
||||||
834379A517F97EA100584396 /* HighlyAdvanced.framework in Frameworks */,
|
834379A517F97EA100584396 /* HighlyAdvanced.framework in Frameworks */,
|
||||||
8343792917F96F1D00584396 /* HighlyQuixotic.framework in Frameworks */,
|
8343792917F96F1D00584396 /* HighlyQuixotic.framework in Frameworks */,
|
||||||
|
@ -220,6 +242,7 @@
|
||||||
8360EEE617F92AC8005208A4 /* Frameworks */ = {
|
8360EEE617F92AC8005208A4 /* Frameworks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
83DE0CBF180B27C200269051 /* libz.dylib */,
|
||||||
8360EEE717F92AC8005208A4 /* Cocoa.framework */,
|
8360EEE717F92AC8005208A4 /* Cocoa.framework */,
|
||||||
8360EEE917F92AC8005208A4 /* Other Frameworks */,
|
8360EEE917F92AC8005208A4 /* Other Frameworks */,
|
||||||
8360EF3E17F92C91005208A4 /* HighlyExperimental.xcodeproj */,
|
8360EF3E17F92C91005208A4 /* HighlyExperimental.xcodeproj */,
|
||||||
|
@ -228,6 +251,7 @@
|
||||||
8343790C17F96E2600584396 /* HighlyQuixotic.xcodeproj */,
|
8343790C17F96E2600584396 /* HighlyQuixotic.xcodeproj */,
|
||||||
8343796317F97BDB00584396 /* HighlyAdvanced.xcodeproj */,
|
8343796317F97BDB00584396 /* HighlyAdvanced.xcodeproj */,
|
||||||
83848FE61807623F00E7332D /* SSEQPlayer.xcodeproj */,
|
83848FE61807623F00E7332D /* SSEQPlayer.xcodeproj */,
|
||||||
|
83DE0C34180A9BD400269051 /* vio2sf.xcodeproj */,
|
||||||
);
|
);
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -280,6 +304,14 @@
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
83DE0C35180A9BD400269051 /* Products */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
83DE0C3A180A9BD500269051 /* vio2sf.framework */,
|
||||||
|
);
|
||||||
|
name = Products;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
|
@ -295,6 +327,7 @@
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
|
83DE0CBB180B02C500269051 /* PBXTargetDependency */,
|
||||||
83849049180764AC00E7332D /* PBXTargetDependency */,
|
83849049180764AC00E7332D /* PBXTargetDependency */,
|
||||||
834379A417F97E9C00584396 /* PBXTargetDependency */,
|
834379A417F97E9C00584396 /* PBXTargetDependency */,
|
||||||
8343792817F96F1900584396 /* PBXTargetDependency */,
|
8343792817F96F1900584396 /* PBXTargetDependency */,
|
||||||
|
@ -351,6 +384,10 @@
|
||||||
ProductGroup = 83848FE71807623F00E7332D /* Products */;
|
ProductGroup = 83848FE71807623F00E7332D /* Products */;
|
||||||
ProjectRef = 83848FE61807623F00E7332D /* SSEQPlayer.xcodeproj */;
|
ProjectRef = 83848FE61807623F00E7332D /* SSEQPlayer.xcodeproj */;
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
ProductGroup = 83DE0C35180A9BD400269051 /* Products */;
|
||||||
|
ProjectRef = 83DE0C34180A9BD400269051 /* vio2sf.xcodeproj */;
|
||||||
|
},
|
||||||
);
|
);
|
||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
targets = (
|
targets = (
|
||||||
|
@ -402,6 +439,13 @@
|
||||||
remoteRef = 83848FEB1807624000E7332D /* PBXContainerItemProxy */;
|
remoteRef = 83848FEB1807624000E7332D /* PBXContainerItemProxy */;
|
||||||
sourceTree = BUILT_PRODUCTS_DIR;
|
sourceTree = BUILT_PRODUCTS_DIR;
|
||||||
};
|
};
|
||||||
|
83DE0C3A180A9BD500269051 /* vio2sf.framework */ = {
|
||||||
|
isa = PBXReferenceProxy;
|
||||||
|
fileType = wrapper.framework;
|
||||||
|
path = vio2sf.framework;
|
||||||
|
remoteRef = 83DE0C39180A9BD500269051 /* PBXContainerItemProxy */;
|
||||||
|
sourceTree = BUILT_PRODUCTS_DIR;
|
||||||
|
};
|
||||||
/* End PBXReferenceProxy section */
|
/* End PBXReferenceProxy section */
|
||||||
|
|
||||||
/* Begin PBXResourcesBuildPhase section */
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
@ -457,6 +501,11 @@
|
||||||
name = SSEQPlayer;
|
name = SSEQPlayer;
|
||||||
targetProxy = 83849048180764AC00E7332D /* PBXContainerItemProxy */;
|
targetProxy = 83849048180764AC00E7332D /* PBXContainerItemProxy */;
|
||||||
};
|
};
|
||||||
|
83DE0CBB180B02C500269051 /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
name = vio2sf;
|
||||||
|
targetProxy = 83DE0CBA180B02C500269051 /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
/* End PBXTargetDependency section */
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
/* Begin PBXVariantGroup section */
|
/* Begin PBXVariantGroup section */
|
||||||
|
|
|
@ -28,6 +28,10 @@
|
||||||
#import <SSEQPlayer/SDAT.h>
|
#import <SSEQPlayer/SDAT.h>
|
||||||
#import <SSEQPlayer/Player.h>
|
#import <SSEQPlayer/Player.h>
|
||||||
|
|
||||||
|
#import <vio2sf/state.h>
|
||||||
|
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
@interface psf_file_container : NSObject {
|
@interface psf_file_container : NSObject {
|
||||||
NSLock * lock;
|
NSLock * lock;
|
||||||
NSMutableDictionary * list;
|
NSMutableDictionary * list;
|
||||||
|
@ -267,16 +271,6 @@ static int psf_info_meta(void * context, const char * name, const char * value)
|
||||||
{
|
{
|
||||||
state->utf8 = true;
|
state->utf8 = true;
|
||||||
}
|
}
|
||||||
else if ([taglc hasPrefix:@"_lib"])
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else if ([taglc isEqualToString:@"_refresh"])
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else if ([taglc hasPrefix:@"_"])
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else if ([taglc isEqualToString:@"title"] ||
|
else if ([taglc isEqualToString:@"title"] ||
|
||||||
[taglc isEqualToString:@"artist"] ||
|
[taglc isEqualToString:@"artist"] ||
|
||||||
[taglc isEqualToString:@"album"] ||
|
[taglc isEqualToString:@"album"] ||
|
||||||
|
@ -473,7 +467,7 @@ struct qsf_loader_state
|
||||||
uint32_t sample_size;
|
uint32_t sample_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int upload_section( struct qsf_loader_state * state, const char * section, uint32_t start,
|
static int upload_gsf_section( struct qsf_loader_state * state, const char * section, uint32_t start,
|
||||||
const uint8_t * data, uint32_t size )
|
const uint8_t * data, uint32_t size )
|
||||||
{
|
{
|
||||||
uint8_t ** array = NULL;
|
uint8_t ** array = NULL;
|
||||||
|
@ -517,7 +511,7 @@ static int qsf_loader(void * context, const uint8_t * exe, size_t exe_size,
|
||||||
if ( datasize > exe_size )
|
if ( datasize > exe_size )
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if ( upload_section( state, s, dataofs, exe, datasize ) < 0 )
|
if ( upload_gsf_section( state, s, dataofs, exe, datasize ) < 0 )
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
exe += datasize;
|
exe += datasize;
|
||||||
|
@ -535,7 +529,7 @@ struct gsf_loader_state
|
||||||
size_t data_size;
|
size_t data_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
int gsf_loader(void * context, const uint8_t * exe, size_t exe_size,
|
static int gsf_loader(void * context, const uint8_t * exe, size_t exe_size,
|
||||||
const uint8_t * reserved, size_t reserved_size)
|
const uint8_t * reserved, size_t reserved_size)
|
||||||
{
|
{
|
||||||
if ( exe_size < 12 ) return -1;
|
if ( exe_size < 12 ) return -1;
|
||||||
|
@ -637,7 +631,7 @@ struct ncsf_loader_state
|
||||||
ncsf_loader_state() : sseq( 0 ) { }
|
ncsf_loader_state() : sseq( 0 ) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
int ncsf_loader(void * context, const uint8_t * exe, size_t exe_size,
|
static int ncsf_loader(void * context, const uint8_t * exe, size_t exe_size,
|
||||||
const uint8_t * reserved, size_t reserved_size)
|
const uint8_t * reserved, size_t reserved_size)
|
||||||
{
|
{
|
||||||
struct ncsf_loader_state * state = ( struct ncsf_loader_state * ) context;
|
struct ncsf_loader_state * state = ( struct ncsf_loader_state * ) context;
|
||||||
|
@ -662,6 +656,227 @@ int ncsf_loader(void * context, const uint8_t * exe, size_t exe_size,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct twosf_loader_state
|
||||||
|
{
|
||||||
|
uint8_t * rom;
|
||||||
|
uint8_t * state;
|
||||||
|
size_t rom_size;
|
||||||
|
size_t state_size;
|
||||||
|
|
||||||
|
int initial_frames;
|
||||||
|
int sync_type;
|
||||||
|
int clockdown;
|
||||||
|
int arm9_clockdown_level;
|
||||||
|
int arm7_clockdown_level;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int load_twosf_map(struct twosf_loader_state *state, int issave, const unsigned char *udata, unsigned usize)
|
||||||
|
{
|
||||||
|
if (usize < 8) return -1;
|
||||||
|
|
||||||
|
unsigned char *iptr;
|
||||||
|
size_t isize;
|
||||||
|
unsigned char *xptr;
|
||||||
|
unsigned xsize = get_le32(udata + 4);
|
||||||
|
unsigned xofs = get_le32(udata + 0);
|
||||||
|
if (issave)
|
||||||
|
{
|
||||||
|
iptr = state->state;
|
||||||
|
isize = state->state_size;
|
||||||
|
state->state = 0;
|
||||||
|
state->state_size = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iptr = state->rom;
|
||||||
|
isize = state->rom_size;
|
||||||
|
state->rom = 0;
|
||||||
|
state->rom_size = 0;
|
||||||
|
}
|
||||||
|
if (!iptr)
|
||||||
|
{
|
||||||
|
size_t rsize = xofs + xsize;
|
||||||
|
if (!issave)
|
||||||
|
{
|
||||||
|
rsize -= 1;
|
||||||
|
rsize |= rsize >> 1;
|
||||||
|
rsize |= rsize >> 2;
|
||||||
|
rsize |= rsize >> 4;
|
||||||
|
rsize |= rsize >> 8;
|
||||||
|
rsize |= rsize >> 16;
|
||||||
|
rsize += 1;
|
||||||
|
}
|
||||||
|
iptr = (unsigned char *) malloc(rsize + 10);
|
||||||
|
if (!iptr)
|
||||||
|
return -1;
|
||||||
|
memset(iptr, 0, rsize + 10);
|
||||||
|
isize = rsize;
|
||||||
|
}
|
||||||
|
else if (isize < xofs + xsize)
|
||||||
|
{
|
||||||
|
size_t rsize = xofs + xsize;
|
||||||
|
if (!issave)
|
||||||
|
{
|
||||||
|
rsize -= 1;
|
||||||
|
rsize |= rsize >> 1;
|
||||||
|
rsize |= rsize >> 2;
|
||||||
|
rsize |= rsize >> 4;
|
||||||
|
rsize |= rsize >> 8;
|
||||||
|
rsize |= rsize >> 16;
|
||||||
|
rsize += 1;
|
||||||
|
}
|
||||||
|
xptr = (unsigned char *) realloc(iptr, xofs + rsize + 10);
|
||||||
|
if (!xptr)
|
||||||
|
{
|
||||||
|
free(iptr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
iptr = xptr;
|
||||||
|
isize = rsize;
|
||||||
|
}
|
||||||
|
memcpy(iptr + xofs, udata + 8, xsize);
|
||||||
|
if (issave)
|
||||||
|
{
|
||||||
|
state->state = iptr;
|
||||||
|
state->state_size = isize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state->rom = iptr;
|
||||||
|
state->rom_size = isize;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int load_twosf_mapz(struct twosf_loader_state *state, int issave, const unsigned char *zdata, unsigned zsize, unsigned zcrc)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int zerr;
|
||||||
|
uLongf usize = 8;
|
||||||
|
uLongf rsize = usize;
|
||||||
|
unsigned char *udata;
|
||||||
|
unsigned char *rdata;
|
||||||
|
|
||||||
|
udata = (unsigned char *) malloc(usize);
|
||||||
|
if (!udata)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
while (Z_OK != (zerr = uncompress(udata, &usize, zdata, zsize)))
|
||||||
|
{
|
||||||
|
if (Z_MEM_ERROR != zerr && Z_BUF_ERROR != zerr)
|
||||||
|
{
|
||||||
|
free(udata);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (usize >= 8)
|
||||||
|
{
|
||||||
|
usize = get_le32(udata + 4) + 8;
|
||||||
|
if (usize < rsize)
|
||||||
|
{
|
||||||
|
rsize += rsize;
|
||||||
|
usize = rsize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rsize = usize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rsize += rsize;
|
||||||
|
usize = rsize;
|
||||||
|
}
|
||||||
|
rdata = (unsigned char *) realloc(udata, usize);
|
||||||
|
if (!rdata)
|
||||||
|
{
|
||||||
|
free(udata);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
udata = rdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
rdata = (unsigned char *) realloc(udata, usize);
|
||||||
|
if (!rdata)
|
||||||
|
{
|
||||||
|
free(udata);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0)
|
||||||
|
{
|
||||||
|
uLong ccrc = crc32(crc32(0L, Z_NULL, 0), rdata, (uInt) usize);
|
||||||
|
if (ccrc != zcrc)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = load_twosf_map(state, issave, rdata, (unsigned) usize);
|
||||||
|
free(rdata);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int twosf_loader(void * context, const uint8_t * exe, size_t exe_size,
|
||||||
|
const uint8_t * reserved, size_t reserved_size)
|
||||||
|
{
|
||||||
|
struct twosf_loader_state * state = ( struct twosf_loader_state * ) context;
|
||||||
|
|
||||||
|
if ( exe_size >= 8 )
|
||||||
|
{
|
||||||
|
if ( load_twosf_map(state, 0, exe, (unsigned) exe_size) )
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( reserved_size )
|
||||||
|
{
|
||||||
|
size_t resv_pos = 0;
|
||||||
|
if ( reserved_size < 16 )
|
||||||
|
return -1;
|
||||||
|
while ( resv_pos + 12 < reserved_size )
|
||||||
|
{
|
||||||
|
unsigned save_size = get_le32(reserved + resv_pos + 4);
|
||||||
|
unsigned save_crc = get_le32(reserved + resv_pos + 8);
|
||||||
|
if (get_le32(reserved + resv_pos + 0) == 0x45564153)
|
||||||
|
{
|
||||||
|
if (resv_pos + 12 + save_size > reserved_size)
|
||||||
|
return -1;
|
||||||
|
if (load_twosf_mapz(state, 1, reserved + resv_pos + 12, save_size, save_crc))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
resv_pos += 12 + save_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int twosf_info(void * context, const char * name, const char * value)
|
||||||
|
{
|
||||||
|
struct twosf_loader_state * state = ( struct twosf_loader_state * ) context;
|
||||||
|
|
||||||
|
NSString * sname = [[NSString stringWithUTF8String:name] lowercaseString];
|
||||||
|
NSString * svalue = [NSString stringWithUTF8String:value];
|
||||||
|
|
||||||
|
if ( [sname isEqualToString:@"_frames"] )
|
||||||
|
{
|
||||||
|
state->initial_frames = [svalue intValue];
|
||||||
|
}
|
||||||
|
else if ( [sname isEqualToString:@"_clockdown"] )
|
||||||
|
{
|
||||||
|
state->clockdown = [svalue intValue];
|
||||||
|
}
|
||||||
|
else if ( [sname isEqualToString:@"_vio2sf_sync_type"] )
|
||||||
|
{
|
||||||
|
state->sync_type = [svalue intValue];
|
||||||
|
}
|
||||||
|
else if ( [sname isEqualToString:@"_vio2sf_arm9_clockdown_level"] )
|
||||||
|
{
|
||||||
|
state->arm9_clockdown_level = [svalue intValue];
|
||||||
|
}
|
||||||
|
else if ( [sname isEqualToString:@"_vio2sf_arm7_clockdown_level"] )
|
||||||
|
{
|
||||||
|
state->arm7_clockdown_level = [svalue intValue];
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL)initializeDecoder
|
- (BOOL)initializeDecoder
|
||||||
{
|
{
|
||||||
if ( type == 1 )
|
if ( type == 1 )
|
||||||
|
@ -760,6 +975,45 @@ int ncsf_loader(void * context, const uint8_t * exe, size_t exe_size,
|
||||||
CPUInit( system );
|
CPUInit( system );
|
||||||
CPUReset( system );
|
CPUReset( system );
|
||||||
}
|
}
|
||||||
|
else if ( type == 0x24 )
|
||||||
|
{
|
||||||
|
struct twosf_loader_state state;
|
||||||
|
memset( &state, 0, sizeof(state) );
|
||||||
|
state.initial_frames = -1;
|
||||||
|
|
||||||
|
if ( psf_load( [currentUrl UTF8String], &source_callbacks, 0x24, twosf_loader, &state, twosf_info, &state) <= 0 )
|
||||||
|
{
|
||||||
|
if (state.rom) free(state.rom);
|
||||||
|
if (state.state) free(state.state);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( state.rom_size > UINT_MAX || state.state_size > UINT_MAX )
|
||||||
|
{
|
||||||
|
if (state.rom) free(state.rom);
|
||||||
|
if (state.state) free(state.state);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
NDS_state * core = ( NDS_state * ) calloc(1, sizeof(NDS_state));
|
||||||
|
if (!core)
|
||||||
|
{
|
||||||
|
if (state.rom) free(state.rom);
|
||||||
|
if (state.state) free(state.state);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
emulatorCore = ( uint8_t * ) core;
|
||||||
|
emulatorExtra = state.rom;
|
||||||
|
|
||||||
|
if ( state_init(core) )
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
if ( state.rom )
|
||||||
|
state_setrom(core, state.rom, (u32) state.rom_size );
|
||||||
|
|
||||||
|
state_loadstate(core, state.state, (u32) state.state_size);
|
||||||
|
}
|
||||||
else if ( type == 0x25 )
|
else if ( type == 0x25 )
|
||||||
{
|
{
|
||||||
struct ncsf_loader_state * state = new struct ncsf_loader_state;
|
struct ncsf_loader_state * state = new struct ncsf_loader_state;
|
||||||
|
@ -928,6 +1182,11 @@ int ncsf_loader(void * context, const uint8_t * exe, size_t exe_size,
|
||||||
}
|
}
|
||||||
sound_out->samples_written = frames_rendered;
|
sound_out->samples_written = frames_rendered;
|
||||||
}
|
}
|
||||||
|
else if ( type == 0x24 )
|
||||||
|
{
|
||||||
|
NDS_state * state = ( NDS_state * ) emulatorCore;
|
||||||
|
state_render(state, (s16*) buf, frames);
|
||||||
|
}
|
||||||
else if ( type == 0x25 )
|
else if ( type == 0x25 )
|
||||||
{
|
{
|
||||||
size_t buffer_size = frames * sizeof(int16_t) * 2;
|
size_t buffer_size = frames * sizeof(int16_t) * 2;
|
||||||
|
@ -944,8 +1203,8 @@ int ncsf_loader(void * context, const uint8_t * exe, size_t exe_size,
|
||||||
frames = howmany;
|
frames = howmany;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( framesRead >= framesLength ) {
|
if ( framesRead + frames > framesLength ) {
|
||||||
long fadeStart = framesRead;
|
long fadeStart = (framesLength > framesRead) ? framesLength : framesRead;
|
||||||
long fadeEnd = framesRead + frames;
|
long fadeEnd = framesRead + frames;
|
||||||
long fadeTotal = totalFrames - framesLength;
|
long fadeTotal = totalFrames - framesLength;
|
||||||
long fadePos;
|
long fadePos;
|
||||||
|
@ -976,7 +1235,11 @@ int ncsf_loader(void * context, const uint8_t * exe, size_t exe_size,
|
||||||
CPUCleanUp( system );
|
CPUCleanUp( system );
|
||||||
soundShutdown( system );
|
soundShutdown( system );
|
||||||
delete system;
|
delete system;
|
||||||
} else if ( type == 0x25 ) {
|
} else if ( type == 0x24 ) {
|
||||||
|
NDS_state * state = ( NDS_state * ) emulatorCore;
|
||||||
|
state_deinit(state);
|
||||||
|
free(state);
|
||||||
|
}else if ( type == 0x25 ) {
|
||||||
Player * player = ( Player * ) emulatorCore;
|
Player * player = ( Player * ) emulatorCore;
|
||||||
delete player;
|
delete player;
|
||||||
} else {
|
} else {
|
||||||
|
@ -991,6 +1254,9 @@ int ncsf_loader(void * context, const uint8_t * exe, size_t exe_size,
|
||||||
} else if ( type == 0x22 && emulatorExtra ) {
|
} else if ( type == 0x22 && emulatorExtra ) {
|
||||||
delete ( gsf_sound_out * ) emulatorExtra;
|
delete ( gsf_sound_out * ) emulatorExtra;
|
||||||
emulatorExtra = nil;
|
emulatorExtra = nil;
|
||||||
|
} else if ( type == 0x24 && emulatorExtra ) {
|
||||||
|
free( emulatorExtra );
|
||||||
|
emulatorExtra = nil;
|
||||||
} else if ( type == 0x25 && emulatorExtra ) {
|
} else if ( type == 0x25 && emulatorExtra ) {
|
||||||
struct ncsf_loader_state * state = ( struct ncsf_loader_state * ) emulatorExtra;
|
struct ncsf_loader_state * state = ( struct ncsf_loader_state * ) emulatorExtra;
|
||||||
delete state;
|
delete state;
|
||||||
|
@ -1058,6 +1324,24 @@ int ncsf_loader(void * context, const uint8_t * exe, size_t exe_size,
|
||||||
CPULoop( system, 250000 );
|
CPULoop( system, 250000 );
|
||||||
} while ( frames_to_run );
|
} while ( frames_to_run );
|
||||||
}
|
}
|
||||||
|
else if ( type == 0x24 )
|
||||||
|
{
|
||||||
|
NDS_state * state = ( NDS_state * ) emulatorCore;
|
||||||
|
s16 temp[2048];
|
||||||
|
|
||||||
|
long frames_to_run = frame - framesRead;
|
||||||
|
|
||||||
|
while ( frames_to_run )
|
||||||
|
{
|
||||||
|
unsigned frames_this_run = 1024;
|
||||||
|
if ( frames_this_run > frames_to_run )
|
||||||
|
frames_this_run = (unsigned) frames_to_run;
|
||||||
|
|
||||||
|
state_render(state, temp, frames_this_run);
|
||||||
|
|
||||||
|
frames_to_run -= frames_this_run;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if ( type == 0x25 )
|
else if ( type == 0x25 )
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> buffer;
|
std::vector<uint8_t> buffer;
|
||||||
|
@ -1126,7 +1410,7 @@ int ncsf_loader(void * context, const uint8_t * exe, size_t exe_size,
|
||||||
|
|
||||||
+ (NSArray *)fileTypes
|
+ (NSArray *)fileTypes
|
||||||
{
|
{
|
||||||
return [NSArray arrayWithObjects:@"psf",@"minipsf",@"psf2", @"minipsf2", @"ssf", @"minissf", @"dsf", @"minidsf", @"qsf", @"miniqsf", @"gsf", @"minigsf", @"ncsf", @"minincsf", nil];
|
return [NSArray arrayWithObjects:@"psf",@"minipsf",@"psf2", @"minipsf2", @"ssf", @"minissf", @"dsf", @"minidsf", @"qsf", @"miniqsf", @"gsf", @"minigsf", @"ncsf", @"minincsf", @"2sf", @"mini2sf", nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSArray *)mimeTypes
|
+ (NSArray *)mimeTypes
|
||||||
|
|
Loading…
Reference in New Issue