#include "bbbank.hpp" #include #include "bbstream.hpp" struct bbBank { char* data; int size, capacity; bbBank(int sz) : size(sz) { capacity = (size + 15) & ~15; data = new char[capacity]; memset(data, 0, size); } virtual ~bbBank() { delete[] data; } void resize(int n) { if (n > size) { if (n > capacity) { capacity = capacity * 3 / 2; if (n > capacity) capacity = n; capacity = (capacity + 15) & ~15; char* p = new char[capacity]; memcpy(p, data, size); delete[] data; data = p; } else memset(data + size, 0, n - size); } size = n; } }; static std::set bank_set; #ifdef _DEBUG static inline void debugBank(bbBank* b) { if (debug) { if (!bank_set.count(b)) ThrowRuntimeException("bbBank does not exist"); } } static inline void debugBank(bbBank* b, int offset) { if (debug) { debugBank(b); if (offset >= b->size) ThrowRuntimeException("Offset out of range"); } } #else #define debugBank #endif bbBank* bbCreateBank(int size) { bbBank* b = new bbBank(size); bank_set.insert(b); return b; } void bbFreeBank(bbBank* b) { if (bank_set.erase(b)) delete b; } int bbBankSize(bbBank* b) { debugBank(b); return b->size; } void bbResizeBank(bbBank* b, int size) { debugBank(b); b->resize(size); } void bbCopyBank(bbBank* src, int src_p, bbBank* dest, int dest_p, int count) { if (debug) { debugBank(src, src_p + count - 1); debugBank(dest, dest_p + count - 1); } memmove(dest->data + dest_p, src->data + src_p, count); } int bbPeekByte(bbBank* b, int offset) { debugBank(b, offset); return *(unsigned char*)(b->data + offset); } int bbPeekShort(bbBank* b, int offset) { debugBank(b, offset + 1); return *(unsigned short*)(b->data + offset); } int bbPeekInt(bbBank* b, int offset) { debugBank(b, offset + 3); return *(int*)(b->data + offset); } float bbPeekFloat(bbBank* b, int offset) { debugBank(b, offset + 3); return *(float*)(b->data + offset); } void bbPokeByte(bbBank* b, int offset, int value) { debugBank(b, offset); *(char*)(b->data + offset) = value; } void bbPokeShort(bbBank* b, int offset, int value) { debugBank(b, offset); *(unsigned short*)(b->data + offset) = value; } void bbPokeInt(bbBank* b, int offset, int value) { debugBank(b, offset); *(int*)(b->data + offset) = value; } void bbPokeFloat(bbBank* b, int offset, float value) { debugBank(b, offset); *(float*)(b->data + offset) = value; } int bbReadBytes(bbBank* b, bbStream* s, int offset, int count) { if (debug) { debugBank(b, offset + count - 1); debugStream(s); } return s->read(b->data + offset, count); } int bbWriteBytes(bbBank* b, bbStream* s, int offset, int count) { if (debug) { debugBank(b, offset + count - 1); debugStream(s); } return s->write(b->data + offset, count); } int bbCallDLL(BBStr* dll, BBStr* fun, bbBank* in, bbBank* out) { if (debug) { if (in) debugBank(in); if (out) debugBank(out); } int t = gx_runtime->callDll(*dll, *fun, in ? in->data : 0, in ? in->size : 0, out ? out->data : 0, out ? out->size : 0); delete dll; delete fun; return t; } bool bank_create() { return true; } bool bank_destroy() { while (bank_set.size()) bbFreeBank(*bank_set.begin()); return true; } void bank_link(void (*rtSym)(const char*, void*)) { rtSym("%CreateBank%size=0", bbCreateBank); rtSym("FreeBank%bank", bbFreeBank); rtSym("%BankSize%bank", bbBankSize); rtSym("ResizeBank%bank%size", bbResizeBank); rtSym("CopyBank%src_bank%src_offset%dest_bank%dest_offset%count", bbCopyBank); rtSym("%PeekByte%bank%offset", bbPeekByte); rtSym("%PeekShort%bank%offset", bbPeekShort); rtSym("%PeekInt%bank%offset", bbPeekInt); rtSym("#PeekFloat%bank%offset", bbPeekFloat); rtSym("PokeByte%bank%offset%value", bbPokeByte); rtSym("PokeShort%bank%offset%value", bbPokeShort); rtSym("PokeInt%bank%offset%value", bbPokeInt); rtSym("PokeFloat%bank%offset#value", bbPokeFloat); rtSym("%ReadBytes%bank%file%offset%count", bbReadBytes); rtSym("%WriteBytes%bank%file%offset%count", bbWriteBytes); rtSym("%CallDLL$dll_name$func_name%in_bank=0%out_bank=0", bbCallDLL); }