diff --git a/GBGameCore.mm b/GBGameCore.mm index 5a47f46..b56f8be 100644 --- a/GBGameCore.mm +++ b/GBGameCore.mm @@ -29,6 +29,7 @@ #import "OEGBSystemResponderClient.h" #import +#include #include "gambatte.h" #include "gbcpalettes.h" #include "resamplerinfo.h" @@ -222,6 +223,65 @@ - (void)loadStateFromFileAtPath:(NSString *)fileName completionHandler:(void (^) if(block) block(success==1, nil); } +- (NSData*)serializeStateWithError:(NSError **)outError +{ + std::stringstream stream(std::ios::in|std::ios::out|std::ios::binary); + + if(gb.serializeState(stream)) + { + stream.seekg(0, std::ios::end); + NSUInteger length = stream.tellg(); + stream.seekg(0, std::ios::beg); + + char *bytes = (char *)malloc(length); + stream.read(bytes, length); + + return [NSData dataWithBytesNoCopy:bytes length:length]; + } + else + { + if(outError) + { + *outError = [NSError errorWithDomain:OEGameCoreErrorDomain + code:OEGameCoreCouldNotSaveStateError + userInfo:@{ + NSLocalizedDescriptionKey : @"Save state data could not be written", + NSLocalizedRecoverySuggestionErrorKey : @"The emulator could not write the state data." + }]; + } + + return nil; + } +} + +- (BOOL)deserializeState:(NSData *)state withError:(NSError **)outError +{ + std::stringstream stream(std::ios::in|std::ios::out|std::ios::binary); + + char const *bytes = (char const *)([state bytes]); + std::streamsize size = [state length]; + stream.write(bytes, size); + + if(gb.deserializeState(stream)) + { + return YES; + } + else + { + if(outError) + { + *outError = [NSError errorWithDomain:OEGameCoreErrorDomain + code:OEGameCoreCouldNotLoadStateError + userInfo:@{ + NSLocalizedDescriptionKey : @"The save state data could not be read", + NSLocalizedRecoverySuggestionErrorKey : @"Could not load data from the save state" + }]; + } + + return NO; + } +} + # pragma mark - Input const int GBMap[] = {gambatte::InputGetter::UP, gambatte::InputGetter::DOWN, gambatte::InputGetter::LEFT, gambatte::InputGetter::RIGHT, gambatte::InputGetter::A, gambatte::InputGetter::B, gambatte::InputGetter::START, gambatte::InputGetter::SELECT};