From 02f963a4bab95b3a328b6a792c9a7e027ade0e26 Mon Sep 17 00:00:00 2001 From: Hannes Schulze Date: Mon, 13 Jan 2025 22:03:10 +0100 Subject: implement display --- src/scene.mm | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 src/scene.mm (limited to 'src/scene.mm') diff --git a/src/scene.mm b/src/scene.mm new file mode 100644 index 0000000..944d01a --- /dev/null +++ b/src/scene.mm @@ -0,0 +1,96 @@ +#import "scene.hh" +#import "nes/nes.hh" +#import "nes/display.hh" +#import "nes/util/rgb.hh" +#import + +namespace +{ + class display_impl : public nes::display + { + SKSpriteNode* node_; + NSMutableData* buffer_front_; + NSMutableData* buffer_back_; + std::uint8_t* bytes_back_; + + public: + explicit display_impl(SKSpriteNode* node) + : node_{ node } + , buffer_front_{ make_buffer() } + , buffer_back_{ make_buffer() } + , bytes_back_{ static_cast([buffer_back_ mutableBytes]) } + { + } + + ~display_impl() = default; + + virtual auto switch_buffers() -> void override + { + auto tmp = buffer_back_; + buffer_back_ = buffer_front_; + buffer_front_ = tmp; + bytes_back_ = static_cast([buffer_back_ mutableBytes]); + + auto texture = [SKTexture textureWithData:buffer_front_ size:CGSizeMake(width, height)]; + [texture setFilteringMode:SKTextureFilteringNearest]; + [node_ setTexture:texture]; + } + + virtual auto set(unsigned x, unsigned y, nes::rgb value) -> void override + { + auto const offset = (y * width + x) * 4; + bytes_back_[offset + 0] = value.r; + bytes_back_[offset + 1] = value.g; + bytes_back_[offset + 2] = value.b; + bytes_back_[offset + 3] = 255; + } + + virtual auto get(unsigned x, unsigned y) const -> nes::rgb override + { + auto const offset = (y * width + x) * 4; + auto res = nes::rgb{}; + res.r = bytes_back_[offset + 0]; + res.g = bytes_back_[offset + 1]; + res.b = bytes_back_[offset + 2]; + return res; + } + + private: + static auto make_buffer() -> NSMutableData* + { + auto const length = NSUInteger{ width * height * 4 }; + return [NSMutableData dataWithLength:length]; + } + }; +} // namespace + +@implementation Scene +{ + std::unique_ptr display_; + std::unique_ptr nes_; +} + +- (instancetype)init +{ + self = [super initWithSize:CGSizeMake(nes::display::width, nes::display::height)]; + if (self) + { + SKSpriteNode* node = [[SKSpriteNode alloc] init]; + [node setAnchorPoint:CGPointZero]; + [node setSize:[self size]]; + + [self setScaleMode:SKSceneScaleModeAspectFit]; + [self addChild:node]; + + self->display_ = std::make_unique(node); + self->nes_ = std::make_unique(*self->display_); + } + return self; +} + +- (void)update:(NSTimeInterval)currentTime +{ + [super update:currentTime]; +} + +@end \ No newline at end of file -- cgit v1.3.1