summaryrefslogtreecommitdiff
path: root/Database/internals/database-segment.cpp
blob: 8ee5b4b636a48a3fc4bc4d852d0de9e0f835d29e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <assert.h>

#include <allocator.h>
#include <log.h>
#include "database-segment.h"

Segment::Segment(Uint32 size, Uint32 id, Uint64 cpu_base, Uint32 extra_size, const Byte * data) : plainmemory(0), patches(0), size(size), extra_size(extra_size), id(id), cpu_base(cpu_base) {
    Uint64 fullsize = size + extra_size;
    
    assert(size);
    
    if (data) {
        plainmemory = (Byte *) data;
        loaded = true;
        allocated = false;
    } else {
        plainmemory = Allocator<Byte>::alloc(size);
        loaded = false;
        allocated = true;
    }
    tags = Allocator<memory_tags_t>::alloc(fullsize);
    refData = Allocator<SegmentRefData *>::alloc(fullsize);
}

Segment::~Segment() {
    if (allocated)
        Allocator<Byte>::free(plainmemory);
    if (patches)
        Allocator<Byte>::free(patches);
    if (patchesmap)
        Allocator<Byte>::free(patchesmap);
    Allocator<memory_tags_t>::free(tags);
    Allocator<SegmentRefData *>::free(refData);
}

short Segment::Read(Uint32 ptr) {
    if (ptr >= size) {
        LOG(CONSOLE, ERROR, "Out of bound read attempt in segment %i at %08X\n", id, ptr);
        return -1;
    }
    if (IsPatched(ptr))
        return patches[ptr];
    return plainmemory[ptr];
}

short Segment::RawRead(Uint32 ptr) {
    if (ptr >= size) {
        LOG(CONSOLE, ERROR, "Out of bound rawread attempt in segment %i at %08X\n", id, ptr);
        return -1;
    }
    return plainmemory[ptr];
}

void Segment::Patch(Uint32 ptr, Byte val) {
    if (!patchesmap) {
        patches = Allocator<Byte>::alloc(size);
        patchesmap = Allocator<Byte>::alloc((size << 3) + ((size & 7) ? 1 : 0));
    }
    if (ptr >= size) {
        LOG(CONSOLE, ERROR, "Out of bound patch attempt in segment %i at %08X\n", id, ptr);
        return;
    }
    patches[ptr] = val;
    patchesmap[ptr / 8] |= (1 << ptr % 8);
}

void Segment::Restore(Uint32 ptr) {
    if (!patchesmap)
        return;
    if (ptr >= size) {
        LOG(CONSOLE, ERROR, "Out of bound patch attempt in segment %i at %08X\n", id, ptr);
        return;
    }
    patchesmap[ptr / 8] &= ~(1 << (ptr % 8));
}

bool Segment::IsPatched(Uint32 ptr) {
    if (!patchesmap)
        return false;
    return patchesmap[ptr / 8] & (1 << (ptr % 8));
}

void Segment::LoadMemory(Handle * src) {
    if (loaded) {
        LOG(CONSOLE, WARNING, "Memory segment already loaded, second attempt ignored.");
        return;
    }

    src->read(plainmemory, size);
}

void Segment::setTag(Uint32 ptr, memory_tags_t tag) {
    if (ptr >= (size + extra_size)) {
        LOG(CONSOLE, ERROR, "Out of bound setTag attempt in segment %i at %08X\n", id, ptr);
        return;
    }
    tags[ptr] = tag;
}

memory_tags_t Segment::getTag(Uint32 ptr) {
    if (ptr >= (size + extra_size)) {
        memory_tags_t z = { 0, 0 };
        LOG(CONSOLE, ERROR, "Out of bound getTag attempt in segment %i at %08X\n", id, ptr);
        return z;
    }
    return tags[ptr];
}

SegmentRefData * Segment::getSegmentRefData(Uint32 ptr) {
    if (ptr >= (size + extra_size)) {
        LOG(CONSOLE, ERROR, "Out of bound getSegmentRefData attempt in segment %i at %08X\n", id, ptr);
        return 0;
    }
    return refData[ptr];
}

void Segment::setSegmentRefData(Uint32 ptr, SegmentRefData * data) {
    if (ptr >= (size + extra_size)) {
        LOG(CONSOLE, ERROR, "Out of bound setSegmentRefData attempt in segment %i at %08X\n", id, ptr);
        return;
    }
    refData[ptr] = data;
}