A pixel art painter geared specifically at NES pixel art. Includes export for .chr binary file as well as palette and namespace data.
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. const package = require("./package.json");
  2. const vendors = require("./vendors.json");
  3. const exec = require('child_process').execSync;
  4. const fs = require("fs");
  5. const path = require("path");
  6. const express = require("express");
  7. const app = express();
  8. const http = require("http");
  9. const https = require("https");
  10. const sass = require("sass");
  11. const SASS_PATH = path.join(__dirname, "sass");
  12. const SASS_FILE = "style.scss";
  13. const watcher = require("chokidar").watch(SASS_PATH, {ignored: /[\/\\]\./, persistent: true});
  14. // --------------------------------------------------------
  15. // Environment options for the server.
  16. var production = process.env.PRODUCTION || false;
  17. var forceCSSRegen = process.env.FORCECSSREGEN || false;
  18. // NOTE: The default ports are blocked by default on linux without some hocus pocus.
  19. var port = process.env.NESPORT || 80;
  20. var portSSL = process.env.NESPORTSSL || 443;
  21. var sslKeyPath = process.env.SSLKEYPATH || null;
  22. var sslCertPath = process.env.SSLCERTPATH || null;
  23. var sslCaPath = process.env.SSLCAPATH || null;
  24. var css_output = ""; // Used to hold dynamic css.
  25. // -------------------------------------------------------
  26. // Simple helper function
  27. function debounce(func, delay, scope){
  28. var timeout = null;
  29. return function(){
  30. var context = scope || this;
  31. var args = arguments;
  32. clearTimeout(timeout);
  33. timeout = setTimeout(function(){
  34. func.apply(context, args);
  35. }, delay);
  36. };
  37. }
  38. var generateCSS = debounce(function(src, cb){
  39. sass.render({file: src}, (err, res)=>{
  40. if (err){
  41. cb("Failed to generate css - " + err.toString());
  42. } else {
  43. css_output = res.css.toString();
  44. cb();
  45. }
  46. });
  47. }, 1000);
  48. // -------------------------------------------------------
  49. // Configuring the current version of the application.
  50. function GitClean(){
  51. try {
  52. exec("git diff --quiet HEAD");
  53. } catch(e) {
  54. return false;
  55. }
  56. return true;
  57. }
  58. function GenVersion(){
  59. var v = package.version;
  60. var clean = GitClean();
  61. // Testing for a GIT repo... if not in a production environment.
  62. if (production === false){
  63. try{
  64. var res = exec("git rev-parse --abbrev-ref HEAD").toString();
  65. v += "-[" + res.trim();
  66. res = exec("git rev-parse HEAD").toString();
  67. v += ":" + res.substring(0, 5) + ((clean) ? "" : "-X") + "]";
  68. } catch(e) {
  69. if (v !== package.version){
  70. v += "]"; // If v doesn't match package.version, then assume that the first git call worked.
  71. }
  72. }
  73. }
  74. return v;
  75. }
  76. // ---------------------------------------------------
  77. // Configuring the express server.
  78. app.set('views', path.join(__dirname, "/views"));
  79. app.engine('html', require('ejs').renderFile);
  80. app.set('view engine', 'html');
  81. app.use("/app", express.static(path.join(__dirname, "/app")));
  82. vendors.modules.forEach((m) => {
  83. var p = path.normalize(path.join(__dirname, vendors.default_path, m.path));
  84. var url = path.join(vendors.url_path, m.url_path);
  85. app.use(url, express.static(p));
  86. });
  87. app.use("/app/css/nespaint.css", function(req, res){
  88. res.set("Content-Type", "text/css");
  89. res.send(new Buffer.from(css_output));
  90. });
  91. app.get('/', function(req, res){
  92. res.render('index.html', {version:GenVersion(), author:package.author, description:package.description, license:package.license});
  93. });
  94. // ----------------------------------------------------
  95. // Watching for any needed file updates (to minimize the need to restart the server.
  96. watcher.on('ready', () => {
  97. generateCSS(path.join(SASS_PATH, SASS_FILE), (err) => {
  98. if (err){
  99. console.log("ERROR: " + err);
  100. exit();
  101. } else {
  102. startServer();
  103. }
  104. });
  105. });
  106. watcher.on('change', (fpath) => {
  107. generateCSS(path.join(SASS_PATH, SASS_FILE), (err) => {
  108. if (err)
  109. console.log("WARNING: " + err);
  110. });
  111. });
  112. // --------------------------------------------------
  113. // Announce app version!
  114. console.log("NESPaint (v" + GenVersion() + ") Server");
  115. // --------------------------------------------------
  116. // KICK THE PIG!
  117. function startServer(){
  118. // Check if given SSL key and cert(s). If so, attempt to start an HTTPS server and
  119. // reroute HTTP requests to HTTPS.
  120. if (sslKeyPath !== null && sslCertPath !== null){
  121. try {
  122. var options = {
  123. key: fs.readFileSync(sslKeyPath),
  124. cert: fs.readFileSync(sslCertPath)
  125. }
  126. if (sslCaPath !== null)
  127. options.ca = fs.readFileSync(sslCaPath);
  128. app.use(function(req, res, next){
  129. if (req.secure){
  130. next();
  131. } else {
  132. res.redirect('https://' + req.headers.host + req.url);
  133. }
  134. });
  135. https.createServer(options, app).listen(portSSL, () => {
  136. console.log("HTTPS Listening on port " + portSSL + "!");
  137. });
  138. } catch (e) {
  139. console.log("WARNING: Failed to initialize HTTPS server. \"" + e.toString() + "\"");
  140. }
  141. }
  142. // Start the HTTP server.
  143. http.createServer(app).listen(port, () => {
  144. console.log("HTTP Listening on port " + port + "!");
  145. });
  146. }