Merge branch 'master' of ssh://code.nikooneshot.ru:222/Sunshine/mkxp-sunshine

This commit is contained in:
niko(depressedTWM) 2026-07-16 09:08:00 -04:00
commit 34059c5d8b
33 changed files with 201 additions and 114 deletions

View file

@ -82,6 +82,7 @@ set(MAIN_HEADERS
src/signals/signal.h
src/signals/signalconnection.h
src/signals/rubydispatcher.h
src/signals/maindispatcher.h
)
set(MAIN_SOURCE
@ -129,6 +130,7 @@ set(MAIN_SOURCE
src/sunshine.cpp
src/lightmap.cpp
src/signals/rubydispatcher.cpp
src/signals/maindispatcher.cpp
)
if(WIN32)

View file

@ -10,6 +10,7 @@ Artists:
* DesMo
* Обси
* DepressedTWM
* K1RMAN
Testers:
* Rubik

View file

@ -1,34 +1,35 @@
# mkxp-sunshine
This is a specialized fork of [mkxp-oneshot](https://github.com/elizagamedev/mkxp-oneshot) designed for OneShot: sunshine mod.
This is a specialized fork of [mkxp-oneshot](https://github.com/elizagamedev/mkxp-oneshot) designed for OneShot: Sunshine mod.
Target of sunshine mod - improve original game.
# xScripts.rxdata
## xScripts.rxdata
./rpgscript.rb scripts/ [GameDir]
# Build
1.Install required packages
* Cmake
* C/C++ compiler
* xxd
* Ruby 3+
* Boost
* SDL3
* pixman
* SDL3_image
* SDL3_ttf
* [SDL3_sound](https://github.com/icculus/SDL_sound)
* OpenAL
* PhysFS
* sigc++-2.0
* OpenSSL
* libzip
* GTK3(Linux only!)
* libxfconf(Linux only!)
## Build
2.build
1. Install required packages
* Cmake
* C/C++ compiler
* xxd
* Ruby 3+
* Boost
* SDL3
* pixman
* SDL3_image
* SDL3_ttf
* [SDL3_sound](https://github.com/icculus/SDL_sound)
* OpenAL
* PhysFS
* sigc++-2.0
* OpenSSL
* libzip
* GTK3(Linux only!)
* libxfconf(Linux only!)
* In project dir create build dir
* cmake -S . -B build
* cd build
* make -jn (n - count of threads for compilation)
2. build
* In project dir create build dir
* cmake -S . -B build
* cd build
* make -jn (n - count of threads for compilation)

View file

@ -297,5 +297,5 @@ void graphicsBindingInit(){
INIT_GRA_PROP_BIND( Frameskip, "frameskip" );
const Config &conf = shState->rtData().config;
rb_define_const(module, "RESOLUTION_ASPECT", rb_str_new_cstr(conf.AspectPresetRubyConst.c_str()));
rb_define_const(module, "RESOLUTION_OVERRIDDEN", rb_bool_new(conf.resolutionOverridden));
}

View file

@ -17,10 +17,7 @@ module RPG
module Cache
@cache = {}
def self.load_bitmap(folder_name, filename, hue = 0)
path = folder_name + filename
if File.exist?(folder_name + filename + Graphics::RESOLUTION_ASPECT + ".png")
path += Graphics::RESOLUTION_ASPECT
end
path = Graphics.adapted_file(folder_name + filename)
if not @cache.include?(path) or @cache[path].disposed?
if filename != ""
@cache[path] = Bitmap.new(path)

View file

@ -67,3 +67,5 @@ main viewport resize, main window resize and move signals bindings for ruby
Dynamic resolution support (WIP)
Rewrited to use SDL3 libc methods instead default
Removed useless debug logs
Glen reworked
GLLogger \n bug fix

0
libraries.rb Normal file → Executable file
View file

0
make-appimage.sh Normal file → Executable file
View file

1
make-journal-linux.sh Normal file → Executable file
View file

@ -1,5 +1,6 @@
#!/bin/bash -eu
if [ $# -lt 2 ]; then
echo "usage: make-journal-linux.sh SOURCE_PATH OUTPUT_DIR"
exit 1

View file

@ -1,5 +1,4 @@
#!/bin/sh
#set -e
set -euo pipefail
cd `dirname $0`

0
mklang.rb Normal file → Executable file
View file

0
mklangsrc.rb Normal file → Executable file
View file

View file

@ -25,25 +25,11 @@ printFPS=false
# as opposed to stretch-to-fill
fixedAspectRatio=true
# Set Monitor Aspect preset
# Value, Aspect, Window Resolusion
# (ratio and resolution are not acceptable values)
# Where X - not recommended, the correctness of
# the game is not guaranteed.
# 0 - 3:2 - 720:480
# 1 - 4:3 - 640x480 (default)
# 2 - 16:9 - 960x540
# 3 - 16:10 - 960x600
# 4 - 16:9 HD - 1280x720 X
# 5 - 16:9 FHD - 1920x1080 X
AspectPreset=1
# Controlling the resolution of the game window,
# it is not recommended to change.
# If you want to configure 16:9 or any other,
# use AspectPreset.
# defScreenW=0
# defScreenH=0
# Controlling the resolution of the game window,
# and disables resolution setting in game,
# it is not recommended to change.
defScreenW=0
defScreenH=0
# Apply linear interpolation when game screen
# is upscaled

View file

@ -84,8 +84,9 @@ set(scripts
Window_TPtL.rb
Settings.rb
Input.rb
DynamicLight.rb
Gamepad_Colors.rb)
Dynamic_Light.rb
Gamepad_Colors.rb
Dynamic_Resolution.rb)
find_program(RUBY_EXE ruby
DOC "Location of the Ruby executable")

View file

@ -8,6 +8,7 @@ module Settings
# Video
:fullscreen => false,
:resolution => 0,
:colorblind => false,
:frameskip => true,
:twm_shader => true,
@ -142,6 +143,13 @@ class Window_Settings
:name => tr('Fullscreen'),
:parameter => :fullscreen
},
{
:type => :enum,
:name => tr('Resolution'),
:default => 0,
:parameter => Graphics::RESOLUTION_OVERRIDDEN ? nil : :resolution,
:values => Graphics::RESOLUTION_OVERRIDDEN ? ["Resolution is redefined via config"] : Graphics.resolutions_names_list
},
{
:type => :bool,
:name => tr('Colorblind mode'),

View file

@ -18,16 +18,19 @@ class Window_Settings
attr_reader :viewport
attr_reader :offset
def initialize(viewport, offset_y)
def initialize(viewport, offset_y, screen = 0, index = 0)
Window_Settings.send(:remove_const, :PARAMETER_WIDTH)
Window_Settings.const_set(:PARAMETER_WIDTH, (Graphics.width - 640) / 2 + 512) # костыль бля
@viewport = viewport
@screen = 0
@index = 0
@screen = screen
@index = index
@opacity = 255
@offset = offset_y
@waiting_for_key = false
@wait_timer = 0
@visible_x = 0
@visible_x = @screen * Graphics.width
@visible_y = offset_y
@x = (Graphics.width - PARAMETER_WIDTH) / 2
@y = offset_y
@ -36,7 +39,7 @@ class Window_Settings
@selection_sprite.bitmap = Bitmap.new(PARAMETER_WIDTH + 16, PARAMETER_HEIGHT)
@selection_sprite.bitmap.fill_rect(Rect.new(0, 0, PARAMETER_WIDTH + 16, PARAMETER_HEIGHT), Color.new(255, 255, 255, 64))
@selection_sprite.x = @x - 8
@selection_sprite.y = @offset
@selection_sprite.y = @index * PARAMETER_HEIGHT + @y
@selection_sprite.blend_type = 1
@selection_sprite.z = 1

View file

@ -20,6 +20,17 @@ module Settings
def fullscreen(value)
Graphics.fullscreen = $console = value
end
def resolution(value)
if (!Graphics::RESOLUTION_OVERRIDDEN)
res_data = Graphics::RESOLUTIONS&.[](value) || {:width => 480, :height => 640}
old_width = Graphics.width
old_height = Graphics.height
new_width = res_data[:width]
new_height = res_data[:height]
Graphics.move_screen(Graphics.x - (new_width - old_width) / 2, Graphics.y - (new_height - old_height) / 2)
Graphics.resize_screen(new_width, new_height)
end
end
def colorblind(value)
$game_switches[252] = value
end

View file

@ -0,0 +1,48 @@
module Graphics
# 0 - 3:2 - 720x480
# 1 - 4:3 - 640x480 (default)
# 2 - 16:9 - 960x540
# 3 - 16:10 - 960x600
RESOLUTIONS = [
{
:display_name => "4:3 - 640x480",
:file_tag => "_4_3",
:width => 640,
:height => 480,
},
{
:display_name => "3:2 - 720x480",
:file_tag => "_3_2",
:width => 720,
:height => 480,
},
{
:display_name => "16:9 - 960x540",
:file_tag => "_16_9",
:width => 960,
:height => 540,
},
{
:display_name => "16:10 - 960x600",
:file_tag => "_16_10",
:width => 960,
:height => 600,
},
]
def self.resolutions_names_list
list = []
RESOLUTIONS.each do |res_data|
list << res_data[:display_name]
end
list
end
def self.adapted_file(path, extention = ".png")
file_tag = RESOLUTIONS[Settings[:resolution] || 999]&.[](:file_tag) || ""
if File.exist?(path + file_tag + extention)
path + file_tag
end
path
end
end

View file

@ -3,7 +3,7 @@ module Settings
class << self
def [](k)
@data[k]
@data&.[](k)
end
def []=(k, v)

View file

@ -10,8 +10,10 @@ class Window_Settings
@viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
@viewport.z = 9998
@bg = Sprite.new(@viewport)
@bg.bitmap = Bitmap.new(Graphics.width, Graphics.height)
@bg.bitmap.fill_rect(0, 0, Graphics.width, Graphics.height, Color.new(0, 0, 0, 196))
@bg.bitmap = Bitmap.new(1, 1)
@bg.bitmap.fill_rect(0, 0, 1, 1, Color.new(0, 0, 0, 196))
@bg.zoom_x = Graphics.width
@bg.zoom_y = Graphics.height
@title = Sprite.new(@viewport)
@title.bitmap = Bitmap.new(320, 20)
@title.bitmap.font.size = 20
@ -27,9 +29,11 @@ class Window_Settings
if self.visible
@viewport.rect.width = w
@viewport.rect.height = h
@bg.bitmap.dispose
@bg.bitmap = Bitmap.new(w, h)
@bg.bitmap.fill_rect(0, 0, w, h, Color.new(0, 0, 0, 196))
@bg.zoom_x = w
@bg.zoom_y = h
#@bg.bitmap.dispose
#@bg.bitmap = Bitmap.new(w, h)
#@bg.bitmap.fill_rect(0, 0, w, h, Color.new(0, 0, 0, 196))
@title.x = (w - @title.bitmap.width) / 2
init_content
else
@ -50,11 +54,15 @@ class Window_Settings
end
def init_content
old_screen = 0
old_index = 0
if (@content)
old_screen = @content.screen
old_index = @content.index
@content.dispose
end
@content = SettingsContent.new(@viewport, TITLE_TOP_MARGIN + TITLE_MARGIN + 100)
@content = SettingsContent.new(@viewport, TITLE_TOP_MARGIN + TITLE_MARGIN + 100, old_screen, old_index)
DATA.each_with_index do |(screen_title, parameters_info), screen_index|
@content.add_screen(screen_title)

View file

@ -31,6 +31,8 @@ Game_Light
Settings
Input
Gamepad_Colors
Dynamic_Resolution
Dynamic_Light
Sprite_Character
Sprite_Picture
@ -103,7 +105,6 @@ Doc_Message
Desktop_Message
Credits_Message
Particles
DynamicLight
EdText
Main

View file

@ -12,7 +12,6 @@ class Language
def set(lc)
@data = nil
@tr = nil
script = nil
[lc.full.to_s, lc.lang.to_s].each do |name|
path = "Languages/#{name}.po"
if FileTest.exist?(path)
@ -35,36 +34,36 @@ class Language
str.chars.each do |c|
if not string_began
string_began = true if c == '"'
next
next
end
next if c == "\n"
next if c == "\r"
if not escape
break if c == '"'
if c == '\\'
escape = true
next
end
else
escape = false
case c
when 'n'
unescaped.push("\n")
when 'r'
unescaped.push("\r")
else
unescaped.push(c)
end
next
end
escape = true
next
end
else
escape = false
case c
when 'n'
unescaped.push("\n")
when 'r'
unescaped.push("\r")
else
unescaped.push(c)
end
next
end
unescaped.push(c)
end
return unescaped.join('')
end
end
return unescaped.join('')
end
def load_pot(path)
msgid = nil

View file

@ -72,11 +72,11 @@ void Config::read(int argc, char *argv[]){
PO_DESC(printFPS, bool, false) \
PO_DESC(fullscreen, bool, false) \
PO_DESC(fixedAspectRatio, bool, true) \
PO_DESC(AspectPreset, int, 1) \
/*PO_DESC(AspectPreset, int, 1)*/ \
PO_DESC(smoothScaling, bool, false) \
PO_DESC(vsync, bool, true) \
PO_DESC(defScreenW, int, 640) \
PO_DESC(defScreenH, int, 480) \
PO_DESC(defScreenW, int, 0) \
PO_DESC(defScreenH, int, 0) \
PO_DESC(windowTitle, std::string, "") \
PO_DESC(commonDataPath, std::string, "") \
PO_DESC(Modloader.ModsDirPath, std::string,"mods") \
@ -181,6 +181,10 @@ void Config::read(int argc, char *argv[]){
game.title = "OneShot: Sunshine";
game.scripts = "Data/xScripts.rxdata";
resolutionOverridden = defScreenW > 0 || defScreenH > 0;
defScreenW = defScreenW <= 0 ? 640 : defScreenW;
defScreenH = defScreenH <= 0 ? 480 : defScreenH;
/*
#define ASPECT_SELECT(id, x, y, rubyConst) \
case id: { \
defScreenW = x; \
@ -202,7 +206,7 @@ void Config::read(int argc, char *argv[]){
}
#undef ASPECT_SELECT
*/
#ifdef STEAM
/* Override fullscreen config if Big Picture */
if (const char *env = SDL_getenv("SteamTenfoot")){

View file

@ -32,6 +32,7 @@ struct Config{
bool printFPS;
bool fullscreen;
bool fixedAspectRatio;
bool resolutionOverridden;
bool Windows_AllocConsole;
bool smoothScaling;
bool vsync;
@ -51,8 +52,8 @@ struct Config{
int maxTextureSize;
std::string gameFolder;
int AspectPreset;
std::string AspectPresetRubyConst;
//int AspectPreset;
//std::string AspectPresetRubyConst;
bool allowSymlinks;
bool pathCache;

View file

@ -180,6 +180,9 @@ void EventThread::process(RGSSThreadData &rtData){
SDL_GetWindowPosition(win, &rtData.ethread->winX, &rtData.ethread->winY);
while (true) {
if (shState != nullptr)
shState->mainDispatcher().process();
if (!SDL_WaitEvent(&event)) {
Debug() << "[EventThread::process] Event error:\n" << SDL_GetError();
break;

View file

@ -38,8 +38,12 @@ struct GLDebugLoggerPrivate{
~GLDebugLoggerPrivate(){}
void writeTimestamp(){
//https://stackoverflow.com/questions/9628637/how-can-i-get-rid-of-n-from-string-in-c
time(&timestamp);
*stream << "[GLDEBUG] [" << ctime(&timestamp) << "]";
char *foo = ctime(&timestamp);
if (strlen(foo) > 0) // i dont want segfault, im afraid of it >m<
foo[strlen(foo) - 1] = '\0';
*stream << "[GLDEBUG] [" << foo << "] ";
}
void writeLine(const char *line){

View file

@ -336,8 +336,6 @@ int main(int argc, char *argv[]){
* dealing with icons; don't interfere with them */
#ifdef unix_like
setupWindowIcon(conf, win);
#elif __EMSCRIPTEN__
Debug() << "meow";
#else
(void) setupWindowIcon;
#endif

View file

@ -57,7 +57,7 @@ struct SharedStatePrivate{
Scene *screen;
RubyDispatcher rubyDispatcher;
RenderDispatcher renderDispatcher;
MainDispatcher mainDispatcher;
FileSystem fileSystem;
@ -100,7 +100,7 @@ struct SharedStatePrivate{
: bindingData(0),
sdlWindow(threadData->window),
rubyDispatcher(),
renderDispatcher(),
mainDispatcher(),
fileSystem(threadData->config.allowSymlinks),
eThread(*threadData->ethread),
rtData(*threadData),
@ -200,7 +200,7 @@ GSATT(void*, bindingData)
GSATT(SDL_Window*, sdlWindow)
GSATT(Scene*, screen)
GSATT(RubyDispatcher&, rubyDispatcher)
GSATT(RenderDispatcher&, renderDispatcher)
GSATT(MainDispatcher&, mainDispatcher)
GSATT(FileSystem&, fileSystem)
GSATT(EventThread&, eThread)
GSATT(RGSSThreadData&, rtData)

View file

@ -24,7 +24,7 @@
#include "signals/signal.h"
#include "signals/rubydispatcher.h"
#include "signals/renderdispatcher.h"
#include "signals/maindispatcher.h"
#define shState SharedState::instance
#define glState shState->_glState()
@ -74,7 +74,7 @@ struct SharedState{
// dispatchers, they redirect signals from another thread to their own
RubyDispatcher &rubyDispatcher() const;
RenderDispatcher &renderDispatcher() const;
MainDispatcher &mainDispatcher() const;
// other shit idk
void *bindingData() const;

View file

@ -1,11 +1,11 @@
#include "renderdispatcher.h"
#include "maindispatcher.h"
void RenderDispatcher::invoke(std::function<void()> fn){
void MainDispatcher::invoke(std::function<void()> fn){
std::lock_guard lock(mutex);
queue.push(std::move(fn));
}
void RenderDispatcher::process(){
void MainDispatcher::process(){
std::queue<std::function<void()>> local;
{

View file

@ -4,9 +4,9 @@
#include <mutex>
#include <queue>
class RenderDispatcher{
class MainDispatcher{
public:
RenderDispatcher() {};
MainDispatcher() {};
void invoke(std::function<void()> fn);
void process();

View file

@ -1,26 +1,35 @@
#pragma once
#include <sigc++/connection.h>
#include "debugwriter.h"
class SignalConnection{
public:
SignalConnection() = default;
SignalConnection(sigc::connection conn)
: connection(std::move(conn))
{}
void Disconnect()
{
connection.disconnect();
if (&connection != nullptr)
//if (connection.connected())
connection.disconnect();
//else
// Debug() << "Double disconnect!";
else
Debug() << "Couldn't disconnect nullptr connection!";
}
bool Connected() const
{
if (&connection == nullptr)
Debug() << "nullptr connection!";
return false;
return connection.connected();
}
private:
SignalConnection(sigc::connection conn)
: connection(std::move(conn))
{}
sigc::connection connection;
template<typename>