~ubuntu-branches/ubuntu/karmic/e-uae/karmic

« back to all changes in this revision

Viewing changes to src/enforcer.c

  • Committer: Bazaar Package Importer
  • Author(s): Stephan Suerken
  • Date: 2008-07-05 14:02:02 UTC
  • Revision ID: james.westby@ubuntu.com-20080705140202-u5aagnhtg31pmjc3
Tags: upstream-0.8.29-WIP4
ImportĀ upstreamĀ versionĀ 0.8.29-WIP4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * UAE - The Un*x Amiga Emulator
 
3
 *
 
4
 * Enforcer Like Support
 
5
 *
 
6
 * Copyright 2000-2003 Bernd Roesch and Sebastian Bauer
 
7
 * Copyright 2004      Richard Drummond
 
8
 */
 
9
 
 
10
#ifdef ENFORCER
 
11
 
 
12
#include <stdlib.h>
 
13
 
 
14
#include "sysconfig.h"
 
15
#include "sysdeps.h"
 
16
 
 
17
#include "memory.h"
 
18
#include "custom.h"
 
19
#include "options.h"
 
20
#include "newcpu.h"
 
21
#include "enforcer.h"
 
22
 
 
23
#ifndef _WIN32
 
24
#define console_out printf
 
25
#else
 
26
#define console_out(...) do {;} while (0)
 
27
#endif
 
28
 
 
29
/* Configurable options */
 
30
#define ENFORCESIZE 1024
 
31
#define STACKLINES 5
 
32
#define INSTRUCTIONLINES 17
 
33
 
 
34
#define ISILLEGAL(addr) (addr < 4 || (addr > 4 && addr < ENFORCESIZE))
 
35
 
 
36
extern uae_u32 natmem_offset;
 
37
 
 
38
int flashscreen = 0;
 
39
static int enforcer_installed = 0;
 
40
static int enforcer_hit = 0; /* set to 1 if displaying the hit */
 
41
 
 
42
#define ENFORCER_BUF_SIZE 4096
 
43
static char enforcer_buf[ENFORCER_BUF_SIZE];
 
44
 
 
45
#define GET_PC m68k_getpc (&regs)
 
46
 
 
47
static addrbank saved_dummy_bank;
 
48
static addrbank saved_chipmem_bank;
 
49
 
 
50
 
 
51
/*************************************************************
 
52
 Returns the first node entry of an exec list or 0 if
 
53
 empty
 
54
*************************************************************/
 
55
static uae_u32 amiga_list_first (uae_u32 list)
 
56
{
 
57
    uae_u32 node = get_long (list);      /* lh_Head */
 
58
    if (!node)
 
59
        return 0;
 
60
    if (!get_long (node))
 
61
        return 0;   /* ln_Succ */
 
62
    return node;
 
63
}
 
64
 
 
65
/*************************************************************
 
66
 Returns the next node of an exec node or 0 if it was the
 
67
 last element
 
68
*************************************************************/
 
69
static uae_u32 amiga_node_next (uae_u32 node)
 
70
{
 
71
    uae_u32 next = get_long (node);    /* ln_Succ */
 
72
    if (!next)
 
73
        return 0;
 
74
    if (!get_long (next))
 
75
        return 0; /* ln_Succ */
 
76
    return next;
 
77
}
 
78
 
 
79
/*************************************************************
 
80
 Converts an amiga address to a native one or NULL if this
 
81
 is not possible, Size specified the number of bytes you
 
82
 want to access
 
83
*************************************************************/
 
84
static uae_u8 *amiga2native (uae_u32 aptr, int size)
 
85
{
 
86
    addrbank bank = get_mem_bank (aptr);
 
87
 
 
88
    /* Check if the address can be translated to native */
 
89
    if (bank.check (aptr,size)) {
 
90
        return bank.xlateaddr (aptr);
 
91
    }
 
92
    return NULL;
 
93
}
 
94
 
 
95
/*************************************************************
 
96
 Writes the Hunk and Offset of the given Address into buf
 
97
*************************************************************/
 
98
static int enforcer_decode_hunk_and_offset (char *buf, uae_u32 pc)
 
99
{
 
100
    uae_u32 sysbase = get_long(4);
 
101
    uae_u32 semaphore_list = sysbase + 532;
 
102
 
 
103
    /* First step is searching for the SegTracker semaphore */
 
104
    uae_u32 node = amiga_list_first (semaphore_list);
 
105
    while (node) {
 
106
        uae_u32 string = get_long (node + 10); /* ln_Name */
 
107
        uae_u8 *native_string = amiga2native (string, 100);
 
108
 
 
109
        if (native_string) {
 
110
            if (!strcmp ((char *) native_string, "SegTracker"))
 
111
                break;
 
112
        }
 
113
        node = amiga_node_next (node);
 
114
    }
 
115
 
 
116
    if (node) {
 
117
        /* We have found the segtracker semaphore. Soon after the
 
118
         * public documented semaphore structure Segtracker holds
 
119
         * an own list of all segements. We will use this list to
 
120
         * find out the hunk and offset (simliar to segtracker).
 
121
         *
 
122
         * Source of segtracker can be found at:
 
123
         *    http://www.sinz.org/Michael.Sinz/Enforcer/SegTracker.c.html
 
124
         */
 
125
        uae_u32 seg_list = node + 46 + 4; /* sizeof(struct SignalSemaphore) + seg find */
 
126
 
 
127
        node = amiga_list_first (seg_list);
 
128
        while (node) {
 
129
            uae_u32 seg_entry = node + 12;
 
130
            uae_u32 address, size;
 
131
            int hunk = 0;
 
132
 
 
133
            /* Go through all entries until an address is 0
 
134
             * or the segment has been found */
 
135
            while ((address = get_long (seg_entry))) {
 
136
                size = get_long (seg_entry + 4);
 
137
 
 
138
                if (pc >= address && pc < address + size) {
 
139
                    uae_u32 name, offset;
 
140
                    const char *native_name;
 
141
 
 
142
                    offset = pc - address - 4;
 
143
                    name = get_long (node + 8); /* ln_Name */
 
144
                    if (name) {
 
145
                        native_name = (char *) amiga2native (name, 100);
 
146
                        if (!native_name)
 
147
                            native_name = "Unknown";
 
148
                    } else
 
149
                        native_name = "Unknown";
 
150
 
 
151
                    sprintf (buf, "----> %08lx - \"%s\" Hunk %04lx Offset %08lx\n", pc,
 
152
                        native_name, hunk, offset);
 
153
                    return 1;
 
154
                }
 
155
                seg_entry += 8;
 
156
                hunk++;
 
157
            }
 
158
            node = amiga_node_next (node);
 
159
        }
 
160
    }
 
161
    return 0;
 
162
}
 
163
 
 
164
/*************************************************************
 
165
 Display the enforcer hit
 
166
*************************************************************/
 
167
static void enforcer_display_hit (const char *addressmode, uae_u32 pc, uaecptr addr)
 
168
{
 
169
    uae_u32 a7;
 
170
    uae_u32 sysbase;
 
171
    uae_u32 this_task;
 
172
    uae_u32 task_name;
 
173
    const char *native_task_name;
 
174
    int i, j;
 
175
    static char buf[256], instrcode[256];
 
176
    static char lines[INSTRUCTIONLINES/2][256];
 
177
    static uaecptr bestpc_array[INSTRUCTIONLINES/2][5];
 
178
    static int bestpc_idxs[INSTRUCTIONLINES/2];
 
179
    char *enforcer_buf_ptr = enforcer_buf;
 
180
    uaecptr bestpc, pospc, nextpc, temppc;
 
181
 
 
182
    if (enforcer_hit) return; /* our function itself generated a hit ;), avoid endless loop */
 
183
        enforcer_hit = 1;
 
184
 
 
185
    if (!(sysbase = get_long (4)))
 
186
        return;
 
187
    if (!(this_task = get_long (sysbase + 276)))
 
188
        return;
 
189
 
 
190
    task_name = get_long (this_task + 10); /* ln_Name */
 
191
    native_task_name = (char *) amiga2native (task_name, 100);
 
192
 
 
193
    strcpy (enforcer_buf_ptr, "Enforcer Hit! Bad program\n");
 
194
    enforcer_buf_ptr += strlen (enforcer_buf_ptr);
 
195
 
 
196
    sprintf (buf, "Illegal %s: %08lx", addressmode, addr);
 
197
    sprintf (enforcer_buf_ptr,"%-48sPC: %0lx\n", buf, pc);
 
198
    enforcer_buf_ptr += strlen (enforcer_buf_ptr);
 
199
 
 
200
    /* Data registers */
 
201
    sprintf (enforcer_buf_ptr, "Data: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
 
202
        m68k_dreg (&regs, 0), m68k_dreg (&regs, 1), m68k_dreg (&regs, 2), m68k_dreg (&regs, 3),
 
203
        m68k_dreg (&regs, 4), m68k_dreg (&regs, 5), m68k_dreg (&regs, 6), m68k_dreg (&regs, 7));
 
204
    enforcer_buf_ptr += strlen (enforcer_buf_ptr);
 
205
 
 
206
    /* Address registers */
 
207
    sprintf (enforcer_buf_ptr, "Addr: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
 
208
        m68k_areg (&regs, 0), m68k_areg (&regs, 1), m68k_areg (&regs, 2), m68k_areg (&regs, 3),
 
209
        m68k_areg (&regs, 4), m68k_areg (&regs, 5), m68k_areg (&regs, 6), m68k_areg (&regs, 7));
 
210
    enforcer_buf_ptr += strlen(enforcer_buf_ptr);
 
211
 
 
212
    /* Stack */
 
213
    a7 = m68k_areg (&regs, 7);
 
214
    for (i = 0; i < 8 * STACKLINES; i++) {
 
215
        a7 -= 4;
 
216
        if (!(i % 8)) {
 
217
            strcpy (enforcer_buf_ptr,"Stck:");
 
218
            enforcer_buf_ptr += strlen (enforcer_buf_ptr);
 
219
        }
 
220
        sprintf (enforcer_buf_ptr," %08lx", get_long (a7));
 
221
        enforcer_buf_ptr += strlen (enforcer_buf_ptr);
 
222
 
 
223
        if (i%8 == 7)
 
224
            *enforcer_buf_ptr++ = '\n';
 
225
    }
 
226
 
 
227
    /* Segtracker output */
 
228
    a7 = m68k_areg (&regs, 7);
 
229
    if (get_long (a7-4) != pc) {
 
230
        if (enforcer_decode_hunk_and_offset (buf, pc)) {
 
231
            strcpy (enforcer_buf_ptr, buf);
 
232
            enforcer_buf_ptr += strlen (enforcer_buf_ptr);
 
233
        }
 
234
    }
 
235
 
 
236
    for (i = 0; i < 8 * STACKLINES; i++) {
 
237
        a7 -= 4;
 
238
        if (enforcer_decode_hunk_and_offset (buf, get_long (a7))) {
 
239
            int l = strlen (buf);
 
240
 
 
241
            if (ENFORCER_BUF_SIZE - (enforcer_buf_ptr - enforcer_buf) > l + 256) {
 
242
                strcpy(enforcer_buf_ptr, buf);
 
243
                enforcer_buf_ptr += l;
 
244
            }
 
245
        }
 
246
    }
 
247
 
 
248
    /* Decode the instructions around the pc where the enforcer hit was caused.
 
249
     *
 
250
     * At first, the area before the pc, this not always done correctly because
 
251
     * it's done backwards */
 
252
    temppc = pc;
 
253
 
 
254
    memset (bestpc_array, 0, sizeof (bestpc_array));
 
255
    for (i = 0; i < INSTRUCTIONLINES / 2; i++)
 
256
        bestpc_idxs[i] = -1;
 
257
 
 
258
    for (i = 0; i < INSTRUCTIONLINES / 2; i++) {
 
259
        pospc = temppc;
 
260
        bestpc = 0;
 
261
 
 
262
        if (bestpc_idxs[i] == -1) {
 
263
            for (j = 0; j < 5; j++) {
 
264
                pospc -= 2;
 
265
                sm68k_disasm (buf, NULL, pospc, &nextpc);
 
266
                if (nextpc == temppc) {
 
267
                    bestpc_idxs[i] = j;
 
268
                    bestpc_array[i][j] = bestpc = pospc;
 
269
                }
 
270
            }
 
271
        } else {
 
272
            bestpc = bestpc_array[i][bestpc_idxs[i]];
 
273
        }
 
274
 
 
275
        if (!bestpc) {
 
276
            /* there was no best pc found, so it is high probable that
 
277
             * a former used best pc was wrong.
 
278
             *
 
279
             * We trace back and use the former best pc instead
 
280
             */
 
281
 
 
282
            int former_idx;
 
283
            int leave = 0;
 
284
 
 
285
            do {
 
286
                if (!i) {
 
287
                    leave = 1;
 
288
                    break;
 
289
                }
 
290
                i--;
 
291
                former_idx = bestpc_idxs[i];
 
292
                bestpc_idxs[i] = -1;
 
293
                bestpc_array[i][former_idx] = 0;
 
294
 
 
295
                for (j = former_idx - 1; j >= 0; j--) {
 
296
                    if (bestpc_array[i][j]) {
 
297
                        bestpc_idxs[i] = j;
 
298
                        break;
 
299
                    }
 
300
                }
 
301
            } while (bestpc_idxs[i] == -1);
 
302
            if (leave)
 
303
                break;
 
304
            if (i)
 
305
                temppc = bestpc_array[i-1][bestpc_idxs[i-1]];
 
306
            else temppc = pc;
 
307
                i--; /* will be increased in after continue */
 
308
            continue;
 
309
        }
 
310
 
 
311
        sm68k_disasm (buf, instrcode, bestpc, NULL);
 
312
        sprintf (lines[i], "%08lx :   %-20s %s\n", bestpc, instrcode, buf);
 
313
        temppc = bestpc;
 
314
    }
 
315
 
 
316
    i--;
 
317
    for (; i>=0; i--) {
 
318
        strcpy (enforcer_buf_ptr,lines[i]);
 
319
        enforcer_buf_ptr += strlen (enforcer_buf_ptr);
 
320
    }
 
321
 
 
322
    /* Now the instruction after the pc including the pc */
 
323
    temppc = pc;
 
324
    for (i=0; i < (INSTRUCTIONLINES+1) / 2; i++) {
 
325
        sm68k_disasm (buf, instrcode, temppc, &nextpc);
 
326
        sprintf (enforcer_buf_ptr, "%08lx : %s %-20s %s\n", temppc,
 
327
                (i == 0 ? "*" : " "), instrcode, buf);
 
328
        enforcer_buf_ptr += strlen (enforcer_buf_ptr);
 
329
        temppc = nextpc;
 
330
    }
 
331
 
 
332
    if (!native_task_name)
 
333
        native_task_name = "Unknown";
 
334
    sprintf (enforcer_buf_ptr, "Name: \"%s\"\n\n", native_task_name);
 
335
    enforcer_buf_ptr += strlen (enforcer_buf_ptr);
 
336
 
 
337
    console_out (enforcer_buf);
 
338
    write_log (enforcer_buf);
 
339
 
 
340
    enforcer_hit = 0;
 
341
    flashscreen = 30;
 
342
}
 
343
 
 
344
/*
 
345
 * Replacement chipmem accessors
 
346
 */
 
347
 
 
348
static uae_u32  chipmem_lget2  (uaecptr addr) REGPARAM;
 
349
static uae_u32  chipmem_wget2  (uaecptr addr) REGPARAM;
 
350
static uae_u32  chipmem_bget2  (uaecptr addr) REGPARAM;
 
351
static void     chipmem_lput2  (uaecptr addr, uae_u32 l) REGPARAM;
 
352
static void     chipmem_wput2  (uaecptr addr, uae_u32 w) REGPARAM;
 
353
static void     chipmem_bput2  (uaecptr addr, uae_u32 b) REGPARAM;
 
354
static int      chipmem_check2 (uaecptr addr, uae_u32 size) REGPARAM;
 
355
static uae_u8 * chipmem_xlate2 (uaecptr addr) REGPARAM;
 
356
 
 
357
static uae_u32 REGPARAM2 chipmem_lget2 (uaecptr addr)
 
358
{
 
359
    uae_u32 *m;
 
360
 
 
361
    addr -= chipmem_start & chipmem_mask;
 
362
    addr &= chipmem_mask;
 
363
    m = (uae_u32 *)(chipmemory + addr);
 
364
 
 
365
    if (ISILLEGAL (addr))
 
366
        enforcer_display_hit ("LONG READ from", GET_PC, addr);
 
367
 
 
368
    return do_get_mem_long (m);
 
369
}
 
370
 
 
371
static uae_u32 REGPARAM2 chipmem_wget2 (uaecptr addr)
 
372
{
 
373
    uae_u16 *m;
 
374
 
 
375
    addr -= chipmem_start & chipmem_mask;
 
376
    addr &= chipmem_mask;
 
377
    m = (uae_u16 *)(chipmemory + addr);
 
378
 
 
379
    if (ISILLEGAL (addr))
 
380
        enforcer_display_hit ("WORD READ from", GET_PC, addr);
 
381
 
 
382
    return do_get_mem_word (m);
 
383
}
 
384
 
 
385
static uae_u32 REGPARAM2 chipmem_bget2 (uaecptr addr)
 
386
{
 
387
    addr -= chipmem_start & chipmem_mask;
 
388
    addr &= chipmem_mask;
 
389
 
 
390
    if (ISILLEGAL (addr))
 
391
        enforcer_display_hit ("BYTE READ from", GET_PC, addr);
 
392
 
 
393
    return chipmemory[addr];
 
394
}
 
395
 
 
396
static void REGPARAM2 chipmem_lput2 (uaecptr addr, uae_u32 l)
 
397
{
 
398
    uae_u32 *m;
 
399
 
 
400
    addr -= chipmem_start & chipmem_mask;
 
401
    addr &= chipmem_mask;
 
402
    m = (uae_u32 *)(chipmemory + addr);
 
403
 
 
404
    if (ISILLEGAL (addr))
 
405
        enforcer_display_hit ("LONG WRITE to", GET_PC, addr);
 
406
 
 
407
    do_put_mem_long (m, l);
 
408
}
 
409
 
 
410
static void REGPARAM2 chipmem_wput2 (uaecptr addr, uae_u32 w)
 
411
{
 
412
    uae_u16 *m;
 
413
 
 
414
    addr -= chipmem_start & chipmem_mask;
 
415
    addr &= chipmem_mask;
 
416
    m = (uae_u16 *)(chipmemory + addr);
 
417
 
 
418
    if (ISILLEGAL (addr))
 
419
        enforcer_display_hit ("WORD WRITE to", GET_PC, addr);
 
420
 
 
421
    do_put_mem_word (m, w);
 
422
}
 
423
 
 
424
static void REGPARAM2 chipmem_bput2 (uaecptr addr, uae_u32 b)
 
425
{
 
426
    addr -= chipmem_start & chipmem_mask;
 
427
    addr &= chipmem_mask;
 
428
 
 
429
    if (ISILLEGAL (addr))
 
430
        enforcer_display_hit ("BYTE WRITE to", GET_PC, addr);
 
431
    chipmemory[addr] = b;
 
432
}
 
433
 
 
434
static int REGPARAM2 chipmem_check2 (uaecptr addr, uae_u32 size)
 
435
{
 
436
    addr -= chipmem_start & chipmem_mask;
 
437
    addr &= chipmem_mask;
 
438
    return (addr + size) <= allocated_chipmem;
 
439
}
 
440
 
 
441
static uae_u8 * REGPARAM2 chipmem_xlate2 (uaecptr addr)
 
442
{
 
443
    addr -= chipmem_start & chipmem_mask;
 
444
    addr &= chipmem_mask;
 
445
    return chipmemory + addr;
 
446
}
 
447
 
 
448
static const addrbank enforcer_chipmem_bank = {
 
449
    chipmem_lget2, chipmem_wget2, chipmem_bget2,
 
450
    chipmem_lput2, chipmem_wput2, chipmem_bput2,
 
451
    chipmem_xlate2, chipmem_check2, NULL
 
452
};
 
453
 
 
454
/*
 
455
 * Replacement dummy memory accessors
 
456
 */
 
457
static uae_u32  dummy_lget2    (uaecptr addr) REGPARAM;
 
458
static uae_u32  dummy_wget2    (uaecptr addr) REGPARAM;
 
459
static uae_u32  dummy_bget2    (uaecptr addr) REGPARAM;
 
460
static void     dummy_lput2    (uaecptr addr, uae_u32 l) REGPARAM;
 
461
static void     dummy_wput2    (uaecptr addr, uae_u32 w) REGPARAM;
 
462
static void     dummy_bput2    (uaecptr addr, uae_u32 b) REGPARAM;
 
463
static int      dummy_check2   (uaecptr addr, uae_u32 size) REGPARAM;
 
464
 
 
465
static uae_u32 REGPARAM2 dummy_lget2 (uaecptr addr)
 
466
{
 
467
#ifdef JIT
 
468
    special_mem |= SPECIAL_MEM_READ;
 
469
#endif
 
470
    enforcer_display_hit ("LONG READ from", GET_PC, addr);
 
471
    return 0xbadedeef;
 
472
}
 
473
 
 
474
#ifdef JIT
 
475
static int warned_JIT_0xF10000 = 0;
 
476
#endif
 
477
 
 
478
static uae_u32 REGPARAM2 dummy_wget2 (uaecptr addr)
 
479
{
 
480
#ifdef JIT
 
481
    special_mem |= SPECIAL_MEM_READ;
 
482
 
 
483
    if (addr >= 0x00F10000 && addr <= 0x00F7FFFF) {
 
484
        if (!warned_JIT_0xF10000) {
 
485
            warned_JIT_0xF10000 = 1;
 
486
            enforcer_display_hit ("LONG READ from", GET_PC, addr);
 
487
        }
 
488
        return 0;
 
489
    }
 
490
#endif
 
491
    enforcer_display_hit ("WORD READ from", GET_PC, addr);
 
492
    return 0xbadf;
 
493
}
 
494
 
 
495
static uae_u32 REGPARAM2 dummy_bget2 (uaecptr addr)
 
496
{
 
497
#ifdef JIT
 
498
    special_mem |= SPECIAL_MEM_READ;
 
499
#endif
 
500
    enforcer_display_hit ("BYTE READ from", GET_PC, addr);
 
501
    return 0xbadedeef;
 
502
}
 
503
 
 
504
static void REGPARAM2 dummy_lput2 (uaecptr addr, uae_u32 l)
 
505
{
 
506
#ifdef JIT
 
507
    special_mem |= SPECIAL_MEM_WRITE;
 
508
#endif
 
509
    enforcer_display_hit ("LONG WRITE to", GET_PC, addr);
 
510
}
 
511
 
 
512
static void REGPARAM2 dummy_wput2 (uaecptr addr, uae_u32 w)
 
513
{
 
514
#ifdef JIT
 
515
    special_mem |= SPECIAL_MEM_WRITE;
 
516
#endif
 
517
    enforcer_display_hit ("WORD WRITE to", GET_PC, addr);
 
518
}
 
519
 
 
520
static void REGPARAM2 dummy_bput2 (uaecptr addr, uae_u32 b)
 
521
{
 
522
#ifdef JIT
 
523
    special_mem |= SPECIAL_MEM_WRITE;
 
524
#endif
 
525
    enforcer_display_hit ("BYTE WRITE to", GET_PC, addr);
 
526
}
 
527
 
 
528
static int REGPARAM2 dummy_check2 (uaecptr addr, uae_u32 size)
 
529
{
 
530
#ifdef JIT
 
531
    special_mem |= SPECIAL_MEM_READ;
 
532
#endif
 
533
    enforcer_display_hit ("CHECK from ", GET_PC, addr);
 
534
    return 0;
 
535
}
 
536
 
 
537
const addrbank enforcer_dummy_bank = {
 
538
    dummy_lget2, dummy_wget2, dummy_bget2,
 
539
    dummy_lput2, dummy_wput2, dummy_bput2,
 
540
    default_xlate, dummy_check2, NULL
 
541
};
 
542
 
 
543
/*************************************************************
 
544
 enable the enforcer like support, maybe later this make MMU
 
545
 exceptions so enforcer can use it. Returns 1 if enforcer
 
546
 is enabled
 
547
*************************************************************/
 
548
int enforcer_enable (void)
 
549
{
 
550
    extern addrbank chipmem_bank, dummy_bank;
 
551
 
 
552
    if (!enforcer_installed) {
 
553
        saved_dummy_bank   = dummy_bank;
 
554
        saved_chipmem_bank = chipmem_bank;
 
555
 
 
556
        dummy_bank   = enforcer_dummy_bank;
 
557
        chipmem_bank = enforcer_chipmem_bank;
 
558
 
 
559
        enforcer_installed = 1;
 
560
    }
 
561
    write_log ("Enforcer enabled\n");
 
562
    return 1;
 
563
}
 
564
 
 
565
/*************************************************************
 
566
 Disable Enforcer like support
 
567
*************************************************************/
 
568
int enforcer_disable (void)
 
569
{
 
570
    if (enforcer_installed) {
 
571
        dummy_bank   = saved_dummy_bank;
 
572
        chipmem_bank = saved_chipmem_bank;
 
573
 
 
574
        enforcer_installed = 0;
 
575
    }
 
576
    return 1;
 
577
}
 
578
 
 
579
#endif