From 66580f32c2f4d39a82b77e4b6982e7ea6dde0766 Mon Sep 17 00:00:00 2001
From: Scott Lahteine <thinkyhead@users.noreply.github.com>
Date: Fri, 16 Nov 2018 22:39:16 -0600
Subject: [PATCH] Make CardReader class static (#12451)

* Make CardReader a static class
* Make CardReader flags into bitfields
---
 Marlin/src/HAL/HAL_DUE/usb/sd_mmc_spi_mem.cpp |  10 +-
 Marlin/src/HAL/HAL_LPC1768/main.cpp           |   2 +-
 .../HAL_STM32F1/persistent_store_sdcard.cpp   |   4 +-
 Marlin/src/Marlin.cpp                         |   2 +-
 Marlin/src/feature/power_loss_recovery.cpp    |   4 +-
 Marlin/src/feature/power_loss_recovery.h      |   2 +-
 Marlin/src/gcode/queue.cpp                    |  12 +-
 .../sdcard/M20-M30_M32-M34_M524_M928.cpp      |  12 +-
 Marlin/src/lcd/extensible_ui/ui_api.cpp       |  12 +-
 Marlin/src/lcd/malyanlcd.cpp                  |   6 +-
 Marlin/src/lcd/menu/menu_main.cpp             |   4 +-
 Marlin/src/lcd/menu/menu_sdcard.cpp           |   2 +-
 Marlin/src/sd/SdFatConfig.h                   |   4 +-
 Marlin/src/sd/cardreader.cpp                  | 212 ++++++++++++------
 Marlin/src/sd/cardreader.h                    | 183 ++++++++-------
 15 files changed, 281 insertions(+), 190 deletions(-)

diff --git a/Marlin/src/HAL/HAL_DUE/usb/sd_mmc_spi_mem.cpp b/Marlin/src/HAL/HAL_DUE/usb/sd_mmc_spi_mem.cpp
index 1054f5ab34c..cdb81b24892 100644
--- a/Marlin/src/HAL/HAL_DUE/usb/sd_mmc_spi_mem.cpp
+++ b/Marlin/src/HAL/HAL_DUE/usb/sd_mmc_spi_mem.cpp
@@ -19,7 +19,7 @@ void sd_mmc_spi_mem_init(void) {
 }
 
 Ctrl_status sd_mmc_spi_test_unit_ready(void) {
-  if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.cardOK)
+  if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.flag.cardOK)
     return CTRL_NO_PRESENT;
   return CTRL_GOOD;
 }
@@ -27,7 +27,7 @@ Ctrl_status sd_mmc_spi_test_unit_ready(void) {
 // NOTE: This function is defined as returning the address of the last block
 // in the card, which is cardSize() - 1
 Ctrl_status sd_mmc_spi_read_capacity(uint32_t *nb_sector) {
-  if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.cardOK)
+  if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.flag.cardOK)
     return CTRL_NO_PRESENT;
   *nb_sector = card.getSd2Card().cardSize() - 1;
   return CTRL_GOOD;
@@ -42,7 +42,7 @@ bool sd_mmc_spi_wr_protect(void) {
 }
 
 bool sd_mmc_spi_removal(void) {
-  if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.cardOK)
+  if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.flag.cardOK)
     return true;
   return false;
 }
@@ -61,7 +61,7 @@ uint8_t sector_buf[SD_MMC_BLOCK_SIZE];
 // #define DEBUG_MMC
 
 Ctrl_status sd_mmc_spi_usb_read_10(uint32_t addr, uint16_t nb_sector) {
-  if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.cardOK)
+  if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.flag.cardOK)
     return CTRL_NO_PRESENT;
 
   #ifdef DEBUG_MMC
@@ -95,7 +95,7 @@ Ctrl_status sd_mmc_spi_usb_read_10(uint32_t addr, uint16_t nb_sector) {
 }
 
 Ctrl_status sd_mmc_spi_usb_write_10(uint32_t addr, uint16_t nb_sector) {
-  if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.cardOK)
+  if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.flag.cardOK)
     return CTRL_NO_PRESENT;
 
   #ifdef DEBUG_MMC
diff --git a/Marlin/src/HAL/HAL_LPC1768/main.cpp b/Marlin/src/HAL/HAL_LPC1768/main.cpp
index 02207c61099..c4aea39660d 100644
--- a/Marlin/src/HAL/HAL_LPC1768/main.cpp
+++ b/Marlin/src/HAL/HAL_LPC1768/main.cpp
@@ -106,7 +106,7 @@ void HAL_idletask(void) {
     // the disk if Marlin has it mounted. Unfortuately there is currently no way
     // to unmount the disk from the LCD menu.
     // if (IS_SD_PRINTING() || IS_SD_FILE_OPEN())
-    if (card.cardOK)
+    if (card.flag.cardOK)
       MSC_Aquire_Lock();
     else
       MSC_Release_Lock();
diff --git a/Marlin/src/HAL/HAL_STM32F1/persistent_store_sdcard.cpp b/Marlin/src/HAL/HAL_STM32F1/persistent_store_sdcard.cpp
index 349abba246b..757d62fd591 100644
--- a/Marlin/src/HAL/HAL_STM32F1/persistent_store_sdcard.cpp
+++ b/Marlin/src/HAL/HAL_STM32F1/persistent_store_sdcard.cpp
@@ -41,7 +41,7 @@ char HAL_STM32F1_eeprom_content[HAL_STM32F1_EEPROM_SIZE];
 char eeprom_filename[] = "eeprom.dat";
 
 bool PersistentStore::access_start() {
-  if (!card.cardOK) return false;
+  if (!card.flag.cardOK) return false;
   int16_t bytes_read = 0;
   constexpr char eeprom_zero = 0xFF;
   card.openFile(eeprom_filename, true);
@@ -54,7 +54,7 @@ bool PersistentStore::access_start() {
 }
 
 bool PersistentStore::access_finish() {
-  if (!card.cardOK) return false;
+  if (!card.flag.cardOK) return false;
   card.openFile(eeprom_filename, true);
   int16_t bytes_written = card.write(HAL_STM32F1_eeprom_content, HAL_STM32F1_EEPROM_SIZE);
   card.closefile();
diff --git a/Marlin/src/Marlin.cpp b/Marlin/src/Marlin.cpp
index f2522f2ee95..50957517b5c 100644
--- a/Marlin/src/Marlin.cpp
+++ b/Marlin/src/Marlin.cpp
@@ -967,7 +967,7 @@ void loop() {
     #if ENABLED(SDSUPPORT)
       card.checkautostart();
 
-      if (card.abort_sd_printing) {
+      if (card.flag.abort_sd_printing) {
         card.stopSDPrint(
           #if SD_RESORT
             true
diff --git a/Marlin/src/feature/power_loss_recovery.cpp b/Marlin/src/feature/power_loss_recovery.cpp
index 3661f555129..1971dde898e 100644
--- a/Marlin/src/feature/power_loss_recovery.cpp
+++ b/Marlin/src/feature/power_loss_recovery.cpp
@@ -84,8 +84,8 @@ void PrintJobRecovery::changed() {
  */
 void PrintJobRecovery::check() {
   if (enabled) {
-    if (!card.cardOK) card.initsd();
-    if (card.cardOK) {
+    if (!card.flag.cardOK) card.initsd();
+    if (card.flag.cardOK) {
       load();
       if (!valid()) return purge();
       enqueue_and_echo_commands_P(PSTR("M1000 S"));
diff --git a/Marlin/src/feature/power_loss_recovery.h b/Marlin/src/feature/power_loss_recovery.h
index 0de0457c002..356ff13f21d 100644
--- a/Marlin/src/feature/power_loss_recovery.h
+++ b/Marlin/src/feature/power_loss_recovery.h
@@ -68,7 +68,7 @@ typedef struct {
   char command_queue[BUFSIZE][MAX_CMD_SIZE];
 
   // SD Filename and position
-  char sd_filename[MAXPATHNAMELENGTH];
+  char sd_filename[MAXPATHNAMELENGTH + 1];
   uint32_t sdpos;
 
   // Job elapsed time
diff --git a/Marlin/src/gcode/queue.cpp b/Marlin/src/gcode/queue.cpp
index 4cf508dca4c..0b6bb4ba77d 100644
--- a/Marlin/src/gcode/queue.cpp
+++ b/Marlin/src/gcode/queue.cpp
@@ -503,7 +503,7 @@ static int read_serial(const uint8_t index) {
             break;
           case StreamState::STREAM_COMPLETE:
             stream_state = StreamState::STREAM_RESET;
-            card.binary_mode = false;
+            card.flag.binary_mode = false;
             card.closefile();
             CARD_ECHO_P("echo: ");
             CARD_ECHO_P(card.filename);
@@ -514,7 +514,7 @@ static int read_serial(const uint8_t index) {
             return;
           case StreamState::STREAM_FAILED:
             stream_state = StreamState::STREAM_RESET;
-            card.binary_mode = false;
+            card.flag.binary_mode = false;
             card.closefile();
             card.removeFile(card.filename);
             CARD_ECHOLN_P("echo: File transfer failed");
@@ -549,7 +549,7 @@ inline void get_serial_commands() {
             ;
 
   #if ENABLED(FAST_FILE_TRANSFER)
-    if (card.saving && card.binary_mode) {
+    if (card.flag.saving && card.flag.binary_mode) {
       /**
        * For binary stream file transfer, use serial_line_buffer as the working
        * receive buffer (which limits the packet size to MAX_CMD_SIZE).
@@ -630,7 +630,7 @@ inline void get_serial_commands() {
           gcode_LastN = gcode_N;
         }
         #if ENABLED(SDSUPPORT)
-          else if (card.saving && strcmp(command, "M29") != 0) // No line number with M29 in Pronterface
+          else if (card.flag.saving && strcmp(command, "M29") != 0) // No line number with M29 in Pronterface
             return gcode_line_error(PSTR(MSG_ERR_NO_CHECKSUM), i);
         #endif
 
@@ -838,7 +838,7 @@ void advance_command_queue() {
 
   #if ENABLED(SDSUPPORT)
 
-    if (card.saving) {
+    if (card.flag.saving) {
       char* command = command_queue[cmd_queue_index_r];
       if (strstr_P(command, PSTR("M29"))) {
         // M29 closes the file
@@ -860,7 +860,7 @@ void advance_command_queue() {
       else {
         // Write the string from the read buffer to SD
         card.write_command(command);
-        if (card.logging)
+        if (card.flag.logging)
           gcode.process_next_command(); // The card is saving because it's logging
         else
           ok_to_send();
diff --git a/Marlin/src/gcode/sdcard/M20-M30_M32-M34_M524_M928.cpp b/Marlin/src/gcode/sdcard/M20-M30_M32-M34_M524_M928.cpp
index a8de7f44b7d..379c4e054b7 100644
--- a/Marlin/src/gcode/sdcard/M20-M30_M32-M34_M524_M928.cpp
+++ b/Marlin/src/gcode/sdcard/M20-M30_M32-M34_M524_M928.cpp
@@ -118,7 +118,7 @@ void GcodeSuite::M25() {
  * M26: Set SD Card file index
  */
 void GcodeSuite::M26() {
-  if (card.cardOK && parser.seenval('S'))
+  if (card.flag.cardOK && parser.seenval('S'))
     card.setIndex(parser.value_long());
 }
 
@@ -178,7 +178,7 @@ void GcodeSuite::M28() {
     }
 
     // Binary transfer mode
-    if ((card.binary_mode = binary_mode)) {
+    if ((card.flag.binary_mode = binary_mode)) {
       SERIAL_ECHO_START_P(port);
       SERIAL_ECHO_P(port, " preparing to receive: ");
       SERIAL_ECHOLN_P(port, p);
@@ -202,14 +202,14 @@ void GcodeSuite::M28() {
  * Processed in write to file routine
  */
 void GcodeSuite::M29() {
-  // card.saving = false;
+  // card.flag.saving = false;
 }
 
 /**
  * M30 <filename>: Delete SD Card file
  */
 void GcodeSuite::M30() {
-  if (card.cardOK) {
+  if (card.flag.cardOK) {
     card.closefile();
     card.removeFile(parser.string_arg);
   }
@@ -228,7 +228,7 @@ void GcodeSuite::M30() {
 void GcodeSuite::M32() {
   if (IS_SD_PRINTING()) planner.synchronize();
 
-  if (card.cardOK) {
+  if (card.flag.cardOK) {
     const bool call_procedure = parser.boolval('P');
 
     card.openFile(parser.string_arg, true, call_procedure);
@@ -286,7 +286,7 @@ void GcodeSuite::M32() {
  * M524: Abort the current SD print job (started with M24)
  */
 void GcodeSuite::M524() {
-  if (IS_SD_PRINTING()) card.abort_sd_printing = true;
+  if (IS_SD_PRINTING()) card.flag.abort_sd_printing = true;
 }
 
 /**
diff --git a/Marlin/src/lcd/extensible_ui/ui_api.cpp b/Marlin/src/lcd/extensible_ui/ui_api.cpp
index 932a276af4b..390b0811749 100644
--- a/Marlin/src/lcd/extensible_ui/ui_api.cpp
+++ b/Marlin/src/lcd/extensible_ui/ui_api.cpp
@@ -575,7 +575,7 @@ namespace ExtUI {
   }
 
   bool isPrintingFromMedia() {
-    return IFSD(card.cardOK && card.isFileOpen(), false);
+    return IFSD(card.flag.cardOK && card.isFileOpen(), false);
   }
 
   bool isPrinting() {
@@ -583,7 +583,7 @@ namespace ExtUI {
   }
 
   bool isMediaInserted() {
-    return IFSD(IS_SD_INSERTED() && card.cardOK, false);
+    return IFSD(IS_SD_INSERTED() && card.flag.cardOK, false);
   }
 
   void pausePrint() {
@@ -612,7 +612,7 @@ namespace ExtUI {
   void stopPrint() {
     #if ENABLED(SDSUPPORT)
       wait_for_heatup = wait_for_user = false;
-      card.abort_sd_printing = true;
+      card.flag.abort_sd_printing = true;
       ExtUI::onStatusChanged(PSTR(MSG_PRINT_ABORTED));
     #endif
   }
@@ -648,7 +648,7 @@ namespace ExtUI {
   }
 
   bool FileList::isDir() {
-    return IFSD(card.filenameIsDir, false);
+    return IFSD(card.flag.filenameIsDir, false);
   }
 
   uint16_t FileList::count() {
@@ -697,13 +697,13 @@ void MarlinUI::update() {
       last_sd_status = sd_status;
       if (sd_status) {
         card.initsd();
-        if (card.cardOK)
+        if (card.flag.cardOK)
           ExtUI::onMediaInserted();
         else
           ExtUI::onMediaError();
       }
       else {
-        const bool ok = card.cardOK;
+        const bool ok = card.flag.cardOK;
         card.release();
         if (ok) ExtUI::onMediaRemoved();
       }
diff --git a/Marlin/src/lcd/malyanlcd.cpp b/Marlin/src/lcd/malyanlcd.cpp
index 3e57cb1b3d8..5380497ee8d 100644
--- a/Marlin/src/lcd/malyanlcd.cpp
+++ b/Marlin/src/lcd/malyanlcd.cpp
@@ -278,7 +278,7 @@ void process_lcd_p_command(const char* command) {
         // There may be a difference in how V1 and V2 LCDs handle subdirectory
         // prints. Investigate more. This matches the V1 motion controller actions
         // but the V2 LCD switches to "print" mode on {SYS:DIR} response.
-        if (card.filenameIsDir) {
+        if (card.flag.filenameIsDir) {
           card.chdir(card.filename);
           write_to_lcd_P(PSTR("{SYS:DIR}"));
         }
@@ -330,7 +330,7 @@ void process_lcd_s_command(const char* command) {
 
     case 'L': {
       #if ENABLED(SDSUPPORT)
-        if (!card.cardOK) card.initsd();
+        if (!card.flag.cardOK) card.initsd();
 
         // A more efficient way to do this would be to
         // implement a callback in the ls_SerialPrint code, but
@@ -342,7 +342,7 @@ void process_lcd_s_command(const char* command) {
         uint16_t file_count = card.get_num_Files();
         for (uint16_t i = 0; i < file_count; i++) {
           card.getfilename(i);
-          sprintf_P(message_buffer, card.filenameIsDir ? PSTR("{DIR:%s}") : PSTR("{FILE:%s}"), card.longest_filename());
+          sprintf_P(message_buffer, card.flag.filenameIsDir ? PSTR("{DIR:%s}") : PSTR("{FILE:%s}"), card.longest_filename());
           write_to_lcd(message_buffer);
         }
 
diff --git a/Marlin/src/lcd/menu/menu_main.cpp b/Marlin/src/lcd/menu/menu_main.cpp
index fdddc95b14c..0287036f70e 100644
--- a/Marlin/src/lcd/menu/menu_main.cpp
+++ b/Marlin/src/lcd/menu/menu_main.cpp
@@ -58,7 +58,7 @@
 
   void lcd_sdcard_stop() {
     wait_for_heatup = wait_for_user = false;
-    card.abort_sd_printing = true;
+    card.flag.abort_sd_printing = true;
     ui.setstatusPGM(PSTR(MSG_PRINT_ABORTED), -1);
     ui.return_to_status();
   }
@@ -86,7 +86,7 @@ void menu_main() {
   MENU_BACK(MSG_WATCH);
 
   #if ENABLED(SDSUPPORT)
-    if (card.cardOK) {
+    if (card.flag.cardOK) {
       if (card.isFileOpen()) {
         if (IS_SD_PRINTING())
           MENU_ITEM(function, MSG_PAUSE_PRINT, lcd_sdcard_pause);
diff --git a/Marlin/src/lcd/menu/menu_sdcard.cpp b/Marlin/src/lcd/menu/menu_sdcard.cpp
index 7f405300306..1ea33799266 100644
--- a/Marlin/src/lcd/menu/menu_sdcard.cpp
+++ b/Marlin/src/lcd/menu/menu_sdcard.cpp
@@ -125,7 +125,7 @@ void menu_sdcard() {
 
       card.getfilename_sorted(nr);
 
-      if (card.filenameIsDir)
+      if (card.flag.filenameIsDir)
         MENU_ITEM(sdfolder, MSG_CARD_MENU, card);
       else
         MENU_ITEM(sdfile, MSG_CARD_MENU, card);
diff --git a/Marlin/src/sd/SdFatConfig.h b/Marlin/src/sd/SdFatConfig.h
index d203aa38ae4..5f90b0102e2 100644
--- a/Marlin/src/sd/SdFatConfig.h
+++ b/Marlin/src/sd/SdFatConfig.h
@@ -106,7 +106,7 @@
  * Defines for 8.3 and long (vfat) filenames
  */
 
-#define FILENAME_LENGTH 13 // Number of UTF-16 characters per entry
+#define FILENAME_LENGTH 12 // Number of UTF-16 characters per entry
 
 // Total bytes needed to store a single long filename
-#define LONG_FILENAME_LENGTH (FILENAME_LENGTH * MAX_VFAT_ENTRIES + 1)
+#define LONG_FILENAME_LENGTH ((FILENAME_LENGTH) * (MAX_VFAT_ENTRIES))
diff --git a/Marlin/src/sd/cardreader.cpp b/Marlin/src/sd/cardreader.cpp
index 1610f2ff456..949c530a06a 100644
--- a/Marlin/src/sd/cardreader.cpp
+++ b/Marlin/src/sd/cardreader.cpp
@@ -45,7 +45,83 @@
   #include "../feature/pause.h"
 #endif
 
-#include <ctype.h>
+// public:
+
+card_flags_t CardReader::flag;
+char CardReader::filename[FILENAME_LENGTH + 1], CardReader::longFilename[LONG_FILENAME_LENGTH + 1];
+int8_t CardReader::autostart_index;
+
+#if ENABLED(FAST_FILE_TRANSFER)
+  #if NUM_SERIAL > 1
+    uint8_t CardReader::transfer_port;
+  #endif
+#endif
+
+// private:
+
+SdFile CardReader::root, CardReader::workDir, CardReader::workDirParents[MAX_DIR_DEPTH];
+uint8_t CardReader::workDirDepth;
+
+#if ENABLED(SDCARD_SORT_ALPHA)
+  uint16_t CardReader::sort_count;
+  #if ENABLED(SDSORT_GCODE)
+    bool CardReader::sort_alpha;
+    int CardReader::sort_folders;
+    //bool CardReader::sort_reverse;
+  #endif
+
+  #if ENABLED(SDSORT_DYNAMIC_RAM)
+    uint8_t *CardReader::sort_order;
+  #else
+    uint8_t CardReader::sort_order[SDSORT_LIMIT];
+  #endif
+
+  #if ENABLED(SDSORT_USES_RAM)
+
+    #if ENABLED(SDSORT_CACHE_NAMES)
+      #if ENABLED(SDSORT_DYNAMIC_RAM)
+        char **CardReader::sortshort, **CardReader::sortnames;
+      #else
+        char CardReader::sortshort[SDSORT_LIMIT][FILENAME_LENGTH + 1];
+        char CardReader::sortnames[SDSORT_LIMIT][SORTED_LONGNAME_MAXLEN + 1];
+      #endif
+    #elif DISABLED(SDSORT_USES_STACK)
+      char CardReader::sortnames[SDSORT_LIMIT][SORTED_LONGNAME_MAXLEN + 1];
+    #endif
+
+    #if HAS_FOLDER_SORTING
+      #if ENABLED(SDSORT_DYNAMIC_RAM)
+        uint8_t *CardReader::isDir;
+      #elif ENABLED(SDSORT_CACHE_NAMES) || DISABLED(SDSORT_USES_STACK)
+        uint8_t CardReader::isDir[(SDSORT_LIMIT+7)>>3];
+      #endif
+    #endif
+
+  #endif // SDSORT_USES_RAM
+
+#endif // SDCARD_SORT_ALPHA
+
+Sd2Card CardReader::sd2card;
+SdVolume CardReader::volume;
+SdFile CardReader::file;
+
+uint8_t CardReader::file_subcall_ctr;
+uint32_t CardReader::filespos[SD_PROCEDURE_DEPTH];
+char CardReader::proc_filenames[SD_PROCEDURE_DEPTH][MAXPATHNAMELENGTH + 1];
+
+uint32_t CardReader::filesize, CardReader::sdpos;
+
+LsAction CardReader::lsAction; //stored for recursion.
+uint16_t CardReader::nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory.
+char *CardReader::diveDirName;
+
+#if ENABLED(AUTO_REPORT_SD_STATUS)
+  uint8_t CardReader::auto_report_sd_interval;
+  millis_t CardReader::next_sd_report_ms;
+  #if NUM_SERIAL > 1
+    int8_t CardReader::serialport;
+  #endif
+#endif
 
 CardReader::CardReader() {
   #if ENABLED(SDCARD_SORT_ALPHA)
@@ -56,9 +132,8 @@ CardReader::CardReader() {
       //sort_reverse = false;
     #endif
   #endif
-  sdprinting = cardOK = saving = logging = false;
-  filesize = 0;
-  sdpos = 0;
+  flag.sdprinting = flag.cardOK = flag.saving = flag.logging = false;
+  filesize = sdpos = 0;
   file_subcall_ctr = 0;
 
   workDirDepth = 0;
@@ -73,7 +148,7 @@ CardReader::CardReader() {
   #endif
 }
 
-char *createFilename(char *buffer, const dir_t &p) { //buffer > 12characters
+char *createFilename(char *buffer, const dir_t &p) {
   char *pos = buffer;
   for (uint8_t i = 0; i < 11; i++) {
     if (p.name[i] == ' ') continue;
@@ -108,7 +183,7 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
     if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) {
 
       // Get the short name for the item, which we know is a folder
-      char dosFilename[FILENAME_LENGTH];
+      char dosFilename[FILENAME_LENGTH + 1];
       createFilename(dosFilename, p);
 
       // Allocate enough stack space for the full path to a folder, trailing slash, and nul
@@ -120,8 +195,8 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
       // It contains the full path to the "parent" argument.
       // We now have the full path to the item in this folder.
       strcpy(path, prepend_is_empty ? "/" : prepend); // root slash if prepend is empty
-      strcat(path, dosFilename); // FILENAME_LENGTH-1 characters maximum
-      strcat(path, "/");       // 1 character
+      strcat(path, dosFilename);                      // FILENAME_LENGTH characters maximum
+      strcat(path, "/");                              // 1 character
 
       // Serial.print(path);
 
@@ -150,9 +225,9 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
 
       if (!DIR_IS_FILE_OR_SUBDIR(&p) || (p.attributes & DIR_ATT_HIDDEN)) continue;
 
-      filenameIsDir = DIR_IS_SUBDIR(&p);
+      flag.filenameIsDir = DIR_IS_SUBDIR(&p);
 
-      if (!filenameIsDir && (p.name[8] != 'G' || p.name[9] == '~')) continue;
+      if (!flag.filenameIsDir && (p.name[8] != 'G' || p.name[9] == '~')) continue;
 
       switch (lsAction) {  // 1 based file count
         case LS_Count:
@@ -242,7 +317,7 @@ void CardReader::ls(
       SERIAL_PROTOCOL_P(port, longFilename[0] ? longFilename : "???");
 
       // If the filename was printed then that's it
-      if (!filenameIsDir) break;
+      if (!flag.filenameIsDir) break;
 
       // SERIAL_ECHOPGM_P(port, "Opening dir: "); SERIAL_ECHOLN_P(port, segment);
 
@@ -275,7 +350,7 @@ void CardReader::printFilename(
   #endif
 ) {
   if (file.isOpen()) {
-    char dosFilename[FILENAME_LENGTH];
+    char dosFilename[FILENAME_LENGTH + 1];
     file.getFilename(dosFilename);
     SERIAL_ECHO_P(port, dosFilename);
     #if ENABLED(LONG_FILENAME_HOST_SUPPORT)
@@ -293,7 +368,7 @@ void CardReader::printFilename(
 }
 
 void CardReader::initsd() {
-  cardOK = false;
+  flag.cardOK = false;
   if (root.isOpen()) root.close();
 
   #ifndef SPI_SPEED
@@ -318,7 +393,7 @@ void CardReader::initsd() {
     SERIAL_ERRORLNPGM(MSG_SD_OPENROOT_FAIL);
   }
   else {
-    cardOK = true;
+    flag.cardOK = true;
     SERIAL_ECHO_START();
     SERIAL_ECHOLNPGM(MSG_SD_CARD_OK);
   }
@@ -327,7 +402,7 @@ void CardReader::initsd() {
 
 void CardReader::release() {
   stopSDPrint();
-  cardOK = false;
+  flag.cardOK = false;
 }
 
 void CardReader::openAndPrintFile(const char *name) {
@@ -339,8 +414,8 @@ void CardReader::openAndPrintFile(const char *name) {
 }
 
 void CardReader::startFileprint() {
-  if (cardOK) {
-    sdprinting = true;
+  if (flag.cardOK) {
+    flag.sdprinting = true;
     #if SD_RESORT
       flush_presort();
     #endif
@@ -355,7 +430,7 @@ void CardReader::stopSDPrint(
   #if ENABLED(ADVANCED_PAUSE_FEATURE)
     did_pause_print = 0;
   #endif
-  sdprinting = abort_sd_printing = false;
+  flag.sdprinting = flag.abort_sd_printing = false;
   if (isFileOpen()) file.close();
   #if SD_RESORT
     if (re_sort) presort();
@@ -363,7 +438,7 @@ void CardReader::stopSDPrint(
 }
 
 void CardReader::openLogFile(char * const path) {
-  logging = true;
+  flag.logging = true;
   openFile(path, false);
 }
 
@@ -380,7 +455,7 @@ void CardReader::getAbsFilename(char *t) {
   for (uint8_t i = 0; i < workDirDepth; i++)                // Loop to current work dir
     appendAtom(workDirParents[i], t, cnt);
 
-  if (cnt < MAXPATHNAMELENGTH - (FILENAME_LENGTH)) {
+  if (cnt < MAXPATHNAMELENGTH - (FILENAME_LENGTH) - 1) {    // Leave room for filename and nul
     appendAtom(file, t, cnt);
     --t;
   }
@@ -389,7 +464,7 @@ void CardReader::getAbsFilename(char *t) {
 
 void CardReader::openFile(char * const path, const bool read, const bool subcall/*=false*/) {
 
-  if (!cardOK) return;
+  if (!flag.cardOK) return;
 
   uint8_t doing = 0;
   if (isFileOpen()) {                     // Replacing current file or doing a subroutine
@@ -464,7 +539,7 @@ void CardReader::openFile(char * const path, const bool read, const bool subcall
       SERIAL_EOL();
     }
     else {
-      saving = true;
+      flag.saving = true;
       getfilename(0, fname);
       #if ENABLED(EMERGENCY_PARSER)
         emergency_parser.disable();
@@ -476,7 +551,7 @@ void CardReader::openFile(char * const path, const bool read, const bool subcall
 }
 
 void CardReader::removeFile(const char * const name) {
-  if (!cardOK) return;
+  if (!flag.cardOK) return;
 
   //stopSDPrint();
 
@@ -504,7 +579,7 @@ void CardReader::getStatus(
     const int8_t port/*= -1*/
   #endif
 ) {
-  if (cardOK && sdprinting) {
+  if (flag.cardOK && flag.sdprinting) {
     SERIAL_PROTOCOLPGM_P(port, MSG_SD_PRINTING_BYTE);
     SERIAL_PROTOCOL_P(port, sdpos);
     SERIAL_PROTOCOLCHAR_P(port, '/');
@@ -543,11 +618,11 @@ void CardReader::write_command(char *buf) {
 
 void CardReader::checkautostart() {
 
-  if (autostart_index < 0 || sdprinting) return;
+  if (autostart_index < 0 || flag.sdprinting) return;
 
-  if (!cardOK) initsd();
+  if (!flag.cardOK) initsd();
 
-  if (cardOK
+  if (flag.cardOK
     #if ENABLED(POWER_LOSS_RECOVERY)
       && !recovery.valid() // Don't run auto#.g when a resume file exists
     #endif
@@ -576,7 +651,7 @@ void CardReader::beginautostart() {
 void CardReader::closefile(const bool store_location) {
   file.sync();
   file.close();
-  saving = logging = false;
+  flag.saving = flag.logging = false;
   sdpos = 0;
   #if ENABLED(EMERGENCY_PARSER)
     emergency_parser.enable();
@@ -603,7 +678,7 @@ void CardReader::getfilename(uint16_t nr, const char * const match/*=NULL*/) {
     if (nr < sort_count) {
       strcpy(filename, sortshort[nr]);
       strcpy(longFilename, sortnames[nr]);
-      filenameIsDir = TEST(isDir[nr>>3], nr & 0x07);
+      flag.filenameIsDir = TEST(isDir[nr>>3], nr & 0x07);
       return;
     }
   #endif // SDSORT_CACHE_NAMES
@@ -712,6 +787,33 @@ void CardReader::setroot() {
     );
   }
 
+  #if ENABLED(SDSORT_USES_RAM)
+    #if ENABLED(SDSORT_DYNAMIC_RAM)
+      // Use dynamic method to copy long filename
+      #define SET_SORTNAME(I) (sortnames[I] = strdup(longest_filename()))
+      #if ENABLED(SDSORT_CACHE_NAMES)
+        // When caching also store the short name, since
+        // we're replacing the getfilename() behavior.
+        #define SET_SORTSHORT(I) (sortshort[I] = strdup(filename))
+      #else
+        #define SET_SORTSHORT(I) NOOP
+      #endif
+    #else
+      // Copy filenames into the static array
+      #if SORTED_LONGNAME_MAXLEN != LONG_FILENAME_LENGTH
+        #define SET_SORTNAME(I) do{ strncpy(sortnames[I], longest_filename(), SORTED_LONGNAME_MAXLEN); \
+                                    sortnames[I][SORTED_LONGNAME_MAXLEN] = '\0'; }while(0)
+      #else
+        #define SET_SORTNAME(I) strncpy(sortnames[I], longest_filename(), SORTED_LONGNAME_MAXLEN)
+      #endif
+      #if ENABLED(SDSORT_CACHE_NAMES)
+        #define SET_SORTSHORT(I) strcpy(sortshort[I], filename)
+      #else
+        #define SET_SORTSHORT(I) NOOP
+      #endif
+    #endif
+  #endif
+
   /**
    * Read all the files and produce a sort key
    *
@@ -754,7 +856,7 @@ void CardReader::setroot() {
             sortnames = new char*[fileCnt];
           #endif
         #elif ENABLED(SDSORT_USES_STACK)
-          char sortnames[fileCnt][SORTED_LONGNAME_MAXLEN];
+          char sortnames[fileCnt][SORTED_LONGNAME_MAXLEN + 1];
         #endif
 
         // Folder sorting needs 1 bit per entry for flags.
@@ -783,33 +885,15 @@ void CardReader::setroot() {
           // If using RAM then read all filenames now.
           #if ENABLED(SDSORT_USES_RAM)
             getfilename(i);
-            #if ENABLED(SDSORT_DYNAMIC_RAM)
-              // Use dynamic method to copy long filename
-              sortnames[i] = strdup(longest_filename());
-              #if ENABLED(SDSORT_CACHE_NAMES)
-                // When caching also store the short name, since
-                // we're replacing the getfilename() behavior.
-                sortshort[i] = strdup(filename);
-              #endif
-            #else
-              // Copy filenames into the static array
-              #if SORTED_LONGNAME_MAXLEN != LONG_FILENAME_LENGTH
-                strncpy(sortnames[i], longest_filename(), SORTED_LONGNAME_MAXLEN);
-                sortnames[i][SORTED_LONGNAME_MAXLEN - 1] = '\0';
-              #else
-                strncpy(sortnames[i], longest_filename(), SORTED_LONGNAME_MAXLEN);
-              #endif
-              #if ENABLED(SDSORT_CACHE_NAMES)
-                strcpy(sortshort[i], filename);
-              #endif
-            #endif
+            SET_SORTNAME(i);
+            SET_SORTSHORT(i);
             // char out[30];
-            // sprintf_P(out, PSTR("---- %i %s %s"), i, filenameIsDir ? "D" : " ", sortnames[i]);
+            // sprintf_P(out, PSTR("---- %i %s %s"), i, flag.filenameIsDir ? "D" : " ", sortnames[i]);
             // SERIAL_ECHOLN(out);
             #if HAS_FOLDER_SORTING
               const uint16_t bit = i & 0x07, ind = i >> 3;
               if (bit == 0) isDir[ind] = 0x00;
-              if (filenameIsDir) isDir[ind] |= _BV(bit);
+              if (flag.filenameIsDir) isDir[ind] |= _BV(bit);
             #endif
           #endif
         }
@@ -837,7 +921,7 @@ void CardReader::setroot() {
                     ? _SORT_CMP_NODIR() \
                     : (isDir[fs > 0 ? ind1 : ind2] & (fs > 0 ? _BV(bit1) : _BV(bit2))) != 0)
               #else
-                #define _SORT_CMP_DIR(fs) ((dir1 == filenameIsDir) ? _SORT_CMP_NODIR() : (fs > 0 ? dir1 : !dir1))
+                #define _SORT_CMP_DIR(fs) ((dir1 == flag.filenameIsDir) ? _SORT_CMP_NODIR() : (fs > 0 ? dir1 : !dir1))
               #endif
             #endif
 
@@ -847,7 +931,7 @@ void CardReader::setroot() {
               getfilename(o1);
               strcpy(name1, longest_filename()); // save (or getfilename below will trounce it)
               #if HAS_FOLDER_SORTING
-                bool dir1 = filenameIsDir;
+                bool dir1 = flag.filenameIsDir;
               #endif
               getfilename(o2);
               char *name2 = longest_filename(); // use the string in-place
@@ -885,27 +969,17 @@ void CardReader::setroot() {
       else {
         sort_order[0] = 0;
         #if ENABLED(SDSORT_USES_RAM) && ENABLED(SDSORT_CACHE_NAMES)
-          getfilename(0);
           #if ENABLED(SDSORT_DYNAMIC_RAM)
             sortnames = new char*[1];
-            sortnames[0] = strdup(longest_filename()); // malloc
             #if ENABLED(SDSORT_CACHE_NAMES)
               sortshort = new char*[1];
-              sortshort[0] = strdup(filename);       // malloc
             #endif
             isDir = new uint8_t[1];
-          #else
-            #if SORTED_LONGNAME_MAXLEN != LONG_FILENAME_LENGTH
-              strncpy(sortnames[0], longest_filename(), SORTED_LONGNAME_MAXLEN);
-              sortnames[0][SORTED_LONGNAME_MAXLEN - 1] = '\0';
-            #else
-              strncpy(sortnames[0], longest_filename(), SORTED_LONGNAME_MAXLEN);
-            #endif
-            #if ENABLED(SDSORT_CACHE_NAMES)
-              strcpy(sortshort[0], filename);
-            #endif
           #endif
-          isDir[0] = filenameIsDir ? 0x01 : 0x00;
+          getfilename(0);
+          SET_SORTNAME(0);
+          SET_SORTSHORT(0);
+          isDir[0] = flag.filenameIsDir ? 0x01 : 0x00;
         #endif
       }
 
@@ -1007,7 +1081,7 @@ void CardReader::printingHasFinished() {
   }
 
   void CardReader::openJobRecoveryFile(const bool read) {
-    if (!cardOK) return;
+    if (!flag.cardOK) return;
     if (recovery.file.isOpen()) return;
     if (!recovery.file.open(&root, job_recovery_file_name, read ? O_READ : O_CREAT | O_WRITE | O_TRUNC | O_SYNC)) {
       SERIAL_PROTOCOLPAIR(MSG_SD_OPEN_FILE_FAIL, job_recovery_file_name);
diff --git a/Marlin/src/sd/cardreader.h b/Marlin/src/sd/cardreader.h
index c8f114822ea..57e43763002 100644
--- a/Marlin/src/sd/cardreader.h
+++ b/Marlin/src/sd/cardreader.h
@@ -27,106 +27,121 @@
 
 #define SD_RESORT ENABLED(SDCARD_SORT_ALPHA) && ENABLED(SDSORT_DYNAMIC_RAM)
 
-#define MAX_DIR_DEPTH 10          // Maximum folder depth
+#define MAX_DIR_DEPTH     10       // Maximum folder depth
+#define MAXDIRNAMELENGTH   8       // DOS folder name size
+#define MAXPATHNAMELENGTH  (1 + (MAXDIRNAMELENGTH + 1) * (MAX_DIR_DEPTH) + 1 + FILENAME_LENGTH) // "/" + N * ("ADIRNAME/") + "filename.ext"
 
 #include "SdFile.h"
 
 enum LsAction : uint8_t { LS_SerialPrint, LS_Count, LS_GetFilename };
 
+typedef struct {
+  bool saving:1,
+       logging:1,
+       sdprinting:1,
+       cardOK:1,
+       filenameIsDir:1,
+       abort_sd_printing:1
+       #if ENABLED(FAST_FILE_TRANSFER)
+         , binary_mode:1
+       #endif
+    ;
+} card_flags_t;
+
 class CardReader {
 public:
   CardReader();
 
-  void initsd();
-  void write_command(char *buf);
+  static void initsd();
+  static void write_command(char *buf);
 
-  void beginautostart();
-  void checkautostart();
+  static void beginautostart();
+  static void checkautostart();
 
-  void openFile(char * const path, const bool read, const bool subcall=false);
-  void openLogFile(char * const path);
-  void removeFile(const char * const name);
-  void closefile(const bool store_location=false);
-  void release();
-  void openAndPrintFile(const char *name);
-  void startFileprint();
-  void stopSDPrint(
+  static void openFile(char * const path, const bool read, const bool subcall=false);
+  static void openLogFile(char * const path);
+  static void removeFile(const char * const name);
+  static void closefile(const bool store_location=false);
+  static void release();
+  static void openAndPrintFile(const char *name);
+  static void startFileprint();
+  static void stopSDPrint(
     #if SD_RESORT
       const bool re_sort=false
     #endif
   );
-  void getStatus(
+  static void getStatus(
     #if NUM_SERIAL > 1
       const int8_t port = -1
     #endif
   );
-  void printingHasFinished();
-  void printFilename(
+  static void printingHasFinished();
+  static void printFilename(
     #if NUM_SERIAL > 1
       const int8_t port = -1
     #endif
   );
 
   #if ENABLED(LONG_FILENAME_HOST_SUPPORT)
-    void printLongPath(char *path
+    static void printLongPath(char *path
       #if NUM_SERIAL > 1
         , const int8_t port = -1
       #endif
     );
   #endif
 
-  void getfilename(uint16_t nr, const char* const match=NULL);
-  uint16_t getnrfilenames();
+  static void getfilename(uint16_t nr, const char* const match=NULL);
+  static uint16_t getnrfilenames();
 
-  void getAbsFilename(char *t);
+  static void getAbsFilename(char *t);
 
-  void ls(
+  static void ls(
     #if NUM_SERIAL > 1
       const int8_t port = -1
     #endif
   );
-  void chdir(const char *relpath);
-  int8_t updir();
-  void setroot();
+  static void chdir(const char *relpath);
+  static int8_t updir();
+  static void setroot();
 
-  const char* diveToFile(SdFile*& curDir, const char * const path, const bool echo);
+  static const char* diveToFile(SdFile*& curDir, const char * const path, const bool echo);
 
-  uint16_t get_num_Files();
+  static uint16_t get_num_Files();
 
   #if ENABLED(SDCARD_SORT_ALPHA)
-    void presort();
-    void getfilename_sorted(const uint16_t nr);
+    static void presort();
+    static void getfilename_sorted(const uint16_t nr);
     #if ENABLED(SDSORT_GCODE)
-      FORCE_INLINE void setSortOn(bool b) { sort_alpha = b; presort(); }
-      FORCE_INLINE void setSortFolders(int i) { sort_folders = i; presort(); }
-      //FORCE_INLINE void setSortReverse(bool b) { sort_reverse = b; }
+      FORCE_INLINE static void setSortOn(bool b) { sort_alpha = b; presort(); }
+      FORCE_INLINE static void setSortFolders(int i) { sort_folders = i; presort(); }
+      //FORCE_INLINE static void setSortReverse(bool b) { sort_reverse = b; }
     #endif
   #else
-    FORCE_INLINE void getfilename_sorted(const uint16_t nr) { getfilename(nr); }
+    FORCE_INLINE static void getfilename_sorted(const uint16_t nr) { getfilename(nr); }
   #endif
 
   #if ENABLED(POWER_LOSS_RECOVERY)
-    bool jobRecoverFileExists();
-    void openJobRecoveryFile(const bool read);
-    void removeJobRecoveryFile();
+    static bool jobRecoverFileExists();
+    static void openJobRecoveryFile(const bool read);
+    static void removeJobRecoveryFile();
   #endif
 
-  inline void pauseSDPrint() { sdprinting = false; }
-  inline bool isFileOpen() { return file.isOpen(); }
-  inline bool eof() { return sdpos >= filesize; }
-  inline int16_t get() { sdpos = file.curPosition(); return (int16_t)file.read(); }
-  inline void setIndex(const uint32_t index) { sdpos = index; file.seekSet(index); }
-  inline uint32_t getIndex() { return sdpos; }
-  inline uint8_t percentDone() { return (isFileOpen() && filesize) ? sdpos / ((filesize + 99) / 100) : 0; }
-  inline char* getWorkDirName() { workDir.getFilename(filename); return filename; }
-  inline int16_t read(void* buf, uint16_t nbyte) { return file.isOpen() ? file.read(buf, nbyte) : -1; }
-  inline int16_t write(void* buf, uint16_t nbyte) { return file.isOpen() ? file.write(buf, nbyte) : -1; }
+  static inline void pauseSDPrint() { flag.sdprinting = false; }
+  static inline bool isFileOpen() { return file.isOpen(); }
+  static inline bool eof() { return sdpos >= filesize; }
+  static inline int16_t get() { sdpos = file.curPosition(); return (int16_t)file.read(); }
+  static inline void setIndex(const uint32_t index) { sdpos = index; file.seekSet(index); }
+  static inline uint32_t getIndex() { return sdpos; }
+  static inline uint8_t percentDone() { return (isFileOpen() && filesize) ? sdpos / ((filesize + 99) / 100) : 0; }
+  static inline char* getWorkDirName() { workDir.getFilename(filename); return filename; }
+  static inline int16_t read(void* buf, uint16_t nbyte) { return file.isOpen() ? file.read(buf, nbyte) : -1; }
+  static inline int16_t write(void* buf, uint16_t nbyte) { return file.isOpen() ? file.write(buf, nbyte) : -1; }
 
-  Sd2Card& getSd2Card() { return sd2card; }
+  static Sd2Card& getSd2Card() { return sd2card; }
 
   #if ENABLED(AUTO_REPORT_SD_STATUS)
-    void auto_report_sd_status(void);
-    inline void set_auto_report_interval(uint8_t v
+    static void auto_report_sd_status(void);
+    static inline void set_auto_report_interval(uint8_t v
       #if NUM_SERIAL > 1
         , int8_t port
       #endif
@@ -140,40 +155,39 @@ public:
     }
   #endif
 
-  inline char* longest_filename() { return longFilename[0] ? longFilename : filename; }
+  static inline char* longest_filename() { return longFilename[0] ? longFilename : filename; }
 
 public:
-  bool saving, logging, sdprinting, cardOK, filenameIsDir, abort_sd_printing;
-  char filename[FILENAME_LENGTH], longFilename[LONG_FILENAME_LENGTH];
-  int8_t autostart_index;
+  static card_flags_t flag;
+  static char filename[FILENAME_LENGTH + 1], longFilename[LONG_FILENAME_LENGTH + 1];
+  static int8_t autostart_index;
 
   #if ENABLED(FAST_FILE_TRANSFER)
-    bool binary_mode;
     #if NUM_SERIAL > 1
-      uint8_t transfer_port;
+      static uint8_t transfer_port;
     #else
       static constexpr uint8_t transfer_port = 0;
     #endif
   #endif
 
 private:
-  SdFile root, workDir, workDirParents[MAX_DIR_DEPTH];
-  uint8_t workDirDepth;
+  static SdFile root, workDir, workDirParents[MAX_DIR_DEPTH];
+  static uint8_t workDirDepth;
 
   // Sort files and folders alphabetically.
   #if ENABLED(SDCARD_SORT_ALPHA)
-    uint16_t sort_count;        // Count of sorted items in the current directory
+    static uint16_t sort_count;   // Count of sorted items in the current directory
     #if ENABLED(SDSORT_GCODE)
-      bool sort_alpha;          // Flag to enable / disable the feature
-      int sort_folders;         // Flag to enable / disable folder sorting
-      //bool sort_reverse;      // Flag to enable / disable reverse sorting
+      static bool sort_alpha;     // Flag to enable / disable the feature
+      static int sort_folders;    // Folder sorting before/none/after
+      //static bool sort_reverse; // Flag to enable / disable reverse sorting
     #endif
 
     // By default the sort index is static
     #if ENABLED(SDSORT_DYNAMIC_RAM)
-      uint8_t *sort_order;
+      static uint8_t *sort_order;
     #else
-      uint8_t sort_order[SDSORT_LIMIT];
+      static uint8_t sort_order[SDSORT_LIMIT];
     #endif
 
     #if ENABLED(SDSORT_USES_RAM) && ENABLED(SDSORT_CACHE_NAMES) && DISABLED(SDSORT_DYNAMIC_RAM)
@@ -188,21 +202,21 @@ private:
       // If using dynamic ram for names, allocate on the heap.
       #if ENABLED(SDSORT_CACHE_NAMES)
         #if ENABLED(SDSORT_DYNAMIC_RAM)
-          char **sortshort, **sortnames;
+          static char **sortshort, **sortnames;
         #else
-          char sortshort[SDSORT_LIMIT][FILENAME_LENGTH];
-          char sortnames[SDSORT_LIMIT][SORTED_LONGNAME_MAXLEN];
+          static char sortshort[SDSORT_LIMIT][FILENAME_LENGTH + 1];
+          static char sortnames[SDSORT_LIMIT][SORTED_LONGNAME_MAXLEN + 1];
         #endif
       #elif DISABLED(SDSORT_USES_STACK)
-        char sortnames[SDSORT_LIMIT][SORTED_LONGNAME_MAXLEN];
+        static char sortnames[SDSORT_LIMIT][SORTED_LONGNAME_MAXLEN + 1];
       #endif
 
       // Folder sorting uses an isDir array when caching items.
       #if HAS_FOLDER_SORTING
         #if ENABLED(SDSORT_DYNAMIC_RAM)
-          uint8_t *isDir;
+          static uint8_t *isDir;
         #elif ENABLED(SDSORT_CACHE_NAMES) || DISABLED(SDSORT_USES_STACK)
-          uint8_t isDir[(SDSORT_LIMIT+7)>>3];
+          static uint8_t isDir[(SDSORT_LIMIT+7)>>3];
         #endif
       #endif
 
@@ -210,28 +224,31 @@ private:
 
   #endif // SDCARD_SORT_ALPHA
 
-  Sd2Card sd2card;
-  SdVolume volume;
-  SdFile file;
+  static Sd2Card sd2card;
+  static SdVolume volume;
+  static SdFile file;
 
-  #define SD_PROCEDURE_DEPTH 1
-  #define MAXPATHNAMELENGTH (FILENAME_LENGTH*MAX_DIR_DEPTH + MAX_DIR_DEPTH + 1)
-  uint8_t file_subcall_ctr;
-  uint32_t filespos[SD_PROCEDURE_DEPTH];
-  char proc_filenames[SD_PROCEDURE_DEPTH][MAXPATHNAMELENGTH];
-  uint32_t filesize, sdpos;
+  #ifndef SD_PROCEDURE_DEPTH
+    #define SD_PROCEDURE_DEPTH 1
+  #endif
 
-  LsAction lsAction; //stored for recursion.
-  uint16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory.
-  char* diveDirName;
-  void lsDive(const char *prepend, SdFile parent, const char * const match=NULL
+  static uint8_t file_subcall_ctr;
+  static uint32_t filespos[SD_PROCEDURE_DEPTH];
+  static char proc_filenames[SD_PROCEDURE_DEPTH][MAXPATHNAMELENGTH + 1];
+
+  static uint32_t filesize, sdpos;
+
+  static LsAction lsAction; //stored for recursion.
+  static uint16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory.
+  static char *diveDirName;
+  static void lsDive(const char *prepend, SdFile parent, const char * const match=NULL
     #if NUM_SERIAL > 1
       , const int8_t port = -1
     #endif
   );
 
   #if ENABLED(SDCARD_SORT_ALPHA)
-    void flush_presort();
+    static void flush_presort();
   #endif
 
   #if ENABLED(AUTO_REPORT_SD_STATUS)
@@ -256,7 +273,7 @@ private:
   #define IS_SD_INSERTED() true
 #endif
 
-#define IS_SD_PRINTING()  card.sdprinting
+#define IS_SD_PRINTING()  card.flag.sdprinting
 #define IS_SD_FILE_OPEN() card.isFileOpen()
 
 extern CardReader card;