src/file/SDL_rwops.c
author Ryan C. Gordon <icculus@icculus.org>
Fri, 20 Jul 2012 13:33:15 -0400
changeset 6375 93f9a24d1c02
parent 6138 4c64952a58fb
child 6430 48d519500f7e
permissions -rwxr-xr-x
Fixed some minor compiler warnings.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "SDL_config.h"
    22 
    23 /* This file provides a general interface for SDL to read and write
    24    data sources.  It can easily be extended to files, memory, etc.
    25 */
    26 
    27 #include "SDL_endian.h"
    28 #include "SDL_rwops.h"
    29 
    30 #ifdef __APPLE__
    31 #include "cocoa/SDL_rwopsbundlesupport.h"
    32 #endif /* __APPLE__ */
    33 
    34 #ifdef ANDROID
    35 #include "../core/android/SDL_android.h"
    36 #endif
    37 
    38 #ifdef __NDS__
    39 /* include libfat headers for fatInitDefault(). */
    40 #include <fat.h>
    41 #endif /* __NDS__ */
    42 
    43 #ifdef __WIN32__
    44 
    45 /* Functions to read/write Win32 API file pointers */
    46 /* Will not use it on WinCE because stdio is buffered, it means
    47    faster, and all stdio functions anyway are embedded in coredll.dll - 
    48    the main wince dll*/
    49 
    50 #include "../core/windows/SDL_windows.h"
    51 
    52 #ifndef INVALID_SET_FILE_POINTER
    53 #define INVALID_SET_FILE_POINTER 0xFFFFFFFF
    54 #endif
    55 
    56 #define READAHEAD_BUFFER_SIZE	1024
    57 
    58 static int SDLCALL
    59 windows_file_open(SDL_RWops * context, const char *filename, const char *mode)
    60 {
    61 #ifndef _WIN32_WCE
    62     UINT old_error_mode;
    63 #endif
    64     HANDLE h;
    65     DWORD r_right, w_right;
    66     DWORD must_exist, truncate;
    67     int a_mode;
    68 
    69     if (!context)
    70         return -1;              /* failed (invalid call) */
    71 
    72     context->hidden.windowsio.h = INVALID_HANDLE_VALUE;   /* mark this as unusable */
    73     context->hidden.windowsio.buffer.data = NULL;
    74     context->hidden.windowsio.buffer.size = 0;
    75     context->hidden.windowsio.buffer.left = 0;
    76 
    77     /* "r" = reading, file must exist */
    78     /* "w" = writing, truncate existing, file may not exist */
    79     /* "r+"= reading or writing, file must exist            */
    80     /* "a" = writing, append file may not exist             */
    81     /* "a+"= append + read, file may not exist              */
    82     /* "w+" = read, write, truncate. file may not exist    */
    83 
    84     must_exist = (SDL_strchr(mode, 'r') != NULL) ? OPEN_EXISTING : 0;
    85     truncate = (SDL_strchr(mode, 'w') != NULL) ? CREATE_ALWAYS : 0;
    86     r_right = (SDL_strchr(mode, '+') != NULL
    87                || must_exist) ? GENERIC_READ : 0;
    88     a_mode = (SDL_strchr(mode, 'a') != NULL) ? OPEN_ALWAYS : 0;
    89     w_right = (a_mode || SDL_strchr(mode, '+')
    90                || truncate) ? GENERIC_WRITE : 0;
    91 
    92     if (!r_right && !w_right)   /* inconsistent mode */
    93         return -1;              /* failed (invalid call) */
    94 
    95     context->hidden.windowsio.buffer.data =
    96         (char *) SDL_malloc(READAHEAD_BUFFER_SIZE);
    97     if (!context->hidden.windowsio.buffer.data) {
    98         SDL_OutOfMemory();
    99         return -1;
   100     }
   101 #ifdef _WIN32_WCE
   102     {
   103         LPTSTR tstr = WIN_UTF8ToString(filename);
   104         h = CreateFile(tstr, (w_right | r_right),
   105                        (w_right) ? 0 : FILE_SHARE_READ, NULL,
   106                        (must_exist | truncate | a_mode),
   107                        FILE_ATTRIBUTE_NORMAL, NULL);
   108         SDL_free(tstr);
   109     }
   110 #else
   111     /* Do not open a dialog box if failure */
   112     old_error_mode =
   113         SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
   114 
   115     {
   116         LPTSTR tstr = WIN_UTF8ToString(filename);
   117         h = CreateFile(tstr, (w_right | r_right),
   118                        (w_right) ? 0 : FILE_SHARE_READ, NULL,
   119                        (must_exist | truncate | a_mode),
   120                        FILE_ATTRIBUTE_NORMAL, NULL);
   121         SDL_free(tstr);
   122     }
   123 
   124     /* restore old behavior */
   125     SetErrorMode(old_error_mode);
   126 #endif /* _WIN32_WCE */
   127 
   128     if (h == INVALID_HANDLE_VALUE) {
   129         SDL_free(context->hidden.windowsio.buffer.data);
   130         context->hidden.windowsio.buffer.data = NULL;
   131         SDL_SetError("Couldn't open %s", filename);
   132         return -2;              /* failed (CreateFile) */
   133     }
   134     context->hidden.windowsio.h = h;
   135     context->hidden.windowsio.append = a_mode ? SDL_TRUE : SDL_FALSE;
   136 
   137     return 0;                   /* ok */
   138 }
   139 
   140 static long SDLCALL
   141 windows_file_seek(SDL_RWops * context, long offset, int whence)
   142 {
   143     DWORD windowswhence;
   144     long file_pos;
   145 
   146     if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE) {
   147         SDL_SetError("windows_file_seek: invalid context/file not opened");
   148         return -1;
   149     }
   150 
   151     /* FIXME: We may be able to satisfy the seek within buffered data */
   152     if (whence == RW_SEEK_CUR && context->hidden.windowsio.buffer.left) {
   153         offset -= (long)context->hidden.windowsio.buffer.left;
   154     }
   155     context->hidden.windowsio.buffer.left = 0;
   156 
   157     switch (whence) {
   158     case RW_SEEK_SET:
   159         windowswhence = FILE_BEGIN;
   160         break;
   161     case RW_SEEK_CUR:
   162         windowswhence = FILE_CURRENT;
   163         break;
   164     case RW_SEEK_END:
   165         windowswhence = FILE_END;
   166         break;
   167     default:
   168         SDL_SetError("windows_file_seek: Unknown value for 'whence'");
   169         return -1;
   170     }
   171 
   172     file_pos =
   173         SetFilePointer(context->hidden.windowsio.h, offset, NULL, windowswhence);
   174 
   175     if (file_pos != INVALID_SET_FILE_POINTER)
   176         return file_pos;        /* success */
   177 
   178     SDL_Error(SDL_EFSEEK);
   179     return -1;                  /* error */
   180 }
   181 
   182 static size_t SDLCALL
   183 windows_file_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
   184 {
   185     size_t total_need;
   186     size_t total_read = 0;
   187     size_t read_ahead;
   188     DWORD byte_read;
   189 
   190     total_need = size * maxnum;
   191 
   192     if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE
   193         || !total_need)
   194         return 0;
   195 
   196     if (context->hidden.windowsio.buffer.left > 0) {
   197         void *data = (char *) context->hidden.windowsio.buffer.data +
   198             context->hidden.windowsio.buffer.size -
   199             context->hidden.windowsio.buffer.left;
   200         read_ahead =
   201             SDL_min(total_need, context->hidden.windowsio.buffer.left);
   202         SDL_memcpy(ptr, data, read_ahead);
   203         context->hidden.windowsio.buffer.left -= read_ahead;
   204 
   205         if (read_ahead == total_need) {
   206             return maxnum;
   207         }
   208         ptr = (char *) ptr + read_ahead;
   209         total_need -= read_ahead;
   210         total_read += read_ahead;
   211     }
   212 
   213     if (total_need < READAHEAD_BUFFER_SIZE) {
   214         if (!ReadFile
   215             (context->hidden.windowsio.h, context->hidden.windowsio.buffer.data,
   216              READAHEAD_BUFFER_SIZE, &byte_read, NULL)) {
   217             SDL_Error(SDL_EFREAD);
   218             return 0;
   219         }
   220         read_ahead = SDL_min(total_need, (int) byte_read);
   221         SDL_memcpy(ptr, context->hidden.windowsio.buffer.data, read_ahead);
   222         context->hidden.windowsio.buffer.size = byte_read;
   223         context->hidden.windowsio.buffer.left = byte_read - read_ahead;
   224         total_read += read_ahead;
   225     } else {
   226         if (!ReadFile
   227             (context->hidden.windowsio.h, ptr, (DWORD)total_need, &byte_read, NULL)) {
   228             SDL_Error(SDL_EFREAD);
   229             return 0;
   230         }
   231         total_read += byte_read;
   232     }
   233     return (total_read / size);
   234 }
   235 
   236 static size_t SDLCALL
   237 windows_file_write(SDL_RWops * context, const void *ptr, size_t size,
   238                  size_t num)
   239 {
   240 
   241     size_t total_bytes;
   242     DWORD byte_written;
   243     size_t nwritten;
   244 
   245     total_bytes = size * num;
   246 
   247     if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE
   248         || total_bytes <= 0 || !size)
   249         return 0;
   250 
   251     if (context->hidden.windowsio.buffer.left) {
   252         SetFilePointer(context->hidden.windowsio.h,
   253                        -(LONG)context->hidden.windowsio.buffer.left, NULL,
   254                        FILE_CURRENT);
   255         context->hidden.windowsio.buffer.left = 0;
   256     }
   257 
   258     /* if in append mode, we must go to the EOF before write */
   259     if (context->hidden.windowsio.append) {
   260         if (SetFilePointer(context->hidden.windowsio.h, 0L, NULL, FILE_END) ==
   261             INVALID_SET_FILE_POINTER) {
   262             SDL_Error(SDL_EFWRITE);
   263             return 0;
   264         }
   265     }
   266 
   267     if (!WriteFile
   268         (context->hidden.windowsio.h, ptr, (DWORD)total_bytes, &byte_written, NULL)) {
   269         SDL_Error(SDL_EFWRITE);
   270         return 0;
   271     }
   272 
   273     nwritten = byte_written / size;
   274     return nwritten;
   275 }
   276 
   277 static int SDLCALL
   278 windows_file_close(SDL_RWops * context)
   279 {
   280 
   281     if (context) {
   282         if (context->hidden.windowsio.h != INVALID_HANDLE_VALUE) {
   283             CloseHandle(context->hidden.windowsio.h);
   284             context->hidden.windowsio.h = INVALID_HANDLE_VALUE;   /* to be sure */
   285         }
   286         if (context->hidden.windowsio.buffer.data) {
   287             SDL_free(context->hidden.windowsio.buffer.data);
   288             context->hidden.windowsio.buffer.data = NULL;
   289         }
   290         SDL_FreeRW(context);
   291     }
   292     return (0);
   293 }
   294 #endif /* __WIN32__ */
   295 
   296 #ifdef HAVE_STDIO_H
   297 
   298 /* Functions to read/write stdio file pointers */
   299 
   300 static long SDLCALL
   301 stdio_seek(SDL_RWops * context, long offset, int whence)
   302 {
   303     if (fseek(context->hidden.stdio.fp, offset, whence) == 0) {
   304         return (ftell(context->hidden.stdio.fp));
   305     } else {
   306         SDL_Error(SDL_EFSEEK);
   307         return (-1);
   308     }
   309 }
   310 
   311 static size_t SDLCALL
   312 stdio_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
   313 {
   314     size_t nread;
   315 
   316     nread = fread(ptr, size, maxnum, context->hidden.stdio.fp);
   317     if (nread == 0 && ferror(context->hidden.stdio.fp)) {
   318         SDL_Error(SDL_EFREAD);
   319     }
   320     return (nread);
   321 }
   322 
   323 static size_t SDLCALL
   324 stdio_write(SDL_RWops * context, const void *ptr, size_t size, size_t num)
   325 {
   326     size_t nwrote;
   327 
   328     nwrote = fwrite(ptr, size, num, context->hidden.stdio.fp);
   329     if (nwrote == 0 && ferror(context->hidden.stdio.fp)) {
   330         SDL_Error(SDL_EFWRITE);
   331     }
   332     return (nwrote);
   333 }
   334 
   335 static int SDLCALL
   336 stdio_close(SDL_RWops * context)
   337 {
   338     int status = 0;
   339     if (context) {
   340         if (context->hidden.stdio.autoclose) {
   341             /* WARNING:  Check the return value here! */
   342             if (fclose(context->hidden.stdio.fp) != 0) {
   343                 SDL_Error(SDL_EFWRITE);
   344                 status = -1;
   345             }
   346         }
   347         SDL_FreeRW(context);
   348     }
   349     return status;
   350 }
   351 #endif /* !HAVE_STDIO_H */
   352 
   353 /* Functions to read/write memory pointers */
   354 
   355 static long SDLCALL
   356 mem_seek(SDL_RWops * context, long offset, int whence)
   357 {
   358     Uint8 *newpos;
   359 
   360     switch (whence) {
   361     case RW_SEEK_SET:
   362         newpos = context->hidden.mem.base + offset;
   363         break;
   364     case RW_SEEK_CUR:
   365         newpos = context->hidden.mem.here + offset;
   366         break;
   367     case RW_SEEK_END:
   368         newpos = context->hidden.mem.stop + offset;
   369         break;
   370     default:
   371         SDL_SetError("Unknown value for 'whence'");
   372         return (-1);
   373     }
   374     if (newpos < context->hidden.mem.base) {
   375         newpos = context->hidden.mem.base;
   376     }
   377     if (newpos > context->hidden.mem.stop) {
   378         newpos = context->hidden.mem.stop;
   379     }
   380     context->hidden.mem.here = newpos;
   381     return (long)(context->hidden.mem.here - context->hidden.mem.base);
   382 }
   383 
   384 static size_t SDLCALL
   385 mem_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
   386 {
   387     size_t total_bytes;
   388     size_t mem_available;
   389 
   390     total_bytes = (maxnum * size);
   391     if ((maxnum <= 0) || (size <= 0)
   392         || ((total_bytes / maxnum) != (size_t) size)) {
   393         return 0;
   394     }
   395 
   396     mem_available = (context->hidden.mem.stop - context->hidden.mem.here);
   397     if (total_bytes > mem_available) {
   398         total_bytes = mem_available;
   399     }
   400 
   401     SDL_memcpy(ptr, context->hidden.mem.here, total_bytes);
   402     context->hidden.mem.here += total_bytes;
   403 
   404     return (total_bytes / size);
   405 }
   406 
   407 static size_t SDLCALL
   408 mem_write(SDL_RWops * context, const void *ptr, size_t size, size_t num)
   409 {
   410     if ((context->hidden.mem.here + (num * size)) > context->hidden.mem.stop) {
   411         num = (context->hidden.mem.stop - context->hidden.mem.here) / size;
   412     }
   413     SDL_memcpy(context->hidden.mem.here, ptr, num * size);
   414     context->hidden.mem.here += num * size;
   415     return (num);
   416 }
   417 
   418 static size_t SDLCALL
   419 mem_writeconst(SDL_RWops * context, const void *ptr, size_t size, size_t num)
   420 {
   421     SDL_SetError("Can't write to read-only memory");
   422     return (-1);
   423 }
   424 
   425 static int SDLCALL
   426 mem_close(SDL_RWops * context)
   427 {
   428     if (context) {
   429         SDL_FreeRW(context);
   430     }
   431     return (0);
   432 }
   433 
   434 
   435 /* Functions to create SDL_RWops structures from various data sources */
   436 
   437 SDL_RWops *
   438 SDL_RWFromFile(const char *file, const char *mode)
   439 {
   440     SDL_RWops *rwops = NULL;
   441     if (!file || !*file || !mode || !*mode) {
   442         SDL_SetError("SDL_RWFromFile(): No file or no mode specified");
   443         return NULL;
   444     }
   445 #if defined(ANDROID)
   446     rwops = SDL_AllocRW();
   447     if (!rwops)
   448         return NULL;            /* SDL_SetError already setup by SDL_AllocRW() */
   449     if (Android_JNI_FileOpen(rwops, file, mode) < 0) {
   450         SDL_FreeRW(rwops);
   451         return NULL;
   452     }
   453     rwops->seek = Android_JNI_FileSeek;
   454     rwops->read = Android_JNI_FileRead;
   455     rwops->write = Android_JNI_FileWrite;
   456     rwops->close = Android_JNI_FileClose;
   457 
   458 #elif defined(__WIN32__)
   459     rwops = SDL_AllocRW();
   460     if (!rwops)
   461         return NULL;            /* SDL_SetError already setup by SDL_AllocRW() */
   462     if (windows_file_open(rwops, file, mode) < 0) {
   463         SDL_FreeRW(rwops);
   464         return NULL;
   465     }
   466     rwops->seek = windows_file_seek;
   467     rwops->read = windows_file_read;
   468     rwops->write = windows_file_write;
   469     rwops->close = windows_file_close;
   470 
   471 #elif HAVE_STDIO_H
   472     {
   473     	#ifdef __APPLE__
   474     	FILE *fp = SDL_OpenFPFromBundleOrFallback(file, mode);
   475         #else
   476     	FILE *fp = fopen(file, mode);
   477     	#endif
   478     	if (fp == NULL) {
   479             SDL_SetError("Couldn't open %s", file);
   480         } else {
   481             rwops = SDL_RWFromFP(fp, 1);
   482         }
   483     }
   484 #else
   485     SDL_SetError("SDL not compiled with stdio support");
   486 #endif /* !HAVE_STDIO_H */
   487 
   488     return (rwops);
   489 }
   490 
   491 #ifdef HAVE_STDIO_H
   492 SDL_RWops *
   493 SDL_RWFromFP(FILE * fp, SDL_bool autoclose)
   494 {
   495     SDL_RWops *rwops = NULL;
   496 
   497 #if 0
   498 /*#ifdef __NDS__*/
   499     /* set it up so we can use stdio file function */
   500     fatInitDefault();
   501     printf("called fatInitDefault()");
   502 #endif /* __NDS__ */
   503 
   504     rwops = SDL_AllocRW();
   505     if (rwops != NULL) {
   506         rwops->seek = stdio_seek;
   507         rwops->read = stdio_read;
   508         rwops->write = stdio_write;
   509         rwops->close = stdio_close;
   510         rwops->hidden.stdio.fp = fp;
   511         rwops->hidden.stdio.autoclose = autoclose;
   512     }
   513     return (rwops);
   514 }
   515 #else
   516 SDL_RWops *
   517 SDL_RWFromFP(void * fp, SDL_bool autoclose)
   518 {
   519     SDL_SetError("SDL not compiled with stdio support");
   520     return NULL;
   521 }
   522 #endif /* HAVE_STDIO_H */
   523 
   524 SDL_RWops *
   525 SDL_RWFromMem(void *mem, int size)
   526 {
   527     SDL_RWops *rwops;
   528 
   529     rwops = SDL_AllocRW();
   530     if (rwops != NULL) {
   531         rwops->seek = mem_seek;
   532         rwops->read = mem_read;
   533         rwops->write = mem_write;
   534         rwops->close = mem_close;
   535         rwops->hidden.mem.base = (Uint8 *) mem;
   536         rwops->hidden.mem.here = rwops->hidden.mem.base;
   537         rwops->hidden.mem.stop = rwops->hidden.mem.base + size;
   538     }
   539     return (rwops);
   540 }
   541 
   542 SDL_RWops *
   543 SDL_RWFromConstMem(const void *mem, int size)
   544 {
   545     SDL_RWops *rwops;
   546 
   547     rwops = SDL_AllocRW();
   548     if (rwops != NULL) {
   549         rwops->seek = mem_seek;
   550         rwops->read = mem_read;
   551         rwops->write = mem_writeconst;
   552         rwops->close = mem_close;
   553         rwops->hidden.mem.base = (Uint8 *) mem;
   554         rwops->hidden.mem.here = rwops->hidden.mem.base;
   555         rwops->hidden.mem.stop = rwops->hidden.mem.base + size;
   556     }
   557     return (rwops);
   558 }
   559 
   560 SDL_RWops *
   561 SDL_AllocRW(void)
   562 {
   563     SDL_RWops *area;
   564 
   565     area = (SDL_RWops *) SDL_malloc(sizeof *area);
   566     if (area == NULL) {
   567         SDL_OutOfMemory();
   568     }
   569     return (area);
   570 }
   571 
   572 void
   573 SDL_FreeRW(SDL_RWops * area)
   574 {
   575     SDL_free(area);
   576 }
   577 
   578 /* Functions for dynamically reading and writing endian-specific values */
   579 
   580 Uint16
   581 SDL_ReadLE16(SDL_RWops * src)
   582 {
   583     Uint16 value;
   584 
   585     SDL_RWread(src, &value, (sizeof value), 1);
   586     return (SDL_SwapLE16(value));
   587 }
   588 
   589 Uint16
   590 SDL_ReadBE16(SDL_RWops * src)
   591 {
   592     Uint16 value;
   593 
   594     SDL_RWread(src, &value, (sizeof value), 1);
   595     return (SDL_SwapBE16(value));
   596 }
   597 
   598 Uint32
   599 SDL_ReadLE32(SDL_RWops * src)
   600 {
   601     Uint32 value;
   602 
   603     SDL_RWread(src, &value, (sizeof value), 1);
   604     return (SDL_SwapLE32(value));
   605 }
   606 
   607 Uint32
   608 SDL_ReadBE32(SDL_RWops * src)
   609 {
   610     Uint32 value;
   611 
   612     SDL_RWread(src, &value, (sizeof value), 1);
   613     return (SDL_SwapBE32(value));
   614 }
   615 
   616 Uint64
   617 SDL_ReadLE64(SDL_RWops * src)
   618 {
   619     Uint64 value;
   620 
   621     SDL_RWread(src, &value, (sizeof value), 1);
   622     return (SDL_SwapLE64(value));
   623 }
   624 
   625 Uint64
   626 SDL_ReadBE64(SDL_RWops * src)
   627 {
   628     Uint64 value;
   629 
   630     SDL_RWread(src, &value, (sizeof value), 1);
   631     return (SDL_SwapBE64(value));
   632 }
   633 
   634 size_t
   635 SDL_WriteLE16(SDL_RWops * dst, Uint16 value)
   636 {
   637     value = SDL_SwapLE16(value);
   638     return (SDL_RWwrite(dst, &value, (sizeof value), 1));
   639 }
   640 
   641 size_t
   642 SDL_WriteBE16(SDL_RWops * dst, Uint16 value)
   643 {
   644     value = SDL_SwapBE16(value);
   645     return (SDL_RWwrite(dst, &value, (sizeof value), 1));
   646 }
   647 
   648 size_t
   649 SDL_WriteLE32(SDL_RWops * dst, Uint32 value)
   650 {
   651     value = SDL_SwapLE32(value);
   652     return (SDL_RWwrite(dst, &value, (sizeof value), 1));
   653 }
   654 
   655 size_t
   656 SDL_WriteBE32(SDL_RWops * dst, Uint32 value)
   657 {
   658     value = SDL_SwapBE32(value);
   659     return (SDL_RWwrite(dst, &value, (sizeof value), 1));
   660 }
   661 
   662 size_t
   663 SDL_WriteLE64(SDL_RWops * dst, Uint64 value)
   664 {
   665     value = SDL_SwapLE64(value);
   666     return (SDL_RWwrite(dst, &value, (sizeof value), 1));
   667 }
   668 
   669 size_t
   670 SDL_WriteBE64(SDL_RWops * dst, Uint64 value)
   671 {
   672     value = SDL_SwapBE64(value);
   673     return (SDL_RWwrite(dst, &value, (sizeof value), 1));
   674 }
   675 
   676 /* vi: set ts=4 sw=4 expandtab: */