ilo-vm/source/ilo-68k-mac.c

1 line
5.5 KiB
C
Raw Normal View History

/* ilo for System 6 / Mac 68k Copyright (c) 2022, Charles Childers Deriving from the ilo for MS-DOS, this makes use of an internally segmented memory model. The 68k CPU is big endian. Since the ilo images and blocks are stored in little endian a fix() function has been written and is used to convert between the formats as needed. As with all ilo systems, this needs an ilo.rom and ilo.blocks. It's likely to crash if these are not present. I'm building this using Think C 5.0.2, using the ANSI library. It's not tested with any other compiler on 68k. */ #include <stdio.h> #include <stdlib.h> #define SLICES 8 #define SLICESIZE 8192 long ip, sp, rp, data[32], address[256]; long *memory[SLICES]; #define TOS data[sp] #define NOS data[sp-1] #define TORS address[rp] unsigned long fix(unsigned long v) { return (((v & 0x000000FF) << 24)| ((v & 0x0000FF00) << 8) | ((v & 0x00FF0000) >> 8) | ((v & 0xFF000000) >> 24)); } long pop() { sp--; return data[sp + 1]; } void push(long value) { sp++; data[sp] = value; } void store(long a, long v) { long slice = a / SLICESIZE; long actual = a - (slice * SLICESIZE); memory[slice][actual] = v; } long fetch(long a) { long slice = a / SLICESIZE; long actual = a - (slice * SLICESIZE); return memory[slice][actual]; } void prepare_vm() { for (ip = 0; ip < 32; ip++) data[ip] = 0; for (ip = 0; ip < 128; ip++) address[ip] = 0; ip = sp = rp = 0; } void load_image() { FILE *fp; long x, y, z; fp = fopen("ilo.rom", "rb"); for (y = 0; y < 65536; y++) { x = 0; fread(&x, 4, 1, fp); store(y, fix(x)); } fclose(fp); prepare_vm(); } void save_image() { FILE *fp; long i, x; fp = fopen("ilo.rom", "wb"); for (i = 0; i < 65536; i++) { x = fix(fetch(i)); fwrite(&x, 4, 1, fp); } fclose(fp); } void read_block() { FILE *f; long block, buffer, x, c; buffer = pop(); block = pop(); f = fopen("ilo.blocks", "r+b"); fseek(f, 4096 * block, SEEK_SET); for (x = 0; x < 1024; x++) { c = 0; fread(&c, 4, 1, f); store(buffer + x, fix(c)); } fclose(f); } void write_block() { FILE *f; long block, buffer, x, c; buffer = pop(); block = pop(); f = fopen("ilo.blocks", "r+b"); fseek(f, 4096 * block, SEEK_SET); for (x = 0; x < 1024; x++) { c = fix(fetch(buffer + x)); fwrite(&c, 4, 1, f); } fclose(f); } void process(long o) { long a, b, target, flag; long src, dest, len; switch (o) { case 0: break; case 1: ip++; push(fetch(ip)); break; case 2: push(TOS); break; case 3: data[sp] = 0; sp--; break; case 4: a = TOS; TOS = NOS; NOS = a; break; case 5: rp++; TORS = pop(); break; case 6: push(TORS); rp--; break; case 7: ip = pop() - 1; break; case 8: rp++; TORS = ip; ip = pop() - 1; break; case 9: target = pop(); flag = pop(); if (flag != 0) { rp++; TORS = ip; ip = target - 1; } break; case 10: target = pop(); flag = pop(); if (flag != 0) ip = target - 1; break; case 11: ip = TORS; rp--; break; case 12: NOS = (NOS == TOS) ? -1 : 0; sp--; break; case 13: NOS = (NOS != TOS) ? -1 : 0; sp--; break; case 14: NOS = (NOS < TOS) ? -1 : 0; sp--; break; case 15: NOS = (NOS > TOS) ? -1 : 0; sp--; break; case 16: TOS = fetch(TOS); break; case 17: store(TOS, NOS); sp--; sp--; break; case 18: NOS += TOS; sp--; break; case 19: NOS -= TOS; sp--; break; case 20: NOS *= TOS; sp--; break; case 21: a = TOS; b = NOS; TOS = b / a; NOS = b % a; break; case 22: NOS = TOS & NOS; sp--; break; case 23: NOS = TOS | NOS; sp--; break; case 24: NOS = TOS ^ NOS; sp--; break; case 25: NOS = NOS << TOS; sp--; break; case 26: NOS = NOS >> TOS; sp--; break; case 27: len = pop(); dest = pop(); src = pop(); flag = -1; while (len) { if (fetch(dest) != fetch(src)) flag = 0; len -= 1; src += 1; dest += 1; }; push(flag); break; case 28: len = pop