1// Aseprite
2// Copyright (C) 2019-2022 Igara Studio S.A.
3// Copyright (C) 2001-2016 David Capello
4//
5// This program is distributed under the terms of
6// the End-User License Agreement for Aseprite.
7
8#ifdef HAVE_CONFIG_H
9#include "config.h"
10#endif
11
12#include "app/app.h"
13#include "app/cli/app_options.h"
14#include "app/console.h"
15#include "app/resource_finder.h"
16#include "app/send_crash.h"
17#include "base/exception.h"
18#include "base/memory.h"
19#include "base/system_console.h"
20#include "doc/palette.h"
21#include "os/error.h"
22#include "os/system.h"
23#include "ver/info.h"
24
25#if ENABLE_SENTRY
26 #include "app/sentry_wrapper.h"
27 #if LAF_WINDOWS
28 #define USE_SENTRY_BREADCRUMB_FOR_WINTAB 1
29 #include "os/win/wintab.h"
30 #endif
31#else
32 #include "base/memory_dump.h"
33#endif
34
35#include <clocale>
36#include <cstdlib>
37#include <ctime>
38#include <iostream>
39
40#if LAF_WINDOWS
41 #include <windows.h>
42#endif
43
44namespace {
45
46 // Memory leak detector wrapper
47 class MemLeak {
48 public:
49#ifdef LAF_MEMLEAK
50 MemLeak() { base_memleak_init(); }
51 ~MemLeak() { base_memleak_exit(); }
52#else
53 MemLeak() { }
54#endif
55 };
56
57#if LAF_WINDOWS
58 // Successful calls to CoInitialize() (S_OK or S_FALSE) must match
59 // the calls to CoUninitialize().
60 // From: https://docs.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-couninitialize#remarks
61 struct CoInit {
62 HRESULT hr;
63 CoInit() {
64 hr = CoInitialize(nullptr);
65 }
66 ~CoInit() {
67 if (hr == S_OK || hr == S_FALSE)
68 CoUninitialize();
69 }
70 };
71#endif // LAF_WINDOWS
72
73#if USE_SENTRY_BREADCRUMB_FOR_WINTAB
74 // Delegate to write Wintab information as a Sentry breadcrumb (to
75 // know if there is a specific Wintab driver giving problems)
76 class WintabApiDelegate : public os::WintabAPI::Delegate {
77 bool m_done = false;
78 public:
79 WintabApiDelegate() {
80 os::instance()->setWintabDelegate(this);
81 }
82 ~WintabApiDelegate() {
83 os::instance()->setWintabDelegate(nullptr);
84 }
85 void onWintabID(const std::string& id) override {
86 if (!m_done) {
87 m_done = true;
88 app::Sentry::addBreadcrumb("Wintab ID=" + id);
89 }
90 }
91 void onWintabFields(const std::map<std::string, std::string>& fields) override {
92 app::Sentry::addBreadcrumb("Wintab DLL", fields);
93 }
94 };
95#endif // USE_SENTRY_BREADCRUMB_FOR_WINTAB
96
97}
98
99// Aseprite entry point. (Called from "os" library.)
100int app_main(int argc, char* argv[])
101{
102 // Initialize the locale. Aseprite isn't ready to handle numeric
103 // fields with other locales (e.g. we expect strings like "10.32" be
104 // used in std::strtod(), not something like "10,32").
105 std::setlocale(LC_ALL, "en-US");
106 ASSERT(std::strtod("10.32", nullptr) == 10.32);
107
108 // Initialize the random seed.
109 std::srand(static_cast<unsigned int>(std::time(nullptr)));
110
111#if LAF_WINDOWS
112 CoInit com; // To create COM objects
113#endif
114
115 try {
116#if ENABLE_SENTRY
117 app::Sentry sentry;
118#else
119 base::MemoryDump memoryDump;
120#endif
121 MemLeak memleak;
122 base::SystemConsole systemConsole;
123 app::AppOptions options(argc, const_cast<const char**>(argv));
124 os::SystemRef system(os::make_system());
125 doc::Palette::initBestfit();
126 app::App app;
127
128#if ENABLE_SENTRY
129 sentry.init();
130 #if USE_SENTRY_BREADCRUMB_FOR_WINTAB
131 WintabApiDelegate wintabDelegate;
132 #endif
133#else
134 // Change the memory dump filename to save on disk (.dmp
135 // file). Note: Only useful on Windows.
136 {
137 const std::string fn = app::SendCrash::DefaultMemoryDumpFilename();
138 if (!fn.empty())
139 memoryDump.setFileName(fn);
140 }
141#endif
142
143 const int code = app.initialize(options);
144
145 if (options.startShell())
146 systemConsole.prepareShell();
147
148 app.run();
149
150 // After starting the GUI, we'll always return 0, but in batch
151 // mode we can return the error code.
152 return (app.isGui() ? 0: code);
153 }
154 catch (std::exception& e) {
155 std::cerr << e.what() << '\n';
156 os::error_message(e.what());
157 return 1;
158 }
159}
160