2022-02-19 23:58:59 +00:00
|
|
|
#import "GBObjectView.h"
|
|
|
|
|
|
|
|
@interface GBObjectViewItem : NSObject
|
|
|
|
@property IBOutlet NSView *view;
|
|
|
|
@property IBOutlet NSImageView *image;
|
|
|
|
@property IBOutlet NSTextField *oamAddress;
|
|
|
|
@property IBOutlet NSTextField *position;
|
|
|
|
@property IBOutlet NSTextField *attributes;
|
|
|
|
@property IBOutlet NSTextField *tile;
|
|
|
|
@property IBOutlet NSTextField *tileAddress;
|
|
|
|
@property IBOutlet NSImageView *warningIcon;
|
|
|
|
@property IBOutlet NSBox *verticalLine;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation GBObjectViewItem
|
2022-02-20 01:18:29 +00:00
|
|
|
{
|
|
|
|
@public
|
|
|
|
uint32_t _lastImageData[128];
|
|
|
|
uint8_t _lastHeight;
|
|
|
|
}
|
2022-02-19 23:58:59 +00:00
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation GBObjectView
|
|
|
|
{
|
|
|
|
NSMutableArray<GBObjectViewItem *> *_items;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (instancetype)initWithCoder:(NSCoder *)coder
|
|
|
|
{
|
|
|
|
self = [super initWithCoder:coder];
|
|
|
|
_items = [NSMutableArray array];
|
|
|
|
CGFloat height = self.frame.size.height;
|
|
|
|
for (unsigned i = 0; i < 40; i++) {
|
|
|
|
GBObjectViewItem *item = [[GBObjectViewItem alloc] init];
|
|
|
|
[_items addObject:item];
|
|
|
|
[[NSBundle mainBundle] loadNibNamed:@"GBObjectViewItem" owner:item topLevelObjects:nil];
|
|
|
|
item.view.hidden = true;
|
|
|
|
[self addSubview:item.view];
|
|
|
|
[item.view setFrameOrigin:NSMakePoint((i % 4) * 120, height - (i / 4 * 68) - 68)];
|
|
|
|
item.oamAddress.toolTip = @"OAM address";
|
|
|
|
item.position.toolTip = @"Position";
|
|
|
|
item.attributes.toolTip = @"Attributes";
|
|
|
|
item.tile.toolTip = @"Tile index";
|
|
|
|
item.tileAddress.toolTip = @"Tile address";
|
|
|
|
item.warningIcon.toolTip = @"Dropped: too many objects in line";
|
|
|
|
if ((i % 4) == 3) {
|
|
|
|
[item.verticalLine removeFromSuperview];
|
|
|
|
}
|
|
|
|
item.view.autoresizingMask = NSViewMaxXMargin | NSViewMinYMargin;
|
|
|
|
}
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)reloadData:(Document *)document
|
|
|
|
{
|
|
|
|
GB_oam_info_t *info = document.oamInfo;
|
|
|
|
uint8_t length = document.oamCount;
|
|
|
|
bool cgb = GB_is_cgb(document.gb);
|
|
|
|
uint8_t height = document.oamHeight;
|
|
|
|
for (unsigned i = 0; i < 40; i++) {
|
|
|
|
GBObjectViewItem *item = _items[i];
|
|
|
|
if (i >= length) {
|
|
|
|
item.view.hidden = true;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
item.view.hidden = false;
|
|
|
|
item.oamAddress.stringValue = [NSString stringWithFormat:@"$%04X", info[i].oam_addr];
|
|
|
|
item.position.stringValue = [NSString stringWithFormat:@"(%d, %d)",
|
|
|
|
((signed)(unsigned)info[i].x) - 8,
|
|
|
|
((signed)(unsigned)info[i].y) - 16];
|
|
|
|
item.tile.stringValue = [NSString stringWithFormat:@"$%02X", info[i].tile];
|
|
|
|
item.tileAddress.stringValue = [NSString stringWithFormat:@"$%04X", 0x8000 + info[i].tile * 0x10];
|
|
|
|
item.warningIcon.hidden = !info[i].obscured_by_line_limit;
|
|
|
|
if (cgb) {
|
|
|
|
item.attributes.stringValue = [NSString stringWithFormat:@"%c%c%c%d%d",
|
|
|
|
info[i].flags & 0x80? 'P' : '-',
|
|
|
|
info[i].flags & 0x40? 'Y' : '-',
|
|
|
|
info[i].flags & 0x20? 'X' : '-',
|
|
|
|
info[i].flags & 0x08? 1 : 0,
|
|
|
|
info[i].flags & 0x07];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
item.attributes.stringValue = [NSString stringWithFormat:@"%c%c%c%d",
|
|
|
|
info[i].flags & 0x80? 'P' : '-',
|
|
|
|
info[i].flags & 0x40? 'Y' : '-',
|
|
|
|
info[i].flags & 0x20? 'X' : '-',
|
|
|
|
info[i].flags & 0x10? 1 : 0];
|
|
|
|
}
|
2022-02-20 01:18:29 +00:00
|
|
|
size_t imageSize = 8 * 4 * height;
|
|
|
|
if (height == item->_lastHeight && memcmp(item->_lastImageData, info[i].image, imageSize) == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
memcpy(item->_lastImageData, info[i].image, imageSize);
|
|
|
|
item->_lastHeight = height;
|
2022-02-19 23:58:59 +00:00
|
|
|
item.image.image = [Document imageFromData:[NSData dataWithBytesNoCopy:info[i].image
|
|
|
|
length:64 * 4 * 2
|
|
|
|
freeWhenDone:false]
|
|
|
|
width:8
|
|
|
|
height:height
|
|
|
|
scale:32.0 / height];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NSRect frame = self.frame;
|
2022-02-20 12:23:49 +00:00
|
|
|
CGFloat newHeight = MAX(68 * ((length + 3) / 4), self.superview.frame.size.height);
|
2022-02-19 23:58:59 +00:00
|
|
|
frame.origin.y -= newHeight - frame.size.height;
|
|
|
|
frame.size.height = newHeight;
|
|
|
|
self.frame = frame;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)drawRect:(NSRect)dirtyRect
|
|
|
|
{
|
|
|
|
if (@available(macOS 10.14, *)) {
|
|
|
|
[[NSColor alternatingContentBackgroundColors].lastObject setFill];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
[[NSColor colorWithDeviceWhite:0.96 alpha:1] setFill];
|
|
|
|
}
|
|
|
|
NSRect frame = self.frame;
|
|
|
|
for (unsigned i = 1; i <= 5; i++) {
|
|
|
|
NSRectFill(NSMakeRect(0, frame.size.height - i * 68 * 2, frame.size.width, 68));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@end
|