diff --git a/go.mod b/go.mod index 8e2c558d..b3f792fa 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( github.com/kr/text v0.2.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 github.com/mholt/archiver/v3 v3.5.1 + github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 github.com/nwaples/rardecode v1.1.2 // indirect github.com/pelletier/go-toml v1.9.4 github.com/pierrec/lz4/v4 v4.1.12 // indirect diff --git a/go.sum b/go.sum index a7824bdf..af1feecf 100644 --- a/go.sum +++ b/go.sum @@ -46,6 +46,8 @@ github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69 github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo= github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4= +github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= +github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= github.com/nwaples/rardecode v1.1.2 h1:Cj0yZY6T1Zx1R7AhTbyGSALm44/Mmq+BAPc4B/p/d3M= github.com/nwaples/rardecode v1.1.2/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= diff --git a/menu/hints.go b/menu/hints.go index ace0d6cc..023bef8c 100644 --- a/menu/hints.go +++ b/menu/hints.go @@ -8,9 +8,9 @@ import ( func stackHint(stack *float32, icon uint32, label string, h int) { menu.Font.SetColor(darkGrey) *stack += 30 * menu.ratio - menu.DrawImage(icon, *stack, float32(h)-70*menu.ratio, 70*menu.ratio, 70*menu.ratio, 1.0, darkGrey) + menu.DrawImage(icon, *stack, float32(h)-70*menu.ratio2, 70*menu.ratio, 70*menu.ratio2, 1.0, darkGrey) *stack += 70 * menu.ratio - menu.Font.Printf(*stack, float32(h)-23*menu.ratio, 0.4*menu.ratio, label) + menu.Font.Printf(*stack, float32(h)-23*menu.ratio2, 0.4*menu.ratio2, label) *stack += menu.Font.Width(0.4*menu.ratio, label) } diff --git a/menu/menu.go b/menu/menu.go index 192b5f6c..42911543 100644 --- a/menu/menu.go +++ b/menu/menu.go @@ -21,6 +21,7 @@ type Menu struct { tweens Tweens scroll float32 ratio float32 + ratio2 float32 t float64 *video.Video // we embbed video here to have direct access to drawing functions @@ -30,13 +31,23 @@ type Menu struct { // If a game is already running, it will warp the user to the quick menu. // If not, it will display the menu tabs. func Init(v *video.Video) *Menu { - w, _ := v.GetFramebufferSize() + // donmor: Now the h value is getting in use + w, h := v.GetFramebufferSize() menu = &Menu{} menu.Video = v menu.stack = []Scene{} menu.tweens = make(Tweens) menu.ratio = float32(w) / 1920 + // donmor: Added ratio2 for all HEIGHT values if we are under superres and using aspect correction + if settings.Current.VideoSuperRes == "16:9" { + menu.ratio2 = float32(h) / 1080 + } else if settings.Current.VideoSuperRes == "4:3" { + menu.ratio2 = float32(h) / 1440 + } else { + // donmor: Just give a same value if aspect correction is disabled + menu.ratio2 = menu.ratio + } menu.icons = map[string]uint32{} menu.Push(buildTabs()) @@ -63,6 +74,14 @@ func (m *Menu) Render(dt float32) { m.t += float64(dt * 8) w, h := m.GetFramebufferSize() m.ratio = float32(w) / 1920 + // donmor: Don't forget the recalculation :) + if settings.Current.VideoSuperRes == "16:9" { + menu.ratio2 = float32(h) / 1080 + } else if settings.Current.VideoSuperRes == "4:3" { + menu.ratio2 = float32(h) / 1440 + } else { + menu.ratio2 = menu.ratio + } if state.CoreRunning { m.DrawRect(0, 0, float32(w), float32(h), 0, bgColor.Alpha(0.85)) diff --git a/menu/notifications.go b/menu/notifications.go index b71945c7..4a432c21 100644 --- a/menu/notifications.go +++ b/menu/notifications.go @@ -36,8 +36,8 @@ func (m *Menu) RenderNotifications() { bg := severityBgColor[n.Severity] m.DrawRect( 25*m.ratio, - (stack+offset-46)*m.ratio, - lw+40*m.ratio, + (stack+offset-46)*m.ratio2, + lw+40*m.ratio2, 70*m.ratio, 0.25, bg.Alpha(fading), @@ -45,8 +45,8 @@ func (m *Menu) RenderNotifications() { m.Font.SetColor(fg.Alpha(fading)) m.Font.Printf( 45*m.ratio, - (stack+offset)*m.ratio, - 0.5*m.ratio, + (stack+offset)*m.ratio2, + 0.5*m.ratio2, n.Message, ) stack += h + offset diff --git a/menu/scene.go b/menu/scene.go index f3020a6b..1654dfb2 100644 --- a/menu/scene.go +++ b/menu/scene.go @@ -152,11 +152,11 @@ func genericSegueNext(list *entry) { func genericDrawCursor(list *entry) { w, h := menu.GetFramebufferSize() menu.DrawImage(menu.icons["arrow"], - 530*menu.ratio, float32(h)*list.cursor.yp-35*menu.ratio, - 70*menu.ratio, 70*menu.ratio, 1, cursorBg.Alpha(list.cursor.alpha)) + 530*menu.ratio, float32(h)*list.cursor.yp-35*menu.ratio2, + 70*menu.ratio, 70*menu.ratio2, 1, cursorBg.Alpha(list.cursor.alpha)) menu.DrawRect( - 550*menu.ratio, float32(h)*list.cursor.yp-50*menu.ratio, - float32(w)-630*menu.ratio, 100*menu.ratio, 1, cursorBg.Alpha(list.cursor.alpha)) + 550*menu.ratio, float32(h)*list.cursor.yp-50*menu.ratio2, + float32(w)-630*menu.ratio, 100*menu.ratio2, 1, cursorBg.Alpha(list.cursor.alpha)) } // thumbnailDrawCursor draws the blinking rectangular background of the active @@ -164,11 +164,11 @@ func genericDrawCursor(list *entry) { func thumbnailDrawCursor(list *entry) { w, h := menu.GetFramebufferSize() menu.DrawImage(menu.icons["arrow"], - 500*menu.ratio, float32(h)*list.cursor.yp-50*menu.ratio, - 100*menu.ratio, 100*menu.ratio, 1, cursorBg.Alpha(list.cursor.alpha)) + 500*menu.ratio, float32(h)*list.cursor.yp-50*menu.ratio2, + 100*menu.ratio, 100*menu.ratio2, 1, cursorBg.Alpha(list.cursor.alpha)) menu.DrawRect( - 530*menu.ratio, float32(h)*list.cursor.yp-120*menu.ratio, - float32(w)-630*menu.ratio, 240*menu.ratio, 0.2, cursorBg.Alpha(list.cursor.alpha)) + 530*menu.ratio, float32(h)*list.cursor.yp-120*menu.ratio2, + float32(w)-630*menu.ratio, 240*menu.ratio2, 0.2, cursorBg.Alpha(list.cursor.alpha)) } // genericRender renders a vertical list of menu entries @@ -185,12 +185,12 @@ func genericRender(list *entry) { continue } - fontOffset := 64 * 0.7 * menu.ratio * 0.3 + fontOffset := 64 * 0.7 * menu.ratio2 * 0.3 menu.DrawImage(menu.icons[e.icon], 610*menu.ratio-64*0.5*menu.ratio, - float32(h)*e.yp-14*menu.ratio-64*0.5*menu.ratio+fontOffset, - 128*menu.ratio, 128*menu.ratio, + float32(h)*e.yp-14*menu.ratio2-64*0.5*menu.ratio2+fontOffset, + 128*menu.ratio, 128*menu.ratio2, 0.5, textColor.Alpha(e.iconAlpha)) if e.labelAlpha > 0 { @@ -198,7 +198,7 @@ func genericRender(list *entry) { menu.Font.Printf( 670*menu.ratio, float32(h)*e.yp+fontOffset, - 0.5*menu.ratio, e.label) + 0.5*menu.ratio2, e.label) if e.widget != nil { e.widget(&e) @@ -207,7 +207,7 @@ func genericRender(list *entry) { menu.Font.Printf( float32(w)-lw-128*menu.ratio, float32(h)*e.yp+fontOffset, - 0.5*menu.ratio, e.stringValue()) + 0.5*menu.ratio2, e.stringValue()) } } } @@ -264,7 +264,7 @@ func askDeleteSavestateConfirmation(cb func()) { func genericDrawHintBar() { w, h := menu.GetFramebufferSize() - menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey) + menu.DrawRect(0, float32(h)-70*menu.ratio2, float32(w), 70*menu.ratio2, 0, lightGrey) _, upDown, _, a, b, _, _, _, _, guide := hintIcons() diff --git a/menu/scene_core_disk_control.go b/menu/scene_core_disk_control.go index ef3dfd13..dd7483c5 100644 --- a/menu/scene_core_disk_control.go +++ b/menu/scene_core_disk_control.go @@ -77,7 +77,7 @@ func (s *sceneCoreDiskControl) render() { func (s *sceneCoreDiskControl) drawHintBar() { w, h := menu.GetFramebufferSize() - menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey) + menu.DrawRect(0, float32(h)-70*menu.ratio2, float32(w), 70*menu.ratio2, 0, lightGrey) _, upDown, leftRight, _, b, _, _, _, _, guide := hintIcons() diff --git a/menu/scene_core_options.go b/menu/scene_core_options.go index e347d7dd..8e0b8efe 100644 --- a/menu/scene_core_options.go +++ b/menu/scene_core_options.go @@ -81,7 +81,7 @@ func (s *sceneCoreOptions) render() { func (s *sceneCoreOptions) drawHintBar() { w, h := menu.GetFramebufferSize() - menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey) + menu.DrawRect(0, float32(h)-70*menu.ratio2, float32(w), 70*menu.ratio2, 0, lightGrey) _, upDown, leftRight, _, b, _, _, _, _, guide := hintIcons() diff --git a/menu/scene_dialog.go b/menu/scene_dialog.go index 7da8c35e..0b227253 100644 --- a/menu/scene_dialog.go +++ b/menu/scene_dialog.go @@ -63,21 +63,21 @@ func (s *sceneDialog) render() { menu.DrawRect( fw/2-width/2*menu.ratio, - fh/2-height/2*menu.ratio, + fh/2-height/2*menu.ratio2, width*menu.ratio, - height*menu.ratio, + height*menu.ratio2, 0.05, white, ) menu.Font.SetColor(orange) lw1 := menu.Font.Width(0.7*menu.ratio, s.title) - menu.Font.Printf(fw/2-lw1/2, fh/2-120*menu.ratio+20*menu.ratio, 0.7*menu.ratio, s.title) + menu.Font.Printf(fw/2-lw1/2, fh/2-120*menu.ratio2+20*menu.ratio2, 0.7*menu.ratio2, s.title) menu.Font.SetColor(black) lw2 := menu.Font.Width(0.5*menu.ratio, s.line1) - menu.Font.Printf(fw/2-lw2/2, fh/2-30*menu.ratio+20*menu.ratio, 0.5*menu.ratio, s.line1) + menu.Font.Printf(fw/2-lw2/2, fh/2-30*menu.ratio2+20*menu.ratio2, 0.5*menu.ratio2, s.line1) lw3 := menu.Font.Width(0.5*menu.ratio, s.line2) - menu.Font.Printf(fw/2-lw3/2, fh/2+30*menu.ratio+20*menu.ratio, 0.5*menu.ratio, s.line2) + menu.Font.Printf(fw/2-lw3/2, fh/2+30*menu.ratio2+20*menu.ratio2, 0.5*menu.ratio2, s.line2) menu.Font.SetColor(darkGrey) @@ -88,23 +88,23 @@ func (s *sceneDialog) render() { menu.DrawImage( b, fw/2-width/2*menu.ratio+margin*menu.ratio, - fh/2+height/2*menu.ratio-70*menu.ratio-margin*menu.ratio, - 70*menu.ratio, 70*menu.ratio, 1.0, darkGrey) + fh/2+height/2*menu.ratio2-70*menu.ratio2-margin*menu.ratio2, + 70*menu.ratio, 70*menu.ratio2, 1.0, darkGrey) menu.Font.Printf( fw/2-width/2*menu.ratio+margin*menu.ratio+70*menu.ratio, - fh/2+height/2*menu.ratio-23*menu.ratio-margin*menu.ratio, - 0.4*menu.ratio, + fh/2+height/2*menu.ratio2-23*menu.ratio2-margin*menu.ratio2, + 0.4*menu.ratio2, "NO") menu.DrawImage( a, fw/2+width/2*menu.ratio-150*menu.ratio-margin*menu.ratio, - fh/2+height/2*menu.ratio-70*menu.ratio-margin*menu.ratio, - 70*menu.ratio, 70*menu.ratio, 1.0, darkGrey) + fh/2+height/2*menu.ratio2-70*menu.ratio2-margin*menu.ratio2, + 70*menu.ratio, 70*menu.ratio2, 1.0, darkGrey) menu.Font.Printf( fw/2+width/2*menu.ratio-150*menu.ratio-margin*menu.ratio+70*menu.ratio, - fh/2+height/2*menu.ratio-23*menu.ratio-margin*menu.ratio, - 0.4*menu.ratio, + fh/2+height/2*menu.ratio2-23*menu.ratio2-margin*menu.ratio2, + 0.4*menu.ratio2, "YES") } diff --git a/menu/scene_history.go b/menu/scene_history.go index c52b4ccd..bdc09505 100644 --- a/menu/scene_history.go +++ b/menu/scene_history.go @@ -1,6 +1,7 @@ package menu import ( + "math" "os" "path/filepath" @@ -163,39 +164,40 @@ func (s *sceneHistory) render() { continue } - fontOffset := 64 * 0.7 * menu.ratio * 0.3 + fontOffset := 64 * 0.7 * menu.ratio2 * 0.3 if e.labelAlpha > 0 { drawThumbnail( list, i, e.system, e.gameName, 680*menu.ratio-85*e.scale*menu.ratio, - float32(h)*e.yp-14*menu.ratio-64*e.scale*menu.ratio+fontOffset, - 170*menu.ratio, 128*menu.ratio, + float32(h)*e.yp-14*menu.ratio2-64*e.scale*menu.ratio2+fontOffset, + 170*menu.ratio, 128*menu.ratio2, e.scale, white.Alpha(e.iconAlpha), ) menu.DrawBorder( 680*menu.ratio-85*e.scale*menu.ratio, - float32(h)*e.yp-14*menu.ratio-64*e.scale*menu.ratio+fontOffset, - 170*menu.ratio*e.scale, 128*menu.ratio*e.scale, 0.02/e.scale, + float32(h)*e.yp-14*menu.ratio2-64*e.scale*menu.ratio2+fontOffset, + 170*menu.ratio*e.scale, 128*menu.ratio2*e.scale, 0.02/e.scale, textColor.Alpha(e.iconAlpha)) if e.path == state.GamePath && e.path != "" { + // donmor: TODO: Does anyone know how to draw an oval here? menu.DrawCircle( 680*menu.ratio, - float32(h)*e.yp-14*menu.ratio+fontOffset, - 90*menu.ratio*e.scale, + float32(h)*e.yp-14*menu.ratio2+fontOffset, + 90*float32(math.Sqrt(float64(menu.ratio*menu.ratio2)))*e.scale, black.Alpha(e.iconAlpha)) menu.DrawImage(menu.icons["resume"], 680*menu.ratio-25*e.scale*menu.ratio, - float32(h)*e.yp-14*menu.ratio-25*e.scale*menu.ratio+fontOffset, - 50*menu.ratio, 50*menu.ratio, + float32(h)*e.yp-14*menu.ratio2-25*e.scale*menu.ratio2+fontOffset, + 50*menu.ratio, 50*menu.ratio2, e.scale, white.Alpha(e.iconAlpha)) } // Offset on Y to vertically center label + sublabel if there is a sublabel slOffset := float32(0) if e.subLabel != "" { - slOffset = 30 * menu.ratio * e.subLabelAlpha + slOffset = 30 * menu.ratio2 * e.subLabelAlpha } menu.Font.SetColor(textColor.Alpha(e.labelAlpha)) @@ -203,7 +205,7 @@ func (s *sceneHistory) render() { menu.Font.Printf( 840*menu.ratio, float32(h)*e.yp+fontOffset-slOffset, - 0.5*menu.ratio, e.label) + 0.5*menu.ratio2, e.label) stack += float32(int(menu.Font.Width(0.5*menu.ratio, e.label))) stack += 10 @@ -212,10 +214,10 @@ func (s *sceneHistory) render() { stack += 20 menu.DrawImage( menu.icons[tag], - stack, float32(h)*e.yp-22*menu.ratio-slOffset, - 60*menu.ratio, 44*menu.ratio, 1.0, white.Alpha(e.tagAlpha)) - menu.DrawBorder(stack, float32(h)*e.yp-22*menu.ratio-slOffset, - 60*menu.ratio, 44*menu.ratio, 0.05/menu.ratio, black.Alpha(e.tagAlpha/4)) + stack, float32(h)*e.yp-22*menu.ratio2-slOffset, + 60*menu.ratio, 44*menu.ratio2, 1.0, white.Alpha(e.tagAlpha)) + menu.DrawBorder(stack, float32(h)*e.yp-22*menu.ratio2-slOffset, + 60*menu.ratio, 44*menu.ratio2, 0.05/menu.ratio, black.Alpha(e.tagAlpha/4)) stack += 60 * menu.ratio } } @@ -223,8 +225,8 @@ func (s *sceneHistory) render() { menu.Font.SetColor(mediumGrey.Alpha(e.subLabelAlpha)) menu.Font.Printf( 840*menu.ratio, - float32(h)*e.yp+fontOffset+60*menu.ratio-slOffset, - 0.5*menu.ratio, e.subLabel) + float32(h)*e.yp+fontOffset+60*menu.ratio2-slOffset, + 0.5*menu.ratio2, e.subLabel) } } @@ -233,7 +235,7 @@ func (s *sceneHistory) render() { func (s *sceneHistory) drawHintBar() { w, h := menu.GetFramebufferSize() - menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey) + menu.DrawRect(0, float32(h)-70*menu.ratio2, float32(w), 70*menu.ratio2, 0, lightGrey) _, upDown, _, a, b, x, _, _, _, guide := hintIcons() diff --git a/menu/scene_keyboard.go b/menu/scene_keyboard.go index 96765b23..507ab582 100644 --- a/menu/scene_keyboard.go +++ b/menu/scene_keyboard.go @@ -152,7 +152,7 @@ func (s *sceneKeyboard) render() { w, h := menu.GetFramebufferSize() lines := float32(4) kbh := float32(h) * 0.6 - ksp := (kbh - (50 * menu.ratio)) / (lines + 1) + ksp := (kbh - (50 * menu.ratio2)) / (lines + 1) ksz := ksp * 0.9 ttw := 10 * ksp @@ -205,7 +205,7 @@ func (s *sceneKeyboard) render() { func (s *sceneKeyboard) drawHintBar() { w, h := menu.GetFramebufferSize() - menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey) + menu.DrawRect(0, float32(h)-70*menu.ratio2, float32(w), 70*menu.ratio2, 0, lightGrey) arrows, _, _, a, b, x, y, start, _, _ := hintIcons() diff --git a/menu/scene_playlist.go b/menu/scene_playlist.go index 705cf18a..bca9ddc2 100644 --- a/menu/scene_playlist.go +++ b/menu/scene_playlist.go @@ -1,6 +1,7 @@ package menu import ( + "math" "os" "path/filepath" "regexp" @@ -203,32 +204,33 @@ func (s *scenePlaylist) render() { continue } - fontOffset := 64 * 0.7 * menu.ratio * 0.3 + fontOffset := 64 * 0.7 * menu.ratio2 * 0.3 if e.labelAlpha > 0 { drawThumbnail( list, i, list.label, e.gameName, 680*menu.ratio-85*e.scale*menu.ratio, - float32(h)*e.yp-14*menu.ratio-64*e.scale*menu.ratio+fontOffset, - 170*menu.ratio, 128*menu.ratio, + float32(h)*e.yp-14*menu.ratio2-64*e.scale*menu.ratio2+fontOffset, + 170*menu.ratio, 128*menu.ratio2, e.scale, white.Alpha(e.iconAlpha), ) menu.DrawBorder( 680*menu.ratio-85*e.scale*menu.ratio, - float32(h)*e.yp-14*menu.ratio-64*e.scale*menu.ratio+fontOffset, - 170*menu.ratio*e.scale, 128*menu.ratio*e.scale, 0.02/e.scale, + float32(h)*e.yp-14*menu.ratio2-64*e.scale*menu.ratio2+fontOffset, + 170*menu.ratio*e.scale, 128*menu.ratio2*e.scale, 0.02/e.scale, textColor.Alpha(e.iconAlpha)) if e.path == state.GamePath && e.path != "" { + // donmor: TODO: Another place that needs an oval menu.DrawCircle( 680*menu.ratio, - float32(h)*e.yp-14*menu.ratio+fontOffset, - 90*menu.ratio*e.scale, + float32(h)*e.yp-14*menu.ratio2+fontOffset, + 90*float32(math.Sqrt(float64(menu.ratio*menu.ratio2)))*e.scale, black.Alpha(e.iconAlpha)) menu.DrawImage(menu.icons["resume"], 680*menu.ratio-25*e.scale*menu.ratio, - float32(h)*e.yp-14*menu.ratio-25*e.scale*menu.ratio+fontOffset, - 50*menu.ratio, 50*menu.ratio, + float32(h)*e.yp-14*menu.ratio2-25*e.scale*menu.ratio2+fontOffset, + 50*menu.ratio, 50*menu.ratio2, e.scale, white.Alpha(e.iconAlpha)) } @@ -237,7 +239,7 @@ func (s *scenePlaylist) render() { menu.Font.Printf( 840*menu.ratio, float32(h)*e.yp+fontOffset, - 0.5*menu.ratio, e.label) + 0.5*menu.ratio2, e.label) stack += float32(int(menu.Font.Width(0.5*menu.ratio, e.label))) stack += 10 @@ -246,10 +248,10 @@ func (s *scenePlaylist) render() { stack += 20 menu.DrawImage( menu.icons[tag], - stack, float32(h)*e.yp-22*menu.ratio, - 60*menu.ratio, 44*menu.ratio, 1.0, white.Alpha(e.tagAlpha)) - menu.DrawBorder(stack, float32(h)*e.yp-22*menu.ratio, - 60*menu.ratio, 44*menu.ratio, 0.05/menu.ratio, black.Alpha(e.tagAlpha/4)) + stack, float32(h)*e.yp-22*menu.ratio2, + 60*menu.ratio, 44*menu.ratio2, 1.0, white.Alpha(e.tagAlpha)) + menu.DrawBorder(stack, float32(h)*e.yp-22*menu.ratio2, + 60*menu.ratio, 44*menu.ratio2, 0.05/menu.ratio, black.Alpha(e.tagAlpha/4)) stack += 60 * menu.ratio } } @@ -261,7 +263,7 @@ func (s *scenePlaylist) render() { func (s *scenePlaylist) drawHintBar() { w, h := menu.GetFramebufferSize() - menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey) + menu.DrawRect(0, float32(h)-70*menu.ratio2, float32(w), 70*menu.ratio2, 0, lightGrey) _, upDown, _, a, b, x, _, _, _, guide := hintIcons() diff --git a/menu/scene_savestates.go b/menu/scene_savestates.go index 7eb5d7ef..3ad14205 100644 --- a/menu/scene_savestates.go +++ b/menu/scene_savestates.go @@ -127,27 +127,27 @@ func (s *sceneSavestates) render() { continue } - fontOffset := 64 * 0.7 * menu.ratio * 0.3 + fontOffset := 64 * 0.7 * menu.ratio2 * 0.3 if e.labelAlpha > 0 { drawSavestateThumbnail( list, i, filepath.Join(settings.Current.ScreenshotsDirectory, utils.FileName(e.path)+".png"), 680*menu.ratio-85*e.scale*menu.ratio, - float32(h)*e.yp-14*menu.ratio-64*e.scale*menu.ratio+fontOffset, - 170*menu.ratio, 128*menu.ratio, + float32(h)*e.yp-14*menu.ratio2-64*e.scale*menu.ratio2+fontOffset, + 170*menu.ratio, 128*menu.ratio2, e.scale, textColor.Alpha(e.iconAlpha), ) menu.DrawBorder( 680*menu.ratio-85*e.scale*menu.ratio, - float32(h)*e.yp-14*menu.ratio-64*e.scale*menu.ratio+fontOffset, - 170*menu.ratio*e.scale, 128*menu.ratio*e.scale, 0.02/e.scale, + float32(h)*e.yp-14*menu.ratio2-64*e.scale*menu.ratio2+fontOffset, + 170*menu.ratio*e.scale, 128*menu.ratio2*e.scale, 0.02/e.scale, textColor.Alpha(e.iconAlpha)) if i == 0 { menu.DrawImage(menu.icons["savestate"], 680*menu.ratio-25*e.scale*menu.ratio, - float32(h)*e.yp-14*menu.ratio-25*e.scale*menu.ratio+fontOffset, - 50*menu.ratio, 50*menu.ratio, + float32(h)*e.yp-14*menu.ratio2-25*e.scale*menu.ratio2+fontOffset, + 50*menu.ratio, 50*menu.ratio2, e.scale, textColor.Alpha(e.iconAlpha)) } @@ -155,14 +155,14 @@ func (s *sceneSavestates) render() { menu.Font.Printf( 840*menu.ratio, float32(h)*e.yp+fontOffset, - 0.5*menu.ratio, e.label) + 0.5*menu.ratio2, e.label) } } } func (s *sceneSavestates) drawHintBar() { w, h := menu.GetFramebufferSize() - menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey) + menu.DrawRect(0, float32(h)-70*menu.ratio2, float32(w), 70*menu.ratio2, 0, lightGrey) ptr := menu.stack[len(menu.stack)-1].Entry().ptr diff --git a/menu/scene_settings.go b/menu/scene_settings.go index c5e93bf1..b57e10f2 100644 --- a/menu/scene_settings.go +++ b/menu/scene_settings.go @@ -2,6 +2,7 @@ package menu import ( "fmt" + "math" "os" "path/filepath" @@ -137,8 +138,8 @@ var widgets = map[string]func(*entry){ w, h := menu.GetFramebufferSize() menu.DrawImage(menu.icons[icon], float32(w)-128*menu.ratio-128*menu.ratio, - float32(h)*e.yp-64*1.25*menu.ratio, - 128*menu.ratio, 128*menu.ratio, + float32(h)*e.yp-64*1.25*menu.ratio2, + 128*menu.ratio, 128*menu.ratio2, 1.25, textColor.Alpha(e.iconAlpha)) }, @@ -146,13 +147,14 @@ var widgets = map[string]func(*entry){ "range": func(e *entry) { fbw, fbh := menu.GetFramebufferSize() x := float32(fbw) - 128*menu.ratio - 175*menu.ratio - y := float32(fbh)*e.yp - 4*menu.ratio + y := float32(fbh)*e.yp - 4*menu.ratio2 w := 175 * menu.ratio - h := 8 * menu.ratio + h := 8 * menu.ratio2 menu.DrawRect(x, y, w, h, 0.9, textColor.Alpha(e.iconAlpha/4)) w = 175 * menu.ratio * e.value().(float32) menu.DrawRect(x, y, w, h, 0.9, textColor.Alpha(e.iconAlpha)) - menu.DrawCircle(x+w, y+4*menu.ratio, 38*menu.ratio, textColor.Alpha(e.iconAlpha)) + // donmor: TODO: Another place that needs an oval + menu.DrawCircle(x+w, y+4*menu.ratio2, 38*float32(math.Sqrt(float64(menu.ratio*menu.ratio2))), textColor.Alpha(e.iconAlpha)) }, } @@ -168,6 +170,30 @@ var incrCallbacks = map[string]callbackIncrement{ menu.ContextReset() settings.Save() }, + // donmor: + // New option for integer scaling here + "VideoIntScaling": func(f *structs.Field, direction int) { + v := f.Value().(bool) + v = !v + f.Set(v) + settings.Save() + }, + // donmor: + // New option for aspect correction here (mostly used under super resolution) + "VideoSuperRes": func(f *structs.Field, direction int) { + filters := []string{"Disabled", "4:3", "16:9"} + v := f.Value().(string) + i := utils.IndexOfString(v, filters) + i += direction + if i < 0 { + i = len(filters) - 1 + } + if i > len(filters)-1 { + i = 0 + } + f.Set(filters[i]) + settings.Save() + }, "VideoMonitorIndex": func(f *structs.Field, direction int) { v := f.Value().(int) v += direction @@ -203,6 +229,16 @@ var incrCallbacks = map[string]callbackIncrement{ f.Set(v) settings.Save() }, + // donmor: + // New option for unicode font here (Can we get rid of this somedays by using unifont by default? It needs polishing, though) + "VideoUniFont": func(f *structs.Field, direction int) { + v := f.Value().(bool) + v = !v + f.Set(v) + menu.Reconfigure(settings.Current.VideoFullscreen) + menu.ContextReset() + settings.Save() + }, "MapAxisToDPad": func(f *structs.Field, direction int) { v := f.Value().(bool) v = !v @@ -274,7 +310,7 @@ func (s *sceneSettings) render() { func (s *sceneSettings) drawHintBar() { w, h := menu.GetFramebufferSize() - menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey) + menu.DrawRect(0, float32(h)-70*menu.ratio2, float32(w), 70*menu.ratio2, 0, lightGrey) _, upDown, leftRight, a, b, _, _, _, _, guide := hintIcons() diff --git a/menu/scene_tabs.go b/menu/scene_tabs.go index 630d4a1a..9af7f3d9 100644 --- a/menu/scene_tabs.go +++ b/menu/scene_tabs.go @@ -295,24 +295,24 @@ func (tabs sceneTabs) render() { if e.labelAlpha > 0 { menu.Font.SetColor(c.Alpha(e.labelAlpha)) lw := menu.Font.Width(0.5*menu.ratio, e.label) - menu.Font.Printf(x-lw/2, float32(int(float32(h)/2+250*menu.ratio)), 0.5*menu.ratio, e.label) + menu.Font.Printf(x-lw/2, float32(int(float32(h)/2+250*menu.ratio2)), 0.5*menu.ratio2, e.label) lw = menu.Font.Width(0.4*menu.ratio, e.subLabel) - menu.Font.Printf(x-lw/2, float32(int(float32(h)/2+330*menu.ratio)), 0.4*menu.ratio, e.subLabel) + menu.Font.Printf(x-lw/2, float32(int(float32(h)/2+330*menu.ratio2)), 0.4*menu.ratio2, e.subLabel) } menu.DrawImage(menu.icons["hexagon"], - x-220*e.scale*menu.ratio, float32(h)/2-220*e.scale*menu.ratio, - 440*menu.ratio, 440*menu.ratio, e.scale, c) + x-220*e.scale*menu.ratio, float32(h)/2-220*e.scale*menu.ratio2, + 440*menu.ratio, 440*menu.ratio2, e.scale, c) menu.DrawImage(menu.icons[e.icon], - x-128*e.scale*menu.ratio, float32(h)/2-128*e.scale*menu.ratio, - 256*menu.ratio, 256*menu.ratio, e.scale, white.Alpha(e.iconAlpha)) + x-128*e.scale*menu.ratio, float32(h)/2-128*e.scale*menu.ratio2, + 256*menu.ratio, 256*menu.ratio2, e.scale, white.Alpha(e.iconAlpha)) } } func (tabs sceneTabs) drawHintBar() { w, h := menu.GetFramebufferSize() - menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey) + menu.DrawRect(0, float32(h)-70*menu.ratio2, float32(w), 70*menu.ratio2, 0, lightGrey) _, _, leftRight, a, _, x, _, _, _, guide := hintIcons() diff --git a/menu/scene_wifi.go b/menu/scene_wifi.go index 0af9d257..ce5c01f8 100644 --- a/menu/scene_wifi.go +++ b/menu/scene_wifi.go @@ -86,7 +86,7 @@ func (s *sceneWiFi) render() { func (s *sceneWiFi) drawHintBar() { w, h := menu.GetFramebufferSize() - menu.DrawRect(0, float32(h)-70*menu.ratio, float32(w), 70*menu.ratio, 0, lightGrey) + menu.DrawRect(0, float32(h)-70*menu.ratio2, float32(w), 70*menu.ratio2, 0, lightGrey) _, upDown, _, a, b, _, _, _, _, _ := hintIcons() diff --git a/settings/defaults.go b/settings/defaults.go index 072615ec..b620ad42 100644 --- a/settings/defaults.go +++ b/settings/defaults.go @@ -8,9 +8,13 @@ import ( func defaultSettings() Settings { return Settings{ - VideoFullscreen: false, + VideoFullscreen: false, + // donmor: All new features disabled by default + VideoIntScaling: false, + VideoSuperRes: "Disabled", VideoMonitorIndex: 0, VideoFilter: "Pixel Perfect", + VideoUniFont: false, MapAxisToDPad: false, AudioVolume: 0.5, MenuAudioVolume: 0.25, diff --git a/settings/settings.go b/settings/settings.go index b3d6fb87..1135ac3a 100644 --- a/settings/settings.go +++ b/settings/settings.go @@ -23,9 +23,12 @@ import ( // Widget sets the graphical representation of the value. type Settings struct { VideoFullscreen bool `hide:"ludos" toml:"video_fullscreen" label:"Video Fullscreen" fmt:"%t" widget:"switch"` + VideoIntScaling bool `toml:"video_int_scaling" label:"Video Integer Scaling" fmt:"%t" widget:"switch"` + VideoSuperRes string `toml:"video_super_res" label:"Video Aspect Correction" fmt:"<%s>"` VideoMonitorIndex int `toml:"video_monitor_index" label:"Video Monitor Index" fmt:"%d"` VideoFilter string `toml:"video_filter" label:"Video Filter" fmt:"<%s>"` VideoDarkMode bool `toml:"video_dark_mode" label:"Video Dark Mode" fmt:"%t" widget:"switch"` + VideoUniFont bool `toml:"video_uni_font" label:"Video Enable Unicode Font" fmt:"%t" widget:"switch"` AudioVolume float32 `toml:"audio_volume" label:"Audio Volume" fmt:"%.1f" widget:"range"` diff --git a/video/font.go b/video/font.go index 2a139782..1dd6ef28 100644 --- a/video/font.go +++ b/video/font.go @@ -4,13 +4,17 @@ import ( "fmt" "image" "image/draw" + "image/png" "io" "io/ioutil" + "math" "os" "github.com/go-gl/gl/v2.1/gl" "github.com/golang/freetype" "github.com/golang/freetype/truetype" + "github.com/libretro/ludo/settings" + "github.com/nfnt/resize" "golang.org/x/image/font" "golang.org/x/image/math/fixed" ) @@ -44,6 +48,7 @@ type Font struct { color Color atlasWidth float32 atlasHeight float32 + xScale float32 } type point [4]float32 @@ -206,6 +211,109 @@ func LoadTrueTypeFont(program uint32, r io.Reader, scale int32, low, high rune, return f, nil } +// donmor: LoadUniFont builds a set of textures out of a png gylphs +func LoadUniFont(program uint32, r io.Reader, scale int32) (*Font, error) { + var bMap image.Image + var err error + // PNG image decoded here + bMap, err = png.Decode(r) + if err != nil { + return nil, err + } + + // 131072 if with plane 1 in the future + low, high := 1, 65536 + + // Make Font stuct type + f := new(Font) + f.fontChar = make([]*character, 0, high-low+1) + f.program = program // TODO: Can we use a basic one here? It looks blurry under super resolution + f.SetColor(Color{R: 1, G: 1, B: 1, A: 1}) // Set default white + + hOffset, vOffset := 32, 64 // Blanking in unifont glyphs + iScale := int(scale) + lineHeight := 16 * iScale + f.atlasWidth = float32(16 * 256 * iScale) + f.atlasHeight = float32(16 * 256 * iScale) + rect := image.Rect(0, 0, 16*256, int(16*256)) + rgba := image.NewRGBA(rect) + draw.Draw(rgba, rgba.Bounds(), bMap, image.Pt(hOffset, vOffset), draw.Over) + rgba = resize.Resize(uint(16*256*iScale), uint(16*256*iScale), rgba, resize.NearestNeighbor).(*image.RGBA) + x := 0 + y := 0 + + // Make each gylph + for ch := low; ch <= high; ch++ { + char := new(character) + char.x = x + char.y = y + char.width = 8 * iScale + char.height = 16 * iScale + char.advance = char.width << 6 + char.bearingV = char.height + char.bearingH = char.width + + // Check if is full-widthed + sRune := image.NewRGBA(image.Rect(0, 0, 16*iScale, 16*iScale)) + draw.Draw(sRune, sRune.Bounds(), rgba, image.Pt(x, y), draw.Over) + isFW := false + for i := 0; i < 8*iScale; i++ { + for j := 0; j < 16*iScale; j++ { + r, g, b, _ := sRune.At(8*iScale+i, j).RGBA() + isFW = r != 0 || g != 0 || b != 0 + if isFW { + char.width *= 2 + char.advance = char.width << 6 + char.bearingV = char.height + char.bearingH = char.width + break + } + } + if isFW { + break + } + } + + x += 16 * iScale + if x+16*iScale > int(f.atlasWidth) { + x = 0 + y += lineHeight + } + f.fontChar = append(f.fontChar, char) + } + + // Generate texture + gl.GenTextures(1, &f.textureID) + gl.BindTexture(gl.TEXTURE_2D, f.textureID) + gl.PixelStorei(gl.UNPACK_ALIGNMENT, 1) + gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) + gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) + + gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int32(rgba.Rect.Dx()), int32(rgba.Rect.Dy()), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(rgba.Pix)) + + gl.GenerateMipmap(gl.TEXTURE_2D) + gl.BindTexture(gl.TEXTURE_2D, 0) + + // Configure VAO/VBO for texture quads + genVertexArrays(1, &f.vao) + gl.GenBuffers(1, &f.vbo) + bindVertexArray(f.vao) + gl.BindBuffer(gl.ARRAY_BUFFER, f.vbo) + + vertAttrib := uint32(gl.GetAttribLocation(f.program, gl.Str("vert\x00"))) + gl.EnableVertexAttribArray(vertAttrib) + gl.VertexAttribPointerWithOffset(vertAttrib, 2, gl.FLOAT, false, 4*4, 0) + + texCoordAttrib := uint32(gl.GetAttribLocation(f.program, gl.Str("vertTexCoord\x00"))) + gl.EnableVertexAttribArray(texCoordAttrib) + gl.VertexAttribPointerWithOffset(texCoordAttrib, 2, gl.FLOAT, false, 4*4, 2*4) + + gl.BindBuffer(gl.ARRAY_BUFFER, 0) + bindVertexArray(0) + + return f, nil +} + // LoadFont loads the specified font at the given scale. func LoadFont(file string, scale int32, windowWidth int, windowHeight int) (*Font, error) { fd, err := os.Open(file) @@ -227,7 +335,11 @@ func LoadFont(file string, scale int32, windowWidth int, windowHeight int) (*Fon resUniform := gl.GetUniformLocation(program, gl.Str("resolution\x00")) gl.Uniform2f(resUniform, float32(windowWidth), float32(windowHeight)) - return LoadTrueTypeFont(program, fd, scale, 32, 256, LeftToRight) + if settings.Current.VideoUniFont { + return LoadUniFont(program, fd, 1) // 16x16, for performance + } else { + return LoadTrueTypeFont(program, fd, scale, 32, 256, LeftToRight) + } } // SetColor allows you to set the text color to be used when you draw the text @@ -241,17 +353,31 @@ func (f *Font) UpdateResolution(windowWidth int, windowHeight int) { resUniform := gl.GetUniformLocation(f.program, gl.Str("resolution\x00")) gl.Uniform2f(resUniform, float32(windowWidth), float32(windowHeight)) gl.UseProgram(0) + // donmor: Stretch the glyphs for super resolution + f.xScale = float32(1) + if settings.Current.VideoSuperRes == "16:9" { + bw, bh := float32(windowWidth), float32(windowHeight) + f.xScale = (bw / bh) / (16.0 / 9.0) + } else if settings.Current.VideoSuperRes == "4:3" { + bw, bh := float32(windowWidth), float32(windowHeight) + f.xScale = (bw / bh) / (4.0 / 3.0) + } } // Printf draws a string to the screen, takes a list of arguments like printf func (f *Font) Printf(x, y float32, scale float32, fs string, argv ...interface{}) error { indices := []rune(fmt.Sprintf(fs, argv...)) + unifont := settings.Current.VideoUniFont if len(indices) == 0 { return nil } - lowChar := rune(32) + // donmor: Unifont allows char below 32, doesn't make much sense though + lowChar := rune(0) + if !unifont { + lowChar = rune(32) + } // Setup blending mode gl.Enable(gl.BLEND) @@ -264,6 +390,19 @@ func (f *Font) Printf(x, y float32, scale float32, fs string, argv ...interface{ var coords []point + // donmor: Unifont is always integer-scaled + uniScale := int(scale*5 + 0.01) + uniXScale := int(f.xScale + 0.75) + if f.xScale < 0.8 { + uniScale -= int(1 / f.xScale) + } + if uniScale <= 0 { + uniScale = 1 + } + if uniXScale <= 0 { + uniXScale = 1 + } + // Iterate through all characters in string for i := range indices { // Get rune @@ -280,26 +419,49 @@ func (f *Font) Printf(x, y float32, scale float32, fs string, argv ...interface{ } // Calculate position and size for current rune - xpos := x - 1 + float32(ch.bearingH)*scale - ypos := y - 2 - float32(ch.height-ch.bearingV)*scale - w := float32(ch.width+2) * scale - h := float32(ch.height+2) * scale + var xpos float32 + var ypos float32 + if unifont { + xpos = x + ypos = y - float32(ch.height*uniScale) + } else { + xpos = x - 1 + float32(ch.bearingH)*scale*f.xScale + ypos = y - 2 - float32(ch.height-ch.bearingV)*scale + } + var w float32 + var h float32 + if unifont { + w = float32(ch.width * uniScale * uniXScale) + h = float32(ch.height * uniScale) + } else { + w = float32(ch.width+2) * scale * f.xScale + h = float32(ch.height+2) * scale + } // Set quad positions var x1 = xpos var x2 = xpos + w var y1 = ypos var y2 = ypos + h + // donmor: No padding for unifont + padding := 0 + if !unifont { + padding = 1 + } - coords = append(coords, point{x1, y1, float32(ch.x-1) / f.atlasWidth, float32(ch.y-1) / f.atlasHeight}) - coords = append(coords, point{x2, y1, float32(ch.x+ch.width+1) / f.atlasWidth, float32(ch.y-1) / f.atlasHeight}) - coords = append(coords, point{x1, y2, float32(ch.x-1) / f.atlasWidth, float32(ch.y+ch.height+1) / f.atlasHeight}) - coords = append(coords, point{x2, y1, float32(ch.x+ch.width+1) / f.atlasWidth, float32(ch.y-1) / f.atlasHeight}) - coords = append(coords, point{x1, y2, float32(ch.x-1) / f.atlasWidth, float32(ch.y+ch.height+1) / f.atlasHeight}) - coords = append(coords, point{x2, y2, float32(ch.x+ch.width+1) / f.atlasWidth, float32(ch.y+ch.height+1) / f.atlasHeight}) + coords = append(coords, point{x1, y1, float32(ch.x-padding) / f.atlasWidth, float32(ch.y-padding) / f.atlasHeight}) + coords = append(coords, point{x2, y1, float32(ch.x+ch.width+padding) / f.atlasWidth, float32(ch.y-padding) / f.atlasHeight}) + coords = append(coords, point{x1, y2, float32(ch.x-padding) / f.atlasWidth, float32(ch.y+ch.height+padding) / f.atlasHeight}) + coords = append(coords, point{x2, y1, float32(ch.x+ch.width+padding) / f.atlasWidth, float32(ch.y-padding) / f.atlasHeight}) + coords = append(coords, point{x1, y2, float32(ch.x-padding) / f.atlasWidth, float32(ch.y+ch.height+padding) / f.atlasHeight}) + coords = append(coords, point{x2, y2, float32(ch.x+ch.width+padding) / f.atlasWidth, float32(ch.y+ch.height+padding) / f.atlasHeight}) // Now advance cursors for next glyph (note that advance is number of 1/64 pixels) - x += float32((ch.advance >> 6)) * scale // Bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels)) + if unifont { + x += float32(ch.width * uniScale * uniXScale) + } else { + x += float32((ch.advance >> 6)) * scale * f.xScale // Bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels)) + } } bindVertexArray(f.vao) @@ -321,12 +483,28 @@ func (f *Font) Width(scale float32, fs string, argv ...interface{}) float32 { var width float32 indices := []rune(fmt.Sprintf(fs, argv...)) + unifont := settings.Current.VideoUniFont if len(indices) == 0 { return 0 } - lowChar := rune(32) + lowChar := rune(0) + if !unifont { + lowChar = rune(32) + } + + uniScale := int(scale*5 + 0.01) + uniXScale := int(math.Sqrt(float64(f.xScale + 0.75))) + if f.xScale < 0.8 { + uniScale -= int(1 / f.xScale) + } + if uniScale <= 0 { + uniScale = 1 + } + if uniXScale <= 0 { + uniXScale = 1 + } // Iterate through all characters in string for i := range indices { @@ -344,7 +522,11 @@ func (f *Font) Width(scale float32, fs string, argv ...interface{}) float32 { ch := f.fontChar[runeIndex-lowChar] // Now advance cursors for next glyph (note that advance is number of 1/64 pixels) - width += float32((ch.advance >> 6)) * scale // Bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels)) + if unifont { + width += float32(ch.width * uniScale * uniXScale) + } else { + width += float32((ch.advance >> 6)) * scale // Bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels)) + } } diff --git a/video/video.go b/video/video.go index 03d2dc71..091c6b3b 100644 --- a/video/video.go +++ b/video/video.go @@ -83,22 +83,31 @@ func (video *Video) SetShouldClose(b bool) { // Configure instanciates the video package func (video *Video) Configure(fullscreen bool) { - var width, height int + var width, height, refresh int var m *glfw.Monitor if fullscreen { m = glfw.GetMonitors()[settings.Current.VideoMonitorIndex] - vms := m.GetVideoModes() - vm := vms[len(vms)-1] + // donmor: Just get the correct video mode here + vm := m.GetVideoMode() width = vm.Width height = vm.Height + // donmor: Now we have refresh rate + refresh = vm.RefreshRate } else { width = 320 * 3 height = 180 * 3 } var err error - video.Window, err = glfw.CreateWindow(width, height, "Ludo", m, nil) + video.Window, err = glfw.CreateWindow(width, height, "Ludo", nil, nil) + if fullscreen { + // donmor: + // Set full screen mode separately with correct video mode + // Is it possible to set color bit depth? + mx, my := video.Window.GetPos() + video.Window.SetMonitor(m, mx, my, width, height, refresh) + } if err != nil { panic("Window creation failed:" + err.Error()) } @@ -119,6 +128,9 @@ func (video *Video) Configure(fullscreen bool) { // LoadFont (fontfile, font scale, window width, window height) fontPath := filepath.Join(settings.Current.AssetsDirectory, "font.ttf") + if settings.Current.VideoUniFont { + fontPath = filepath.Join(settings.Current.AssetsDirectory, "unifont.png") + } video.Font, err = LoadFont(fontPath, int32(36*2), fbw, fbh) if err != nil { panic(err) @@ -309,12 +321,62 @@ func (video *Video) coreRatioViewport(fbWidth int, fbHeight int) (x, y, w, h flo aspectRatio = float32(video.Geom.BaseWidth) / float32(video.Geom.BaseHeight) } - h = fbh - w = fbh * aspectRatio - if w > fbw { - h = fbw / aspectRatio - w = fbw + // donmor: 2022 patch-1 BEGIN + if settings.Current.VideoIntScaling { + gw := video.Geom.BaseWidth + gh := video.Geom.BaseHeight + if gh == 0 { + gh = fbHeight + } + scale := fbHeight / gh + h = float32(gh * scale) + if scale == 0 { + h = fbh + } + if settings.Current.VideoSuperRes == "16:9" { + w = aspectRatio * h * fbw * 9 / 16 / fbh + } else if settings.Current.VideoSuperRes == "4:3" { + w = aspectRatio * h * fbw * 3 / 4 / fbh + } else { + w = h * float32(gw) / float32(gh) + } + for w > fbw { + scale -= 1 + h = float32(gh * scale) + if scale == 0 { + h = float32(gh) + } + if settings.Current.VideoSuperRes == "16:9" && scale > 0 { + w = aspectRatio * h * fbw * 9 / 16 / fbh + } else if settings.Current.VideoSuperRes == "4:3" && scale > 0 { + w = aspectRatio * h * fbw * 3 / 4 / fbh + } else { + w = fbw + h = fbw * float32(gh) / float32(gw) + } + } + } else { + h = fbh + if settings.Current.VideoSuperRes == "16:9" { + w = aspectRatio * fbw * 9 / 16 + } else if settings.Current.VideoSuperRes == "4:3" { + w = aspectRatio * fbw * 3 / 4 + } else { + w = fbh * aspectRatio + } + if w > fbw { + w = fbw + if settings.Current.VideoSuperRes == "16:9" { + h = fbh * 16 / 9 / aspectRatio + } else if settings.Current.VideoSuperRes == "4:3" { + h = fbh * 16 / 9 / aspectRatio + } else { + h = fbw / aspectRatio + } + } } + // donmor: 2022 patch-1 END + // Now only God knows what I wrote here <:-/ // Place the content in the middle of the window. x = (fbw - w) / 2