NESe (pronounced "Nessie") is a NES emulator based on the e6502 emulator, also written in C with a focus on speed and portability for use on embedded platforms, especially ARM.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

116 line
2.9KB

  1. #include <errno.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include "file.h"
  5. const char* basename(const char* filename) {
  6. const char* slash = filename + strlen(filename) - 1;
  7. for ( ; slash >= filename &&
  8. *slash != '\\' &&
  9. *slash != '/';
  10. --slash );
  11. return &slash[1];
  12. }
  13. int make_filename(char* filename, int max_len,
  14. const char* orig_name,
  15. const char* subdir, const char* ext) {
  16. int status = 0;
  17. int remain = max_len;
  18. const char* orig_base = basename(orig_name);
  19. const char* orig_dot = strrchr(orig_base, '.');
  20. int orig_path_len = orig_base - orig_name;
  21. int orig_base_len = (NULL == orig_dot) ?
  22. strlen(orig_base) :
  23. (orig_dot - orig_base);
  24. // Part 1/4: Leading path
  25. if (0 == status && orig_path_len <= remain) {
  26. memcpy(filename, orig_name, orig_path_len);
  27. remain -= orig_path_len;
  28. filename += orig_path_len;
  29. } else {
  30. status = -1;
  31. }
  32. // Part 2/4: Subdirectory
  33. if (0 == status && NULL != subdir) {
  34. int subdir_len = strlen(subdir);
  35. if ((subdir_len + 1) <= remain) {
  36. memcpy(filename, subdir, subdir_len);
  37. filename += subdir_len;
  38. *filename++ = '/';
  39. remain -= (subdir_len + 1);
  40. } else {
  41. status = -1;
  42. }
  43. }
  44. // Part 3/4: Basename
  45. if (0 == status && orig_base_len <= remain) {
  46. memcpy(filename, orig_name, orig_base_len);
  47. remain -= orig_base_len;
  48. filename += orig_base_len;
  49. } else {
  50. status = -1;
  51. }
  52. // Part 4/4: Extension
  53. if (0 == status && NULL != ext) {
  54. int ext_len = strlen(ext);
  55. if ((ext_len + 1) <= remain) {
  56. *filename++ = '.';
  57. memcpy(filename, ext, ext_len);
  58. remain -= (ext_len + 1);
  59. filename += ext_len;
  60. } else {
  61. status = -1;
  62. }
  63. }
  64. return (status < 0 ? status : (max_len - remain));
  65. }
  66. int write_file(const char* filename, const void* data, int len) {
  67. int status = -1;
  68. FILE* file = fopen(filename, "wb");
  69. if (NULL != file) {
  70. if (1 == fwrite(data, len, 1, file)) {
  71. status = 0;
  72. } else {
  73. fprintf(stderr, "Failed to write %d bytes from %s: %d\n", len, filename, errno);
  74. }
  75. fclose(file);
  76. } else {
  77. fprintf(stderr, "Failed to open %s: %d\n", filename, errno);
  78. }
  79. return status;
  80. }
  81. int read_file(const char* filename, void* data, int len) {
  82. int status = -1;
  83. FILE* file = fopen(filename, "rb");
  84. if (NULL != file) {
  85. if (1 == fread(data, len, 1, file)) {
  86. status = 0;
  87. } else {
  88. fprintf(stderr, "Failed to read %d bytes from %s: %d\n", len, filename, errno);
  89. }
  90. fclose(file);
  91. } else {
  92. fprintf(stderr, "Failed to open %s: %d\n", filename, errno);
  93. }
  94. return status;
  95. }