mirror of
https://github.com/wiiu-env/ScreenshotWUPS.git
synced 2024-11-21 14:09:15 +01:00
Port plugin to Aroma
This commit is contained in:
parent
539e06b46c
commit
425c52add3
67
.clang-format
Normal file
67
.clang-format
Normal file
@ -0,0 +1,67 @@
|
||||
# Generated from CLion C/C++ Code Style settings
|
||||
BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: Consecutive
|
||||
AlignConsecutiveMacros: AcrossEmptyLinesAndComments
|
||||
AlignOperands: Align
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowAllConstructorInitializersOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: Always
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Always
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterUnion: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakInheritanceList: BeforeColon
|
||||
ColumnLimit: 0
|
||||
CompactNamespaces: false
|
||||
ContinuationIndentWidth: 8
|
||||
IndentCaseLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 4
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MaxEmptyLinesToKeep: 2
|
||||
NamespaceIndentation: All
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PointerAlignment: Right
|
||||
ReflowComments: false
|
||||
SpaceAfterCStyleCast: true
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
72
.github/workflows/ci.yml
vendored
Normal file
72
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
name: CI-Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
clang-format:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: clang-format
|
||||
run: |
|
||||
docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./src
|
||||
build-binary:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: clang-format
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: create version.h
|
||||
run: |
|
||||
git_hash=$(git rev-parse --short "$GITHUB_SHA")
|
||||
cat <<EOF > ./src/version.h
|
||||
#pragma once
|
||||
#define VERSION_EXTRA " (nightly-$git_hash)"
|
||||
EOF
|
||||
- name: build binary
|
||||
run: |
|
||||
docker build . -t builder
|
||||
docker run --rm -v ${PWD}:/project builder make
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: binary
|
||||
path: "*.wps"
|
||||
deploy-binary:
|
||||
needs: build-binary
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Get environment variables
|
||||
id: get_repository_name
|
||||
run: |
|
||||
echo REPOSITORY_NAME=$(echo "$GITHUB_REPOSITORY" | awk -F / '{print $2}' | sed -e "s/:refs//") >> $GITHUB_ENV
|
||||
echo DATETIME=$(echo $(date '+%Y%m%d-%H%M%S')) >> $GITHUB_ENV
|
||||
- uses: actions/download-artifact@master
|
||||
with:
|
||||
name: binary
|
||||
- name: zip artifact
|
||||
run: zip -r ${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip *.wps
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ env.REPOSITORY_NAME }}-${{ env.DATETIME }}
|
||||
release_name: Nightly-${{ env.REPOSITORY_NAME }}-${{ env.DATETIME }}
|
||||
draft: false
|
||||
prerelease: true
|
||||
body: |
|
||||
Not a stable release:
|
||||
${{ github.event.head_commit.message }}
|
||||
- name: Upload Release Asset
|
||||
id: upload-release-asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
|
||||
asset_path: ./${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip
|
||||
asset_name: ${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip
|
||||
asset_content_type: application/zip
|
32
.github/workflows/pr.yml
vendored
Normal file
32
.github/workflows/pr.yml
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
name: CI-PR
|
||||
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
clang-format:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: clang-format
|
||||
run: |
|
||||
docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./src
|
||||
build-binary:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: clang-format
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: create version.h
|
||||
run: |
|
||||
git_hash=$(git rev-parse --short "${{ github.event.pull_request.head.sha }}")
|
||||
cat <<EOF > ./src/version.h
|
||||
#pragma once
|
||||
#define VERSION_EXTRA " (nightly-$git_hash)"
|
||||
EOF
|
||||
- name: build binary
|
||||
run: |
|
||||
docker build . -t builder
|
||||
docker run --rm -v ${PWD}:/project builder make
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: binary
|
||||
path: "*.wps"
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,2 +1,7 @@
|
||||
build/*
|
||||
*.mod
|
||||
cmake-build-debug/
|
||||
.idea/
|
||||
*.wps
|
||||
*.elf
|
||||
CMakeLists.txt
|
||||
|
31
.travis.yml
31
.travis.yml
@ -1,31 +0,0 @@
|
||||
sudo: required
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
services:
|
||||
- docker
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- p7zip-full
|
||||
before_script:
|
||||
- docker build . -t screenshot-builder
|
||||
script:
|
||||
- docker run -it --rm -v ${PWD}:/project screenshot-builder make
|
||||
before_deploy:
|
||||
- cd $TRAVIS_BUILD_DIR/
|
||||
- mkdir -p "wiiu/plugins"
|
||||
- commit="$(git rev-parse --short=7 HEAD)"
|
||||
- find -type f -name "*.mod" | xargs -i cp {} wiiu/plugins
|
||||
- zip -r screenshot_wups_nightly_$commit.zip wiiu
|
||||
- git config --local user.name "Maschell"
|
||||
- git config --local user.email "Maschell@gmx.de"
|
||||
- git tag "ScreenshotWUPS-$(date +'%Y%m%d%H%M%S')-$(git log --format=%h -1)"
|
||||
deploy:
|
||||
provider: releases
|
||||
skip_cleanup: true
|
||||
api_key:
|
||||
secure: HU3Ymp5pGjTj4z59sFAkDc02WhQol+CER9UTEpvLjLuklzbguuSc6rtnorA+krWBJvk1+Gl50JqlhhI9HuauU/oTvNQLah3DC29aDmxAHFQ7fk5FDap+BBYTkb7CKPI5l1k4GRqK3EwKQMJ2L+/BdwraLHazLbU22OPPYSZvrsGBej3Nvdg6C6QcwYN3E2nO5lbxnclag+6MduKKfyvd7zA/llexrZXYC71HskEcRHIX/ol5l3yiR9L/0LcGU1hn63+O6wdC58+RxuvfRE8Zj/O853yWmAs4ltUBsFstDMvzmw9aYlN0bK8nvYvv1oBOR4ql4aPwkaEjAUzEorIBIFn8gSSdHNM5QmW+Zf+nPdIQVpS4EsDZbvM7QoptdgOuZVk7MnTVKg/7vZVDI7IMm3T/GleuwsvKs6+/jPjEhvslyKLKRaQGREGPCtAkPbDn9S8eVyhgkqQk1g5+O0RA6t9FmiOS+QPyhjSyqGPaHXQvsiN2PmGnE1YbjqUBBoy2tly4TUb+M/gGYDipKyCuQiqCpp04GYmIIHjxpIZOTZGA/klUODKTBG6DOnVNBqsYBpSwO9PIYO+gPWWBXzRF4A2/fB2TuAWVSB3FZ/Ml7AVZWXcU8l84uhKmLNJ+oeXDDDcrt4iAvjfoiWWATD0WEoZgiFDQ98nM6EqgRMQ4f1Q=
|
||||
file: screenshot_wups_nightly_$commit.zip
|
||||
on:
|
||||
repo: Maschell/ScreenshotWUPS
|
@ -1,6 +1,6 @@
|
||||
FROM wups/core-with-wut:0.1
|
||||
FROM wiiuenv/devkitppc:20220917
|
||||
|
||||
# Get dependencies
|
||||
COPY --from=wiiuwut/libutils:0.1 /artifacts $WUT_ROOT
|
||||
COPY --from=wiiuenv/wiiupluginsystem:20220904 /artifacts $DEVKITPRO
|
||||
COPY --from=wiiuenv/libmappedmemory:20220904 /artifacts $DEVKITPRO
|
||||
|
||||
WORKDIR project
|
355
Makefile
355
Makefile
@ -1,300 +1,147 @@
|
||||
# You probably never need to adjust this Makefile.
|
||||
# All changes can be done in the makefile.mk
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# Clear the implicit built in rules
|
||||
#---------------------------------------------------------------------------------
|
||||
#-------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(DEVKITPPC)),)
|
||||
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
|
||||
endif
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITPRO)),)
|
||||
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>devkitPRO")
|
||||
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
|
||||
endif
|
||||
|
||||
export PATH := $(DEVKITPPC)/bin:$(PORTLIBS)/bin:$(PATH)
|
||||
export PORTLIBS := $(DEVKITPRO)/portlibs/ppc
|
||||
export WUPSDIR := $(DEVKITPRO)/wups
|
||||
export GCC_VER := $(shell $(DEVKITPPC)/bin/powerpc-eabi-gcc -dumpversion)
|
||||
TOPDIR ?= $(CURDIR)
|
||||
|
||||
PREFIX := powerpc-eabi-
|
||||
include $(DEVKITPRO)/wups/share/wups_rules
|
||||
|
||||
export AS := $(PREFIX)as
|
||||
export CC := $(PREFIX)gcc
|
||||
export CXX := $(PREFIX)g++
|
||||
export LD := $(PREFIX)ld
|
||||
export AR := $(PREFIX)ar
|
||||
export OBJCOPY := $(PREFIX)objcopy
|
||||
WUT_ROOT := $(DEVKITPRO)/wut
|
||||
WUMS_ROOT := $(DEVKITPRO)/wums
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
#-------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# INCLUDES is a list of directories containing extra header files
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := $(notdir $(CURDIR))
|
||||
BUILD := build
|
||||
# DATA is a list of directories containing data files
|
||||
# INCLUDES is a list of directories containing header files
|
||||
#-------------------------------------------------------------------------------
|
||||
TARGET := screenshot
|
||||
BUILD := build
|
||||
SOURCES := src src/utils src/fs
|
||||
DATA := data
|
||||
INCLUDES := src
|
||||
|
||||
ifeq ($(notdir $(CURDIR)),$(BUILD))
|
||||
include ../makefile.mk
|
||||
else
|
||||
include makefile.mk
|
||||
endif
|
||||
|
||||
include $(WUPSDIR)/plugin_makefile.mk
|
||||
|
||||
|
||||
#MAP ?= $(TARGET:.mod=.map)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
#-------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
#-------------------------------------------------------------------------------
|
||||
CFLAGS := -Wall -O2 -ffunction-sections \
|
||||
$(MACHDEP)
|
||||
|
||||
# -Os: optimise size
|
||||
# -Wall: generate lots of warnings
|
||||
# -D__wiiu__: define the symbol __wiiu__ (used in some headers)
|
||||
# -mcpu=750: enable processor specific compilation
|
||||
# -meabi: enable eabi specific compilation
|
||||
# -mhard-float: enable hardware floating point instructions
|
||||
# -nostartfiles: Do not use the standard system startup files when linking
|
||||
# -ffunction-sections: split up functions so linker can garbage collect
|
||||
# -fdata-sections: split up data so linker can garbage collect
|
||||
COMMON_CFLAGS := -Os -Wall -mcpu=750 -meabi -mhard-float -D__WIIU__ -nostartfiles -ffunction-sections -fdata-sections -Wl,-q $(COMMON_CFLAGS)
|
||||
CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__ -D__WUPS__
|
||||
|
||||
# -x c: compile as c code
|
||||
# -std=c11: use the c11 standard
|
||||
CFLAGS := $(COMMON_CFLAGS) -x c -std=gnu11 $(CFLAGS)
|
||||
CXXFLAGS := $(CFLAGS)
|
||||
|
||||
# -x c: compile as c++ code
|
||||
# -std=gnu++11: use the c++11 standard
|
||||
CXXFLAGS := $(COMMON_CFLAGS) -x c++ -std=gnu++11 $(CXXFLAGS)
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -g $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map) -T$(WUMS_ROOT)/share/libmappedmemory.ld $(WUPSSPECS)
|
||||
|
||||
ifeq ($(DO_LOGGING), 1)
|
||||
CFLAGS += -D__LOGGING__
|
||||
CXXFLAGS += -D__LOGGING__
|
||||
ifeq ($(DEBUG),1)
|
||||
CXXFLAGS += -DDEBUG -g
|
||||
CFLAGS += -DDEBUG -g
|
||||
endif
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# any extra ld flags
|
||||
#--------------------------------------------------------------------------------
|
||||
# --gc-sections: remove unneeded symbols
|
||||
# -Map: generate a map file
|
||||
LDFLAGS += -Wl,-Map,$(notdir $@).map,--gc-sections
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
Q := @
|
||||
MAKEFLAGS += --no-print-directory
|
||||
#---------------------------------------------------------------------------------
|
||||
# any extra libraries we wish to link with the project
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBS +=
|
||||
#
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS +=
|
||||
|
||||
NEEDS_WUT := 0
|
||||
|
||||
ifeq ($(WUT_ENABLE_CPP), 1)
|
||||
WUT_ENABLE_NEWLIB := 1
|
||||
|
||||
LDFLAGS += -Wl,-whole-archive,-lwutstdc++,-no-whole-archive
|
||||
NEEDS_WUT := 1
|
||||
ifeq ($(DEBUG),VERBOSE)
|
||||
CXXFLAGS += -DDEBUG -DVERBOSE_DEBUG -g
|
||||
CFLAGS += -DDEBUG -DVERBOSE_DEBUG -g
|
||||
endif
|
||||
|
||||
ifeq ($(WUT_ENABLE_NEWLIB), 1)
|
||||
LDFLAGS += -Wl,-whole-archive,-lwutnewlib,-no-whole-archive
|
||||
NEEDS_WUT := 1
|
||||
endif
|
||||
LIBS := -lwups -lwut -lgd -lpng -ljpeg -lz -lmappedmemory
|
||||
|
||||
ifeq ($(WUT_DEFAULT_MALLOC), 1)
|
||||
LDFLAGS += -Wl,-whole-archive,-lwutmalloc,-no-whole-archive
|
||||
NEEDS_WUT := 1
|
||||
endif
|
||||
#-------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level
|
||||
# containing include and lib
|
||||
#-------------------------------------------------------------------------------
|
||||
LIBDIRS := $(PORTLIBS) $(WUPS_ROOT) $(WUT_ROOT) $(WUMS_ROOT)
|
||||
|
||||
ifeq ($(NEEDS_WUT), 1)
|
||||
ifeq ($(strip $(WUT_ROOT)),)
|
||||
$(error "Please set WUT_ROOT in your environment. export WUT_ROOT=<path to>wut)
|
||||
endif
|
||||
CFLAGS += -D__WUT__
|
||||
CXXFLAGS += -D__WUT__
|
||||
endif
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
#-------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
#-------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
export PROJECTDIR := $(CURDIR)
|
||||
export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET)
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# automatically build a list of object files for our project
|
||||
#---------------------------------------------------------------------------------
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
TTFFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.ttf)))
|
||||
PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
export REAL_LD := $(CC)
|
||||
else
|
||||
export REAL_LD := $(CXX)
|
||||
endif
|
||||
|
||||
export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
|
||||
$(sFILES:.s=.o) $(SFILES:.S=.o) \
|
||||
$(PNGFILES:.png=.png.o) $(addsuffix .o,$(BINFILES))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# build a list of include paths
|
||||
#---------------------------------------------------------------------------------
|
||||
export INCLUDE_FULL += $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
$(EXTERNAL_INCLUDE)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# build a list of library paths
|
||||
#---------------------------------------------------------------------------------
|
||||
export LIBPATHS_FULL += $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
|
||||
$(EXTERNAL_LIBPATHS)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
.PHONY: $(BUILD) clean install
|
||||
export TOPDIR := $(CURDIR)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#-------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
#-------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
#-------------------------------------------------------------------------------
|
||||
else
|
||||
#-------------------------------------------------------------------------------
|
||||
export LD := $(CXX)
|
||||
#-------------------------------------------------------------------------------
|
||||
endif
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
||||
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
||||
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I$(CURDIR)/$(BUILD)
|
||||
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
.PHONY: $(BUILD) clean all
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
all: $(BUILD)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(shell [ ! -d $(BUILD) ] && mkdir -p $(BUILD))
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
#-------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) $(OUTPUT).mod $(OUTPUT)
|
||||
@rm -fr $(BUILD) $(TARGET).wps $(TARGET).elf
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
#-------------------------------------------------------------------------------
|
||||
else
|
||||
.PHONY: all
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
THIS_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||
#-------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#-------------------------------------------------------------------------------
|
||||
all : $(OUTPUT).wps
|
||||
|
||||
###############################################################################
|
||||
# Rule to make everything.
|
||||
PHONY += all
|
||||
$(OUTPUT).wps : $(OUTPUT).elf
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
|
||||
all : $(OUTPUT)
|
||||
###############################################################################
|
||||
# Special build rules
|
||||
$(OFILES_SRC) : $(HFILES_BIN)
|
||||
|
||||
|
||||
# Rule to make the module file.
|
||||
$(OUTPUT) : $(OFILES)
|
||||
@echo "linking ... " $@
|
||||
@$(REAL_LD) $(OFILES) $(LDFLAGS) $(LIBS) $(LIBPATHS_FULL) -o $@
|
||||
|
||||
###############################################################################
|
||||
# Standard build rules
|
||||
#---------------------------------------------------------------------------------
|
||||
%.a:
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $@)
|
||||
@rm -f $@
|
||||
@$(AR) -rc $@ $^
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.o: %.cpp
|
||||
#-------------------------------------------------------------------------------
|
||||
# you need a rule like this for each extension you use as binary data
|
||||
#-------------------------------------------------------------------------------
|
||||
%.bin.o %_bin.h : %.bin
|
||||
#-------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) $(INCLUDE_FULL) -c $< -o $@ $(ERROR_FILTER)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.o: %.c
|
||||
@echo $(notdir $<)
|
||||
@$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(CFLAGS) $(INCLUDE_FULL) -c $< -o $@ $(ERROR_FILTER)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.o: %.S
|
||||
@echo $(notdir $<)
|
||||
@$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(INCLUDE_FULL) -c $< -o $@ $(ERROR_FILTER)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.png.o : %.png
|
||||
@echo $(notdir $<)
|
||||
@bin2s -a 32 $< | $(AS) -o $(@)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.jpg.o : %.jpg
|
||||
@echo $(notdir $<)
|
||||
@bin2s -a 32 $< | $(AS) -o $(@)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.ttf.o : %.ttf
|
||||
@echo $(notdir $<)
|
||||
@bin2s -a 32 $< | $(AS) -o $(@)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o : %.bin
|
||||
@echo $(notdir $<)
|
||||
@bin2s -a 32 $< | $(AS) -o $(@)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.wav.o : %.wav
|
||||
@echo $(notdir $<)
|
||||
@bin2s -a 32 $< | $(AS) -o $(@)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.mp3.o : %.mp3
|
||||
@echo $(notdir $<)
|
||||
@bin2s -a 32 $< | $(AS) -o $(@)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.ogg.o : %.ogg
|
||||
@echo $(notdir $<)
|
||||
@bin2s -a 32 $< | $(AS) -o $(@)
|
||||
|
||||
###############################################################################
|
||||
# Assembly listing rules
|
||||
|
||||
# Rule to make assembly listing.
|
||||
PHONY += list
|
||||
list : $(LIST)
|
||||
|
||||
# Rule to make the listing file.
|
||||
%.list : $(TARGET)
|
||||
$(LOG)
|
||||
-$Qmkdir -p $(dir $@)
|
||||
$Q$(OBJDUMP) -d $< > $@
|
||||
|
||||
###############################################################################
|
||||
# Clean rule
|
||||
|
||||
# Rule to clean files.
|
||||
PHONY += clean
|
||||
clean :
|
||||
$Qrm -rf $(wildcard $(BUILD) $(BIN))
|
||||
|
||||
###############################################################################
|
||||
# Phony targets
|
||||
|
||||
.PHONY : $(PHONY)
|
||||
@$(bin2o)
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
#-------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
#-------------------------------------------------------------------------------
|
||||
|
55
README.md
55
README.md
@ -1,39 +1,52 @@
|
||||
# Screenshot tool [![Build Status](https://api.travis-ci.org/Maschell/ScreenshotWUPS.svg?branch=master)](https://travis-ci.org/Maschell/ScreenshotWUPS)
|
||||
# Screenshot Plugin
|
||||
|
||||
This is just a simple plugin that takes screenshot of the TV and DRC screen. The screenshot will saved on the sd card in the folder "sd:/wiiu/screenshots/"
|
||||
This is just a simple plugin that takes screenshot of the TV and DRC screen.
|
||||
The screenshot will be saved on the SD card in the folder `sd:/wiiu/screenshots`
|
||||
|
||||
## Wii U Plugin System
|
||||
This is a plugin for the [Wii U Plugin System (WUPS)](https://github.com/Maschell/WiiUPluginSystem/). To be able to use this plugin you have to place the resulting `.mod` file into the following folder:
|
||||
## Installation
|
||||
(`[ENVIRONMENT]` is a placeholder for the actual environment name.)
|
||||
|
||||
```
|
||||
sd:/wiiu/plugins
|
||||
```
|
||||
When the file is placed on the SDCard you can load it with [plugin loader](https://github.com/Maschell/WiiUPluginSystem/).
|
||||
1. Copy the file `screenshot.wps` into `sd:/wiiu/environments/[ENVIRONMENT]/plugins`.
|
||||
2. Requires the [WiiUPluginLoaderBackend](https://github.com/wiiu-env/WiiUPluginLoaderBackend) in `sd:/wiiu/environments/[ENVIRONMENT]/modules`.
|
||||
3. Requires the [MemoryMappingModule](https://github.com/wiiu-env/MemoryMappingModule) in `sd:/wiiu/environments/[ENVIRONMENT]/modules`.
|
||||
|
||||
## Usage
|
||||
Press ZL + L + ZR + R on the gamepad to take a screenshot.
|
||||
|
||||
Via the plugin config menu (press L, DPAD Down and Minus on the gamepad) you can configure the plugin. The available options are the following:
|
||||
- **Settings**:
|
||||
- Enabled: (Default is true)
|
||||
- Enables or disables the screenshot plugin.
|
||||
- Output format: (Default is JPEG)
|
||||
- Determines which file is used. Currently saving screens as .jpg, .png and .bmp is supported.
|
||||
- Screen: (Default is TV and Gamepad)
|
||||
- Determines from which screen a screenshot should be taken. Possible options: TV & Gamepad, TV only, Gamepad only.
|
||||
- JPEG quality: (Default is 90)
|
||||
- Determines the quality when saving as JPEG. Lowest possible quality is 10, highest 100.
|
||||
|
||||
## Building
|
||||
|
||||
For building you need:
|
||||
- [wups](https://github.com/Maschell/WiiUPluginSystem)
|
||||
- [wups](https://github.com/wiiu-env/WiiUPluginSystem)
|
||||
- [wut](https://github.com/decaf-emu/wut)
|
||||
- [libutilswut](https://github.com/Maschell/libutils/tree/wut) (WUT version) for common functions.
|
||||
- [libmappedmemory](https://github.com/wiiu-env/libmappedmemory)
|
||||
- PPC versions of zlib, libgd, libpng, libjpeg (install via `pacman -Syu ppc-zlib ppc-libgd ppc-libpng ppc-libjpeg-turbo`)
|
||||
|
||||
Install them (in this order) according to their README's. Don't forget the dependencies of the libs itself.
|
||||
## Building using the Dockerfile
|
||||
|
||||
Other external libraries are already located in the `libs` folder.
|
||||
|
||||
- libjpeg
|
||||
- libturbojpeg
|
||||
|
||||
### Building using the Dockerfile
|
||||
It's possible to use a docker image for building. This way you don't need anything installed on your host system.
|
||||
|
||||
```
|
||||
# Build docker image (only needed once
|
||||
docker build . -t screenshot-builder
|
||||
# Build docker image (only needed once)
|
||||
docker build . -t screenshot-plugin-builder
|
||||
|
||||
# make
|
||||
docker run -it --rm -v ${PWD}:/project screenshot-builder make
|
||||
docker run -it --rm -v ${PWD}:/project screenshot-plugin-builder make
|
||||
|
||||
# make clean
|
||||
docker run -it --rm -v ${PWD}:/project screenshot-builder make clean
|
||||
docker run -it --rm -v ${PWD}:/project screenshot-plugin-builder make clean
|
||||
```
|
||||
|
||||
## Format the code via docker
|
||||
|
||||
`docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./src -i`
|
||||
|
@ -1,47 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
<CodeBlocks_project_file>
|
||||
<FileVersion major="1" minor="6" />
|
||||
<Project>
|
||||
<Option title="ScreenshotPlugin" />
|
||||
<Option makefile_is_custom="1" />
|
||||
<Option pch_mode="2" />
|
||||
<Option compiler="ppc-gcc" />
|
||||
<Build>
|
||||
<Target title="Debug">
|
||||
<Option output="bin/Debug/ScreenshotPlugin" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj/Debug/" />
|
||||
<Option type="1" />
|
||||
<Option compiler="ppc-gcc" />
|
||||
<Compiler>
|
||||
<Add option="-g" />
|
||||
</Compiler>
|
||||
<MakeCommands>
|
||||
<Build command="make -j8" />
|
||||
<CompileFile command="$make -f $makefile $file" />
|
||||
<Clean command="make clean" />
|
||||
<DistClean command="$make -f $makefile distclean$target" />
|
||||
<AskRebuildNeeded command="$make -q -f $makefile $target" />
|
||||
<SilentBuild command="make -j8 > $(CMD_NULL)" />
|
||||
</MakeCommands>
|
||||
</Target>
|
||||
<Target title="Release">
|
||||
<Option output="bin/Release/ScreenshotPlugin" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj/Release/" />
|
||||
<Option type="1" />
|
||||
<Option compiler="ppc-gcc" />
|
||||
<Compiler>
|
||||
<Add option="-O2" />
|
||||
</Compiler>
|
||||
</Target>
|
||||
</Build>
|
||||
<Compiler>
|
||||
<Add option="-Wall" />
|
||||
</Compiler>
|
||||
<Extensions>
|
||||
<code_completion />
|
||||
<envvars />
|
||||
<debugger />
|
||||
<lib_finder disable_auto="1" />
|
||||
</Extensions>
|
||||
</Project>
|
||||
</CodeBlocks_project_file>
|
@ -1,74 +0,0 @@
|
||||
/* jconfig.h. Generated from jconfig.h.in by configure. */
|
||||
/* Version ID for the JPEG library.
|
||||
* Might be useful for tests like "#if JPEG_LIB_VERSION >= 60".
|
||||
*/
|
||||
#define JPEG_LIB_VERSION 62
|
||||
|
||||
/* libjpeg-turbo version */
|
||||
#define LIBJPEG_TURBO_VERSION 1.5.3
|
||||
|
||||
/* libjpeg-turbo version in integer form */
|
||||
#define LIBJPEG_TURBO_VERSION_NUMBER 1005003
|
||||
|
||||
/* Support arithmetic encoding */
|
||||
#define C_ARITH_CODING_SUPPORTED 1
|
||||
|
||||
/* Support arithmetic decoding */
|
||||
#define D_ARITH_CODING_SUPPORTED 1
|
||||
|
||||
/*
|
||||
* Define BITS_IN_JSAMPLE as either
|
||||
* 8 for 8-bit sample values (the usual setting)
|
||||
* 12 for 12-bit sample values
|
||||
* Only 8 and 12 are legal data precisions for lossy JPEG according to the
|
||||
* JPEG standard, and the IJG code does not support anything else!
|
||||
* We do not support run-time selection of data precision, sorry.
|
||||
*/
|
||||
|
||||
#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */
|
||||
|
||||
/* Define to 1 if you have the <locale.h> header file. */
|
||||
#define HAVE_LOCALE_H 1
|
||||
|
||||
/* Define to 1 if you have the <stddef.h> header file. */
|
||||
#define HAVE_STDDEF_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if the system has the type `unsigned char'. */
|
||||
#define HAVE_UNSIGNED_CHAR 1
|
||||
|
||||
/* Define to 1 if the system has the type `unsigned short'. */
|
||||
#define HAVE_UNSIGNED_SHORT 1
|
||||
|
||||
/* Compiler does not support pointers to undefined structures. */
|
||||
/* #undef INCOMPLETE_TYPES_BROKEN */
|
||||
|
||||
/* Support in-memory source/destination managers */
|
||||
#define MEM_SRCDST_SUPPORTED 1
|
||||
|
||||
/* Define if you have BSD-like bzero and bcopy in <strings.h> rather than
|
||||
memset/memcpy in <string.h>. */
|
||||
/* #undef NEED_BSD_STRINGS */
|
||||
|
||||
/* Define if you need to include <sys/types.h> to get size_t. */
|
||||
#define NEED_SYS_TYPES_H 1
|
||||
|
||||
/* Define if your (broken) compiler shifts signed values as if they were
|
||||
unsigned. */
|
||||
/* #undef RIGHT_SHIFT_IS_UNSIGNED */
|
||||
|
||||
/* Use accelerated SIMD routines. */
|
||||
/* #undef WITH_SIMD */
|
||||
|
||||
/* Define to 1 if type `char' is unsigned and you are not using gcc. */
|
||||
#ifndef __CHAR_UNSIGNED__
|
||||
/* # undef __CHAR_UNSIGNED__ */
|
||||
#endif
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
/* #undef const */
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
/* #undef size_t */
|
@ -1,317 +0,0 @@
|
||||
/*
|
||||
* jerror.h
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1994-1997, Thomas G. Lane.
|
||||
* Modified 1997-2009 by Guido Vollbeding.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2014, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
*
|
||||
* This file defines the error and message codes for the JPEG library.
|
||||
* Edit this file to add new codes, or to translate the message strings to
|
||||
* some other language.
|
||||
* A set of error-reporting macros are defined too. Some applications using
|
||||
* the JPEG library may wish to include this file to get the error codes
|
||||
* and/or the macros.
|
||||
*/
|
||||
|
||||
/*
|
||||
* To define the enum list of message codes, include this file without
|
||||
* defining macro JMESSAGE. To create a message string table, include it
|
||||
* again with a suitable JMESSAGE definition (see jerror.c for an example).
|
||||
*/
|
||||
#ifndef JMESSAGE
|
||||
#ifndef JERROR_H
|
||||
/* First time through, define the enum list */
|
||||
#define JMAKE_ENUM_LIST
|
||||
#else
|
||||
/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */
|
||||
#define JMESSAGE(code,string)
|
||||
#endif /* JERROR_H */
|
||||
#endif /* JMESSAGE */
|
||||
|
||||
#ifdef JMAKE_ENUM_LIST
|
||||
|
||||
typedef enum {
|
||||
|
||||
#define JMESSAGE(code,string) code ,
|
||||
|
||||
#endif /* JMAKE_ENUM_LIST */
|
||||
|
||||
JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */
|
||||
|
||||
/* For maintenance convenience, list is alphabetical by message code name */
|
||||
#if JPEG_LIB_VERSION < 70
|
||||
JMESSAGE(JERR_ARITH_NOTIMPL,
|
||||
"Sorry, arithmetic coding is not implemented")
|
||||
#endif
|
||||
JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix")
|
||||
JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix")
|
||||
JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode")
|
||||
JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS")
|
||||
#if JPEG_LIB_VERSION >= 70
|
||||
JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request")
|
||||
#endif
|
||||
JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range")
|
||||
JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported")
|
||||
#if JPEG_LIB_VERSION >= 70
|
||||
JMESSAGE(JERR_BAD_DROP_SAMPLING,
|
||||
"Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c")
|
||||
#endif
|
||||
JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition")
|
||||
JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace")
|
||||
JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace")
|
||||
JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length")
|
||||
JMESSAGE(JERR_BAD_LIB_VERSION,
|
||||
"Wrong JPEG library version: library is %d, caller expects %d")
|
||||
JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan")
|
||||
JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d")
|
||||
JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d")
|
||||
JMESSAGE(JERR_BAD_PROGRESSION,
|
||||
"Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d")
|
||||
JMESSAGE(JERR_BAD_PROG_SCRIPT,
|
||||
"Invalid progressive parameters at scan script entry %d")
|
||||
JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors")
|
||||
JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d")
|
||||
JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d")
|
||||
JMESSAGE(JERR_BAD_STRUCT_SIZE,
|
||||
"JPEG parameter struct mismatch: library thinks size is %u, caller expects %u")
|
||||
JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access")
|
||||
JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small")
|
||||
JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here")
|
||||
JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet")
|
||||
JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d")
|
||||
JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request")
|
||||
JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d")
|
||||
JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x")
|
||||
JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d")
|
||||
JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d")
|
||||
JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)")
|
||||
JMESSAGE(JERR_EMS_READ, "Read from EMS failed")
|
||||
JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed")
|
||||
JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan")
|
||||
JMESSAGE(JERR_FILE_READ, "Input file read error")
|
||||
JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?")
|
||||
JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet")
|
||||
JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow")
|
||||
JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry")
|
||||
JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels")
|
||||
JMESSAGE(JERR_INPUT_EMPTY, "Empty input file")
|
||||
JMESSAGE(JERR_INPUT_EOF, "Premature end of input file")
|
||||
JMESSAGE(JERR_MISMATCHED_QUANT_TABLE,
|
||||
"Cannot transcode due to multiple use of quantization table %d")
|
||||
JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data")
|
||||
JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change")
|
||||
JMESSAGE(JERR_NOTIMPL, "Not implemented yet")
|
||||
JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time")
|
||||
#if JPEG_LIB_VERSION >= 70
|
||||
JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined")
|
||||
#endif
|
||||
JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported")
|
||||
JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined")
|
||||
JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image")
|
||||
JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined")
|
||||
JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x")
|
||||
JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)")
|
||||
JMESSAGE(JERR_QUANT_COMPONENTS,
|
||||
"Cannot quantize more than %d color components")
|
||||
JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors")
|
||||
JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors")
|
||||
JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers")
|
||||
JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker")
|
||||
JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x")
|
||||
JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers")
|
||||
JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF")
|
||||
JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s")
|
||||
JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file")
|
||||
JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file")
|
||||
JMESSAGE(JERR_TFILE_WRITE,
|
||||
"Write failed on temporary file --- out of disk space?")
|
||||
JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines")
|
||||
JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x")
|
||||
JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up")
|
||||
JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation")
|
||||
JMESSAGE(JERR_XMS_READ, "Read from XMS failed")
|
||||
JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed")
|
||||
JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT_SHORT)
|
||||
JMESSAGE(JMSG_VERSION, JVERSION)
|
||||
JMESSAGE(JTRC_16BIT_TABLES,
|
||||
"Caution: quantization tables are too coarse for baseline JPEG")
|
||||
JMESSAGE(JTRC_ADOBE,
|
||||
"Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d")
|
||||
JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u")
|
||||
JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u")
|
||||
JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x")
|
||||
JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x")
|
||||
JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d")
|
||||
JMESSAGE(JTRC_DRI, "Define Restart Interval %u")
|
||||
JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u")
|
||||
JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u")
|
||||
JMESSAGE(JTRC_EOI, "End Of Image")
|
||||
JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d")
|
||||
JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d")
|
||||
JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE,
|
||||
"Warning: thumbnail image size does not match data length %u")
|
||||
JMESSAGE(JTRC_JFIF_EXTENSION,
|
||||
"JFIF extension marker: type 0x%02x, length %u")
|
||||
JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image")
|
||||
JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u")
|
||||
JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x")
|
||||
JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u")
|
||||
JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors")
|
||||
JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors")
|
||||
JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization")
|
||||
JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d")
|
||||
JMESSAGE(JTRC_RST, "RST%d")
|
||||
JMESSAGE(JTRC_SMOOTH_NOTIMPL,
|
||||
"Smoothing not supported with nonstandard sampling ratios")
|
||||
JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d")
|
||||
JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d")
|
||||
JMESSAGE(JTRC_SOI, "Start of Image")
|
||||
JMESSAGE(JTRC_SOS, "Start Of Scan: %d components")
|
||||
JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d")
|
||||
JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d")
|
||||
JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s")
|
||||
JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s")
|
||||
JMESSAGE(JTRC_THUMB_JPEG,
|
||||
"JFIF extension marker: JPEG-compressed thumbnail image, length %u")
|
||||
JMESSAGE(JTRC_THUMB_PALETTE,
|
||||
"JFIF extension marker: palette thumbnail image, length %u")
|
||||
JMESSAGE(JTRC_THUMB_RGB,
|
||||
"JFIF extension marker: RGB thumbnail image, length %u")
|
||||
JMESSAGE(JTRC_UNKNOWN_IDS,
|
||||
"Unrecognized component IDs %d %d %d, assuming YCbCr")
|
||||
JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u")
|
||||
JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u")
|
||||
JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d")
|
||||
#if JPEG_LIB_VERSION >= 70
|
||||
JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code")
|
||||
#endif
|
||||
JMESSAGE(JWRN_BOGUS_PROGRESSION,
|
||||
"Inconsistent progression sequence for component %d coefficient %d")
|
||||
JMESSAGE(JWRN_EXTRANEOUS_DATA,
|
||||
"Corrupt JPEG data: %u extraneous bytes before marker 0x%02x")
|
||||
JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment")
|
||||
JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code")
|
||||
JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d")
|
||||
JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file")
|
||||
JMESSAGE(JWRN_MUST_RESYNC,
|
||||
"Corrupt JPEG data: found marker 0x%02x instead of RST%d")
|
||||
JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG")
|
||||
JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines")
|
||||
#if JPEG_LIB_VERSION < 70
|
||||
JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request")
|
||||
#if defined(C_ARITH_CODING_SUPPORTED) || defined(D_ARITH_CODING_SUPPORTED)
|
||||
JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined")
|
||||
JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef JMAKE_ENUM_LIST
|
||||
|
||||
JMSG_LASTMSGCODE
|
||||
} J_MESSAGE_CODE;
|
||||
|
||||
#undef JMAKE_ENUM_LIST
|
||||
#endif /* JMAKE_ENUM_LIST */
|
||||
|
||||
/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */
|
||||
#undef JMESSAGE
|
||||
|
||||
|
||||
#ifndef JERROR_H
|
||||
#define JERROR_H
|
||||
|
||||
/* Macros to simplify using the error and trace message stuff */
|
||||
/* The first parameter is either type of cinfo pointer */
|
||||
|
||||
/* Fatal errors (print message and exit) */
|
||||
#define ERREXIT(cinfo,code) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
|
||||
#define ERREXIT1(cinfo,code,p1) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
|
||||
#define ERREXIT2(cinfo,code,p1,p2) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(cinfo)->err->msg_parm.i[1] = (p2), \
|
||||
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
|
||||
#define ERREXIT3(cinfo,code,p1,p2,p3) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(cinfo)->err->msg_parm.i[1] = (p2), \
|
||||
(cinfo)->err->msg_parm.i[2] = (p3), \
|
||||
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
|
||||
#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(cinfo)->err->msg_parm.i[1] = (p2), \
|
||||
(cinfo)->err->msg_parm.i[2] = (p3), \
|
||||
(cinfo)->err->msg_parm.i[3] = (p4), \
|
||||
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
|
||||
#define ERREXITS(cinfo,code,str) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
|
||||
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
|
||||
|
||||
#define MAKESTMT(stuff) do { stuff } while (0)
|
||||
|
||||
/* Nonfatal errors (we can keep going, but the data is probably corrupt) */
|
||||
#define WARNMS(cinfo,code) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
|
||||
#define WARNMS1(cinfo,code,p1) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
|
||||
#define WARNMS2(cinfo,code,p1,p2) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(cinfo)->err->msg_parm.i[1] = (p2), \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
|
||||
|
||||
/* Informational/debugging messages */
|
||||
#define TRACEMS(cinfo,lvl,code) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
|
||||
#define TRACEMS1(cinfo,lvl,code,p1) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
|
||||
#define TRACEMS2(cinfo,lvl,code,p1,p2) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(cinfo)->err->msg_parm.i[1] = (p2), \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
|
||||
#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \
|
||||
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
|
||||
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \
|
||||
(cinfo)->err->msg_code = (code); \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
|
||||
#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \
|
||||
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
|
||||
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
|
||||
(cinfo)->err->msg_code = (code); \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
|
||||
#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \
|
||||
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
|
||||
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
|
||||
_mp[4] = (p5); \
|
||||
(cinfo)->err->msg_code = (code); \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
|
||||
#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \
|
||||
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
|
||||
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
|
||||
_mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \
|
||||
(cinfo)->err->msg_code = (code); \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
|
||||
#define TRACEMSS(cinfo,lvl,code,str) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
|
||||
|
||||
#endif /* JERROR_H */
|
@ -1,421 +0,0 @@
|
||||
/*
|
||||
* jmorecfg.h
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Modified 1997-2009 by Guido Vollbeding.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2009, 2011, 2014-2015, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
*
|
||||
* This file contains additional configuration options that customize the
|
||||
* JPEG software for special applications or support machine-dependent
|
||||
* optimizations. Most users will not need to touch this file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Maximum number of components (color channels) allowed in JPEG image.
|
||||
* To meet the letter of the JPEG spec, set this to 255. However, darn
|
||||
* few applications need more than 4 channels (maybe 5 for CMYK + alpha
|
||||
* mask). We recommend 10 as a reasonable compromise; use 4 if you are
|
||||
* really short on memory. (Each allowed component costs a hundred or so
|
||||
* bytes of storage, whether actually used in an image or not.)
|
||||
*/
|
||||
|
||||
#define MAX_COMPONENTS 10 /* maximum number of image components */
|
||||
|
||||
|
||||
/*
|
||||
* Basic data types.
|
||||
* You may need to change these if you have a machine with unusual data
|
||||
* type sizes; for example, "char" not 8 bits, "short" not 16 bits,
|
||||
* or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits,
|
||||
* but it had better be at least 16.
|
||||
*/
|
||||
|
||||
/* Representation of a single sample (pixel element value).
|
||||
* We frequently allocate large arrays of these, so it's important to keep
|
||||
* them small. But if you have memory to burn and access to char or short
|
||||
* arrays is very slow on your hardware, you might want to change these.
|
||||
*/
|
||||
|
||||
#if BITS_IN_JSAMPLE == 8
|
||||
/* JSAMPLE should be the smallest type that will hold the values 0..255.
|
||||
* You can use a signed char by having GETJSAMPLE mask it with 0xFF.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_UNSIGNED_CHAR
|
||||
|
||||
typedef unsigned char JSAMPLE;
|
||||
#define GETJSAMPLE(value) ((int) (value))
|
||||
|
||||
#else /* not HAVE_UNSIGNED_CHAR */
|
||||
|
||||
typedef char JSAMPLE;
|
||||
#ifdef __CHAR_UNSIGNED__
|
||||
#define GETJSAMPLE(value) ((int) (value))
|
||||
#else
|
||||
#define GETJSAMPLE(value) ((int) (value) & 0xFF)
|
||||
#endif /* __CHAR_UNSIGNED__ */
|
||||
|
||||
#endif /* HAVE_UNSIGNED_CHAR */
|
||||
|
||||
#define MAXJSAMPLE 255
|
||||
#define CENTERJSAMPLE 128
|
||||
|
||||
#endif /* BITS_IN_JSAMPLE == 8 */
|
||||
|
||||
|
||||
#if BITS_IN_JSAMPLE == 12
|
||||
/* JSAMPLE should be the smallest type that will hold the values 0..4095.
|
||||
* On nearly all machines "short" will do nicely.
|
||||
*/
|
||||
|
||||
typedef short JSAMPLE;
|
||||
#define GETJSAMPLE(value) ((int) (value))
|
||||
|
||||
#define MAXJSAMPLE 4095
|
||||
#define CENTERJSAMPLE 2048
|
||||
|
||||
#endif /* BITS_IN_JSAMPLE == 12 */
|
||||
|
||||
|
||||
/* Representation of a DCT frequency coefficient.
|
||||
* This should be a signed value of at least 16 bits; "short" is usually OK.
|
||||
* Again, we allocate large arrays of these, but you can change to int
|
||||
* if you have memory to burn and "short" is really slow.
|
||||
*/
|
||||
|
||||
typedef short JCOEF;
|
||||
|
||||
|
||||
/* Compressed datastreams are represented as arrays of JOCTET.
|
||||
* These must be EXACTLY 8 bits wide, at least once they are written to
|
||||
* external storage. Note that when using the stdio data source/destination
|
||||
* managers, this is also the data type passed to fread/fwrite.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_UNSIGNED_CHAR
|
||||
|
||||
typedef unsigned char JOCTET;
|
||||
#define GETJOCTET(value) (value)
|
||||
|
||||
#else /* not HAVE_UNSIGNED_CHAR */
|
||||
|
||||
typedef char JOCTET;
|
||||
#ifdef __CHAR_UNSIGNED__
|
||||
#define GETJOCTET(value) (value)
|
||||
#else
|
||||
#define GETJOCTET(value) ((value) & 0xFF)
|
||||
#endif /* __CHAR_UNSIGNED__ */
|
||||
|
||||
#endif /* HAVE_UNSIGNED_CHAR */
|
||||
|
||||
|
||||
/* These typedefs are used for various table entries and so forth.
|
||||
* They must be at least as wide as specified; but making them too big
|
||||
* won't cost a huge amount of memory, so we don't provide special
|
||||
* extraction code like we did for JSAMPLE. (In other words, these
|
||||
* typedefs live at a different point on the speed/space tradeoff curve.)
|
||||
*/
|
||||
|
||||
/* UINT8 must hold at least the values 0..255. */
|
||||
|
||||
#ifdef HAVE_UNSIGNED_CHAR
|
||||
typedef unsigned char UINT8;
|
||||
#else /* not HAVE_UNSIGNED_CHAR */
|
||||
#ifdef __CHAR_UNSIGNED__
|
||||
typedef char UINT8;
|
||||
#else /* not __CHAR_UNSIGNED__ */
|
||||
typedef short UINT8;
|
||||
#endif /* __CHAR_UNSIGNED__ */
|
||||
#endif /* HAVE_UNSIGNED_CHAR */
|
||||
|
||||
/* UINT16 must hold at least the values 0..65535. */
|
||||
|
||||
#ifdef HAVE_UNSIGNED_SHORT
|
||||
typedef unsigned short UINT16;
|
||||
#else /* not HAVE_UNSIGNED_SHORT */
|
||||
typedef unsigned int UINT16;
|
||||
#endif /* HAVE_UNSIGNED_SHORT */
|
||||
|
||||
/* INT16 must hold at least the values -32768..32767. */
|
||||
|
||||
#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */
|
||||
typedef short INT16;
|
||||
#endif
|
||||
|
||||
/* INT32 must hold at least signed 32-bit values.
|
||||
*
|
||||
* NOTE: The INT32 typedef dates back to libjpeg v5 (1994.) Integers were
|
||||
* sometimes 16-bit back then (MS-DOS), which is why INT32 is typedef'd to
|
||||
* long. It also wasn't common (or at least as common) in 1994 for INT32 to be
|
||||
* defined by platform headers. Since then, however, INT32 is defined in
|
||||
* several other common places:
|
||||
*
|
||||
* Xmd.h (X11 header) typedefs INT32 to int on 64-bit platforms and long on
|
||||
* 32-bit platforms (i.e always a 32-bit signed type.)
|
||||
*
|
||||
* basetsd.h (Win32 header) typedefs INT32 to int (always a 32-bit signed type
|
||||
* on modern platforms.)
|
||||
*
|
||||
* qglobal.h (Qt header) typedefs INT32 to int (always a 32-bit signed type on
|
||||
* modern platforms.)
|
||||
*
|
||||
* This is a recipe for conflict, since "long" and "int" aren't always
|
||||
* compatible types. Since the definition of INT32 has technically been part
|
||||
* of the libjpeg API for more than 20 years, we can't remove it, but we do not
|
||||
* use it internally any longer. We instead define a separate type (JLONG)
|
||||
* for internal use, which ensures that internal behavior will always be the
|
||||
* same regardless of any external headers that may be included.
|
||||
*/
|
||||
|
||||
#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */
|
||||
#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */
|
||||
#ifndef _BASETSD_H /* MinGW is slightly different */
|
||||
#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */
|
||||
typedef long INT32;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Datatype used for image dimensions. The JPEG standard only supports
|
||||
* images up to 64K*64K due to 16-bit fields in SOF markers. Therefore
|
||||
* "unsigned int" is sufficient on all machines. However, if you need to
|
||||
* handle larger images and you don't mind deviating from the spec, you
|
||||
* can change this datatype. (Note that changing this datatype will
|
||||
* potentially require modifying the SIMD code. The x86-64 SIMD extensions,
|
||||
* in particular, assume a 32-bit JDIMENSION.)
|
||||
*/
|
||||
|
||||
typedef unsigned int JDIMENSION;
|
||||
|
||||
#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */
|
||||
|
||||
|
||||
/* These macros are used in all function definitions and extern declarations.
|
||||
* You could modify them if you need to change function linkage conventions;
|
||||
* in particular, you'll need to do that to make the library a Windows DLL.
|
||||
* Another application is to make all functions global for use with debuggers
|
||||
* or code profilers that require it.
|
||||
*/
|
||||
|
||||
/* a function called through method pointers: */
|
||||
#define METHODDEF(type) static type
|
||||
/* a function used only in its module: */
|
||||
#define LOCAL(type) static type
|
||||
/* a function referenced thru EXTERNs: */
|
||||
#define GLOBAL(type) type
|
||||
/* a reference to a GLOBAL function: */
|
||||
#define EXTERN(type) extern type
|
||||
|
||||
|
||||
/* Originally, this macro was used as a way of defining function prototypes
|
||||
* for both modern compilers as well as older compilers that did not support
|
||||
* prototype parameters. libjpeg-turbo has never supported these older,
|
||||
* non-ANSI compilers, but the macro is still included because there is some
|
||||
* software out there that uses it.
|
||||
*/
|
||||
|
||||
#define JMETHOD(type,methodname,arglist) type (*methodname) arglist
|
||||
|
||||
|
||||
/* libjpeg-turbo no longer supports platforms that have far symbols (MS-DOS),
|
||||
* but again, some software relies on this macro.
|
||||
*/
|
||||
|
||||
#undef FAR
|
||||
#define FAR
|
||||
|
||||
|
||||
/*
|
||||
* On a few systems, type boolean and/or its values FALSE, TRUE may appear
|
||||
* in standard header files. Or you may have conflicts with application-
|
||||
* specific header files that you want to include together with these files.
|
||||
* Defining HAVE_BOOLEAN before including jpeglib.h should make it work.
|
||||
*/
|
||||
|
||||
#ifndef HAVE_BOOLEAN
|
||||
typedef int boolean;
|
||||
#endif
|
||||
#ifndef FALSE /* in case these macros already exist */
|
||||
#define FALSE 0 /* values of boolean */
|
||||
#endif
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* The remaining options affect code selection within the JPEG library,
|
||||
* but they don't need to be visible to most applications using the library.
|
||||
* To minimize application namespace pollution, the symbols won't be
|
||||
* defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined.
|
||||
*/
|
||||
|
||||
#ifdef JPEG_INTERNALS
|
||||
#define JPEG_INTERNAL_OPTIONS
|
||||
#endif
|
||||
|
||||
#ifdef JPEG_INTERNAL_OPTIONS
|
||||
|
||||
|
||||
/*
|
||||
* These defines indicate whether to include various optional functions.
|
||||
* Undefining some of these symbols will produce a smaller but less capable
|
||||
* library. Note that you can leave certain source files out of the
|
||||
* compilation/linking process if you've #undef'd the corresponding symbols.
|
||||
* (You may HAVE to do that if your compiler doesn't like null source files.)
|
||||
*/
|
||||
|
||||
/* Capability options common to encoder and decoder: */
|
||||
|
||||
#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */
|
||||
#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */
|
||||
#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */
|
||||
|
||||
/* Encoder capability options: */
|
||||
|
||||
#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
|
||||
#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
|
||||
#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */
|
||||
/* Note: if you selected 12-bit data precision, it is dangerous to turn off
|
||||
* ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit
|
||||
* precision, so jchuff.c normally uses entropy optimization to compute
|
||||
* usable tables for higher precision. If you don't want to do optimization,
|
||||
* you'll have to supply different default Huffman tables.
|
||||
* The exact same statements apply for progressive JPEG: the default tables
|
||||
* don't work for progressive mode. (This may get fixed, however.)
|
||||
*/
|
||||
#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */
|
||||
|
||||
/* Decoder capability options: */
|
||||
|
||||
#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
|
||||
#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
|
||||
#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */
|
||||
#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */
|
||||
#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */
|
||||
#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */
|
||||
#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */
|
||||
#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */
|
||||
#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */
|
||||
|
||||
/* more capability options later, no doubt */
|
||||
|
||||
|
||||
/*
|
||||
* The RGB_RED, RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE macros are a vestigial
|
||||
* feature of libjpeg. The idea was that, if an application developer needed
|
||||
* to compress from/decompress to a BGR/BGRX/RGBX/XBGR/XRGB buffer, they could
|
||||
* change these macros, rebuild libjpeg, and link their application statically
|
||||
* with it. In reality, few people ever did this, because there were some
|
||||
* severe restrictions involved (cjpeg and djpeg no longer worked properly,
|
||||
* compressing/decompressing RGB JPEGs no longer worked properly, and the color
|
||||
* quantizer wouldn't work with pixel sizes other than 3.) Further, since all
|
||||
* of the O/S-supplied versions of libjpeg were built with the default values
|
||||
* of RGB_RED, RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE, many applications have
|
||||
* come to regard these values as immutable.
|
||||
*
|
||||
* The libjpeg-turbo colorspace extensions provide a much cleaner way of
|
||||
* compressing from/decompressing to buffers with arbitrary component orders
|
||||
* and pixel sizes. Thus, we do not support changing the values of RGB_RED,
|
||||
* RGB_GREEN, RGB_BLUE, or RGB_PIXELSIZE. In addition to the restrictions
|
||||
* listed above, changing these values will also break the SIMD extensions and
|
||||
* the regression tests.
|
||||
*/
|
||||
|
||||
#define RGB_RED 0 /* Offset of Red in an RGB scanline element */
|
||||
#define RGB_GREEN 1 /* Offset of Green */
|
||||
#define RGB_BLUE 2 /* Offset of Blue */
|
||||
#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */
|
||||
|
||||
#define JPEG_NUMCS 17
|
||||
|
||||
#define EXT_RGB_RED 0
|
||||
#define EXT_RGB_GREEN 1
|
||||
#define EXT_RGB_BLUE 2
|
||||
#define EXT_RGB_PIXELSIZE 3
|
||||
|
||||
#define EXT_RGBX_RED 0
|
||||
#define EXT_RGBX_GREEN 1
|
||||
#define EXT_RGBX_BLUE 2
|
||||
#define EXT_RGBX_PIXELSIZE 4
|
||||
|
||||
#define EXT_BGR_RED 2
|
||||
#define EXT_BGR_GREEN 1
|
||||
#define EXT_BGR_BLUE 0
|
||||
#define EXT_BGR_PIXELSIZE 3
|
||||
|
||||
#define EXT_BGRX_RED 2
|
||||
#define EXT_BGRX_GREEN 1
|
||||
#define EXT_BGRX_BLUE 0
|
||||
#define EXT_BGRX_PIXELSIZE 4
|
||||
|
||||
#define EXT_XBGR_RED 3
|
||||
#define EXT_XBGR_GREEN 2
|
||||
#define EXT_XBGR_BLUE 1
|
||||
#define EXT_XBGR_PIXELSIZE 4
|
||||
|
||||
#define EXT_XRGB_RED 1
|
||||
#define EXT_XRGB_GREEN 2
|
||||
#define EXT_XRGB_BLUE 3
|
||||
#define EXT_XRGB_PIXELSIZE 4
|
||||
|
||||
static const int rgb_red[JPEG_NUMCS] = {
|
||||
-1, -1, RGB_RED, -1, -1, -1, EXT_RGB_RED, EXT_RGBX_RED,
|
||||
EXT_BGR_RED, EXT_BGRX_RED, EXT_XBGR_RED, EXT_XRGB_RED,
|
||||
EXT_RGBX_RED, EXT_BGRX_RED, EXT_XBGR_RED, EXT_XRGB_RED,
|
||||
-1
|
||||
};
|
||||
|
||||
static const int rgb_green[JPEG_NUMCS] = {
|
||||
-1, -1, RGB_GREEN, -1, -1, -1, EXT_RGB_GREEN, EXT_RGBX_GREEN,
|
||||
EXT_BGR_GREEN, EXT_BGRX_GREEN, EXT_XBGR_GREEN, EXT_XRGB_GREEN,
|
||||
EXT_RGBX_GREEN, EXT_BGRX_GREEN, EXT_XBGR_GREEN, EXT_XRGB_GREEN,
|
||||
-1
|
||||
};
|
||||
|
||||
static const int rgb_blue[JPEG_NUMCS] = {
|
||||
-1, -1, RGB_BLUE, -1, -1, -1, EXT_RGB_BLUE, EXT_RGBX_BLUE,
|
||||
EXT_BGR_BLUE, EXT_BGRX_BLUE, EXT_XBGR_BLUE, EXT_XRGB_BLUE,
|
||||
EXT_RGBX_BLUE, EXT_BGRX_BLUE, EXT_XBGR_BLUE, EXT_XRGB_BLUE,
|
||||
-1
|
||||
};
|
||||
|
||||
static const int rgb_pixelsize[JPEG_NUMCS] = {
|
||||
-1, -1, RGB_PIXELSIZE, -1, -1, -1, EXT_RGB_PIXELSIZE, EXT_RGBX_PIXELSIZE,
|
||||
EXT_BGR_PIXELSIZE, EXT_BGRX_PIXELSIZE, EXT_XBGR_PIXELSIZE, EXT_XRGB_PIXELSIZE,
|
||||
EXT_RGBX_PIXELSIZE, EXT_BGRX_PIXELSIZE, EXT_XBGR_PIXELSIZE, EXT_XRGB_PIXELSIZE,
|
||||
-1
|
||||
};
|
||||
|
||||
/* Definitions for speed-related optimizations. */
|
||||
|
||||
/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying
|
||||
* two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER
|
||||
* as short on such a machine. MULTIPLIER must be at least 16 bits wide.
|
||||
*/
|
||||
|
||||
#ifndef MULTIPLIER
|
||||
#ifndef WITH_SIMD
|
||||
#define MULTIPLIER int /* type for fastest integer multiply */
|
||||
#else
|
||||
#define MULTIPLIER short /* prefer 16-bit with SIMD for parellelism */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* FAST_FLOAT should be either float or double, whichever is done faster
|
||||
* by your compiler. (Note that this type is only used in the floating point
|
||||
* DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.)
|
||||
*/
|
||||
|
||||
#ifndef FAST_FLOAT
|
||||
#define FAST_FLOAT float
|
||||
#endif
|
||||
|
||||
#endif /* JPEG_INTERNAL_OPTIONS */
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
64
makefile.mk
64
makefile.mk
@ -1,64 +0,0 @@
|
||||
# Compiling the projects with libutils logging code?
|
||||
DO_LOGGING := 1
|
||||
|
||||
# Links against the wut implementation of newlib, this is useful for using any function
|
||||
# from the C standard library
|
||||
WUT_ENABLE_NEWLIB := 0
|
||||
|
||||
# Links against the wut implementation of stdcpp, this is useful for using any function
|
||||
# from the C++ standard library. This will enable WUT_ENABLE_NEWLIB if you have not already done so.
|
||||
WUT_ENABLE_CPP := 0
|
||||
|
||||
# By default newlib will allocate 90% of the default heap for use with sbrk & malloc,
|
||||
# if this is unacceptable to you then you should use this as it replaces the newlib
|
||||
# malloc functions which ones which redirect to the CafeOS default heap functions
|
||||
# such as MEMAllocFromDefaultHeap.
|
||||
WUT_DEFAULT_MALLOC := 1
|
||||
|
||||
# Target filename
|
||||
TARGET := screenshot.mod
|
||||
|
||||
# Source directories
|
||||
SOURCES := src/
|
||||
|
||||
# Data directories
|
||||
DATA :=
|
||||
|
||||
# Include directories
|
||||
INCLUDES := src
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation and linking
|
||||
#---------------------------------------------------------------------------------
|
||||
# Extra C AND C++ compiler flags
|
||||
COMMON_CFLAGS :=
|
||||
# Extra C compiler flags
|
||||
CFLAGS :=
|
||||
# Extra C++ compiler flags
|
||||
CXXFLAGS :=
|
||||
# Extra linking flags for all linking steps
|
||||
LDFLAGS :=
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := $(WUPSDIR) $(WUT_ROOT) $(CURDIR)/libs
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# any extra libraries we wish to link with the project
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBS := -lwups -lutilswut -lcoreinit -lturbojpeg -lgx2 -lvpad -lnsysnet
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# Will be added to the final lib paths
|
||||
# example:
|
||||
# -L$C:/library1/lib
|
||||
#---------------------------------------------------------------------------------
|
||||
EXTERNAL_LIBPATHS :=
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# Will be added to the final include paths
|
||||
# -IC:/library1/include
|
||||
#---------------------------------------------------------------------------------
|
||||
EXTERNAL_INCLUDE := -I$(WUT_ROOT)/include/libutilswut
|
@ -1,17 +0,0 @@
|
||||
#include "JpegInformation.h"
|
||||
#include <malloc.h>
|
||||
|
||||
JpegInformation::JpegInformation(tjhandle handle, uint8_t* jpegBuf, uint64_t jpegSize)
|
||||
{
|
||||
this->buffer = jpegBuf;
|
||||
this->size = jpegSize;
|
||||
this->handle = handle;
|
||||
}
|
||||
|
||||
JpegInformation::~JpegInformation()
|
||||
{
|
||||
if(this->buffer) {
|
||||
free(this->buffer);
|
||||
}
|
||||
tjDestroy(this->handle);
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
#ifndef JPEGINFORMATION_H
|
||||
#define JPEGINFORMATION_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <turbojpeg.h>
|
||||
|
||||
class JpegInformation {
|
||||
public:
|
||||
JpegInformation(tjhandle handle, uint8_t* jpegBuf, uint64_t jpegSize);
|
||||
virtual ~JpegInformation();
|
||||
|
||||
uint8_t * getBuffer() {
|
||||
return buffer;
|
||||
};
|
||||
uint64_t getSize() {
|
||||
return size;
|
||||
};
|
||||
|
||||
private:
|
||||
uint8_t* buffer;
|
||||
uint64_t size;
|
||||
tjhandle handle;
|
||||
|
||||
};
|
||||
|
||||
#endif // JPEGINFORMATION_H
|
17
src/common.h
17
src/common.h
@ -1,6 +1,15 @@
|
||||
#ifndef COMMON_H_
|
||||
#define COMMON_H_
|
||||
#pragma once
|
||||
|
||||
#define WIIU_SCREENSHOT_PATH "sd:/wiiu/screenshots/"
|
||||
#define WIIU_SCREENSHOT_PATH "fs:/vol/external01/wiiu/screenshots/"
|
||||
|
||||
#endif // COMMON_H_
|
||||
typedef enum {
|
||||
IMAGE_OUTPUT_FORMAT_JPEG = 0,
|
||||
IMAGE_OUTPUT_FORMAT_PNG = 1,
|
||||
IMAGE_OUTPUT_FORMAT_BMP = 2,
|
||||
} ImageOutputFormatEnum;
|
||||
|
||||
typedef enum {
|
||||
IMAGE_SOURCE_TV_AND_DRC = 0,
|
||||
IMAGE_SOURCE_TV = 1,
|
||||
IMAGE_SOURCE_DRC = 2,
|
||||
} ImageSourceEnum;
|
||||
|
76
src/fs/FSUtils.cpp
Normal file
76
src/fs/FSUtils.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
#include "fs/FSUtils.h"
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <fcntl.h>
|
||||
|
||||
int32_t FSUtils::CheckFile(const char *filepath) {
|
||||
if (!filepath)
|
||||
return 0;
|
||||
|
||||
struct stat filestat;
|
||||
|
||||
char dirnoslash[strlen(filepath) + 2];
|
||||
snprintf(dirnoslash, sizeof(dirnoslash), "%s", filepath);
|
||||
|
||||
while (dirnoslash[strlen(dirnoslash) - 1] == '/')
|
||||
dirnoslash[strlen(dirnoslash) - 1] = '\0';
|
||||
|
||||
char *notRoot = strrchr(dirnoslash, '/');
|
||||
if (!notRoot) {
|
||||
strcat(dirnoslash, "/");
|
||||
}
|
||||
|
||||
if (stat(dirnoslash, &filestat) == 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t FSUtils::CreateSubfolder(const char *fullpath) {
|
||||
if (!fullpath) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t result = 0;
|
||||
|
||||
char dirnoslash[strlen(fullpath) + 1];
|
||||
strcpy(dirnoslash, fullpath);
|
||||
|
||||
int32_t pos = strlen(dirnoslash) - 1;
|
||||
while (dirnoslash[pos] == '/') {
|
||||
dirnoslash[pos] = '\0';
|
||||
pos--;
|
||||
}
|
||||
|
||||
if (CheckFile(dirnoslash)) {
|
||||
return 1;
|
||||
} else {
|
||||
char parentpath[strlen(dirnoslash) + 2];
|
||||
strcpy(parentpath, dirnoslash);
|
||||
char *ptr = strrchr(parentpath, '/');
|
||||
|
||||
if (!ptr) {
|
||||
//! Device root directory (must be with '/')
|
||||
strcat(parentpath, "/");
|
||||
struct stat filestat;
|
||||
if (stat(parentpath, &filestat) == 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ptr++;
|
||||
ptr[0] = '\0';
|
||||
|
||||
result = CreateSubfolder(parentpath);
|
||||
}
|
||||
|
||||
if (!result)
|
||||
return 0;
|
||||
|
||||
if (mkdir(dirnoslash, 0777) == -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
11
src/fs/FSUtils.h
Normal file
11
src/fs/FSUtils.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <wut_types.h>
|
||||
|
||||
class FSUtils {
|
||||
public:
|
||||
//! todo: C++ class
|
||||
static int32_t CreateSubfolder(const char *fullpath);
|
||||
|
||||
static int32_t CheckFile(const char *filepath);
|
||||
};
|
@ -1,61 +1,99 @@
|
||||
#include <wups.h>
|
||||
#include <utils/logger.h>
|
||||
#include <vpad/input.h>
|
||||
#include <gx2/surface.h>
|
||||
#include <coreinit/time.h>
|
||||
#include <utils/StringTools.h>
|
||||
#include <fs/FSUtils.h>
|
||||
#include "common.h"
|
||||
#include "screenshot_utils.h"
|
||||
#include "fs/FSUtils.h"
|
||||
#include "retain_vars.hpp"
|
||||
#include "screenshot_utils.h"
|
||||
#include "utils/StringTools.h"
|
||||
#include "utils/logger.h"
|
||||
#include <coreinit/time.h>
|
||||
#include <coreinit/title.h>
|
||||
#include <gx2/surface.h>
|
||||
#include <vpad/input.h>
|
||||
#include <wups.h>
|
||||
|
||||
static bool takeScreenshotTV __attribute__((section(".data"))) = false;
|
||||
static bool takeScreenshotDRC __attribute__((section(".data"))) = false;
|
||||
static uint8_t screenshotCooldown __attribute__((section(".data"))) = 0;
|
||||
static uint32_t counter __attribute__((section(".data"))) = 0;
|
||||
static bool takeScreenshotTV = false;
|
||||
static bool takeScreenshotDRC = false;
|
||||
static uint8_t screenshotCoolDown = 0;
|
||||
|
||||
DECL_FUNCTION(int32_t, VPADRead, VPADChan chan, VPADStatus *buffer, uint32_t buffer_size, VPADReadError *error) {
|
||||
int32_t result = real_VPADRead(chan, buffer, buffer_size, error);
|
||||
VPADReadError real_error;
|
||||
int32_t result = real_VPADRead(chan, buffer, buffer_size, &real_error);
|
||||
|
||||
if(result > 0 && *error == VPAD_READ_SUCCESS && (buffer[0].hold == gButtonCombo) && screenshotCooldown == 0 && OSIsHomeButtonMenuEnabled()) {
|
||||
counter++;
|
||||
takeScreenshotTV = true;
|
||||
takeScreenshotDRC = true;
|
||||
if (gEnabled) {
|
||||
if (result > 0 && real_error == VPAD_READ_SUCCESS && (buffer[0].hold == gButtonCombo) && screenshotCoolDown == 0 && OSIsHomeButtonMenuEnabled()) {
|
||||
takeScreenshotTV = gImageSource == IMAGE_SOURCE_TV_AND_DRC || gImageSource == IMAGE_SOURCE_TV;
|
||||
takeScreenshotDRC = gImageSource == IMAGE_SOURCE_TV_AND_DRC || gImageSource == IMAGE_SOURCE_DRC;
|
||||
|
||||
screenshotCooldown = 0x3C;
|
||||
}
|
||||
if(screenshotCooldown > 0) {
|
||||
screenshotCooldown--;
|
||||
screenshotCoolDown = 60;
|
||||
}
|
||||
if (screenshotCoolDown > 0) {
|
||||
screenshotCoolDown--;
|
||||
}
|
||||
}
|
||||
|
||||
if (error) {
|
||||
*error = real_error;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DECL_FUNCTION(void, GX2CopyColorBufferToScanBuffer, const GX2ColorBuffer *colorBuffer, int32_t scan_target) {
|
||||
if((takeScreenshotTV || takeScreenshotDRC) && gAppStatus == WUPS_APP_STATUS_FOREGROUND) {
|
||||
DECL_FUNCTION(void, GX2CopyColorBufferToScanBuffer, const GX2ColorBuffer *colorBuffer, GX2ScanTarget scan_target) {
|
||||
if ((takeScreenshotTV || takeScreenshotDRC)) {
|
||||
OSCalendarTime output;
|
||||
OSTicksToCalendarTime(OSGetTime(), &output);
|
||||
char buffer[255] = {0};
|
||||
snprintf(buffer,254,"%s%04ld-%02ld-%02ld/",WIIU_SCREENSHOT_PATH,output.tm_year,output.tm_mon,output.tm_mday);
|
||||
|
||||
FSUtils::CreateSubfolder(buffer);
|
||||
|
||||
snprintf(buffer,254,"%s%04ld-%02ld-%02ld/%04ld-%02ld-%02ld_%02ld.%02ld.%02ld_",
|
||||
WIIU_SCREENSHOT_PATH,output.tm_year,output.tm_mon,output.tm_mday,output.tm_year,output.tm_mon,output.tm_mday,output.tm_hour,output.tm_min,output.tm_sec);
|
||||
|
||||
if(scan_target == 1 && colorBuffer != NULL && takeScreenshotTV && gAppStatus == WUPS_APP_STATUS_FOREGROUND) {
|
||||
DEBUG_FUNCTION_LINE("Lets take a screenshot from TV. Source format: %d \n",colorBuffer->surface.format);
|
||||
takeScreenshot((GX2ColorBuffer *)colorBuffer, StringTools::strfmt("%sTV.jpg",buffer).c_str());
|
||||
takeScreenshotTV = false;
|
||||
std::string buffer = string_format("%s%016llX", WIIU_SCREENSHOT_PATH, OSGetTitleID());
|
||||
if (!gShortNameEn.empty()) {
|
||||
buffer += string_format(" (%s)", gShortNameEn.c_str());
|
||||
}
|
||||
if(scan_target == 4 && colorBuffer != NULL && takeScreenshotDRC && gAppStatus == WUPS_APP_STATUS_FOREGROUND) {
|
||||
DEBUG_FUNCTION_LINE("Lets take a screenshot from DRC. Source format: %d \n",colorBuffer->surface.format);
|
||||
takeScreenshot((GX2ColorBuffer *)colorBuffer, StringTools::strfmt("%sDRC.jpg",buffer).c_str());
|
||||
buffer += string_format("/%04d-%02d-%02d/", output.tm_year, output.tm_mon + 1, output.tm_mday);
|
||||
|
||||
bool dirExists = true;
|
||||
auto dir = opendir(buffer.c_str());
|
||||
if (dir) {
|
||||
closedir(dir);
|
||||
} else {
|
||||
if (!FSUtils::CreateSubfolder(buffer.c_str())) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to create dir: %s", buffer.c_str());
|
||||
dirExists = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (dirExists) {
|
||||
buffer = string_format("%s%04d-%02d-%02d_%02d.%02d.%02d_",
|
||||
buffer.c_str(), output.tm_year, output.tm_mon + 1,
|
||||
output.tm_mday, output.tm_hour, output.tm_min, output.tm_sec);
|
||||
|
||||
if (scan_target == GX2_SCAN_TARGET_TV && colorBuffer != nullptr && takeScreenshotTV) {
|
||||
DEBUG_FUNCTION_LINE("Lets take a screenshot from TV.");
|
||||
takeScreenshot((GX2ColorBuffer *) colorBuffer, buffer, scan_target, gTVSurfaceFormat, gOutputFormat, gQuality);
|
||||
takeScreenshotTV = false;
|
||||
} else if (scan_target == GX2_SCAN_TARGET_DRC0 && colorBuffer != nullptr && takeScreenshotDRC) {
|
||||
DEBUG_FUNCTION_LINE("Lets take a screenshot from DRC.");
|
||||
takeScreenshot((GX2ColorBuffer *) colorBuffer, buffer, scan_target, gDRCSurfaceFormat, gOutputFormat, gQuality);
|
||||
takeScreenshotDRC = false;
|
||||
}
|
||||
} else {
|
||||
takeScreenshotTV = false;
|
||||
takeScreenshotDRC = false;
|
||||
}
|
||||
}
|
||||
real_GX2CopyColorBufferToScanBuffer(colorBuffer,scan_target);
|
||||
real_GX2CopyColorBufferToScanBuffer(colorBuffer, scan_target);
|
||||
}
|
||||
|
||||
WUPS_MUST_REPLACE(VPADRead, WUPS_LOADER_LIBRARY_VPAD, VPADRead);
|
||||
WUPS_MUST_REPLACE(GX2CopyColorBufferToScanBuffer, WUPS_LOADER_LIBRARY_GX2, GX2CopyColorBufferToScanBuffer);
|
||||
DECL_FUNCTION(void, GX2SetTVBuffer, void *buffer, uint32_t buffer_size, int32_t tv_render_mode, GX2SurfaceFormat surface_format, GX2BufferingMode buffering_mode) {
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("Set TV Buffer format to 0x%08X", surface_format);
|
||||
gTVSurfaceFormat = surface_format;
|
||||
|
||||
return real_GX2SetTVBuffer(buffer, buffer_size, tv_render_mode, surface_format, buffering_mode);
|
||||
}
|
||||
|
||||
DECL_FUNCTION(void, GX2SetDRCBuffer, void *buffer, uint32_t buffer_size, uint32_t drc_mode, GX2SurfaceFormat surface_format, GX2BufferingMode buffering_mode) {
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("Set DRC Buffer format to 0x%08X", surface_format);
|
||||
gDRCSurfaceFormat = surface_format;
|
||||
|
||||
return real_GX2SetDRCBuffer(buffer, buffer_size, drc_mode, surface_format, buffering_mode);
|
||||
}
|
||||
|
||||
WUPS_MUST_REPLACE(VPADRead, WUPS_LOADER_LIBRARY_VPAD, VPADRead);
|
||||
WUPS_MUST_REPLACE(GX2CopyColorBufferToScanBuffer, WUPS_LOADER_LIBRARY_GX2, GX2CopyColorBufferToScanBuffer);
|
||||
WUPS_MUST_REPLACE(GX2SetTVBuffer, WUPS_LOADER_LIBRARY_GX2, GX2SetTVBuffer);
|
||||
WUPS_MUST_REPLACE(GX2SetDRCBuffer, WUPS_LOADER_LIBRARY_GX2, GX2SetDRCBuffer);
|
359
src/main.cpp
359
src/main.cpp
@ -1,155 +1,254 @@
|
||||
#include <wups.h>
|
||||
#include <malloc.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <coreinit/cache.h>
|
||||
#include <coreinit/thread.h>
|
||||
#include <coreinit/time.h>
|
||||
#include <coreinit/screen.h>
|
||||
#include <vpad/input.h>
|
||||
#include <nsysnet/socket.h>
|
||||
#include <utils/logger.h>
|
||||
#include "main.h"
|
||||
#include "retain_vars.hpp"
|
||||
#include "utils/logger.h"
|
||||
#include <coreinit/cache.h>
|
||||
#include <coreinit/title.h>
|
||||
#include <malloc.h>
|
||||
#include <nn/acp.h>
|
||||
#include <string>
|
||||
#include <vpad/input.h>
|
||||
#include <wups.h>
|
||||
#include <wups/config/WUPSConfigItemBoolean.h>
|
||||
#include <wups/config/WUPSConfigItemIntegerRange.h>
|
||||
#include <wups/config/WUPSConfigItemMultipleValues.h>
|
||||
|
||||
// Mandatory plugin information.
|
||||
WUPS_PLUGIN_NAME("Screenshot tool");
|
||||
WUPS_PLUGIN_NAME("Screenshot plugin");
|
||||
WUPS_PLUGIN_DESCRIPTION("This plugin allows you to make screenshots that will be saved to the sd card");
|
||||
WUPS_PLUGIN_VERSION("v0.1");
|
||||
WUPS_PLUGIN_VERSION(VERSION_FULL);
|
||||
WUPS_PLUGIN_AUTHOR("Maschell");
|
||||
WUPS_PLUGIN_LICENSE("GPL");
|
||||
|
||||
// FS Access
|
||||
WUPS_FS_ACCESS()
|
||||
WUPS_USE_WUT_DEVOPTAB();
|
||||
|
||||
uint32_t SplashScreen(int32_t time,int32_t combotime);
|
||||
WUPS_USE_STORAGE("screenshot_plugin");
|
||||
|
||||
#define ENABLED_CONFIG_STRING "enabled"
|
||||
#define FORMAT_CONFIG_STRING "format"
|
||||
#define QUALITY_CONFIG_STRING "quality"
|
||||
#define SCREEN_CONFIG_STRING "screen"
|
||||
|
||||
// Gets called once the loader exists.
|
||||
INITIALIZE_PLUGIN() {
|
||||
socket_lib_init();
|
||||
initLogging();
|
||||
gButtonCombo = VPAD_BUTTON_R | VPAD_BUTTON_L | VPAD_BUTTON_ZR | VPAD_BUTTON_ZL;
|
||||
OSMemoryBarrier();
|
||||
|
||||
log_init();
|
||||
// Open storage to read values
|
||||
WUPSStorageError storageRes = WUPS_OpenStorage();
|
||||
if (storageRes != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to open storage %s (%d)", WUPS_GetStorageStatusStr(storageRes), storageRes);
|
||||
} else {
|
||||
// Try to get value from storage
|
||||
if ((storageRes = WUPS_GetInt(nullptr, ENABLED_CONFIG_STRING, reinterpret_cast<int32_t *>(&gEnabled))) == WUPS_STORAGE_ERROR_NOT_FOUND) {
|
||||
// Add the value to the storage if it's missing.
|
||||
if (WUPS_StoreBool(nullptr, ENABLED_CONFIG_STRING, gEnabled) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to store value");
|
||||
}
|
||||
} else if (storageRes != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to get value %s (%d)", WUPS_GetStorageStatusStr(storageRes), storageRes);
|
||||
}
|
||||
// Try to get value from storage
|
||||
if ((storageRes = WUPS_GetInt(nullptr, FORMAT_CONFIG_STRING, reinterpret_cast<int32_t *>(&gOutputFormat))) == WUPS_STORAGE_ERROR_NOT_FOUND) {
|
||||
// Add the value to the storage if it's missing.
|
||||
if (WUPS_StoreBool(nullptr, FORMAT_CONFIG_STRING, gOutputFormat) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to store value");
|
||||
}
|
||||
} else if (storageRes != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to get value %s (%d)", WUPS_GetStorageStatusStr(storageRes), storageRes);
|
||||
}
|
||||
|
||||
uint32_t res = SplashScreen(10,2);
|
||||
// Try to get value from storage
|
||||
if ((storageRes = WUPS_GetInt(nullptr, QUALITY_CONFIG_STRING, reinterpret_cast<int32_t *>(&gQuality))) == WUPS_STORAGE_ERROR_NOT_FOUND) {
|
||||
// Add the value to the storage if it's missing.
|
||||
if (WUPS_StoreInt(nullptr, QUALITY_CONFIG_STRING, (int32_t) gQuality) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to store value");
|
||||
}
|
||||
} else if (storageRes != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to get value %s (%d)", WUPS_GetStorageStatusStr(storageRes), storageRes);
|
||||
}
|
||||
|
||||
gButtonCombo = res;
|
||||
ICInvalidateRange((void*)(&gButtonCombo), 4);
|
||||
DCFlushRange((void*)(&gButtonCombo), 4);
|
||||
// Try to get value from storage
|
||||
if ((storageRes = WUPS_GetInt(nullptr, SCREEN_CONFIG_STRING, reinterpret_cast<int32_t *>(&gImageSource))) == WUPS_STORAGE_ERROR_NOT_FOUND) {
|
||||
// Add the value to the storage if it's missing.
|
||||
if (WUPS_StoreInt(nullptr, SCREEN_CONFIG_STRING, (int32_t) gImageSource) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to store value");
|
||||
}
|
||||
} else if (storageRes != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to get value %s (%d)", WUPS_GetStorageStatusStr(storageRes), storageRes);
|
||||
}
|
||||
|
||||
// Close storage
|
||||
if (WUPS_CloseStorage() != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to close storage");
|
||||
}
|
||||
}
|
||||
if (gOutputFormat >= 3) {
|
||||
gOutputFormat = IMAGE_OUTPUT_FORMAT_JPEG;
|
||||
}
|
||||
if (gQuality < 10) {
|
||||
gQuality = 10;
|
||||
} else if (gQuality > 100) {
|
||||
gQuality = 100;
|
||||
}
|
||||
}
|
||||
|
||||
void formatChanged(ConfigItemMultipleValues *item, uint32_t newValue) {
|
||||
DEBUG_FUNCTION_LINE("New value in %s changed: %d", item->configID, newValue);
|
||||
gOutputFormat = (ImageOutputFormatEnum) newValue;
|
||||
|
||||
if (gOutputFormat >= 3) {
|
||||
gOutputFormat = IMAGE_OUTPUT_FORMAT_JPEG;
|
||||
}
|
||||
|
||||
WUPS_StoreInt(nullptr, item->configID, (int32_t) newValue);
|
||||
}
|
||||
|
||||
void imageSourceChanged(ConfigItemMultipleValues *item, uint32_t newValue) {
|
||||
DEBUG_FUNCTION_LINE("New value in %s changed: %d", item->configID, newValue);
|
||||
gImageSource = (ImageSourceEnum) newValue;
|
||||
|
||||
if (gImageSource >= 3) {
|
||||
gImageSource = IMAGE_SOURCE_TV_AND_DRC;
|
||||
}
|
||||
|
||||
WUPS_StoreInt(nullptr, item->configID, (int32_t) newValue);
|
||||
}
|
||||
|
||||
void qualityChanged(ConfigItemIntegerRange *item, int32_t newValue) {
|
||||
DEBUG_FUNCTION_LINE("New quality: %d", newValue);
|
||||
gQuality = (ImageOutputFormatEnum) newValue;
|
||||
|
||||
if (gQuality < 10) {
|
||||
gQuality = 10;
|
||||
} else if (gQuality > 100) {
|
||||
gQuality = 100;
|
||||
}
|
||||
|
||||
WUPS_StoreInt(nullptr, QUALITY_CONFIG_STRING, (int32_t) gQuality);
|
||||
}
|
||||
|
||||
void enabledChanged(ConfigItemBoolean *item, bool newValue) {
|
||||
DEBUG_FUNCTION_LINE("gEnabled new value: %d", newValue);
|
||||
gEnabled = (ImageOutputFormatEnum) newValue;
|
||||
|
||||
WUPS_StoreBool(nullptr, ENABLED_CONFIG_STRING, gEnabled);
|
||||
}
|
||||
|
||||
WUPS_GET_CONFIG() {
|
||||
// We open the storage, so we can persist the configuration the user did.
|
||||
if (WUPS_OpenStorage() != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to open storage");
|
||||
return 0;
|
||||
}
|
||||
|
||||
WUPSConfigHandle config;
|
||||
WUPSConfig_CreateHandled(&config, "Screenshot plugin");
|
||||
|
||||
WUPSConfigCategoryHandle setting;
|
||||
WUPSConfig_AddCategoryByNameHandled(config, "Settings", &setting);
|
||||
|
||||
|
||||
WUPSConfigItemBoolean_AddToCategoryHandled(config, setting, ENABLED_CONFIG_STRING, "Enabled", gEnabled, &enabledChanged);
|
||||
|
||||
ConfigItemMultipleValuesPair fileFormat[3];
|
||||
fileFormat[0].value = IMAGE_OUTPUT_FORMAT_JPEG;
|
||||
fileFormat[0].valueName = (char *) "JPEG";
|
||||
|
||||
fileFormat[1].value = IMAGE_OUTPUT_FORMAT_PNG;
|
||||
fileFormat[1].valueName = (char *) "PNG";
|
||||
|
||||
fileFormat[2].value = IMAGE_OUTPUT_FORMAT_BMP;
|
||||
fileFormat[2].valueName = (char *) "BMP";
|
||||
|
||||
uint32_t defaultIndex = 0;
|
||||
uint32_t curIndex = 0;
|
||||
for (auto &cur : fileFormat) {
|
||||
if (cur.value == gOutputFormat) {
|
||||
defaultIndex = curIndex;
|
||||
break;
|
||||
}
|
||||
curIndex++;
|
||||
}
|
||||
|
||||
WUPSConfigItemMultipleValues_AddToCategoryHandled(config, setting, FORMAT_CONFIG_STRING, "Output format", defaultIndex, fileFormat,
|
||||
sizeof(fileFormat) / sizeof(fileFormat[0]), &formatChanged);
|
||||
|
||||
|
||||
ConfigItemMultipleValuesPair source[3];
|
||||
source[0].value = IMAGE_SOURCE_TV_AND_DRC;
|
||||
source[0].valueName = (char *) "TV & Gamepad";
|
||||
|
||||
source[1].value = IMAGE_SOURCE_TV;
|
||||
source[1].valueName = (char *) "TV only";
|
||||
|
||||
source[2].value = IMAGE_SOURCE_DRC;
|
||||
source[2].valueName = (char *) "Gamepad only";
|
||||
|
||||
defaultIndex = 0;
|
||||
curIndex = 0;
|
||||
for (auto &cur : source) {
|
||||
if (cur.value == gImageSource) {
|
||||
defaultIndex = curIndex;
|
||||
break;
|
||||
}
|
||||
curIndex++;
|
||||
}
|
||||
|
||||
WUPSConfigItemMultipleValues_AddToCategoryHandled(config, setting, SCREEN_CONFIG_STRING, "Screen", defaultIndex, source,
|
||||
sizeof(source) / sizeof(source[0]), &imageSourceChanged);
|
||||
|
||||
|
||||
WUPSConfigItemIntegerRange_AddToCategoryHandled(config, setting, QUALITY_CONFIG_STRING, "JPEG quality", gQuality, 10, 100, &qualityChanged);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
WUPS_CONFIG_CLOSED() {
|
||||
// Save all changes
|
||||
if (WUPS_CloseStorage() != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to close storage");
|
||||
}
|
||||
}
|
||||
|
||||
// Called whenever an application was started.
|
||||
ON_APPLICATION_START(my_args) {
|
||||
socket_lib_init();
|
||||
log_init();
|
||||
|
||||
gAppStatus = WUPS_APP_STATUS_FOREGROUND;
|
||||
|
||||
log_init();
|
||||
}
|
||||
|
||||
ON_APP_STATUS_CHANGED(status) {
|
||||
gAppStatus = status;
|
||||
}
|
||||
|
||||
|
||||
#define FPS 60
|
||||
uint32_t SplashScreen(int32_t time,int32_t combotime) {
|
||||
uint32_t result = VPAD_BUTTON_R | VPAD_BUTTON_L | VPAD_BUTTON_ZR | VPAD_BUTTON_ZL;
|
||||
|
||||
// Init screen
|
||||
OSScreenInit();
|
||||
|
||||
uint32_t screen_buf0_size = OSScreenGetBufferSizeEx(SCREEN_TV);
|
||||
uint32_t screen_buf1_size = OSScreenGetBufferSizeEx(SCREEN_DRC);
|
||||
|
||||
uint32_t * screenbuffer0 = (uint32_t*)memalign(0x100, screen_buf0_size);
|
||||
uint32_t * screenbuffer1 = (uint32_t*)memalign(0x100, screen_buf1_size);
|
||||
|
||||
if(screenbuffer0 == NULL || screenbuffer1 == NULL) {
|
||||
if(screenbuffer0 != NULL) {
|
||||
free(screenbuffer0);
|
||||
ON_APPLICATION_START() {
|
||||
initLogging();
|
||||
ACPInitialize();
|
||||
auto *metaXml = (ACPMetaXml *) memalign(0x40, sizeof(ACPMetaXml));
|
||||
if (ACPGetTitleMetaXml(OSGetTitleID(), metaXml) == ACP_RESULT_SUCCESS) {
|
||||
gShortNameEn = metaXml->shortname_en;
|
||||
std::string illegalChars = "\\/:?\"<>|@=;`_^][";
|
||||
for (auto it = gShortNameEn.begin(); it < gShortNameEn.end(); ++it) {
|
||||
if (*it < '0' || *it > 'z') {
|
||||
*it = ' ';
|
||||
}
|
||||
}
|
||||
if(screenbuffer1 != NULL) {
|
||||
free(screenbuffer1);
|
||||
for (auto it = gShortNameEn.begin(); it < gShortNameEn.end(); ++it) {
|
||||
bool found = illegalChars.find(*it) != std::string::npos;
|
||||
if (found) {
|
||||
*it = ' ';
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
OSScreenSetBufferEx(SCREEN_TV, (void *)screenbuffer0);
|
||||
OSScreenSetBufferEx(SCREEN_DRC, (void *)screenbuffer1);
|
||||
|
||||
OSScreenEnableEx(SCREEN_TV, 1);
|
||||
OSScreenEnableEx(SCREEN_DRC, 1);
|
||||
|
||||
// Clear screens
|
||||
OSScreenClearBufferEx(SCREEN_TV, 0);
|
||||
OSScreenClearBufferEx(SCREEN_DRC, 0);
|
||||
|
||||
// Flip buffers
|
||||
OSScreenFlipBuffersEx(SCREEN_TV);
|
||||
OSScreenFlipBuffersEx(SCREEN_DRC);
|
||||
|
||||
OSScreenClearBufferEx(SCREEN_TV, 0);
|
||||
OSScreenClearBufferEx(SCREEN_DRC, 0);
|
||||
|
||||
std::vector<std::string> strings;
|
||||
strings.push_back("Screenshot tool 0.1 - by Maschell.");
|
||||
strings.push_back("");
|
||||
strings.push_back("");
|
||||
strings.push_back("Press the combo you want to use for making screenshots now");
|
||||
strings.push_back("for 2 seconds.");
|
||||
strings.push_back(" ");
|
||||
strings.push_back("Otherwise the default combo (L+R+ZR+ZL button) will be used");
|
||||
strings.push_back("in 10 seconds.");
|
||||
strings.push_back(" ");
|
||||
strings.push_back("Press the TV buttons to exit with the default combo.");
|
||||
|
||||
uint8_t pos = 0;
|
||||
for (std::vector<std::string>::iterator it = strings.begin() ; it != strings.end(); ++it) {
|
||||
OSScreenPutFontEx(SCREEN_TV, 0, pos, (*it).c_str());
|
||||
OSScreenPutFontEx(SCREEN_DRC, 0, pos, (*it).c_str());
|
||||
pos++;
|
||||
}
|
||||
|
||||
OSScreenFlipBuffersEx(SCREEN_TV);
|
||||
OSScreenFlipBuffersEx(SCREEN_DRC);
|
||||
|
||||
int32_t tickswait = time * FPS * 16;
|
||||
|
||||
int32_t sleepingtime = 16;
|
||||
int32_t times = tickswait/16;
|
||||
int32_t i=0;
|
||||
|
||||
VPADStatus vpad_data;
|
||||
VPADReadError error;
|
||||
uint32_t last = 0xFFFFFFFF;
|
||||
int32_t timer = 0;
|
||||
while(i<times) {
|
||||
VPADRead(VPAD_CHAN_0, &vpad_data, 1, &error);
|
||||
if(vpad_data.trigger == VPAD_BUTTON_TV) {
|
||||
break;
|
||||
uint32_t length = gShortNameEn.length();
|
||||
for (uint32_t i = 1; i < length; ++i) {
|
||||
if (gShortNameEn[i - 1] == ' ' && gShortNameEn[i] == ' ') {
|
||||
gShortNameEn.erase(i, 1);
|
||||
i--;
|
||||
length--;
|
||||
}
|
||||
}
|
||||
if(last == vpad_data.hold && last != 0) {
|
||||
timer++;
|
||||
if (gShortNameEn.size() == 1 && gShortNameEn[0] == ' ') {
|
||||
gShortNameEn.clear();
|
||||
} else {
|
||||
last = vpad_data.hold;
|
||||
timer = 0;
|
||||
DEBUG_FUNCTION_LINE("Detected name as \"%s\"", gShortNameEn.c_str());
|
||||
}
|
||||
if(timer >= combotime*FPS) {
|
||||
result = vpad_data.hold;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
OSSleepTicks(OSMicrosecondsToTicks(sleepingtime*1000));
|
||||
} else {
|
||||
gShortNameEn.clear();
|
||||
}
|
||||
|
||||
if(screenbuffer0 != NULL) {
|
||||
free(screenbuffer0);
|
||||
}
|
||||
if(screenbuffer1 != NULL) {
|
||||
free(screenbuffer1);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ON_APPLICATION_REQUESTS_EXIT() {
|
||||
deinitLogging();
|
||||
}
|
||||
|
5
src/main.h
Normal file
5
src/main.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
#include "version.h"
|
||||
|
||||
#define VERSION "v0.1"
|
||||
#define VERSION_FULL VERSION VERSION_EXTRA
|
@ -1,3 +1,10 @@
|
||||
#include "retain_vars.hpp"
|
||||
wups_loader_app_status_t gAppStatus __attribute__((section(".data"))) = WUPS_APP_STATUS_UNKNOWN;
|
||||
uint32_t gButtonCombo __attribute__((section(".data"))) = 0;
|
||||
#include <string>
|
||||
GX2SurfaceFormat gTVSurfaceFormat = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8;
|
||||
GX2SurfaceFormat gDRCSurfaceFormat = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8;
|
||||
ImageSourceEnum gImageSource = IMAGE_SOURCE_TV_AND_DRC;
|
||||
bool gEnabled = true;
|
||||
uint32_t gButtonCombo = 0;
|
||||
int32_t gQuality = 90;
|
||||
ImageOutputFormatEnum gOutputFormat = IMAGE_OUTPUT_FORMAT_JPEG;
|
||||
std::string gShortNameEn;
|
@ -1,9 +1,14 @@
|
||||
#ifndef _RETAINS_VARS_H_
|
||||
#define _RETAINS_VARS_H_
|
||||
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
#include <gx2/surface.h>
|
||||
#include <string>
|
||||
#include <wups.h>
|
||||
|
||||
extern wups_loader_app_status_t gAppStatus;
|
||||
extern bool gEnabled;
|
||||
extern ImageSourceEnum gImageSource;
|
||||
extern GX2SurfaceFormat gTVSurfaceFormat;
|
||||
extern GX2SurfaceFormat gDRCSurfaceFormat;
|
||||
extern uint32_t gButtonCombo;
|
||||
|
||||
#endif // _RETAINS_VARS_H_
|
||||
extern int32_t gQuality;
|
||||
extern ImageOutputFormatEnum gOutputFormat;
|
||||
extern std::string gShortNameEn;
|
@ -1,102 +1,138 @@
|
||||
#include "screenshot_utils.h"
|
||||
|
||||
#include <fs/FSUtils.h>
|
||||
#include <malloc.h>
|
||||
#include <coreinit/cache.h>
|
||||
#include "common.h"
|
||||
#include "utils/utils.h"
|
||||
#include <gd.h>
|
||||
#include <gx2/event.h>
|
||||
#include <gx2/surface.h>
|
||||
#include <gx2/mem.h>
|
||||
#include <memory/mappedmemory.h>
|
||||
#include <valarray>
|
||||
|
||||
uint8_t RGBComponentToSRGB[] = {0x00, 0x0C, 0x15, 0x1C, 0x21, 0x26, 0x2A, 0x2E, 0x31, 0x34, 0x37, 0x3A, 0x3D, 0x3F, 0x42, 0x44,
|
||||
0x46, 0x49, 0x4B, 0x4D, 0x4F, 0x51, 0x52, 0x54, 0x56, 0x58, 0x59, 0x5B, 0x5D, 0x5E, 0x60, 0x61,
|
||||
0x63, 0x64, 0x66, 0x67, 0x68, 0x6A, 0x6B, 0x6D, 0x6E, 0x6F, 0x70, 0x72, 0x73, 0x74, 0x75, 0x76,
|
||||
0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
|
||||
0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
||||
0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA1, 0xA2, 0xA3, 0xA4,
|
||||
0xA5, 0xA5, 0xA6, 0xA7, 0xA8, 0xA8, 0xA9, 0xAA, 0xAB, 0xAB, 0xAC, 0xAD, 0xAE, 0xAE, 0xAF, 0xB0,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB3, 0xB4, 0xB5, 0xB5, 0xB6, 0xB7, 0xB7, 0xB8, 0xB9, 0xB9, 0xBA, 0xBB,
|
||||
0xBB, 0xBC, 0xBD, 0xBD, 0xBE, 0xBF, 0xBF, 0xC0, 0xC1, 0xC1, 0xC2, 0xC2, 0xC3, 0xC4, 0xC4, 0xC5,
|
||||
0xC5, 0xC6, 0xC7, 0xC7, 0xC8, 0xC9, 0xC9, 0xCA, 0xCA, 0xCB, 0xCC, 0xCC, 0xCD, 0xCD, 0xCE, 0xCE,
|
||||
0xCF, 0xD0, 0xD0, 0xD1, 0xD1, 0xD2, 0xD2, 0xD3, 0xD4, 0xD4, 0xD5, 0xD5, 0xD6, 0xD6, 0xD7, 0xD7,
|
||||
0xD8, 0xD9, 0xD9, 0xDA, 0xDA, 0xDB, 0xDB, 0xDC, 0xDC, 0xDD, 0xDD, 0xDE, 0xDE, 0xDF, 0xDF, 0xE0,
|
||||
0xE1, 0xE1, 0xE2, 0xE2, 0xE3, 0xE3, 0xE4, 0xE4, 0xE5, 0xE5, 0xE6, 0xE6, 0xE7, 0xE7, 0xE8, 0xE8,
|
||||
0xE9, 0xE9, 0xEA, 0xEA, 0xEB, 0xEB, 0xEC, 0xEC, 0xED, 0xED, 0xED, 0xEE, 0xEE, 0xEF, 0xEF, 0xF0,
|
||||
0xF0, 0xF1, 0xF1, 0xF2, 0xF2, 0xF3, 0xF3, 0xF4, 0xF4, 0xF5, 0xF5, 0xF5, 0xF6, 0xF6, 0xF7, 0xF7,
|
||||
0xF8, 0xF8, 0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFB, 0xFC, 0xFC, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void
|
||||
GX2ResolveAAColorBuffer(const GX2ColorBuffer * srcColorBuffer,
|
||||
GX2Surface * dstSurface,
|
||||
uint32_t dstMip,
|
||||
uint32_t dstSlice);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
JpegInformation * convertToJpeg(uint8_t * sourceBuffer, uint32_t width, uint32_t height, uint32_t pitch, uint32_t format, int32_t quality) {
|
||||
if(sourceBuffer == NULL) {
|
||||
DEBUG_FUNCTION_LINE("path or buffer NULL\n");
|
||||
return NULL;
|
||||
bool saveTextureAsPicture(const std::string &path, uint8_t *sourceBuffer, uint32_t width, uint32_t height, uint32_t pitch, GX2SurfaceFormat format, ImageOutputFormatEnum outputFormat, bool convertRGBtoSRGB, int quality) {
|
||||
if (sourceBuffer == nullptr) {
|
||||
DEBUG_FUNCTION_LINE_ERR("sourceBuffer is nullptr");
|
||||
return false;
|
||||
}
|
||||
if(( format != GX2_SURFACE_FORMAT_SRGB_R8_G8_B8_A8 &&
|
||||
format != GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8)) {
|
||||
DEBUG_FUNCTION_LINE("Format not supported\n");
|
||||
return NULL;
|
||||
if (format != GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Surface format 0x%08X not supported", format);
|
||||
return false;
|
||||
}
|
||||
|
||||
tjhandle handle = tjInitCompress();
|
||||
|
||||
if(handle == NULL) {
|
||||
const char *err = (const char *) tjGetErrorStr();
|
||||
DEBUG_FUNCTION_LINE("TJ Error: %s UNABLE TO INIT TJ Compressor Object\n",err);
|
||||
return NULL;
|
||||
if (quality < 10) {
|
||||
quality = 10;
|
||||
} else if (quality > 100) {
|
||||
quality = 100;
|
||||
}
|
||||
|
||||
int32_t jpegQual = quality;
|
||||
int32_t nbands = 4;
|
||||
int32_t flags = 0;
|
||||
unsigned char* jpegBuf = NULL;
|
||||
auto res = false;
|
||||
|
||||
int32_t pixelFormat = TJPF_GRAY;
|
||||
int32_t jpegSubsamp = TJSAMP_GRAY;
|
||||
if(nbands == 4) {
|
||||
pixelFormat = TJPF_RGBA;
|
||||
jpegSubsamp = TJSAMP_411;
|
||||
}
|
||||
unsigned long jpegSize = 0;
|
||||
|
||||
int32_t tj_stat = tjCompress2( handle, sourceBuffer, width, pitch * nbands, height, pixelFormat, &(jpegBuf), &jpegSize, jpegSubsamp, jpegQual, flags);
|
||||
if(tj_stat != 0) {
|
||||
const char *err = (const char *) tjGetErrorStr();
|
||||
DEBUG_FUNCTION_LINE("TurboJPEG Error: %s UNABLE TO COMPRESS JPEG IMAGE\n", err);
|
||||
tjDestroy(handle);
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE("Success! %08X %08X\n",jpegBuf, jpegSize);
|
||||
return new JpegInformation(handle, jpegBuf, jpegSize);
|
||||
gdImagePtr im = gdImageCreateTrueColor((int) width, (int) height);
|
||||
if (!im) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to create gdImage with dimension: %d x %d", width, height);
|
||||
return false;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
gdImageFill(im, 0, 0, gdImageColorAllocate(im, 255, 255, 255));
|
||||
|
||||
auto *buffer = (uint32_t *) sourceBuffer;
|
||||
|
||||
for (uint32_t y = 0; y < height; ++y) {
|
||||
for (uint32_t x = 0; x < width; ++x) {
|
||||
uint32_t pixel = buffer[(y * pitch) + x];
|
||||
|
||||
uint8_t r = (pixel >> 24) & 0xFF;
|
||||
uint8_t g = (pixel >> 16) & 0xFF;
|
||||
uint8_t b = (pixel >> 8) & 0xFF;
|
||||
|
||||
if (convertRGBtoSRGB) {
|
||||
r = RGBComponentToSRGB[r];
|
||||
g = RGBComponentToSRGB[g];
|
||||
b = RGBComponentToSRGB[b];
|
||||
}
|
||||
|
||||
auto color = gdImageColorAllocate(im, r, g, b);
|
||||
gdImageSetPixel(im, (int) x, (int) y, color);
|
||||
}
|
||||
}
|
||||
|
||||
FILE *file = fopen(path.c_str(), "wb");
|
||||
if (file) {
|
||||
setvbuf(file, nullptr, _IOFBF, 512 * 1024);
|
||||
res = true;
|
||||
|
||||
DEBUG_FUNCTION_LINE("Saving screenshot as %s", path.c_str());
|
||||
switch (outputFormat) {
|
||||
case IMAGE_OUTPUT_FORMAT_JPEG: {
|
||||
gdImageJpeg(im, file, (int32_t) quality);
|
||||
break;
|
||||
}
|
||||
case IMAGE_OUTPUT_FORMAT_PNG: {
|
||||
gdImagePngEx(im, file, -1);
|
||||
break;
|
||||
}
|
||||
case IMAGE_OUTPUT_FORMAT_BMP:
|
||||
gdImageBmp(im, file, -1);
|
||||
break;
|
||||
default:
|
||||
DEBUG_FUNCTION_LINE_ERR("Invalid output format");
|
||||
res = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Close file
|
||||
fclose(file);
|
||||
}
|
||||
gdImageDestroy(im);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool copyBuffer(GX2ColorBuffer * sourceBuffer, GX2ColorBuffer * targetBuffer, uint32_t targetWidth, uint32_t targetHeight) {
|
||||
// Making sure the buffers are not NULL
|
||||
if (sourceBuffer != NULL && targetBuffer != NULL) {
|
||||
uint32_t depth = 1;
|
||||
targetBuffer->surface.use = (GX2SurfaceUse) (GX2_SURFACE_USE_COLOR_BUFFER | GX2_SURFACE_USE_TEXTURE);
|
||||
targetBuffer->surface.dim = GX2_SURFACE_DIM_TEXTURE_2D;
|
||||
targetBuffer->surface.width = targetWidth;
|
||||
targetBuffer->surface.height = targetHeight;
|
||||
targetBuffer->surface.depth = depth;
|
||||
targetBuffer->surface.mipLevels = 1;
|
||||
targetBuffer->surface.format = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8;
|
||||
targetBuffer->surface.aa = GX2_AA_MODE1X;
|
||||
targetBuffer->surface.tileMode = GX2_TILE_MODE_LINEAR_ALIGNED;
|
||||
targetBuffer->viewMip = 0;
|
||||
targetBuffer->viewFirstSlice = 0;
|
||||
targetBuffer->viewNumSlices = 1;
|
||||
targetBuffer->surface.swizzle = 0;
|
||||
targetBuffer->surface.alignment = 0;
|
||||
targetBuffer->surface.pitch = 0;
|
||||
static bool copyBuffer(GX2ColorBuffer *sourceBuffer, GX2ColorBuffer *targetBuffer, uint32_t targetWidth, uint32_t targetHeight) {
|
||||
// Making sure the buffers are not nullptr
|
||||
if (sourceBuffer != nullptr && targetBuffer != nullptr) {
|
||||
uint32_t depth = 1;
|
||||
targetBuffer->surface.use = (GX2SurfaceUse) (GX2_SURFACE_USE_COLOR_BUFFER | GX2_SURFACE_USE_TEXTURE);
|
||||
targetBuffer->surface.dim = GX2_SURFACE_DIM_TEXTURE_2D;
|
||||
targetBuffer->surface.width = targetWidth;
|
||||
targetBuffer->surface.height = targetHeight;
|
||||
targetBuffer->surface.depth = depth;
|
||||
targetBuffer->surface.mipLevels = 1;
|
||||
targetBuffer->surface.format = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8;
|
||||
targetBuffer->surface.aa = GX2_AA_MODE1X;
|
||||
targetBuffer->surface.tileMode = GX2_TILE_MODE_LINEAR_ALIGNED;
|
||||
targetBuffer->viewMip = 0;
|
||||
targetBuffer->viewFirstSlice = 0;
|
||||
targetBuffer->viewNumSlices = 1;
|
||||
targetBuffer->surface.swizzle = 0;
|
||||
targetBuffer->surface.alignment = 0;
|
||||
targetBuffer->surface.pitch = 0;
|
||||
|
||||
uint32_t i;
|
||||
for(i = 0; i < 13; i++) {
|
||||
for (i = 0; i < 13; i++) {
|
||||
targetBuffer->surface.mipLevelOffset[i] = 0;
|
||||
}
|
||||
targetBuffer->viewMip = 0;
|
||||
targetBuffer->viewMip = 0;
|
||||
targetBuffer->viewFirstSlice = 0;
|
||||
targetBuffer->viewNumSlices = depth;
|
||||
targetBuffer->aaBuffer = NULL;
|
||||
targetBuffer->aaSize = 0;
|
||||
for(i = 0; i < 5; i++){
|
||||
targetBuffer->viewNumSlices = depth;
|
||||
targetBuffer->aaBuffer = nullptr;
|
||||
targetBuffer->aaSize = 0;
|
||||
for (i = 0; i < 5; i++) {
|
||||
targetBuffer->regs[i] = 0;
|
||||
}
|
||||
|
||||
@ -104,12 +140,11 @@ bool copyBuffer(GX2ColorBuffer * sourceBuffer, GX2ColorBuffer * targetBuffer, ui
|
||||
GX2InitColorBufferRegs(targetBuffer);
|
||||
|
||||
// Let's allocate the memory.
|
||||
targetBuffer->surface.image = memalign(targetBuffer->surface.alignment,targetBuffer->surface.imageSize);
|
||||
if(targetBuffer->surface.image == NULL) {
|
||||
DEBUG_FUNCTION_LINE("failed to allocate memory.\n");
|
||||
targetBuffer->surface.image = MEMAllocFromMappedMemoryForGX2Ex(targetBuffer->surface.imageSize, targetBuffer->surface.alignment);
|
||||
if (targetBuffer->surface.image == nullptr) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to allocate memory for the surface image");
|
||||
return false;
|
||||
}
|
||||
DEBUG_FUNCTION_LINE("Allocated image data buffer. data %08X size %08X \n",targetBuffer->surface.image,targetBuffer->surface.imageSize);
|
||||
|
||||
GX2Invalidate(GX2_INVALIDATE_MODE_CPU, targetBuffer->surface.image, targetBuffer->surface.imageSize);
|
||||
if (sourceBuffer->surface.aa == GX2_AA_MODE1X) {
|
||||
@ -121,74 +156,106 @@ bool copyBuffer(GX2ColorBuffer * sourceBuffer, GX2ColorBuffer * targetBuffer, ui
|
||||
} else {
|
||||
// If AA is enabled, we need to resolve the AA buffer.
|
||||
GX2Surface tempSurface;
|
||||
tempSurface = sourceBuffer->surface;
|
||||
tempSurface = sourceBuffer->surface;
|
||||
tempSurface.aa = GX2_AA_MODE1X;
|
||||
GX2CalcSurfaceSizeAndAlignment(&tempSurface);
|
||||
|
||||
tempSurface.image = memalign(tempSurface.alignment,tempSurface.imageSize);
|
||||
if(tempSurface.image == NULL) {
|
||||
DEBUG_FUNCTION_LINE("failed to allocate data AA.\n");
|
||||
if(targetBuffer->surface.image != NULL) {
|
||||
free(targetBuffer->surface.image);
|
||||
targetBuffer->surface.image = NULL;
|
||||
tempSurface.image = MEMAllocFromMappedMemoryForGX2Ex(tempSurface.imageSize, tempSurface.alignment);
|
||||
if (tempSurface.image == nullptr) {
|
||||
DEBUG_FUNCTION_LINE_ERR("failed to allocate data for resolving AA");
|
||||
if (targetBuffer->surface.image != nullptr) {
|
||||
MEMFreeToMappedMemory(targetBuffer->surface.image);
|
||||
targetBuffer->surface.image = nullptr;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
GX2ResolveAAColorBuffer(sourceBuffer,&tempSurface, 0, 0);
|
||||
GX2CopySurface(&tempSurface, 0, 0,&targetBuffer->surface, 0, 0);
|
||||
GX2ResolveAAColorBuffer(sourceBuffer, &tempSurface, 0, 0);
|
||||
GX2CopySurface(&tempSurface, 0, 0, &targetBuffer->surface, 0, 0);
|
||||
|
||||
// Sync CPU and GPU
|
||||
GX2DrawDone();
|
||||
|
||||
if(tempSurface.image != NULL) {
|
||||
free(tempSurface.image);
|
||||
tempSurface.image = NULL;
|
||||
if (tempSurface.image != nullptr) {
|
||||
MEMFreeToMappedMemory(tempSurface.image);
|
||||
tempSurface.image = nullptr;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE("Couldn't copy buffer, pointer was NULL\n");
|
||||
DEBUG_FUNCTION_LINE_ERR("Couldn't copy buffer, pointer was nullptr");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool takeScreenshot(GX2ColorBuffer *srcBuffer,const char * path) {
|
||||
if(srcBuffer == NULL) {
|
||||
bool takeScreenshot(GX2ColorBuffer *srcBuffer, const std::string &path, GX2ScanTarget scanTarget, GX2SurfaceFormat outputBufferSurfaceFormat, ImageOutputFormatEnum outputFormat, int quality) {
|
||||
if (srcBuffer == nullptr) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Source buffer was NULL");
|
||||
return false;
|
||||
}
|
||||
DEBUG_FUNCTION_LINE("Taking screenshot. %s\n",path);
|
||||
|
||||
GX2ColorBuffer colorBuffer;
|
||||
GX2ColorBuffer * saveBuffer = NULL;
|
||||
GX2ColorBuffer *saveBuffer = nullptr;
|
||||
|
||||
// keep dimensions
|
||||
uint32_t width = srcBuffer->surface.width;
|
||||
uint32_t width = srcBuffer->surface.width;
|
||||
uint32_t height = srcBuffer->surface.height;
|
||||
|
||||
bool valid = false;
|
||||
bool cancel = false;
|
||||
bool low_memory = false;
|
||||
do {
|
||||
// At first we need to copy the buffer to fit our resolution.
|
||||
if(saveBuffer == NULL) {
|
||||
do {
|
||||
valid = copyBuffer(srcBuffer,&colorBuffer,width,height);
|
||||
// If the copying failed, we don't have enough memory. Let's decrease the resolution.
|
||||
if(!valid) {
|
||||
low_memory = true;
|
||||
std::string fullPath = path;
|
||||
|
||||
if(height >= 1080) {
|
||||
width = 1280;
|
||||
if (scanTarget == GX2_SCAN_TARGET_DRC) {
|
||||
fullPath += "DRC";
|
||||
} else if (scanTarget == GX2_SCAN_TARGET_TV) {
|
||||
fullPath += "TV";
|
||||
} else if (scanTarget == GX2_SCAN_TARGET_DRC1) {
|
||||
fullPath += "DRC2";
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_ERR("Invalid scanTarget %d", scanTarget);
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (outputFormat) {
|
||||
case IMAGE_OUTPUT_FORMAT_JPEG:
|
||||
fullPath += ".jpg";
|
||||
break;
|
||||
case IMAGE_OUTPUT_FORMAT_PNG:
|
||||
fullPath += ".png";
|
||||
break;
|
||||
case IMAGE_OUTPUT_FORMAT_BMP:
|
||||
fullPath += ".bmp";
|
||||
break;
|
||||
default:
|
||||
DEBUG_FUNCTION_LINE_WARN("Invalid output format, use jpeg instead");
|
||||
fullPath += ".jpg";
|
||||
break;
|
||||
}
|
||||
|
||||
bool convertRGBToSRGB = false;
|
||||
if ((outputBufferSurfaceFormat & 0x400)) {
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("Images needs to be converted to SRGB");
|
||||
convertRGBToSRGB = true;
|
||||
}
|
||||
|
||||
bool valid;
|
||||
bool cancel = false;
|
||||
do {
|
||||
// At first, we need to copy the buffer to fit our resolution.
|
||||
if (saveBuffer == nullptr) {
|
||||
do {
|
||||
valid = copyBuffer(srcBuffer, &colorBuffer, width, height);
|
||||
// If the copying failed, we don't have enough memory. Let's decrease the resolution.
|
||||
if (!valid) {
|
||||
if (height >= 1080) {
|
||||
width = 1280;
|
||||
height = 720;
|
||||
DEBUG_FUNCTION_LINE("Switching to 720p.\n");
|
||||
} else if(height >= 720) {
|
||||
width = 854;
|
||||
DEBUG_FUNCTION_LINE("Switching to 720p.");
|
||||
} else if (height >= 720) {
|
||||
width = 854;
|
||||
height = 480;
|
||||
DEBUG_FUNCTION_LINE("Switching to 480p.\n");
|
||||
} else if(height >= 480) {
|
||||
width = 640;
|
||||
DEBUG_FUNCTION_LINE("Switching to 480p.");
|
||||
} else if (height >= 480) {
|
||||
width = 640;
|
||||
height = 360;
|
||||
DEBUG_FUNCTION_LINE("Switching to 360p.\n");
|
||||
DEBUG_FUNCTION_LINE("Switching to 360p.");
|
||||
} else {
|
||||
// Cancel the screenshot if the resolution would be too low.
|
||||
cancel = true;
|
||||
@ -198,65 +265,53 @@ bool takeScreenshot(GX2ColorBuffer *srcBuffer,const char * path) {
|
||||
// On success save the pointer.
|
||||
saveBuffer = &colorBuffer;
|
||||
}
|
||||
} while(!valid);
|
||||
} while (!valid);
|
||||
}
|
||||
|
||||
// Check if we should proceed
|
||||
if(cancel) {
|
||||
if (cancel) {
|
||||
// Free the memory on error.
|
||||
if(colorBuffer.surface.image != NULL) {
|
||||
free(colorBuffer.surface.image);
|
||||
colorBuffer.surface.image = NULL;
|
||||
if (colorBuffer.surface.image != nullptr) {
|
||||
MEMFreeToMappedMemory(colorBuffer.surface.image);
|
||||
colorBuffer.surface.image = nullptr;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Flush out destinations caches
|
||||
GX2Invalidate(GX2_INVALIDATE_MODE_COLOR_BUFFER, colorBuffer.surface.image,colorBuffer.surface.imageSize);
|
||||
GX2Invalidate(GX2_INVALIDATE_MODE_COLOR_BUFFER, colorBuffer.surface.image, colorBuffer.surface.imageSize);
|
||||
|
||||
// Wait for GPU to finish
|
||||
GX2DrawDone();
|
||||
|
||||
DEBUG_FUNCTION_LINE("Trying to save.\n");
|
||||
|
||||
JpegInformation * jpegResult = convertToJpeg((uint8_t *) saveBuffer->surface.image,width,height,saveBuffer->surface.pitch,saveBuffer->surface.format, 95);
|
||||
if(jpegResult != NULL) {
|
||||
DEBUG_FUNCTION_LINE("Encoded file as JPEG. size = %lld.\n", jpegResult->getSize());
|
||||
DCFlushRange(jpegResult->getBuffer(), jpegResult->getSize());
|
||||
valid = FSUtils::saveBufferToFile(path, (void *) jpegResult->getBuffer(), jpegResult->getSize());
|
||||
if(!valid) {
|
||||
DEBUG_FUNCTION_LINE("Failed to save buffer to %s \n",path);
|
||||
}
|
||||
delete jpegResult;
|
||||
}
|
||||
valid = saveTextureAsPicture(fullPath, (uint8_t *) saveBuffer->surface.image, width, height, saveBuffer->surface.pitch, saveBuffer->surface.format, outputFormat, convertRGBToSRGB, quality);
|
||||
|
||||
// Free the colorbuffer copy.
|
||||
if(colorBuffer.surface.image != NULL) {
|
||||
free(colorBuffer.surface.image);
|
||||
colorBuffer.surface.image = NULL;
|
||||
saveBuffer = NULL;
|
||||
if (colorBuffer.surface.image != nullptr) {
|
||||
MEMFreeToMappedMemory(colorBuffer.surface.image);
|
||||
colorBuffer.surface.image = nullptr;
|
||||
saveBuffer = nullptr;
|
||||
}
|
||||
|
||||
// When taking the screenshot failed, decrease the resolution again ~.
|
||||
if(!valid) {
|
||||
low_memory = true;
|
||||
if(height >= 1080) {
|
||||
width = 1280;
|
||||
if (!valid) {
|
||||
if (height >= 1080) {
|
||||
width = 1280;
|
||||
height = 720;
|
||||
DEBUG_FUNCTION_LINE("Switching to 720p.\n");
|
||||
} else if(height >= 720) {
|
||||
width = 854;
|
||||
DEBUG_FUNCTION_LINE("Switching to 720p.");
|
||||
} else if (height >= 720) {
|
||||
width = 854;
|
||||
height = 480;
|
||||
DEBUG_FUNCTION_LINE("Switching to 480p.\n");
|
||||
} else if(height >= 480) {
|
||||
width = 640;
|
||||
DEBUG_FUNCTION_LINE("Switching to 480p.");
|
||||
} else if (height >= 480) {
|
||||
width = 640;
|
||||
height = 360;
|
||||
DEBUG_FUNCTION_LINE("Switching to 360p.\n");
|
||||
DEBUG_FUNCTION_LINE("Switching to 360p.");
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} while(!valid);
|
||||
} while (!valid);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1,14 +1,13 @@
|
||||
#ifndef _SCREENSHOT_UTILS_H_
|
||||
#define _SCREENSHOT_UTILS_H_
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include "utils/logger.h"
|
||||
#include <gx2/surface.h>
|
||||
#include <utils/logger.h>
|
||||
#include "JpegInformation.h"
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
JpegInformation * convertToJpeg(uint8_t * sourceBuffer, uint32_t width, uint32_t height, uint32_t pitch, uint32_t format, int32_t quality);
|
||||
bool saveTextureAsPicture(const std::string &path, uint8_t *sourceBuffer, uint32_t width, uint32_t height, uint32_t pitch, GX2SurfaceFormat format, ImageOutputFormatEnum outputFormat, bool convertRGBtoSRGB, int quality);
|
||||
|
||||
bool copyBuffer(GX2ColorBuffer * sourceBuffer, GX2ColorBuffer * targetBuffer, uint32_t targetWidth, uint32_t targetHeight);
|
||||
|
||||
bool takeScreenshot(GX2ColorBuffer *srcBuffer,const char * path);
|
||||
|
||||
#endif
|
||||
bool takeScreenshot(GX2ColorBuffer *srcBuffer, const std::string &path, GX2ScanTarget scanTarget, GX2SurfaceFormat outputBufferSurfaceFormat, ImageOutputFormatEnum outputFormat, int quality);
|
||||
|
14
src/utils/StringTools.h
Normal file
14
src/utils/StringTools.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
template<typename... Args>
|
||||
std::string string_format(const std::string &format, Args... args) {
|
||||
int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1; // Extra space for '\0'
|
||||
auto size = static_cast<size_t>(size_s);
|
||||
auto buf = std::make_unique<char[]>(size);
|
||||
std::snprintf(buf.get(), size, format.c_str(), args...);
|
||||
return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
|
||||
}
|
36
src/utils/logger.c
Normal file
36
src/utils/logger.c
Normal file
@ -0,0 +1,36 @@
|
||||
#ifdef DEBUG
|
||||
#include <stdint.h>
|
||||
#include <whb/log_cafe.h>
|
||||
#include <whb/log_module.h>
|
||||
#include <whb/log_udp.h>
|
||||
|
||||
uint32_t moduleLogInit = false;
|
||||
uint32_t cafeLogInit = false;
|
||||
uint32_t udpLogInit = false;
|
||||
#endif // DEBUG
|
||||
|
||||
void initLogging() {
|
||||
#ifdef DEBUG
|
||||
if (!(moduleLogInit = WHBLogModuleInit())) {
|
||||
cafeLogInit = WHBLogCafeInit();
|
||||
udpLogInit = WHBLogUdpInit();
|
||||
}
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
void deinitLogging() {
|
||||
#ifdef DEBUG
|
||||
if (moduleLogInit) {
|
||||
WHBLogModuleDeinit();
|
||||
moduleLogInit = false;
|
||||
}
|
||||
if (cafeLogInit) {
|
||||
WHBLogCafeDeinit();
|
||||
cafeLogInit = false;
|
||||
}
|
||||
if (udpLogInit) {
|
||||
WHBLogUdpDeinit();
|
||||
udpLogInit = false;
|
||||
}
|
||||
#endif // DEBUG
|
||||
}
|
72
src/utils/logger.h
Normal file
72
src/utils/logger.h
Normal file
@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#include <coreinit/debug.h>
|
||||
#include <string.h>
|
||||
#include <whb/log.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define LOG_APP_TYPE "P"
|
||||
#define LOG_APP_NAME "ScreenshotPlugin"
|
||||
|
||||
#define __FILENAME__ ({ \
|
||||
const char *__filename = __FILE__; \
|
||||
const char *__pos = strrchr(__filename, '/'); \
|
||||
if (!__pos) __pos = strrchr(__filename, '\\'); \
|
||||
__pos ? __pos + 1 : __filename; \
|
||||
})
|
||||
|
||||
#define LOG(LOG_FUNC, FMT, ARGS...) LOG_EX_DEFAULT(LOG_FUNC, "", "", FMT, ##ARGS)
|
||||
|
||||
#define LOG_EX_DEFAULT(LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ARGS...) LOG_EX(__FILENAME__, __FUNCTION__, __LINE__, LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ##ARGS)
|
||||
|
||||
#define LOG_EX(FILENAME, FUNCTION, LINE, LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ARGS...) \
|
||||
do { \
|
||||
LOG_FUNC("[(%s)%18s][%23s]%30s@L%04d: " LOG_LEVEL "" FMT "" LINE_END, LOG_APP_TYPE, LOG_APP_NAME, FILENAME, FUNCTION, LINE, ##ARGS); \
|
||||
} while (0)
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#ifdef VERBOSE_DEBUG
|
||||
#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) LOG(WHBLogPrintf, FMT, ##ARGS)
|
||||
#define DEBUG_FUNCTION_LINE_VERBOSE_EX(FILENAME, FUNCTION, LINE, FMT, ARGS...) LOG_EX(FILENAME, FUNCTION, LINE, WHBLogPrintf, "", "", FMT, ##ARGS);
|
||||
#else
|
||||
#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) while (0)
|
||||
#define DEBUG_FUNCTION_LINE_VERBOSE_EX(FMT, ARGS...) while (0)
|
||||
#endif
|
||||
|
||||
#define DEBUG_FUNCTION_LINE(FMT, ARGS...) LOG(WHBLogPrintf, FMT, ##ARGS)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_WRITE(FMT, ARGS...) LOG(WHBLogWritef, FMT, ##ARGS)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_ERR(FMT, ARGS...) LOG_EX_DEFAULT(WHBLogPrintf, "##ERROR## ", "", FMT, ##ARGS)
|
||||
#define DEBUG_FUNCTION_LINE_WARN(FMT, ARGS...) LOG_EX_DEFAULT(WHBLogPrintf, "##WARN ## ", "", FMT, ##ARGS)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_ERR_LAMBDA(FILENAME, FUNCTION, LINE, FMT, ARGS...) LOG_EX(FILENAME, FUNCTION, LINE, WHBLogPrintf, "##ERROR## ", "", FMT, ##ARGS);
|
||||
|
||||
#else
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_VERBOSE_EX(FMT, ARGS...) while (0)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) while (0)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE(FMT, ARGS...) while (0)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_WRITE(FMT, ARGS...) while (0)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_ERR(FMT, ARGS...) LOG_EX_DEFAULT(OSReport, "##ERROR## ", "\n", FMT, ##ARGS)
|
||||
#define DEBUG_FUNCTION_LINE_WARN(FMT, ARGS...) LOG_EX_DEFAULT(OSReport, "##WARN ## ", "\n", FMT, ##ARGS)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_ERR_LAMBDA(FILENAME, FUNCTION, LINE, FMT, ARGS...) LOG_EX(FILENAME, FUNCTION, LINE, OSReport, "##ERROR## ", "\n", FMT, ##ARGS);
|
||||
|
||||
#endif
|
||||
|
||||
void initLogging();
|
||||
|
||||
void deinitLogging();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
12
src/utils/utils.h
Normal file
12
src/utils/utils.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
|
||||
template<class T, class... Args>
|
||||
std::unique_ptr<T> make_unique_nothrow(Args &&...args) noexcept(noexcept(T(std::forward<Args>(args)...))) {
|
||||
return std::unique_ptr<T>(new (std::nothrow) T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template<class T, class... Args>
|
||||
std::shared_ptr<T> make_shared_nothrow(Args &&...args) noexcept(noexcept(T(std::forward<Args>(args)...))) {
|
||||
return std::shared_ptr<T>(new (std::nothrow) T(std::forward<Args>(args)...));
|
||||
}
|
2
src/version.h
Normal file
2
src/version.h
Normal file
@ -0,0 +1,2 @@
|
||||
#pragma once
|
||||
#define VERSION_EXTRA ""
|
Loading…
Reference in New Issue
Block a user