Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make fullscreenable while disallowing resizability #81

Merged
merged 5 commits into from
Nov 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ You can also specify the scale of the screen between 1x, 2x, and 3x through the

<img src="./images/set_scale.png" />

... or through hitting ⌘-1, ⌘-2, or ⌘-3, respectively. Alternately, if you are on macOS 15.1 or later, you can run the game in fullscreen mode by selecting the "Enter Full Screen" choice from the View menu or via hitting the 🌐-F chord.

Hitting ⌘-R within happiNESs at any time while playing a game will reset it.

# Supported games
Expand All @@ -41,16 +43,27 @@ So far, the following mappers and associated games have been tested in this emul
- 1941
- Donkey Kong
- Galaga
- Galaxian
- Ms. Pacman
- Pacman
- Super Mario Bros.
- Xevious
- 001
- Castlevania II
- Double Dribble
- Pinball Quest
- 002
- 1943
- Blades of Steel
- Castlevania
- 003
- Gradius
- Gyruss
- Tiger Heli
- 007
- Sky Shark (HUD is jumpy)
- Marble Madness (text box glitches a little at start of level)
- Wheel of Fortune

Also, this emulator now supports sound! Games should play and sound _pretty_ close to the original, however certain things like timings and IRQ interrupt handling may not be quite right and will need some work to correct.

Expand Down
3 changes: 2 additions & 1 deletion happiNESsApp/Console.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import SwiftUI

@Observable @MainActor class Console {
static let frameRate = 60
static let defaultScale = 2.0

public static let keyMappings: [KeyEquivalent : JoypadButton] = [
.upArrow : .up,
Expand All @@ -33,7 +34,7 @@ import SwiftUI
// pixels has changed, namely any of the elements of `screenBuffer`.
@ObservationIgnored private var cpu: CPU
var screenBuffer: [UInt8] = PPU.makeEmptyScreenBuffer()
var scale: Double = 2.0
var scale: Double = Console.defaultScale

internal init() throws {
let bus = Bus()
Expand Down
6 changes: 1 addition & 5 deletions happiNESsApp/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ struct ContentView: View {
if self.console.cartridgeLoaded {
Screen(screenBuffer: console.screenBuffer,
scale: console.scale)
.padding()
.focusable()
.focusEffectDisabled()
.focused($focused)
Expand All @@ -42,10 +41,7 @@ struct ContentView: View {
Image("happiNESs")
}
}
.frame(
maxWidth: CGFloat(Screen.width) * console.scale,
maxHeight: CGFloat(Screen.height) * console.scale)
.fixedSize()
.scaledToFit()
}
}

Expand Down
68 changes: 61 additions & 7 deletions happiNESsApp/happiNESsApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,76 @@
// Created by Danielle Kefford on 6/29/24.
//

import happiNESs
import SwiftUI
import UniformTypeIdentifiers

@main
@MainActor
struct happiNESsApp: App {
static let fullscreenNotificationPublisher = NotificationCenter.default.publisher(
for: NSWindow.didEnterFullScreenNotification
).merge(
with: NotificationCenter.default.publisher(
for: NSWindow.didExitFullScreenNotification
)
)

@State var console = try! Console()

@State private var showFileImporter = false
@State private var errorMessage = ""
@State private var showAlert = false
@State private var isFullscreen = false
@State private var oldScale: Double = Console.defaultScale

private func setErrorMessage(message: String) {
self.errorMessage = message
self.showAlert = true
}

var body: some Scene {
let commonView = ContentView()
.environment(console)
.alert(errorMessage, isPresented: $showAlert, actions: {})
.dialogSeverity(.critical)

Window("happiNESs", id: "main") {
ContentView()
.environment(console)
.alert(errorMessage, isPresented: $showAlert, actions: {})
.dialogSeverity(.critical)
if #available(macOS 15.0, *) {
HStack {
if isFullscreen {
// NOTA BENE: We need to set the minimum lenght of the spacer
// here to something large enough so that the centering of the
// ContentView actually works.
Spacer(minLength: NSScreen.main!.frame.width/2.0)
}
commonView
if isFullscreen {
Spacer(minLength: NSScreen.main!.frame.width/2.0)
}
}
.background(Color.black)
.windowFullScreenBehavior(.enabled)
.windowResizeBehavior(.disabled)
.onReceive(Self.fullscreenNotificationPublisher) { notification in
switch notification.name {
case NSWindow.didEnterFullScreenNotification:
if let window = notification.object as? NSWindow, let screen = window.screen {
self.oldScale = console.scale
let newScale = screen.frame.size.height / CGFloat(PPU.height)
console.scale = newScale
}
self.isFullscreen = true
case NSWindow.didExitFullScreenNotification:
console.scale = oldScale
self.isFullscreen = false
default:
break
}
}
} else {
commonView
}
}
.windowResizability(.contentSize)
.commands {
Expand Down Expand Up @@ -69,10 +116,17 @@ struct happiNESsApp: App {
.keyboardShortcut("r", modifiers: .command)
.disabled(!console.cartridgeLoaded)
Picker(selection: $console.scale, label: Text("Scale")) {
Text("1x").tag(1.0)
Text("2x").tag(2.0)
Text("3x").tag(3.0)
Text("1x")
.tag(1.0)
.keyboardShortcut("1", modifiers: .command)
Text("2x")
.tag(2.0)
.keyboardShortcut("2", modifiers: .command)
Text("3x")
.tag(3.0)
.keyboardShortcut("3", modifiers: .command)
}
.disabled(isFullscreen)
}
}
}
Expand Down