#include <sys/ioctl.h>
#include <sys/wait.h>
#include <termios.h>
+#include <time.h>
#include <unistd.h>
#include <SDL2/SDL.h>
#include "stty_sane.h"
#include "vrEmu6502/src/vrEmu6502.h"
-#define APPLE_IIE 1
+#define APPLE_IIE 0
#define APPLE_WIDTH 560
#define APPLE_HEIGHT 192
#define APPLE_TEXT1 0x400
VrEmu6502 *cpu;
-#if APPLE_IIE
+#include "cg_default/cg_default.inc"
+
+#define CG_ROM_SIZE 0x800
+uint8_t *cg_rom;
+
#define VIDEO_ROM_SIZE 0x1000
-uint8_t video_rom[VIDEO_ROM_SIZE];
+uint8_t *video_rom;
+#if APPLE_IIE
#define MEM_SIZE 0x24000
#else
-#define CG_ROM_SIZE 0x800
-uint8_t cg_rom[CG_ROM_SIZE];
-
#define MEM_SIZE 0x14000
#endif
uint8_t mem[MEM_SIZE];
int main(int argc, char **argv) {
int argn = 1;
+ char *cg_rom_file = NULL;
#if APPLE_IIE
char *video_rom_file =
"Apple IIe Video Enhanced - 342-0265-A - 2732.bin";
"Apple IIe CD Enhanced - 342-0304-A - 2764.bin";
char *ef_rom_file =
"Apple IIe EF Enhanced - 342-0303-A - 2764.bin";
- bool timing = false;
- while (argn < argc) {
- if (strcmp(argv[argn], "--help") == 0) {
- printf("usage: %s [--video_rom=file.bin] [--cd_rom=file.bin] [--ef_rom=file.bin] [--timing] [program.obj[,aNNNN] ...] [-- child_executable [child_argument ...]]\n", argv[0]);
- exit(EXIT_FAILURE);
- }
- if (memcmp(argv[argn], "--video_rom=", 12) == 0)
- video_rom_file = argv[argn] + 12;
- else if (memcmp(argv[argn], "--cd_rom=", 9) == 0)
- cd_rom_file = argv[argn] + 9;
- else if (memcmp(argv[argn], "--ef_rom=", 9) == 0)
- ef_rom_file = argv[argn] + 9;
- else if (strcmp(argv[argn], "--timing") == 0)
- timing = true;
- else
- break;
- ++argn;
- }
-
- rom_load(video_rom_file, video_rom, VIDEO_ROM_SIZE);
-
- rom_load(cd_rom_file, mem + 0x20000, 0x2000);
- rom_load(ef_rom_file, mem + 0x22000, 0x2000);
#else
- char *cg_rom_file =
- "Apple II+ - 7341-0036 - Character Generator Rev7+ - 2716.bin";
+ char *video_rom_file = NULL;
char *d0_rom_file =
"Apple II+ - 341-0011 - Applesoft BASIC D000 - 2716.bin";
char *d8_rom_file =
"Apple II+ - 341-0015 - Applesoft BASIC F000 - 2716.bin";
char *f8_rom_file =
"Apple II+ - 341-0020 - Applesoft BASIC Autostart Monitor F800 - 2716.bin";
+#endif
bool timing = false;
while (argn < argc) {
if (strcmp(argv[argn], "--help") == 0) {
- printf("usage: %s [--cg_rom=file.bin] [--d0_rom=file.bin] [--d8_rom=file.bin] [--e0_rom=file.bin] [--e8_rom=file.bin] [--f0_rom=file.bin] [--f8_rom=file.bin] [--timing] [program.obj[,aNNNN] ...] [-- child_executable [child_argument ...]]\n", argv[0]);
+ printf("usage: %s [--no-cg-rom|--cg-rom=file.bin] [--no-video-rom|--video-rom=file.bin] [--no-NN-rom|--NN-rom=file.bin ...] [--timing] [program.obj[,aNNNN] ...] [-- child-executable [child-argument ...]]\n", argv[0]);
exit(EXIT_FAILURE);
}
- if (memcmp(argv[argn], "--cg_rom=", 9) == 0)
+ if (strcmp(argv[argn], "--no-cg-rom") == 0)
+ cg_rom_file = NULL;
+ else if (memcmp(argv[argn], "--cg-rom=", 9) == 0)
cg_rom_file = argv[argn] + 9;
- else if (memcmp(argv[argn], "--d0_rom=", 9) == 0)
+ else if (strcmp(argv[argn], "--no-video-rom") == 0)
+ video_rom_file = NULL;
+ else if (memcmp(argv[argn], "--video_rom=", 12) == 0)
+ video_rom_file = argv[argn] + 12;
+#if APPLE_IIE
+ else if (strcmp(argv[argn], "--no-cd-rom") == 0)
+ cd_rom_file = NULL;
+ else if (memcmp(argv[argn], "--cd-rom=", 9) == 0)
+ cd_rom_file = argv[argn] + 9;
+ else if (strcmp(argv[argn], "--no-ef-rom") == 0)
+ ef_rom_file = NULL;
+ else if (memcmp(argv[argn], "--ef-rom=", 9) == 0)
+ ef_rom_file = argv[argn] + 9;
+#else
+ else if (strcmp(argv[argn], "--no-d0-rom") == 0)
+ d0_rom_file = NULL;
+ else if (memcmp(argv[argn], "--d0-rom=", 9) == 0)
d0_rom_file = argv[argn] + 9;
- else if (memcmp(argv[argn], "--d8_rom=", 9) == 0)
+ else if (strcmp(argv[argn], "--no-d8-rom") == 0)
+ d8_rom_file = NULL;
+ else if (memcmp(argv[argn], "--d8-rom=", 9) == 0)
d8_rom_file = argv[argn] + 9;
- else if (memcmp(argv[argn], "--e0_rom=", 9) == 0)
+ else if (strcmp(argv[argn], "--no-e0-rom") == 0)
+ e0_rom_file = NULL;
+ else if (memcmp(argv[argn], "--e0-rom=", 9) == 0)
e0_rom_file = argv[argn] + 9;
- else if (memcmp(argv[argn], "--e8_rom=", 9) == 0)
+ else if (strcmp(argv[argn], "--no-e8-rom") == 0)
+ e8_rom_file = NULL;
+ else if (memcmp(argv[argn], "--e8-rom=", 9) == 0)
e8_rom_file = argv[argn] + 9;
- else if (memcmp(argv[argn], "--f0_rom=", 9) == 0)
+ else if (strcmp(argv[argn], "--no-f0-rom") == 0)
+ f0_rom_file = NULL;
+ else if (memcmp(argv[argn], "--f0-rom=", 9) == 0)
f0_rom_file = argv[argn] + 9;
- else if (memcmp(argv[argn], "--f8_rom=", 9) == 0)
+ else if (strcmp(argv[argn], "--no-f8-rom") == 0)
+ f8_rom_file = NULL;
+ else if (memcmp(argv[argn], "--f8-rom=", 9) == 0)
f8_rom_file = argv[argn] + 9;
+#endif
else if (strcmp(argv[argn], "--timing") == 0)
timing = true;
else
++argn;
}
- rom_load(cg_rom_file, cg_rom, CG_ROM_SIZE);
+ // the IIe emulation can run without a video ROM and fall back to
+ // II+ style character generation, this is done for the benefit
+ // of DHGR or 128K games that require Apple IIe but not text mode
+ if (video_rom_file) {
+ video_rom = malloc(VIDEO_ROM_SIZE);
+ if (video_rom == NULL) {
+ perror("malloc()");
+ exit(EXIT_FAILURE);
+ }
+ rom_load(video_rom_file, video_rom, VIDEO_ROM_SIZE);
+ }
+ else {
+ cg_rom = malloc(CG_ROM_SIZE);
+ if (cg_rom == NULL) {
+ perror("malloc()");
+ exit(EXIT_FAILURE);
+ }
+ if (cg_rom_file)
+ rom_load(cg_rom_file, cg_rom, CG_ROM_SIZE);
+ else
+ for (int i = 0; i < 4; ++i)
+ memcpy(cg_rom + (i << 9), cg_default, CG_DEFAULT_SIZE);
+ }
+#if APPLE_IIE
+ rom_load(cd_rom_file, mem + 0x20000, 0x2000);
+ rom_load(ef_rom_file, mem + 0x22000, 0x2000);
+#else
memset(mem + 0x10000, 0xff, 0x1000);
rom_load(d0_rom_file, mem + 0x11000, 0x800);
rom_load(d8_rom_file, mem + 0x11800, 0x800);
SDL_RenderClear(renderer);
// draw
+ struct timespec timeval;
+ clock_gettime(CLOCK_MONOTONIC, &timeval);
+ bool flash_state = timeval.tv_nsec >= 500000000;
+
+ // video ROM does inverse/flash by manipulating base address
+ int flash_base[4] = {
+ 0,
+#if APPLE_IIE
+ // in alternate character mode, use video ROM directly (mousetext)
+ (c00x_soft_switches & C00X_SOFT_SWITCH_ALTCHAR) ?
+ 0x200 :
+#endif
+ flash_state ? 0 : 0x400,
+ 0x400,
+ 0x600
+ };
+
+ // CG ROM does inverse/flash by XORing onto the value from ROM
+ int flash_xor[4] = {0x7f, flash_state ? 0x7f : 0, 0, 0};
+
memset(frame, 0, WINDOW_HEIGHT * WINDOW_WIDTH * sizeof(uint32_t));
for (int i = 0; i < APPLE_HEIGHT; ++i) {
int base = (i >> 6) * 40 | ((i & 0x38) << 4);
) | base;
#endif
for (int j = 0; j < 40; ++j) {
-#if APPLE_IIE // inverted, LSB first
- int data = video_rom[(mem[line + j] << 3) | row];
- for (int k = 0; k < 7; ++k) {
- if ((data & 1) == 0) {
- int l = (j * 7 + k) << 1;
- buf[l >> 5] |= 1 << (l & 0x1f);
- ++l;
- buf[l >> 5] |= 1 << (l & 0x1f);
+ int glyph = mem[line + j];
+ if (video_rom) { // inverted, LSB first
+ int data = video_rom[
+ row | ((glyph & 0x3f) << 3) | flash_base[glyph >> 6]
+ ];
+ for (int k = 0; k < 7; ++k) {
+ if ((data & 1) == 0) {
+ int l = (j * 7 + k) << 1;
+ buf[l >> 5] |= 1 << (l & 0x1f);
+ ++l;
+ buf[l >> 5] |= 1 << (l & 0x1f);
+ }
+ data >>= 1;
}
- data >>= 1;
}
-#else // MSB first
- int data = cg_rom[(mem[line + j] << 3) | row];
- for (int k = 0; k < 7; ++k) {
- if (data & 0x40) {
- int l = (j * 7 + k) << 1;
- buf[l >> 5] |= 1 << (l & 0x1f);
- ++l;
- buf[l >> 5] |= 1 << (l & 0x1f);
+ else { // MSB first
+ int data = cg_rom[row | (glyph << 3)] ^ flash_xor[glyph >> 6];
+ for (int k = 0; k < 7; ++k) {
+ if (data & 0x40) {
+ int l = (j * 7 + k) << 1;
+ buf[l >> 5] |= 1 << (l & 0x1f);
+ ++l;
+ buf[l >> 5] |= 1 << (l & 0x1f);
+ }
+ data <<= 1;
}
- data <<= 1;
}
-#endif
}
}