diff --git a/asm/Runtime/ansi_files.s b/asm/Runtime/ansi_files.s index d8b68057..059067b3 100644 --- a/asm/Runtime/ansi_files.s +++ b/asm/Runtime/ansi_files.s @@ -12,15 +12,117 @@ stdout_buff: stdin_buff: .skip 0x100 +.section .data, "wa" +.balign 8 + +.global __files +__files: + # ROM: 0x3EF778 + .4byte 0 + .4byte 0x0A800000 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte stdin_buff + .4byte 0x00000100 + .4byte stdin_buff + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte __read_console + .4byte __write_console + .4byte __close_console + .4byte 0 + .4byte lbl_803F27C8 + +.global lbl_803F27C8 +lbl_803F27C8: + + # ROM: 0x3EF7C8 + .4byte 0x00000001 + .4byte 0x12800000 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte stdout_buff + .4byte 0x00000100 + .4byte stdout_buff + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte __read_console + .4byte __write_console + .4byte __close_console + .4byte 0 + .4byte lbl_803F2818 + +.global lbl_803F2818 +lbl_803F2818: + + # ROM: 0x3EF818 + .4byte 0x00000002 + .4byte 0x10800000 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte stderr_buff + .4byte 0x00000100 + .4byte stderr_buff + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte __read_console + .4byte __write_console + .4byte __close_console + .4byte 0 + .4byte lbl_803F2868 + +.global lbl_803F2868 +lbl_803F2868: + + # ROM: 0x3EF868 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .4byte 0 + .section .text, "ax" .global __flush_all __flush_all: /* 8038B0A8 00388008 94 21 FF F0 */ stwu r1, -0x10(r1) /* 8038B0AC 0038800C 7C 08 02 A6 */ mflr r0 -/* 8038B0B0 00388010 3C 60 80 3F */ lis r3, lbl_803F2778@ha +/* 8038B0B0 00388010 3C 60 80 3F */ lis r3, __files@ha /* 8038B0B4 00388014 90 01 00 14 */ stw r0, 0x14(r1) -/* 8038B0B8 00388018 38 03 27 78 */ addi r0, r3, lbl_803F2778@l +/* 8038B0B8 00388018 38 03 27 78 */ addi r0, r3, __files@l /* 8038B0BC 0038801C 93 E1 00 0C */ stw r31, 0xc(r1) /* 8038B0C0 00388020 3B E0 00 00 */ li r31, 0 /* 8038B0C4 00388024 93 C1 00 08 */ stw r30, 8(r1) @@ -52,9 +154,9 @@ lbl_8038B0F4: __close_all: /* 8038B118 00388078 94 21 FF F0 */ stwu r1, -0x10(r1) /* 8038B11C 0038807C 7C 08 02 A6 */ mflr r0 -/* 8038B120 00388080 3C 60 80 3F */ lis r3, lbl_803F2778@ha +/* 8038B120 00388080 3C 60 80 3F */ lis r3, __files@ha /* 8038B124 00388084 90 01 00 14 */ stw r0, 0x14(r1) -/* 8038B128 00388088 38 03 27 78 */ addi r0, r3, lbl_803F2778@l +/* 8038B128 00388088 38 03 27 78 */ addi r0, r3, __files@l /* 8038B12C 0038808C 93 E1 00 0C */ stw r31, 0xc(r1) /* 8038B130 00388090 7C 1F 03 78 */ mr r31, r0 /* 8038B134 00388094 48 00 00 60 */ b lbl_8038B194 diff --git a/asm/Runtime/ansi_fp.s b/asm/Runtime/ansi_fp.s index 63965da2..ee8b4200 100644 --- a/asm/Runtime/ansi_fp.s +++ b/asm/Runtime/ansi_fp.s @@ -3,105 +3,6 @@ .section .data, "wa" .balign 8 -.global lbl_803F2778 -lbl_803F2778: - # ROM: 0x3EF778 - .4byte 0 - .4byte 0x0A800000 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte stdin_buff - .4byte 0x00000100 - .4byte stdin_buff - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte __read_console - .4byte __write_console - .4byte __close_console - .4byte 0 - .4byte lbl_803F27C8 - -.global lbl_803F27C8 -lbl_803F27C8: - - # ROM: 0x3EF7C8 - .4byte 0x00000001 - .4byte 0x12800000 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte stdout_buff - .4byte 0x00000100 - .4byte stdout_buff - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte __read_console - .4byte __write_console - .4byte __close_console - .4byte 0 - .4byte lbl_803F2818 - -.global lbl_803F2818 -lbl_803F2818: - - # ROM: 0x3EF818 - .4byte 0x00000002 - .4byte 0x10800000 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte stderr_buff - .4byte 0x00000100 - .4byte stderr_buff - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte __read_console - .4byte __write_console - .4byte __close_console - .4byte 0 - .4byte lbl_803F2868 - -.global lbl_803F2868 -lbl_803F2868: - - # ROM: 0x3EF868 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .4byte 0 - .global lbl_803F28B8 lbl_803F28B8: # ROM: 0x3EF8B8 @@ -2389,4 +2290,3 @@ lbl_805AEC80: lbl_805AEC88: # ROM: 0x3FB528 .double 4.503601774854144E15 - diff --git a/asm/Runtime/printf.s b/asm/Runtime/printf.s index 314be077..0526d50d 100644 --- a/asm/Runtime/printf.s +++ b/asm/Runtime/printf.s @@ -289,12 +289,12 @@ lbl_8038DE20: vprintf: /* 8038DE34 0038AD94 94 21 FF E0 */ stwu r1, -0x20(r1) /* 8038DE38 0038AD98 7C 08 02 A6 */ mflr r0 -/* 8038DE3C 0038AD9C 3C A0 80 3F */ lis r5, lbl_803F2778@ha +/* 8038DE3C 0038AD9C 3C A0 80 3F */ lis r5, __files@ha /* 8038DE40 0038ADA0 90 01 00 24 */ stw r0, 0x24(r1) /* 8038DE44 0038ADA4 93 E1 00 1C */ stw r31, 0x1c(r1) /* 8038DE48 0038ADA8 93 C1 00 18 */ stw r30, 0x18(r1) /* 8038DE4C 0038ADAC 7C 9E 23 78 */ mr r30, r4 -/* 8038DE50 0038ADB0 38 85 27 78 */ addi r4, r5, lbl_803F2778@l +/* 8038DE50 0038ADB0 38 85 27 78 */ addi r4, r5, __files@l /* 8038DE54 0038ADB4 93 A1 00 14 */ stw r29, 0x14(r1) /* 8038DE58 0038ADB8 3B E4 00 50 */ addi r31, r4, 0x50 /* 8038DE5C 0038ADBC 7C 7D 1B 78 */ mr r29, r3 @@ -339,9 +339,9 @@ printf: /* 8038DEE4 0038AE44 D8 E1 00 58 */ stfd f7, 0x58(r1) /* 8038DEE8 0038AE48 D9 01 00 60 */ stfd f8, 0x60(r1) lbl_8038DEEC: -/* 8038DEEC 0038AE4C 3D 60 80 3F */ lis r11, lbl_803F2778@ha +/* 8038DEEC 0038AE4C 3D 60 80 3F */ lis r11, __files@ha /* 8038DEF0 0038AE50 90 81 00 0C */ stw r4, 0xc(r1) -/* 8038DEF4 0038AE54 39 6B 27 78 */ addi r11, r11, lbl_803F2778@l +/* 8038DEF4 0038AE54 39 6B 27 78 */ addi r11, r11, __files@l /* 8038DEF8 0038AE58 38 80 FF FF */ li r4, -1 /* 8038DEFC 0038AE5C 90 61 00 08 */ stw r3, 8(r1) /* 8038DF00 0038AE60 3B EB 00 50 */ addi r31, r11, 0x50 @@ -2572,4 +2572,3 @@ lbl_805AEC98: # ROM: 0x3FB538 .4byte 0 .4byte 0 - diff --git a/configure.py b/configure.py index fcef2f0e..9354e96c 100755 --- a/configure.py +++ b/configure.py @@ -852,14 +852,14 @@ LIBS = [ ["Runtime/Gecko_ExceptionPPC", True], ["Runtime/abort_exit", True], "Runtime/alloc", - "Runtime/ansi_files", + ["Runtime/ansi_files", True], "Runtime/ansi_fp", "Runtime/arith", - "Runtime/buffer_io", + ["Runtime/buffer_io", True], ["Runtime/ctype", True], ["Runtime/locale", True], - "Runtime/direct_io", - "Runtime/file_io", + ["Runtime/direct_io", True], + ["Runtime/file_io", True], "Runtime/FILE_POS", "Runtime/mbstring", ["Runtime/mem", True], diff --git a/libc/ansi_files.h b/libc/ansi_files.h new file mode 100644 index 00000000..60a39ece --- /dev/null +++ b/libc/ansi_files.h @@ -0,0 +1,30 @@ +#ifndef _DOLPHIN_ANSI_FILES_H +#define _DOLPHIN_ANSI_FILES_H +#include + +#ifdef __cplusplus +extern "C" { +#endif // ifdef __cplusplus + +#define set_eof(file) \ + do { \ + (file)->state.io_state = __neutral; \ + (file)->state.eof = 1; \ + (file)->buffer_len = 0; \ + } while (0) + +#define set_error(file) \ + do { \ + (file)->state.error = 1; \ + (file)->buffer_len = 0; \ + } while (0) + +int __flush_buffer(FILE* file, size_t* length); +void __prep_buffer(FILE* file); +int __flush_all(); + +#ifdef __cplusplus +}; +#endif // ifdef __cplusplus + +#endif diff --git a/libc/buffer_io.h b/libc/buffer_io.h new file mode 100644 index 00000000..f0b762b4 --- /dev/null +++ b/libc/buffer_io.h @@ -0,0 +1,14 @@ +#ifndef _BUFFER_IO +#define _BUFFER_IO + +#include + +enum { __align_buffer, __dont_align_buffer }; + +void __convert_from_newlines(unsigned char* p, size_t* n); +void __convert_to_newlines(unsigned char* p, size_t* n); +void __prep_buffer(FILE*); +int __load_buffer(FILE*, size_t* bytes_loaded, int alignment); +int __flush_buffer(FILE*, size_t* bytes_flushed); + +#endif // _BUFFER_IO diff --git a/libc/stdio.h b/libc/stdio.h index af732268..914a99c5 100644 --- a/libc/stdio.h +++ b/libc/stdio.h @@ -1,6 +1,7 @@ -#ifndef _STDIO_H_ -#define _STDIO_H_ +#ifndef _STDIO +#define _STDIO +#include "types.h" #include #include @@ -8,6 +9,10 @@ extern "C" { #endif +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + #define __ungetc_buffer_size 2 typedef unsigned long __file_handle; @@ -16,8 +21,29 @@ typedef unsigned long fpos_t; typedef unsigned short wchar_t; #endif -enum __file_kinds { __closed_file, __disk_file, __console_file, __unavailable_file }; -enum __file_orientation { __unoriented, __char_oriented, __wide_oriented }; +enum __io_modes { + __read = 1, + __write = 2, + __read_write = 3, + __append = 4, +}; +enum __file_kinds { + __closed_file, + __disk_file, + __console_file, + __unavailable_file, +}; +enum __file_orientation { + __unoriented, + __char_oriented, + __wide_oriented, +}; + +enum __io_results { + __no_io_error, + __io_error, + __io_EOF, +}; typedef struct { unsigned int open_mode : 2; @@ -28,6 +54,13 @@ typedef struct { unsigned int binary_io : 1; } __file_modes; +enum __io_states { + __neutral, + __writing, + __reading, + __rereading, +}; + typedef struct { unsigned int io_state : 3; unsigned int free_buffer : 1; @@ -35,12 +68,13 @@ typedef struct { unsigned char error; } __file_state; -typedef void* __ref_con; -typedef int (*__pos_proc)(__file_handle file, fpos_t* position, int mode, __ref_con ref_con); -typedef int (*__io_proc)(__file_handle file, unsigned char* buff, size_t* count, __ref_con ref_con); +typedef void (*__idle_proc)(void); +typedef int (*__pos_proc)(__file_handle file, fpos_t* position, int mode, __idle_proc idle_proc); +typedef int (*__io_proc)(__file_handle file, unsigned char* buff, size_t* count, + __idle_proc idle_proc); typedef int (*__close_proc)(__file_handle file); -typedef struct _FILE { +typedef struct _IO_FILE { __file_handle handle; __file_modes mode; __file_state state; @@ -61,18 +95,24 @@ typedef struct _FILE { __io_proc read_proc; __io_proc write_proc; __close_proc close_proc; - __ref_con ref_con; - struct _FILE* next_file_struct; + __idle_proc idle_proc; + struct _IO_FILE* next_file_struct; } FILE; +#define _IONBF 0 +#define _IOLBF 1 +#define _IOFBF 2 + int puts(const char* s); int printf(const char*, ...); int sprintf(char* s, const char* format, ...); int vprintf(const char* format, va_list arg); int vsprintf(char* s, const char* format, va_list arg); +size_t fwrite(const void*, size_t memb_size, size_t num_memb, FILE*); +size_t __fwrite(const void*, size_t, size_t, FILE*); #ifdef __cplusplus } #endif -#endif +#endif // _STDIO diff --git a/obj_files.mk b/obj_files.mk index a90f07e8..f7a31544 100644 --- a/obj_files.mk +++ b/obj_files.mk @@ -727,14 +727,14 @@ MSL_PPCEABI_BARE_H :=\ $(BUILD_DIR)/src/Runtime/Gecko_ExceptionPPC.o\ $(BUILD_DIR)/src/Runtime/abort_exit.o\ $(BUILD_DIR)/asm/Runtime/alloc.o\ - $(BUILD_DIR)/asm/Runtime/ansi_files.o\ + $(BUILD_DIR)/src/Runtime/ansi_files.o\ $(BUILD_DIR)/asm/Runtime/ansi_fp.o\ $(BUILD_DIR)/asm/Runtime/arith.o\ - $(BUILD_DIR)/asm/Runtime/buffer_io.o\ + $(BUILD_DIR)/src/Runtime/buffer_io.o\ $(BUILD_DIR)/src/Runtime/ctype.o\ $(BUILD_DIR)/src/Runtime/locale.o\ - $(BUILD_DIR)/asm/Runtime/direct_io.o\ - $(BUILD_DIR)/asm/Runtime/file_io.o\ + $(BUILD_DIR)/src/Runtime/direct_io.o\ + $(BUILD_DIR)/src/Runtime/file_io.o\ $(BUILD_DIR)/asm/Runtime/FILE_POS.o\ $(BUILD_DIR)/asm/Runtime/mbstring.o\ $(BUILD_DIR)/src/Runtime/mem.o\ diff --git a/src/Kyoto/Streams/CMemoryStreamOut.cpp b/src/Kyoto/Streams/CMemoryStreamOut.cpp new file mode 100644 index 00000000..5fdee6eb --- /dev/null +++ b/src/Kyoto/Streams/CMemoryStreamOut.cpp @@ -0,0 +1,28 @@ +#include "Kyoto/Streams/CMemoryStreamOut.hpp" +#include "Kyoto/Alloc/CMemory.hpp" + +#include + +CMemoryStreamOut::CMemoryStreamOut(void* buffer, size_t len, EOwnerShip ownerShip, int blockLen) +: COutputStream(blockLen) +, mOutPtr(buffer) +, mOutLength(len) +, mCurrentPosition(0) +, mBufferOwned(ownerShip == kOS_Owned) {} + +CMemoryStreamOut::~CMemoryStreamOut() { + COutputStream::Flush(); + + if (mBufferOwned) { + delete[] mOutPtr; + } +} + + +void CMemoryStreamOut::Write(const void* ptr, size_t len) { + len = (mOutLength - mCurrentPosition) < len ? (mOutLength - mCurrentPosition) : len; + if (len != 0) { + memcpy(static_cast(mOutPtr) + mCurrentPosition, ptr, len); + mCurrentPosition += len; + } +} diff --git a/src/Kyoto/Streams/CZipInputStream.cpp b/src/Kyoto/Streams/CZipInputStream.cpp new file mode 100644 index 00000000..bd04d443 --- /dev/null +++ b/src/Kyoto/Streams/CZipInputStream.cpp @@ -0,0 +1,32 @@ +#include "Kyoto/Streams/CZipInputStream.hpp" +#include "Kyoto/Streams/CZipSupport.hpp" + +CZipInputStream::CZipInputStream(rstl::auto_ptr in) +: CInputStream(4096) +, mCompBuf(new uchar[4096]) +, mStream(in) +, mZStream(new z_stream_s) { + z_stream_s* zs = mZStream.get(); + zs->next_in = mCompBuf.get(); + mZStream->avail_in = 0; + mZStream->zalloc = CZipSupport::Alloc; + mZStream->zfree = CZipSupport::Free; + mZStream->opaque = 0; + inflateInit2(mZStream.get()); +} + +CZipInputStream::~CZipInputStream() { + inflateEnd(mZStream.get()); +} + + +size_t CZipInputStream::Read(void* buf, size_t len) { + mZStream->next_out = static_cast(buf); + mZStream->avail_out = len; + if (mZStream->avail_in == 0) { + mZStream->avail_in = mStream->ReadBytes(mCompBuf.get(), 4096); + mZStream->next_in = mCompBuf.get(); + } + inflate(mZStream.get(), Z_NO_FLUSH); + return len - mZStream->avail_out; +} diff --git a/src/Kyoto/Streams/CZipSupport.cpp b/src/Kyoto/Streams/CZipSupport.cpp new file mode 100644 index 00000000..2576fa4a --- /dev/null +++ b/src/Kyoto/Streams/CZipSupport.cpp @@ -0,0 +1,18 @@ +#include "Kyoto/Streams/CZipSupport.hpp" +#include "Kyoto/Alloc/CMemory.hpp" +#include "zlib/zlib.h" + +static char* hack() { + return ZLIB_VERSION; +} + +void* CZipSupport::Alloc(void* ptr1, uint w1, uint w2) { + return new uchar[w1 * w2]; +} + +void CZipSupport::Free(void* ptr1, void* ptr2) { + if (ptr2 == nullptr) { + return; + } + delete[] ptr2; +} diff --git a/src/MetroTRK/mslsupp.c b/src/MetroTRK/mslsupp.c index 70a096e0..0f0a8195 100644 --- a/src/MetroTRK/mslsupp.c +++ b/src/MetroTRK/mslsupp.c @@ -1,4 +1,5 @@ #include "MetroTRK/TrkInit.h" +#include #ifdef __cplusplus extern "C" { @@ -11,7 +12,9 @@ void EnableMetroTRKInterrupts() {} void InitMetroTRK() {} // 80003648 -int __read_console() { return 0; } +int __read_console(__file_handle file, fpos_t* position, int mode, __idle_proc __idle_proc) { + return 0; +} // 80003650 int __TRK_write_console() { return 0; } diff --git a/src/Runtime/alloc.c b/src/Runtime/alloc.c new file mode 100644 index 00000000..e69de29b diff --git a/src/Runtime/ansi_files.c b/src/Runtime/ansi_files.c new file mode 100644 index 00000000..14cd8684 --- /dev/null +++ b/src/Runtime/ansi_files.c @@ -0,0 +1,119 @@ +#include "ansi_files.h" + +static unsigned char stdin_buff[0x100]; +static unsigned char stdout_buff[0x100]; +static unsigned char stderr_buff[0x100]; + +extern int fclose(FILE*); +extern int __read_console(__file_handle file, unsigned char* buff, size_t* count, + __idle_proc idle_proc); +extern int __write_console(__file_handle file, unsigned char* buff, size_t* count, + __idle_proc idle_proc); +extern int __close_console(__file_handle file); + +FILE __files[4] = { + {0, + {0, 1, 1, 2, 0}, + {0, 0, 0, 0}, + 0, + 0, + 0, + {0, 0}, + {0, 0}, + 0, + stdin_buff, + sizeof(stdin_buff), + stdin_buff, + 0, + 0, + 0, + 0, + NULL, + &__read_console, + &__write_console, + &__close_console, + 0, + &__files[1]}, + {1, + {0, 2, 1, 2, 0}, + {0, 0, 0, 0}, + 0, + 0, + 0, + {0, 0}, + {0, 0}, + 0, + stdout_buff, + sizeof(stdout_buff), + stdout_buff, + 0, + 0, + 0, + 0, + NULL, + &__read_console, + &__write_console, + &__close_console, + 0, + &__files[2]}, + {2, + {0, 2, 0, 2, 0}, + {0, 0, 0, 0}, + 0, + 0, + 0, + {0, 0}, + {0, 0}, + 0, + stderr_buff, + sizeof(stderr_buff), + stderr_buff, + 0, + 0, + 0, + 0, + NULL, + &__read_console, + &__write_console, + &__close_console, + 0, + &__files[3]}, +}; + +void __close_all() { + FILE* p = &__files[0]; + FILE* plast; + + // __begin_critical_region(2); + + while (p != NULL) { + if (p->mode.file_kind != __closed_file) { + fclose(p); + } + + plast = p; + p = p->next_file_struct; + if (plast->is_dynamically_allocated) + free(plast); + else { + plast->mode.file_kind = __unavailable_file; + if ((p != NULL) && p->is_dynamically_allocated) + plast->next_file_struct = NULL; + } + } + + // __end_critical_region(2); +} + +int __flush_all() { + int retval = 0; + FILE* __stream; + __stream = &__files[0]; + while (__stream) { + if ((__stream->mode.file_kind) && (fflush(__stream))) { + retval = -1; + } + __stream = __stream->next_file_struct; + }; + return retval; +} diff --git a/src/Runtime/buffer_io.c b/src/Runtime/buffer_io.c new file mode 100644 index 00000000..e760ba87 --- /dev/null +++ b/src/Runtime/buffer_io.c @@ -0,0 +1,43 @@ +#include "buffer_io.h" + +void __convert_from_newlines(unsigned char* buf, size_t* n) { +} + +void __convert_to_newlines(unsigned char* buf, size_t* n) { +} + +void __prep_buffer(FILE* file) { + file->buffer_ptr = file->buffer; + file->buffer_len = file->buffer_size; + file->buffer_len -= file->position & file->buffer_alignment; + file->buffer_pos = file->position; +} + +int __flush_buffer(FILE* file, size_t* bytes_flushed) { + size_t buffer_len; + int ioresult; + + buffer_len = file->buffer_ptr - file->buffer; + + if (buffer_len) { + file->buffer_len = buffer_len; + + if (!file->mode.binary_io) + __convert_from_newlines(file->buffer, (size_t*)&file->buffer_len); + + ioresult = (*file->write_proc)(file->handle, file->buffer, (size_t*)&file->buffer_len, + file->idle_proc); + + if (bytes_flushed) + *bytes_flushed = file->buffer_len; + + if (ioresult) + return (ioresult); + + file->position += file->buffer_len; + } + + __prep_buffer(file); + + return 0; +} diff --git a/src/Runtime/direct_io.c b/src/Runtime/direct_io.c new file mode 100644 index 00000000..a98d19c6 --- /dev/null +++ b/src/Runtime/direct_io.c @@ -0,0 +1,114 @@ +#include +#include + +size_t fwrite(const void* ptr, size_t memb_size, size_t num_memb, FILE* file) { + size_t retval; + retval = __fwrite(ptr, memb_size, num_memb, file); + return (retval); +} + +size_t __fwrite(const void* ptr, size_t memb_size, size_t num_memb, FILE* file) { + unsigned char* write_ptr; + size_t num_bytes, bytes_to_go, bytes_written; + int ioresult, always_buffer; + +#ifndef __NO_WIDE_CHAR + if (fwide(file, 0) == 0) + fwide(file, -1); +#endif + + bytes_to_go = memb_size * num_memb; + + if (!bytes_to_go || file->state.error || file->mode.file_kind == __closed_file) + return 0; + + if (file->mode.file_kind == __console_file) + __stdio_atexit(); + + always_buffer = + !file->mode.binary_io || file->mode.buffer_mode == _IOFBF || file->mode.buffer_mode == _IOLBF; + + if (file->state.io_state == __neutral) { + if (file->mode.io_mode & __write) { + if (file->mode.io_mode & __append) { + if (fseek(file, 0, SEEK_END)) + return 0; + } + file->state.io_state = __writing; + + __prep_buffer(file); + } + } + + if (file->state.io_state != __writing) { + set_error(file); + return 0; + } + + write_ptr = (unsigned char*)ptr; + bytes_written = 0; + + if (bytes_to_go && (file->buffer_ptr != file->buffer || always_buffer)) { + file->buffer_len = file->buffer_size - (file->buffer_ptr - file->buffer); + + do { + unsigned char* newline = NULL; + + num_bytes = file->buffer_len; + + if (num_bytes > bytes_to_go) + num_bytes = bytes_to_go; + if (file->mode.buffer_mode == _IOLBF && num_bytes) + if ((newline = (unsigned char*)__memrchr(write_ptr, '\n', num_bytes)) != NULL) + num_bytes = newline + 1 - write_ptr; + + if (num_bytes) { + memcpy(file->buffer_ptr, write_ptr, num_bytes); + + write_ptr += num_bytes; + bytes_written += num_bytes; + bytes_to_go -= num_bytes; + + file->buffer_ptr += num_bytes; + file->buffer_len -= num_bytes; + } + if (!file->buffer_len || newline != NULL || + (file->mode.buffer_mode == _IONBF)) + { + ioresult = __flush_buffer(file, NULL); + + if (ioresult) { + set_error(file); + bytes_to_go = 0; + break; + } + } + } while (bytes_to_go && always_buffer); + } + + if (bytes_to_go && !always_buffer) { + unsigned char* save_buffer = file->buffer; + size_t save_size = file->buffer_size; + + file->buffer = write_ptr; + file->buffer_size = bytes_to_go; + file->buffer_ptr = write_ptr + bytes_to_go; + + if (__flush_buffer(file, &num_bytes) != __no_io_error) + set_error(file); + + bytes_written += num_bytes; + + file->buffer = save_buffer; + file->buffer_size = save_size; + + __prep_buffer(file); + + file->buffer_len = 0; + } + + if (file->mode.buffer_mode != _IOFBF) + file->buffer_len = 0; + + return ((bytes_written + memb_size - 1) / memb_size); +} diff --git a/src/Runtime/file_io.c b/src/Runtime/file_io.c new file mode 100644 index 00000000..a05a7ab3 --- /dev/null +++ b/src/Runtime/file_io.c @@ -0,0 +1,70 @@ +#include "ansi_files.h" +#include "types.h" + +#pragma dont_inline on +int fclose(FILE* file) { + int flush_result, close_result; + + if (file == nullptr) + return (-1); + if (file->mode.file_kind == __closed_file) + return (0); + + flush_result = fflush(file); + + close_result = (*file->close_proc)(file->handle); + + file->mode.file_kind = __closed_file; + file->handle = NULL; + + if (file->state.free_buffer) + free(file->buffer); + return ((flush_result || close_result) ? -1 : 0); +} + +int fflush(FILE* file) { + int pos; + + if (file == nullptr) { + return __flush_all(); + } + + if (file->state.error != 0 || file->mode.file_kind == __closed_file) { + return -1; + } + + if (file->mode.io_mode == 1) { + return 0; + } + + if (file->state.io_state >= 3) { + file->state.io_state = 2; + } + + if (file->state.io_state == 2) { + file->buffer_len = 0; + } + + if (file->state.io_state != 1) { + file->state.io_state = 0; + return 0; + } + + if (file->mode.file_kind != __disk_file) { + pos = 0; + } else { + pos = ftell(file); + } + + if (__flush_buffer(file, 0) != 0) { + file->state.error = 1; + file->buffer_len = 0; + return -1; + } + + file->state.io_state = 0; + file->position = pos; + file->buffer_len = 0; + return 0; +} +#pragma dont_inline reset